kubernetes 之 Pod调度指定节点与隔离

kubernetes 之 Pod调度指定节点与隔离

摘要:kubernetes pod 的调度主要是靠master中的kube-scheduler组件进行实现的,默认他会随机将我们的Pod 调度到存活的节点上(即节点状态是ready),但是在生产环境或者业务需求,我们往往需要将某类pod 调度到指定的节点,让pod遵循我们的意志去调度,而不是默认随机。在介绍Kubernetes对象一节中介绍过。这类需求kubernetes都是靠lable和selector实现的,这一对东西就像是街头暗号。只要双方一致,那么就会按照计划去实行。我们之前的service 和 pod 之间的联系就是靠这一对“东西”来实现的。(POD中定义了label 例如app=mysql,我们为这组Pod 建立一个对应的service 入口,但是这个service就是为了app=mysql这组pod 而生的,为了能对上“暗号”我们的service定义了selector app=mysql),同理我们的pod 调度到指定Node节点也是依靠这个原理。只不过他叫NodeSelector

一.  Nodeselector 调度指定节点

1.查看节点的label标签

[root@master ~]# kubectl get nodes node-1 –show-labels
NAME STATUS ROLES AGE VERSION LABELS
node-1 Ready <none> 7d9h v1.13.1 app=mysql,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node-1

我们可以看到node-1可以拥有多个标签,os=linux ;hostname=node-1;<app=mysql> 这个是我测试时候填写的。我一会删除并新添加标签

2.删除节点中某个名字的标签

[root@master ~]# kubectl label nodes node-1 app-
node/node-1 labeled

app 是我们node-1 app=mysql这个标签的名字, – 符号代表删除

[root@master ~]# kubectl get nodes node-1 –show-labels
NAME STATUS ROLES AGE VERSION LABELS
node-1 Ready <none> 7d9h v1.13.1 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node-1

再次查看没有app=mysql标签

3.创建标签

[root@master ~]# kubectl label nodes node-1 app=nginx
node/node-1 labeled
[root@master ~]# kubectl get nodes node-1 –show-labels
NAME STATUS ROLES AGE VERSION LABELS
node-1 Ready <none> 7d9h v1.13.1 app=nginx,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node-1

这次创建了app=nginx这个标签

4.修改标签

[root@master ~]# kubectl label nodes node-1 app=tomcat
error: ‘app’ already has a value (nginx), and –overwrite is false
[root@master ~]# kubectl label nodes node-1 app=tomcat –overwrite
node/node-1 labeled
[root@master ~]# kubectl get nodes node-1 –show-labels
NAME STATUS ROLES AGE VERSION LABELS
node-1 Ready <none> 7d9h v1.13.1 app=tomcat,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node-1

这个修改是标签名字不变,对应的值改变。app=nginx变为app=tomcat 修改需要加 –overwrite 参数才可以修改成功

接下来我们创建pod 看是否可以调度到指定节点上

  • pod   文件 

apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
– name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
app: tomcat # 对应Node的Label

  • 创建查看POD

[root@master ~]# kubectl create -f nginx_test.yaml
pod/nginx created
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 0/1 ContainerCreating 0 1s

可以看到容器正在创建,describe看下详细的信息,主要看event事件和

