021.掌握Pod-Pod调度策略
2019-11-21 08:30:25来源:博客园 阅读 ()
021.掌握Pod-Pod调度策略
一 Pod生命周期管理
1.1 Pod生命周期
Pod在整个生命周期过程中被系统定义了如下各种状态。1.2 Pod重启策略
Pod重启策略(RestartPolicy)应用于Pod内的所有容器,并且仅在Pod所处的Node上由kubelet进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet将根据RestartPolicy的设置来进行相应操作。Pod的重启策略包括Always、OnFailure和Never,默认值为Always。- Always:当容器失效时,由kubelet自动重启该容器;
- OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器;
- Never:不论容器运行状态如何,kubelet都不会重启该容器。
kubelet重启失效容器的时间间隔以sync-frequency乘以2n来计算,例如1/2/4/8倍等,最长延时5min,并且在成功重启后的10min后重置该时间。
Pod的重启策略与控制方式关联,当前可用于管理Pod的控制器包括ReplicationController、Job、DaemonSet及直接管理kubelet管理(静态Pod)。 不同控制器的重启策略限制如下:- RC和DaemonSet:必须设置为Always,需要保证该容器持续运行;
- Job:OnFailure或Never,确保容器执行完成后不再重启;
- kubelet:在Pod失效时重启,不论将RestartPolicy设置为何值,也不会对Pod进行健康检查。
1.3 Pod健康检查
对Pod的健康检查可以通过两类探针来检查:LivenessProbe和ReadinessProbe。 LivenessProbe探针:用于判断容器是否存活(running状态),如果LivenessProbe探针探测到容器不健康,则kubelet将杀掉该容器,并根据容器的重启策略做相应处理。若一个容器不包含LivenessProbe探针,kubelet认为该容器的LivenessProbe探针返回值用于是“Success”。 ReadineeProbe探针:用于判断容器是否启动完成(ready状态)。如果ReadinessProbe探针探测到失败,则Pod的状态将被修改。Endpoint Controller将从Service的Endpoint中删除包含该容器所在Pod的Eenpoint。 kubelet定期执行LivenessProbe探针来诊断容器的健康状态,通常有以下三种方式:- ExecAction:在容器内执行一个命令,若返回码为0,则表明容器健康。
1 [root@uk8s-m-01 study]# vi dapi-liveness.yaml 2 apiVersion: v1 3 kind: Pod 4 metadata: 5 name: dapi-liveness-pod 6 labels: 7 test: liveness-exec 8 spec: 9 containers: 10 - name: dapi-liveness 11 image: busybox 12 args: 13 - /bin/sh 14 - -c 15 - echo ok > /tmp/health; sleep 10; rm -rf /tmp/health; sleep 600 16 livenessProbe: 17 exec: 18 command: 19 - cat 20 - /tmp/health 21 22 [root@uk8s-m-01 study]# kubectl describe pod dapi-liveness-pod
- TCPSocketAction:通过容器的IP地址和端口号执行TCP检查,若能建立TCP连接,则表明容器健康。
1 [root@uk8s-m-01 study]# vi dapi-tcpsocket.yaml 2 apiVersion: v1 3 kind: Pod 4 metadata: 5 name: dapi-healthcheck-tcp 6 spec: 7 containers: 8 - name: nginx 9 image: nginx 10 ports: 11 - containerPort: 80 12 livenessProbe: 13 tcpSocket: 14 port: 80 15 initialDelaySeconds: 30 16 timeoutSeconds: 1 17 18 [root@uk8s-m-01 study]# kubectl create -f dapi-tcpsocket.yaml提示:对于每种探测方式,都需要设置如下两个参数,其包含的含义如下: initialDelaySeconds:启动容器后进行首次健康检查的等待时间,单位为s; timeoutSeconds:健康检查发送请求后等待响应的超时时间,单位为s,当超时发生时,kubelet会认为容器已经无法提供服务,将会重启该容器。
二 Pod调度
Kubernetes中,Pod通常是容器的载体,一般需要通过Deployment、DaemonSet、RC、Job等对象来完成一组Pod的调度与自动控制功能。2.1 Depolyment/RC自动调度
Deployment或RC的主要功能之一就是自动部署一个容器应用的多份副本,以及持续监控副本的数量,在集群内始终维持用户指定的副本数量。 示例:1 [root@uk8s-m-01 study]# vi nginx-deployment.yaml 2 apiVersion: apps/v1beta1 3 kind: Deployment 4 metadata: 5 name: nginx-deployment-01 6 spec: 7 replicas: 3 8 template: 9 metadata: 10 labels: 11 app: nginx 12 spec: 13 containers: 14 - name: nginx 15 image: nginx:1.7.9 16 ports: 17 - containerPort: 80 18 19 [root@uk8s-m-01 study]# kubectl get deployments 20 NAME READY UP-TO-DATE AVAILABLE AGE 21 nginx-deployment-01 3/3 3 3 30s 22 [root@uk8s-m-01 study]# kubectl get rs 23 NAME DESIRED CURRENT READY AGE 24 nginx-deployment-01-5754944d6c 3 3 3 75s 25 [root@uk8s-m-01 study]# kubectl get pod | grep nginx 26 nginx-deployment-01-5754944d6c-hmcpg 1/1 Running 0 84s 27 nginx-deployment-01-5754944d6c-mcj8q 1/1 Running 0 84s 28 nginx-deployment-01-5754944d6c-p42mh 1/1 Running 0 84s
2.2 NodeSelector定向调度
当需要手动指定将Pod调度到特定Node上,可以通过Node的标签(Label)和Pod的nodeSelector属性相匹配。 # kubectl label nodes <node-name> <label-key>=<label-value> node节点创建对应的label后,可通过在定义Pod的时候加上nodeSelector的设置实现指定的调度。 示例:1 [root@uk8s-m-01 study]# kubectl label nodes 172.24.9.14 speed=io 2 node/172.24.9.14 labeled 3 [root@uk8s-m-01 study]# vi nginx-master-controller.yaml 4 kind: ReplicationController 5 metadata: 6 name: nginx-master 7 labels: 8 name: nginx-master 9 spec: 10 replicas: 1 11 selector: 12 name: nginx-master 13 template: 14 metadata: 15 labels: 16 name: nginx-master 17 spec: 18 containers: 19 - name: master 20 image: nginx:1.7.9 21 ports: 22 - containerPort: 80 23 nodeSelector: 24 speed: io 25 26 [root@uk8s-m-01 study]# kubectl create -f nginx-master-controller.yaml 27 [root@uk8s-m-01 study]# kubectl get pods -o wide 28 NAME READY STATUS RESTARTS AGE IP NODE 29 nginx-master-7fjgj 1/1 Running 0 82s 172.24.9.71 172.24.9.14提示:可以将集群中具有不同特点的Node贴上不同的标签,实现在部署时就可以根据应用的需求设置NodeSelector来进行指定Node范围的调度。 注意:若在定义Pod中指定了NodeSelector条件,但集群中不存在符合该标签的Node,即使集群有其他可供使用的Node,Pod也无法被成功调度。
2.3 NodeAffinity亲和性调度
亲和性调度机制极大的扩展了Pod的调度能力,主要增强功能如下:- 更具表达力,即更精细的力度控制;
- 可以使用软限制、优先采用等限制方式,即调度器在无法满足优先需求的情况下,会使用其他次条件进行满足;
- 可以依据节点上正在运行的其他Pod的标签来进行限制,而非节点本身的标签,从而实现Pod之间的亲和或互斥关系。
1 [root@uk8s-m-01 study]# vi nodeaffinity-pod.yaml 2 apiVersion: v1 3 kind: Pod 4 metadata: 5 name: with-node-affinity 6 spec: 7 affinity: 8 nodeAffinity: 9 requiredDuringSchedulingIgnoredDuringExecution: 10 nodeSelectorTerms: 11 - matchExpressions: 12 - key: kubernetes.io/arch 13 operator: In 14 values: 15 - amd64 16 preferredDuringSchedulingIgnoredDuringExecution: 17 - weight: 1 18 preference: 19 matchExpressions: 20 - key: disk-type 21 operator: In 22 values: 23 - ssd 24 containers: 25 - name: with-node-affinity 26 image: gcr.azk8s.cn/google_containers/pause:2.0NodeAffinity操作语法;In、NotIn、Exists、DoesNotExist、Gt、Lt。NotIn和DoesNotExist可以实现互斥功能。 NodeAffinity规则设置注意事项:
- 若同时定义nodeSelector和nodeAffinity,则必须两个条件都满足,Pod才能最终运行指定在Node上;;
- 若nodeAffinity指定多个nodeSelectorTerms,则只需要其中一个能够匹配成功即可;
- 若nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有matchExpressions才能运行该Pod。
2.4 PodAffinity亲和性调度
PodAffinity根据节点上正在运行的Pod标签而不是Node标签来判断和调度,要求对节点和Pod两个条件进行匹配。 规则描述为:若在具有标签X的Node上运行了一个或多个符合条件Y的Pod,则Pod应该(或者不应该)运行在这个Node上。 X通常为Node节点的机架、区域等概念,Pod是属于某个命名空间,所以条件Y表达的是一个或全部命名空间中的一个Label Selector。 Pod亲和性定义与PodSpec的affinity字段下的podAffinity字段里,互斥性定义于同一层次的podAntiAffinity子字段中。 举例:1 [root@uk8s-m-01 study]# vi nginx-flag.yaml #创建名为pod-flag,带有两个标签的Pod 2 apiVersion: v1 3 kind: Pod 4 metadata: 5 name: pod-affinity 6 spec: 7 affinity: 8 podAffinity: 9 requiredDuringSchedulingIgnoredDuringExecution: 10 - labelSelector: 11 matchExpressions: 12 - key: security 13 operator: In 14 values: 15 - S1 16 topologyKey: kubernetes.io/hostname 17 containers: 18 - name: with-pod-affinity 19 image: gcr.azk8s.cn/google_containers/pause:2.0
1 [root@uk8s-m-01 study]# vi nginx-affinity-in.yaml #创建定义标签security=S1,对应如上Pod “Pod-flag”。 2 apiVersion: v1 3 kind: Pod 4 metadata: 5 name: pod-affinity 6 spec: 7 affinity: 8 podAffinity: 9 requiredDuringSchedulingIgnoredDuringExecution: 10 - labelSelector: 11 matchExpressions: 12 - key: security 13 operator: In 14 values: 15 - S1 16 topologyKey: kubernetes.io/hostname 17 containers: 18 - name: with-pod-affinity 19 image: gcr.azk8s.cn/google_containers/pause:2.0 20 21 [root@uk8s-m-01 study]# kubectl create -f nginx-affinity-in.yaml 22 [root@uk8s-m-01 study]# kubectl get pods -o wide提示:由上Pod亲和力可知,两个Pod处于同一个Node上。
1 [root@uk8s-m-01 study]# vi nginx-affinity-out.yaml #创建不能与参照目标Pod运行在同一个Node上的调度策略 2 apiVersion: v1 3 kind: Pod 4 metadata: 5 name: anti-affinity 6 spec: 7 affinity: 8 podAffinity: 9 requiredDuringSchedulingIgnoredDuringExecution: 10 - labelSelector: 11 matchExpressions: 12 - key: security 13 operator: In 14 values: 15 - S1 16 topologyKey: failure-domain.beta.kubernetes.io/zone 17 podAntiAffinity: 18 requiredDuringSchedulingIgnoredDuringExecution: 19 - labelSelector: 20 matchExpressions: 21 - key: security 22 operator: In 23 values: 24 - nginx 25 topologyKey: kubernetes.io/hostname 26 containers: 27 - name: anti-affinity 28 image: gcr.azk8s.cn/google_containers/pause:2.0 29 30 [root@uk8s-m-01 study]# kubectl get pods -o wide #验证
2.5 Taints和Tolerations(污点和容忍)
Taint:使Node拒绝特定Pod运行; Toleration:为Pod的属性,表示Pod能容忍(运行)标注了Taint的Node。 Taint语法:$ kubectl taint node node1 key=value:NoSchedule 解释:为node1加上一个Taint,该Taint的键为key,值为value,Taint的效果为NoSchedule。即除非特定声明可以容忍此Taint,否则不会调度至node1上。 Toleration示例:1 tolerations: 2 - key: "key" 3 operator: "Equal" 4 value: "value" 5 effect: "NoSchedule"或
1 tolerations: 2 - key: "key" 3 operator: "Exists" 4 effect: "NoSchedule"注意:Pod的Toleration声明中的key和effect需要与Taint的设置保持一致,并且满足以下条件:
- operator的值是Exists(无须指定value);
- operator的值是Equal并且value相等;
- 空的key配合Exists操作符能够匹配所有的键和值;
- 空的effect匹配所有的effect。
1 $ kubectl taint node node1 key=value1:NoSchedule 2 $ kubectl taint node node1 key=value1:NoExecute 3 $ kubectl taint node node1 key=value2:NoSchedule 4 tolerations: 5 - key: "key1" 6 operator: "Equal" 7 value: "value" 8 effect: "NoSchedule" 9 tolerations: 10 - key: "key1" 11 operator: "Equal" 12 value: "value1" 13 effect: "NoExecute"释义:此Pod声明了两个容忍,且能匹配Node1的taint,但是由于没有能匹配第三个taint的toleration,因此此Pod依旧不能调度至此Node。若该Pod已经在node1上运行了,那么在运行时设置了第3个taint,它还能继续在node1上运行,这是因为Pod可以容忍前两个taint。 通常,若node加上effect=NoExecute的taint,那么该Node上正在运行的所有无对应toleration的Pod都会被立刻驱逐,而具有相应toleration的Pod则永远不会被驱逐。同时,系统可以给具有NoExecute效果的toleration加入一个可选的tolerationSeconds字段,表明Pod可以在taint添加到Node之后还能在此Node运行多久。
1 tolerations: 2 - key: "key1" 3 operator: "Equal" 4 value: "value" 5 effect: "NoSchedule" 6 tolerationSeconds: 3600释义:若Pod正在运行,所在节点被加入一个匹配的taint,则这个pod会持续在该节点运行3600s后被驱逐。若在此期限内,taint被移除,则不会触发驱逐事件。 Taints和Tolerations常用场景:
- 独占节点:
- 具有特殊硬件设备的节点
1 $ kubectl taint nodes 【nodename】 special=true:NoSchedule 2 $ kubectl taint nodes 【nodename】 special=true:PreferNoSchedule
- 定义Pod驱逐行为
- 没有设置toleration的pod会被立刻驱逐;
- 配置了对应toleration的pod,若没有为tolerationSeconds赋值,则会一直保留在此节点中;
- 配置了对应toleration的pod,且为tolerationSeconds赋值,则在指定时间后驱逐。
2.6 DaemonSet
DaemonSet是在每个Node上调度一个Pod的资源对象,用于管理集群中每个Node仅运行一份Pod的副本实例。 常见场景: 在每个Node上运行一个GlusterFS存储的Daemon进程; 在每个Node上运行一个日志采集程序,例如Fluentd; 在每个Node上运行一个性能监控程序,采集该Node的运行性能数据,例如Prometheus。 示例:1 [root@uk8s-m-01 study]# vi fluentd-ds.yaml 2 apiVersion: extensions/v1beta1 3 kind: DaemonSet 4 metadata: 5 name: fluentd-cloud-logging 6 namespace: kube-system 7 labels: 8 k8s-app: fluentd-cloud-logging 9 spec: 10 template: 11 metadata: 12 namespace: kube-system 13 labels: 14 k8s-app: fluentd-cloud-logging 15 spec: 16 containers: 17 - name: fluentd-cloud-logging 18 image: gcr.azk8s.cn/google_containers/fluentd-elasticsearch:1.17 19 resources: 20 limits: 21 cpu: 100m 22 memory: 200Mi 23 env: 24 - name: FLUENTD_ARGS 25 value: -q 26 volumeMounts: 27 - name: varlog 28 mountPath: /var/log 29 readOnly: false 30 - name: containers 31 mountPath: /var/lib/docker/containers 32 readOnly: false 33 volumes: 34 - name: containers 35 hostPath: 36 path: /var/lib/docker/containers 37 - name: varlog 38 hostPath: 39 path: /var/log
2.7 Job批处理调度
通过Kubernetes Job资源对象可以定义并启动一个批处理任务,批处理任务通过并行(或者串行)启动多个计算进程去处理一批工作项。根据批处理方式不同,批处理任务可以分为如下几种模式: Job Template Expansion模式:一个Job对象对应一个待处理的Work item,有几个work item就产生几个独立的Job。通常适合Work item数量少、每个Work item要处理的数据量比较大的场景。 Queue with Pod Per Work Item模式:采用一个任务队列存放Work item,一个Job对象作为消费者去完成这些Work item。此模式下,Job会启动N个Pod,每个Pod都对应一个Work item。 Queue with Variable Pod Count模式:采用一个任务队列存放Work item,一个Job对象作为消费者去完成这些Work item,但此模式下Job启动的数量是可变的。 Kubernetes将Job氛围以下三类:- Non-parallel Jobs
- Parallel Jobs with a fixed completion count
- Parallel Jobs with a work queue
- 每个Pod都能独立判断和决定是否还有任务项需要处理;
- 如果某个Pod正常结束,则Job不会再启动新的Pod;
- 如果一个Pod成功结束,则此时应该不存在其他Pod还在工作的情况。它们应该都处于即将结束、退出的状态;
- 如果所有Pod都结束了,且至少有一个Pod成功结束,则整个Jod成功结束。
2.8 Cronjob定时任务
表达式:Minutes Hours DayofMonth Month DayofWeek Year Minutes:可出现","、"_"、"*"、"/",有效范围为0~59的整数; Hours:出现","、"_"、"*"、"/",有效范围为0~23的整数; DayofMonth:出现","、"_"、"*"、"/"、"L"、"W"、"C",有效范围为0~31的整数; Month:可出现","、"_"、"*"、"/",有效范围为1~12的整数或JAN~DEC; DayofWeek:出现","、"_"、"*"、"/"、"L"、"W"、"C"、"#",有效范围为1~7的整数或SUN~SAT; *: 表示匹配该域的任意值, 假如在Minutes域使用“*”, 则表示每分钟都会触发事件。 /: 表示从起始时间开始触发, 然后每隔固定时间触发一次,例如在Minutes域设置为5/20, 则意味着第1次触发在第5min时, 接下来每20min触发一次, 将在第25min、 第45min等时刻分别触发。 示例:*/1 * * * * #每隔1min执行一次任务1 [root@uk8s-m-01 study]# vi cron.yaml 2 apiVersion: batch/v2alpha1 3 kind: CronJob 4 metadata: 5 name: hello 6 spec: 7 schedule: "*/1 * * * *" 8 jobTemplate: 9 spec: 10 template: 11 spec: 12 containers: 13 - name: hello 14 image: busybox 15 args: 16 - /bin/sh 17 - -c 18 - date; echo Hello from the Kubernetes cluster 19 restartPolicy: OnFailure
1 [root@master study]# kubectl create -f cron.yaml 2 [root@master study]# kubectl get cronjob hello 3 NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE 4 hello */1 * * * * False 0 <none> 29s 5 [root@master study]# kubectl get pods 6 NAME READY STATUS RESTARTS AGE 7 hello-1573378080-zvvm5 0/1 Completed 0 68s 8 hello-1573378140-9pmwz 0/1 Completed 0 8s 9 [root@node1 ~]# docker logs c7 #node节点查看日志 10 Sun Nov 10 09:31:13 UTC 2019 11 Hello from the Kubernetes cluster 12 [root@master study]# kubectl get jobs #查看任务 13 NAME COMPLETIONS DURATION AGE 14 hello-1573378500 1/1 8s 3m7s 15 hello-1573378560 1/1 4s 2m7s 16 hello-1573378620 1/1 6s 67s 17 hello-1573378680 1/1 4s 7s 18 [root@master study]# kubectl get pods -o wide | grep hello-1573378680 #以job任务查看对应的pod 19 [root@master study]# kubectl delete cj hello #删除cronjob
2.9 初始化容器
在很多应用场景中, 应用在启动之前都需要进行如下初始化操作。- 等待其他关联组件正确运行( 例如数据库或某个后台服务) 。
- 基于环境变量或配置模板生成配置文件。
- 从远程数据库获取本地所需配置, 或者将自身注册到某个中央数据库中。
- 下载相关依赖包, 或者对系统进行一些预配置操作。
1 [root@uk8s-m-01 study]# vi nginx-init-containers.yaml 2 apiVersion: v1 3 kind: Pod 4 metadata: 5 name: nginx 6 annotations: 7 spec: 8 initContainers: 9 - name: install 10 image: busybox 11 command: 12 - wget 13 - "-O" 14 - "/work-dir/index.html" 15 - http://kubernetes.io 16 volumeMounts: 17 - name: workdir 18 mountPath: "/work-dir" 19 containers: 20 - name: nginx 21 image: nginx:1.7.9 22 ports: 23 - containerPort: 80 24 volumeMounts: 25 - name: workdir 26 mountPath: /usr/share/nginx/html 27 dnsPolicy: Default 28 volumes: 29 - name: workdir 30 emptyDir: {}
1 [root@uk8s-m-01 study]# kubectl get pods 2 NAME READY STATUS RESTARTS AGE 3 nginx 0/1 Init:0/1 0 2s 4 [root@uk8s-m-01 study]# kubectl get pods 5 NAME READY STATUS RESTARTS AGE 6 nginx 1/1 Running 0 13s 7 [root@uk8s-m-01 study]# kubectl describe pod nginx #查看事件可知会先创建init容器,名为installinit容器与应用容器的区别如下。 (1) init container的运行方式与应用容器不同, 它们必须先于应用容器执行完成, 当设置了多个init container时, 将按顺序逐个运行, 并且只有前一个init container运行成功后才能运行后一个init container。 当所有init container都成功运行后, Kubernetes才会初始化Pod的各种信息, 并开始创建和运行应用容器。 (2) 在init container的定义中也可以设置资源限制、 Volume的使用和安全策略, 等等。 但资源限制的设置与应用容器略有不同。
- 如果多个init container都定义了资源请求/资源限制, 则取最大的值作为所有init container的资源请求值/资源限制值。
- Pod的有效(effective) 资源请求值/资源限制值取以下二者中的较大值。
- 所有应用容器的资源请求值/资源限制值之和。
- init container的有效资源请求值/资源限制值。
- 调度算法将基于Pod的有效资源请求值/资源限制值进行计算,即init container可以为初始化操作预留系统资源, 即使后续应用容器无须使用这些资源。
- Pod的有效QoS等级适用于init container和应用容器。
- 资源配额和限制将根据Pod的有效资源请求值/资源限制值计算生效。
- Pod级别的cgroup将基于Pod的有效资源请求/限制, 与调度机制
- init container的镜像被更新时, init container将会重新运行, 导致Pod重启。 仅更新应用容器的镜像只会使得应用容器被重启。
- Pod的infrastructure容器更新时, Pod将会重启。
- 若Pod中的所有应用容器都终止了, 并且RestartPolicy=Always, 则Pod会重启。
原文链接:https://www.cnblogs.com/itzgr/p/11904794.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- 作业(进程)调度算法 2020-05-16
- 高级操作系统实验2-进程调度与切换分析(2) 2020-03-20
- 【原创】(五)Linux进程调度-CFS调度器 2020-03-14
- 【原创】(四)Linux进程调度-组调度及带宽控制 2020-03-10
- 【原创】(三)Linux进程调度器-进程切换 2020-02-29
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash