• 【云原生 | Kubernetes 实战】06、Pod高级实战:基于污点、容忍度、亲和性的多种调度策略(下)


    目录

    一、Pod节点亲和性

    1.1 案例演示:pod 节点亲和性——podAffinity

    1.2 案例演示:pod 节点反亲和性——podAntiAffinity

    1.3 案例演示: 换一个 topologykey 值

    二、污点和容忍度

    2.1 案例演示: 把 node2 当成是生产环境专用的,其他node是测试的

    2.2 案例演示:给 node1也打上污点

    2.3 案例演示:再次修改

    三、Pod 常见的状态和重启策略

    3.1 常见的 pod 状态

    3.2 pod 重启策略

    3.3 测试 Always 重启策略 

    3.4   测试 Never 重启策略

    3.5  测试 OnFailure 重启策略(生产环境中常用)


    一、Pod节点亲和性

    pod自身的亲和性调度有两种表示形式

    • podAffinity:pod和pod更倾向腻在一起,把相近的pod结合到相近的位置,如同一区域,同一机架,这样的话pod和pod之间更好通信,比方说有两个机房,这两个机房部署的集群有1000台主机,那么我们希望把nginx和tomcat都部署同一个地方的node节点上,可以提高通信效率;
    • podAntiAffinity:pod和pod更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。

            第一个pod随机选则一个节点,做为评判后续的pod能否到达这个pod所在的节点上的运行方式,这就称为pod亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的;我们在定义pod亲和性时需要有一个前提,哪些pod在同一个位置,哪些pod不在同一个位置,这个位置是怎么定义的,标准是什么?以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置。

    1. # 查看pod亲和性帮助命令
    2. [root@k8s-master01 ~]# kubectl explain pods.spec.affinity.podAffinity
    3. KIND: Pod
    4. VERSION: v1
    5. RESOURCE: podAffinity <Object>
    6. DESCRIPTION:
    7. Describes pod affinity scheduling rules (e.g. co-locate this pod in the
    8. same node, zone, etc. as some other pod(s)).
    9. Pod affinity is a group of inter pod affinity scheduling rules.
    10. FIELDS:
    11. # 软亲和性
    12. preferredDuringSchedulingIgnoredDuringExecution <[]Object>
    13. ······
    14. # 硬亲和性
    15. requiredDuringSchedulingIgnoredDuringExecution <[]Object>
    16. ······
    17. # 查看pod硬亲和性帮助命令
    18. [root@k8s-master01 ~]# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution
    19. KIND: Pod
    20. VERSION: v1
    21. RESOURCE: requiredDuringSchedulingIgnoredDuringExecution <[]Object>
    22. DESCRIPTION:
    23. If the affinity requirements specified by this field are not met at
    24. scheduling time, the pod will not be scheduled onto the node. If the
    25. affinity requirements specified by this field cease to be met at some point
    26. during pod execution (e.g. due to a pod label update), the system may or
    27. may not try to eventually evict the pod from its node. When there are
    28. multiple elements, the lists of nodes corresponding to each podAffinityTerm
    29. are intersected, i.e. all terms must be satisfied.
    30. ······
    31. FIELDS:
    32. labelSelector <Object>
    33. A label query over a set of resources, in this case pods.
    34. namespaceSelector <Object>
    35. ······
    36. namespaces <[]string>
    37. ······
    38. topologyKey <string> -required-
    39. ······
    • topologyKey:位置拓扑的键,这个是必须字段。

            那怎么判断是不是同一个位置:给两个节点分别打上 rack=rack1、row=row1 标签,使用rack的键是同一个位置,使用row的键是同一个位置。

    • labelSelector:

            我们要判断pod跟别的pod亲和,跟哪个pod亲和,需要靠labelSelector,通过labelSelector选则一组能作为亲和对象的pod资源。

    • namespace:

            labelSelector需要选则一组资源,那么这组资源是在哪个名称空间中呢,通过namespace指定,如果不指定namespaces,那么就是当前创建pod的名称空间 。

    1.1 案例演示:pod 节点亲和性——podAffinity

    定义两个pod,第一个pod做为基准,第二个pod跟着它走。

    1. [root@k8s-master01 pod-yaml]# vim pod-required-affinity-demo-1.yaml
    2. apiVersion: v1
    3. kind: Pod
    4. metadata:
    5. name: pod-first
    6. labels:
    7. app2: myapp2
    8. tier: frontend
    9. spec:
    10. containers:
    11. - name: myapp
    12. image: tomcat:latest
    13. imagePullPolicy: IfNotPresent
    14. # 下面表示创建的pod必须与拥有app2=myapp2标签的pod在一个节点上
    15. [root@k8s-master01 pod-yaml]# vim pod-required-affinity-demo-2.yaml
    16. apiVersion: v1
    17. kind: Pod
    18. metadata:
    19. name: pod-second
    20. labels:
    21. app: backend
    22. tier: db
    23. spec:
    24. containers:
    25. - name: busybox
    26. image: busybox:latest
    27. imagePullPolicy: IfNotPresent
    28. command: ["sh","-c","sleep 3600"]
    29. affinity:
    30. podAffinity:
    31. requiredDuringSchedulingIgnoredDuringExecution:
    32. - labelSelector:
    33. matchExpressions:
    34. - {key: app2, operator: In, values: ["myapp2"]}
    35. topologyKey: kubernetes.io/hostname
    36. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-required-affinity-demo-1.yaml
    37. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-required-affinity-demo-2.yaml
    38. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide
    39. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    40. pod-first 1/1 Running 0 12m 10.244.169.146 k8s-node2 <none> <none>
    41. pod-second 1/1 Running 0 7s 10.244.169.147 k8s-node2 <none> <none>

    上面说明第一个pod调度到哪,第二个pod也调度到哪,这就是pod节点亲和性。

    1.2 案例演示:pod 节点反亲和性——podAntiAffinity

    定义两个pod,第一个pod做为基准,第二个pod跟它调度节点相反。

    1. # 把前面案例的两个pods 删除
    2. [root@k8s-master01 pod-yaml]# kubectl delete pods pod-first pod-second
    3. # 创建第一个pod
    4. [root@k8s-master01 pod-yaml]# vim pod-required-anti-affinity-demo-1.yaml
    5. apiVersion: v1
    6. kind: Pod
    7. metadata:
    8. name: pod-first
    9. labels:
    10. app1: myapp1
    11. tier: frontend
    12. spec:
    13. containers:
    14. - name: myapp
    15. image: nginx:latest
    16. imagePullPolicy: IfNotPresent
    17. # 创建第二个pod
    18. [root@k8s-master01 pod-yaml]# vim pod-required-anti-affinity-demo-2.yaml
    19. apiVersion: v1
    20. kind: Pod
    21. metadata:
    22. name: pod-second
    23. labels:
    24. app: backend
    25. tier: db
    26. spec:
    27. containers:
    28. - name: busybox
    29. image: busybox:latest
    30. imagePullPolicy: IfNotPresent
    31. command: ["sh","-c","sleep 3600"]
    32. affinity:
    33. podAntiAffinity:
    34. requiredDuringSchedulingIgnoredDuringExecution:
    35. - labelSelector:
    36. matchExpressions:
    37. - {key: app1, operator: In, values: ["myapp1"]}
    38. topologyKey: kubernetes.io/hostname
    39. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-required-anti-affinity-demo-2.yaml
    40. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-required-anti-affinity-demo-2.yaml
    41. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide
    42. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    43. pod-first 1/1 Running 0 5m47s 10.244.169.149 k8s-node2 <none> <none>
    44. pod-second 0/1 ContainerCreating 0 5s <none> k8s-node1 <none> <none>

    上面显示两个pod不在一个node节点上,这就是pod节点反亲和性。

    1.3 案例演示: 换一个 topologykey 值

    1. # 删除前面案例的pods
    2. [root@k8s-master01 pod-yaml]# kubectl delete pods pod-first pod-second
    3. # 查看集群中node节点的所有标签
    4. [root@k8s-master01 pod-yaml]# kubectl get nodes --show-labels
    5. NAME STATUS ROLES AGE VERSION LABELS
    6. k8s-master01 Ready control-plane 42d v1.25.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
    7. k8s-node1 Ready work 42d v1.25.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux,node-role.kubernetes.io/work=work
    8. k8s-node2 Ready work 42d v1.25.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disk=ceph,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux,node-role.kubernetes.io/work=work
    9. # 下面我们创建两个pod,选取一个相同标签为 kubernetes.io/os=linux 作为 topologykey
    10. [root@k8s-master01 pod-yaml]# vim pod-first-required-anti-affinity-demo-1.yaml
    11. apiVersion: v1
    12. kind: Pod
    13. metadata:
    14. name: pod-first
    15. labels:
    16. app3: myapp3
    17. tier: frontend
    18. spec:
    19. containers:
    20. - name: myapp
    21. image: nginx:latest
    22. imagePullPolicy: IfNotPresent
    23. [root@k8s-master01 pod-yaml]# vim pod-first-required-anti-affinity-demo-2.yaml
    24. apiVersion: v1
    25. kind: Pod
    26. metadata:
    27. name: pod-second
    28. labels:
    29. app: backend
    30. tier: db
    31. spec:
    32. containers:
    33. - name: busybox
    34. image: busybox:latest
    35. imagePullPolicy: IfNotPresent
    36. command: ["sh","-c","sleep 3600"]
    37. affinity:
    38. podAntiAffinity:
    39. requiredDuringSchedulingIgnoredDuringExecution:
    40. - labelSelector:
    41. matchExpressions:
    42. - {key: app3 ,operator: In, values: ["myapp3"]}
    43. topologyKey: kubernetes.io/os
    44. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-first-required-anti-affinity-demo-1.yaml
    45. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-first-required-anti-affinity-demo-2.yaml
    46. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide
    47. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    48. pod-first 1/1 Running 0 11m 10.244.169.150 k8s-node2 <none> <none>
    49. pod-second 0/1 Pending 0 14s <none> <none> <none> <none>
    50. [root@k8s-master01 pod-yaml]# kubectl describe pods pod-second

            第二个pod是pending,因为两个节点的标签是相同的,是同一个位置,而且我们要求反亲和性,所以就会处于pending状态,如果在反亲和性这个位置把required改成preferred,或者变为pod亲和性那么也会运行。 

    二、污点和容忍度

            给了节点选则的主动权,我们给节点打一个污点,不容忍的pod就运行(调度)不上来,污点就是定义在节点上的键值属性数据,可以决定拒绝哪些pods。

    • taints 是键值数据,用在节点上,定义污点;
    • tolerations 是键值数据,用在pod上,定义容忍度,能容忍哪些污点。

    pod亲和性是pod属性;但是污点是节点的属性,污点定义在k8s集群的节点上的一个字段。

    1. # 查看控住节点定义的污点
    2. [root@k8s-master01 pod-yaml]# kubectl describe nodes k8s-master01 | grep Taints
    3. Taints: node-role.kubernetes.io/control-plane:NoSchedule
    4. # 两个工作节点是没有定义污点
    5. [root@k8s-master01 pod-yaml]# kubectl describe nodes k8s-node1 | grep Taints
    6. Taints: <none>
    7. [root@k8s-master01 pod-yaml]# kubectl describe nodes k8s-node2 | grep Taints
    8. Taints: <none>

    那么,如何给节点定义污点呢?

    1. # 查看帮助命令
    2. [root@k8s-master01 pod-yaml]# kubectl explain node.spec
    3. ······
    4. taints <[]Object>
    5. If specified, the node's taints.
    6. [root@k8s-master01 pod-yaml]# kubectl explain node.spec.taints
    7. KIND: Node
    8. VERSION: v1
    9. RESOURCE: taints <[]Object>
    10. DESCRIPTION:
    11. If specified, the node's taints.
    12. The node this Taint is attached to has the "effect" on any pod that does
    13. not tolerate the Taint.
    14. FIELDS:
    15. effect <string> -required-
    16. Required. The effect of the taint on pods that do not tolerate the taint.
    17. Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
    18. Possible enum values:
    19. - `"NoExecute"` Evict any already-running pods that do not tolerate the
    20. taint. Currently enforced by NodeController.
    21. - `"NoSchedule"` Do not allow new pods to schedule onto the node unless
    22. they tolerate the taint, but allow all pods submitted to Kubelet without
    23. going through the scheduler to start, and allow all already-running pods to
    24. continue running. Enforced by the scheduler.
    25. - `"PreferNoSchedule"` Like TaintEffectNoSchedule, but the scheduler tries
    26. not to schedule new pods onto the node, rather than prohibiting new pods
    27. from scheduling onto the node entirely. Enforced by the scheduler.
    28. key <string> -required-
    29. Required. The taint key to be applied to a node.
    30. timeAdded <string>
    31. TimeAdded represents the time at which the taint was added. It is only
    32. written for NoExecute taints.
    33. value <string>
    34. The taint value corresponding to the taint key.

    taints 的 effect 用来定义对pod对象的排斥等级(效果):

    • NoSchedule:

            仅影响pod调度过程,当pod能容忍这个节点污点,就可以调度到当前节点,后来这个节点的污点改了,加了一个新的污点,使得之前已经调度到这个节点的pod不能容忍了,但对已经运行的这个pod对象不产生影响,不会被驱逐。但是后面新创建的pod如果不能容忍则不会调度到这个节点来。

    • NoExecute:

            既影响调度过程,又影响现存的pod对象,如果现存的pod不能容忍节点后来加的污点,这个pod就会被驱逐。

    • PreferNoSchedule:

            是NoSchedule的柔性版本。假如node1、node2节点都定义了污点这个排斥等级,但是pod没有定义容忍度,依然会被随机调度到这两个节点中。

    1. # 可以看到master这个节点的污点是Noschedule。所以我们之前创建的pod都不会调度到master上,因为我们创建的pod的时候没有定义容忍度。
    2. [root@k8s-master01 pod-yaml]# kubectl describe nodes k8s-master01 | grep Taints
    3. Taints: node-role.kubernetes.io/control-plane:NoSchedule
    4. # 查看哪些pod被调度到master节点
    5. [root@k8s-master01 pod-yaml]# kubectl get pods -A -o wide
    6. # 可以看到这个pod的容忍度是NoExecute,则可以调度到xianchaomaster1上
    7. [root@k8s-master01 pod-yaml]# kubectl describe pods kube-apiserver-k8s-master01 -n kube-system | grep Tolerations
    8. Tolerations: :NoExecute op=Exists
    9. # 查看节点污点帮助命令
    10. [root@k8s-master01 pod-yaml]# kubectl taint --help

    2.1 案例演示: 把 node2 当成是生产环境专用的,其他node是测试的

    1. # 给 node2 打污点,pod如果不能容忍就不会调度过来
    2. [root@k8s-master01 pod-yaml]# kubectl taint node k8s-node2 node-type=production:NoSchedule
    3. [root@k8s-master01 pod-yaml]# kubectl describe nodes k8s-node2 | grep Taints
    4. Taints: node-type=production:NoSchedule
    5. # 创建一个没有定义容忍度的pod
    6. [root@k8s-master01 pod-yaml]# vim pod-taint.yaml
    7. apiVersion: v1
    8. kind: Pod
    9. metadata:
    10. name: taint-pod
    11. namespace: default
    12. labels:
    13. tomcat: tomcat-pod
    14. spec:
    15. containers:
    16. - name: taint-pod
    17. ports:
    18. - containerPort: 8080
    19. image: tomcat:latest
    20. imagePullPolicy: IfNotPresent
    21. # 可以看到都被调度到 node1上了,因为 node2这个节点打了污点,而我们在创建pod的时候没有容忍度,所以node2上不会有pod调度上去的
    22. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-taint.yaml
    23. pod/taint-pod created
    24. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide
    25. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    26. taint-pod 1/1 Running 0 7s 10.244.36.87 k8s-node1 <none> <none>

    2.2 案例演示:给 node1也打上污点

    1. [root@k8s-master01 pod-yaml]# kubectl taint node k8s-node1 node-type=dev:NoExecute
    2. node/k8s-node1 tainted
    3. [root@k8s-master01 pod-yaml]# kubectl describe nodes k8s-node1 | grep Taints
    4. Taints: node-type=dev:NoExecute
    5. # 可以看到已经存在的pod节点都被撵走了
    6. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide -w
    7. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    8. taint-pod 1/1 Running 0 2m43s 10.244.36.87 k8s-node1 <none> <none>
    9. taint-pod 1/1 Terminating 0 3m1s 10.244.36.87 k8s-node1 <none> <none>
    10. taint-pod 1/1 Terminating 0 3m1s 10.244.36.87 k8s-node1 <none> <none>
    11. taint-pod 0/1 Terminating 0 3m2s 10.244.36.87 k8s-node1 <none> <none>
    12. taint-pod 0/1 Terminating 0 3m2s 10.244.36.87 k8s-node1 <none> <none>
    13. taint-pod 0/1 Terminating 0 3m2s 10.244.36.87 k8s-node1 <none> <none>
    14. ^C您在 /var/spool/mail/root 中有新邮件
    15. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide
    16. No resources found in default namespace.
    17. # 查看定义pod容忍度的帮助命令
    18. [root@k8s-master01 pod-yaml]# kubectl explain pods.spec.tolerations
    19. # 创建一个容忍度为的pod
    20. [root@k8s-master01 pod-yaml]# vim pod-demo-1.yaml
    21. apiVersion: v1
    22. kind: Pod
    23. metadata:
    24. name: myapp-deploy
    25. namespace: default
    26. labels:
    27. app: myapp
    28. release: canary
    29. spec:
    30. containers:
    31. - name: myapp
    32. image: ikubernetes/myapp:v1
    33. imagePullPolicy: IfNotPresent
    34. ports:
    35. - name: http
    36. containerPort: 80
    37. tolerations:
    38. - key: "node-type"
    39. operator: "Equal"
    40. value: "production"
    41. effect: "NoExecute"
    42. tolerationSeconds: 3600 # 3600 秒后驱逐
    43. # 还是显示pending,因为我们使用的是equal(等值匹配),所以keyvalue,effect必须和node节点定义的污点完全匹配才可以。
    44. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-demo-1.yaml
    45. pod/myapp-deploy created
    46. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide
    47. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    48. myapp-deploy 0/1 Pending 0 9s <none> <none> <none> <none>
    49. # 把上面配置 effect: "NoExecute"变成 effect: "NoSchedule"成;tolerationSeconds: 3600 这行去掉。要先删除原来的,因为不能在修改容忍度后去动态更新pod状态
    50. [root@k8s-master01 pod-yaml]# kubectl delete pods myapp-deploy
    51. pod "myapp-deploy" deleted
    52. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-demo-1.yaml
    53. pod/myapp-deploy created
    54. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide
    55. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    56. myapp-deploy 1/1 Running 0 93s 10.244.169.151 k8s-node2 <none> <none>

    上面就可以调度到 node2上了,因为在pod中定义的容忍度能容忍node节点上的污点。

    2.3 案例演示:再次修改

    1. # node的污点
    2. [root@k8s-master01 pod-yaml]# kubectl describe nodes k8s-node2 | grep Taints
    3. Taints: node-type=production:NoSchedule
    4. [root@k8s-master01 pod-yaml]# kubectl describe nodes k8s-node1 | grep Taints
    5. Taints: node-type=dev:NoExecute
    6. # pod-demo-1.yaml 修改如下部分:
    7. tolerations:
    8. - key: "node-type"
    9. operator: "Exists"
    10. value: ""
    11. effect: "NoSchedule"
    12. # 只要对应的键是存在的,exists,其值被自动定义成通配符。发现还是调度到 node2
    13. [root@k8s-master01 pod-yaml]# kubectl delete pods myapp-deploy
    14. pod "myapp-deploy" deleted
    15. 您在 /var/spool/mail/root 中有新邮件
    16. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-demo-1.yaml
    17. pod/myapp-deploy created
    18. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide
    19. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    20. myapp-deploy 1/1 Running 0 7s 10.244.169.152 k8s-node2 <none> <none>
    21. # 再次修改:
    22. tolerations:
    23. - key: "node-type"
    24. operator: "Exists"
    25. value: ""
    26. effect: ""
    27. # 有一个node-type的键,不管值是什么,不管是什么效果,都能容忍。可以看到 node2 和 node1节点上都有可能有pod被调度。
    28. [root@k8s-master01 pod-yaml]# kubectl delete pods myapp-deploy
    29. pod "myapp-deploy" deleted
    30. 您在 /var/spool/mail/root 中有新邮件
    31. [root@k8s-master01 pod-yaml]# kubectl apply -f pod-demo-1.yaml
    32. pod/myapp-deploy created
    33. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide
    34. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    35. myapp-deploy 0/1 ContainerCreating 0 1s <none> k8s-node1 <none> <none>

    删除 pod 和污点:

    1. [root@k8s-master01 pod-yaml]# kubectl delete pods myapp-deploy
    2. pod "myapp-deploy" deleted
    3. 您在 /var/spool/mail/root 中有新邮件
    4. [root@k8s-master01 pod-yaml]# kubectl get pods
    5. No resources found in default namespace.
    6. [root@k8s-master01 pod-yaml]# kubectl taint node k8s-node1 node-type-
    7. node/k8s-node1 untainted
    8. [root@k8s-master01 pod-yaml]# kubectl taint node k8s-node2 node-type-
    9. node/k8s-node2 untainted
    10. [root@k8s-master01 pod-yaml]# kubectl describe nodes k8s-node1 | grep Taints
    11. Taints: <none>
    12. 您在 /var/spool/mail/root 中有新邮件
    13. [root@k8s-master01 pod-yaml]# kubectl describe nodes k8s-node2 | grep Taints
    14. Taints: <none>

    三、Pod 常见的状态和重启策略

    3.1 常见的 pod 状态

    第一阶段:

    • 挂起(Pending):
    1. 正在创建Pod,但是Pod中的容器还没有全部被创建完成,处于此状态的Pod应该检查Pod依赖的存储是否有权限挂载、镜像是否可以下载、调度是否正常等;
    2. 我们在请求创建pod时,条件不满足,调度没有完成,没有任何一个节点能满足调度条件,已经创建了pod但是没有适合它运行的节点叫做挂起,调度没有完成。
    • 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
    • 未知(Unknown):未知状态,所谓pod是什么状态是apiserver和运行在pod节点的kubelet进行通信获取状态信息的,如果节点之上的kubelet本身出故障,那么apiserver就连不上kubelet,得不到信息了,就会看Unknown,通常是由于与pod所在的node节点通信错误。
    • Error 状态:Pod 启动过程中发生了错误
    • 成功(Succeeded):Pod中的所有容器都被成功终止,即pod里所有的containers均已terminated。

    第二阶段:

    • Unschedulable:Pod不能被调度, scheduler没有匹配到合适的node节点 PodScheduled:pod正处于调度中,在scheduler刚开始调度的时候,还没有将pod分配到指定的node,在筛选出合适的节点后就会更新etcd数据,将pod分配到指定的node
    • Initialized:所有pod中的初始化容器已经完成了
    • ImagePullBackOff:Pod所在的node节点下载镜像失败
    • Running:Pod内部的容器已经被创建并且启动。

    扩展:还有其他状态,如下:

    • Evicted状态:出现这种情况,多见于系统内存或硬盘资源不足,可df-h查看docker存储所在目录的资源使用情况,如果百分比大于85%,就要及时清理下资源,尤其是一些大文件、docker镜像。
    • CrashLoopBackOff:容器曾经启动了,但可能又异常退出了。如pod一直在重启

    3.2 pod 重启策略

            Pod的重启策略(RestartPolicy)应用于Pod内的所有容器,当某个容器异常退出或者健康检查失败时,kubelet将根据 重启策略来进行相应的操作。

            Pod 的 spec 中包含一个 restartPolicy 字段,其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。

    • Always:只要容器异常退出,kubelet就会自动重启该容器。(这个是默认的重启策略)
    • OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器。(生产环境中常用)
    • Never:不论容器运行状态如何,kubelet都不会重启该容器。

    3.3 测试 Always 重启策略 

    1. [root@k8s-master01 pod-yaml]# vim pod.yaml
    2. apiVersion: v1
    3. kind: Pod
    4. metadata:
    5. name: demo-pod
    6. namespace: default
    7. labels:
    8. app: myapp
    9. spec:
    10. restartPolicy: Always
    11. containers:
    12. - name: tomcat-pod-java
    13. ports:
    14. - containerPort: 8080
    15. image: tomcat:latest
    16. imagePullPolicy: IfNotPresent
    17. [root@k8s-master01 pod-yaml]# kubectl apply -f pod.yaml
    18. pod/demo-pod created
    19. 您在 /var/spool/mail/root 中有新邮件
    20. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide
    21. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    22. demo-pod 1/1 Running 0 10s 10.244.169.153 k8s-node2 <none> <none>
    23. # 动态显示pod状态信息
    24. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide -w
    25. NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    26. demo-pod 1/1 Running 0 22s 10.244.169.153 k8s-node2 <none> <none>
    27. # 另起一个终端会话,进入pod内部容器,正常停止 tomcat 容器服务。-c 指定容器名称。
    28. [root@k8s-master01 pod-yaml]# kubectl exec -it demo-pod -c tomcat-pod-java -- bash
    29. root@demo-pod:/usr/local/tomcat# ls
    30. root@demo-pod:/usr/local/tomcat# bin/shutdown.sh

    可以看到,容器服务停止后被重启了一次,,pod又恢复正常了:

    1. # 非正常停止容器里的tomcat服务
    2. [root@k8s-master01 pod-yaml]# kubectl exec -it demo-pod -c tomcat-pod-java -- bash
    3. root@demo-pod:/usr/local/tomcat# ps -ef | grep tomcat
    4. root@demo-pod:/usr/local/tomcat# kill 1

    可以看到容器终止了,并且又重启一次,重启次数增加了一次:

    3.4   测试 Never 重启策略

    1. # 修改 pod.yaml,把 Always 改为 Never
    2. [root@k8s-master01 pod-yaml]# kubectl delete pods demo-pod
    3. pod "demo-pod" deleted
    4. [root@k8s-master01 pod-yaml]# kubectl apply -f pod.yaml
    5. pod/demo-pod created
    6. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide -w
    7. # 在另一个终端进入容器,正常停止服务
    8. [root@k8s-master01 pod-yaml]# kubectl exec -it demo-pod -c tomcat-pod-java -- bash
    9. root@demo-pod:/usr/local/tomcat# bin/shutdown.sh

     查看pod状态,发现正常停止容器里的tomcat服务,pod正常运行,但容器没有重启。

    1. # 非正常停止容器里的tomcat服务
    2. [root@k8s-master01 pod-yaml]# kubectl delete pods demo-pod
    3. pod "demo-pod" deleted
    4. [root@k8s-master01 pod-yaml]# kubectl apply -f pod.yaml
    5. pod/demo-pod created
    6. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide -w
    7. # 在另一终端进入容器内容
    8. [root@k8s-master01 pod-yaml]# kubectl exec -it demo-pod -c tomcat-pod-java -- bash
    9. root@demo-pod:/usr/local/tomcat# kill 1

            可以看到容器状态是error,并且没有重启,这说明重启策略是never,那么pod里容器服务无论如何终止,都不会重启:

    3.5  测试 OnFailure 重启策略(生产环境中常用)

    1. # 修改 pod.yaml 文件,把 Never 改为 OnFailure
    2. [root@k8s-master01 pod-yaml]# kubectl delete pods demo-pod
    3. pod "demo-pod" deleted
    4. [root@k8s-master01 pod-yaml]# kubectl apply -f pod.yaml
    5. pod/demo-pod created
    6. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide -w
    7. # 在另一终端进入容器内部,正常停止服务
    8. [root@k8s-master01 pod-yaml]# kubectl exec -it demo-pod -c tomcat-pod-java -- bash
    9. root@demo-pod:/usr/local/tomcat# bin/shutdown.sh

    发现正常停止容器里的tomcat服务,退出码是0,pod里的容器不会重启:

    1. # 非正常停止容器里的tomcat服务
    2. [root@k8s-master01 pod-yaml]# kubectl delete pods demo-pod
    3. pod "demo-pod" deleted
    4. [root@k8s-master01 pod-yaml]# kubectl apply -f pod.yaml
    5. pod/demo-pod created
    6. [root@k8s-master01 pod-yaml]# kubectl get pods -o wide -w
    7. # 在另一终端进入容器内部
    8. [root@k8s-master01 pod-yaml]# kubectl exec -it demo-pod -c tomcat-pod-java -- bash
    9. root@demo-pod:/usr/local/tomcat# kill 1

    可以看到非正常停止pod里的容器,容器退出码不是0,那就会重启容器:

     上一篇文章:【云原生 | Kubernetes 实战】05、Pod高级实战:基于污点、容忍度、亲和性的多种调度策略(上)_Stars.Sky的博客-CSDN博客​​​​​​​

    下一篇文章:【云原生 | Kubernetes 实战】07、Pod 高级实战:Pod 生命周期、启动钩子、停止钩子_Stars.Sky的博客-CSDN博客

  • 相关阅读:
    linux程序返回码的含义
    linux拨号上网
    CUDA生态系统架构是什么样的?CUDA的技术原理是什么?底层原理是什么?怎么开发相关产品
    3GPP-LTE Band3标准定义频点和信道(V17.3.0 (2022-09))
    LSTM的预测算法 - 股票预测 天气预测 房价预测 计算机竞赛
    【第39篇】RepLKNet将内核扩展到 31x31:重新审视 CNN 中的大型内核设计
    【Echarts】学习笔记
    自研系统加入license授权(附源码)
    Linux 如何让远程连接工具操作断开后所做的操作不结束
    Bypass WAF常规绕过思路
  • 原文地址:https://blog.csdn.net/weixin_46560589/article/details/128138633