[root@master ~]# kubectl describe pod nginx
Name: nginx
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: node-1/192.168.137.101
Start Time: Fri, 04 Jan 2019 11:46:38 +0800
Labels: env=test
Annotations: <none>
Status: Pending
IP:
Containers:
nginx:
Container ID:
Image: nginx
Image ID:
Port: <none>
Host Port: <none>
State: Waiting
Reason: ContainerCreating
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-6dwbq (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
default-token-6dwbq:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-6dwbq
Optional: false
QoS Class: BestEffort
Node-Selectors: app=tomcat
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
—- —— —- —- ——-
Normal Pulling 2m44s kubelet, node-1 pulling image “nginx”
Normal Scheduled 10s default-scheduler Successfully assigned default/nginx to node-1

通过输出信息可以看到已经将Pod调度到nginx 并拉取nginx 镜像,过了大概30秒再次查看event事件

Events:
Type Reason Age From Message
—- —— —- —- ——-
Normal Pulling 3m4s kubelet, node-1 pulling image “nginx”
Normal Pulled 2m53s kubelet, node-1 Successfully pulled image “nginx”
Normal Created 2m53s kubelet, node-1 Created container
Normal Started 2m53s kubelet, node-1 Started container
Normal Scheduled 30s default-scheduler Successfully assigned default/nginx to node-1

[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 45s 192.168.1.17 node-1 <none> <none>

pod 已经在节点1正常运行<实验1结束>

二.将某类pod与node隔离(不让调度到具体某个节点上,与Nodeselector正相反)介绍Taint(污点)与Toleration(容忍污点)

概念:Taint和label一样是个动作 能够使节点标记为污点,标记上污点的节点理论上会排斥pod ,当且仅当POD被指定了 toleration (容忍污点),这样的pod才会被调度到污点Node 

注意:Taint对应的是 node ,Toleration对应的是pod 上的,不要混淆。

类型与区别:

tolerations:
- key: "key"
  operator: "Equal"
  value: "value"
  effect: "NoSchedule"

tolerations:
– key: “key”
operator: “Exists”
effect: “NoSchedule”

 

匹配规则:

二者不同的是operator字段,当toleration和taint 的key和effect字段相同时候,此时相匹配。

  • 如果operator是Equal,taint和toleration的value值必须相等
  • 如果operator是Exists,此时二者的torleration不能指定value值

特殊情况:

tolerations:

-operator: “Exists”

  • 如果一个toleration的key为空且operators为Exists(也就是value也为空),表示这个toleration与任意的key value 和effet都匹配,也就是可以容忍任何taint
  • 如果一个toleration的effect为空,则key值 与之相同匹配的taint的effect 可以使任意值

tolerations:

– key: “key”
operator: “Exists”

一个节点可以设置多个taint,一个pod也可以设置多个toleration。kubernetes处理多个Taint和Toleration的过程就像一个过滤器:从一个节点的所有taint开始遍历,过滤掉那些pod中与之存在相匹配的toleration和taint. 余下未被过滤的taint和effect值决定了pod是否会被分派到该node节点上。分为以下几个情况:

  • 如果未被过滤的taint存在一个以上effect的值为NoSchedule的taint ,则kubernetes不会将pod 分配到该节点
  • 如果未被过滤的taint中不存在effect值为noschedule ,但是存在effect值为prefernoschedule 的taint,则尝试将pod分配该节点
  • 如果taint的effect值是NoExecute 的taint 则不会分配到该节点(如果该pod未在该节点运行),如果已经在该节点运行那么这个pod 将会从这个节点驱逐

刚才提到了effect有很多情况,下面看下effect的几个类型

  • NoSchedule:只有拥有和这个taint相匹配的toleration的pod才可以分配到该节点 (本身要求比较严格,暗号需要对上)
  • PreferNoSchedule:系统会尽量避免将pod调度到不能容忍taint的节点上,但不是强制的
  • NoExecute:任何不能忍受这个taint的pod 会马上被驱逐。任何可以忍受的pod都不会驱逐。pod 可指定 tolerationSeconds的值 表示pod 在驱逐之前在节点运行的时间。

tolerations:
– key: “key1”
operator: “Equal”
value: “value1”
effect: “NoExecute”
tolerationSeconds: 3600

专用节点的使用

kubectl taint node node-1 dedicated=<groupName>:NoSchedule

先给node 加taint污点,然后给pod添加对应的toleration与其匹配。则pod可以调度到该节点,也可以调度到其他节点。但是如果想让pod 调度到某些节点切这些节点只能接受对应的pod (换句话说这些节点有了污点,防止别的Pod调度过来),则需要先给Node添加lable   如 dedicated=groupName .同时 给pod 的nodeSelector添加对应的label 

备注:实际上就是上面我们将的NodeSelector 和 taint结合。第一个实验我们仅仅保证了pod去选择什么样的 node,但是我们不能保证node-1 去选择什么样的pod ,而这两者结合就可以保证互相选择。更加精确,真正实现了专用节点。

 特殊硬件节点

如果某些节点配置了特殊硬件(例如CPU),希望不使用这些特殊硬件的Pod不被调度该Node,以便保留必要资源。即可给Node设置

taint

label

,同时给Pod设置

toleration

label

来使得这些Node专门被指定Pod使用。

1
2
3
4
# kubectl taint
kubectl taint nodes nodename special=true:NoSchedule 
# 或者
kubectl taint nodes nodename special=true:PreferNoSchedule

基于taint驱逐

effect 值 

NoExecute

 ,它会影响已经在节点上运行的 pod,即根据策略对Pod进行驱逐。

  • 如果 pod 不能忍受effect 值为 
    NoExecute

     的 taint,那么 pod 将马上被驱逐

  • 如果 pod 能够忍受effect 值为 
    NoExecute

     的 taint,但是在 toleration 定义中没有指定 

    tolerationSeconds

    ,则 pod 还会一直在这个节点上运行。

  • 如果 pod 能够忍受effect 值为 
    NoExecute

     的 taint,而且指定了 

    tolerationSeconds

    ,则 pod 还能在这个节点上继续运行这个指定的时间长度。

 

 

 

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Loading...