Pod健康检查和服务可用性检查

LivenessProbe探针:

用于判断容器是否存活(Running状态),如果该探针探测到容器不正常,那么kubelet会将其kill,并根据容器的重启策略进行处理

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/busybox
    args: # 容器启动时执行该命令
# 容器启动后前30秒,文件是存在的,所以执行cat /tmp/health会返回成功代码;30秒后会删除该文件,再执行cat /tmp/health会返回失败代码
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600 
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy # kubelet在容器内执行cat /tmp/health命令去探测,返回值为0,则认为容器健康
      initialDelaySeconds: 5 # kubelet在执行第一次探测前要等待5秒
      periodSeconds: 5 # kubelet应该每5秒执行一次存活探测

探测时间的设置
  • initialDelaySeconds:容器启动后多少秒再去进行探测,默认时0s,最小值时0s
  • periodSeconds:容器启动后进行探测的间隔为多少秒,默认时10s,最小为1s
  • timeoutSeconds:容器启动后进行探测超时等待的时间为多少秒,默认为1s,最小为1s
  • successThreshold:容器探测失败后,再连续探测几次成功才算成功,存活和启动探测的这个值必须是 1,默认值是1
  • failureThreshold:容器探测成功后,再连续探测几次失败才算失败,默认值是3,最小值是1
探针的三种方式
  • ExecAction:在容器内部运行一个命令,该命令返回码为0,表明容器健康
  • TCPSocketAction:通过容器的IP地址和端口号执行TCP检查,如果能建立TCP连接,则表明容器健康
  • HTTPGetAction:通过容器的IP地址、端口号及路径调用HTTP get方法,如果状态码大于等于200且小于400,则认为容器健康

ReadyinessProbe探针:

用于判断容器是否就绪(Ready状态),Ready状态的Pod才能接收请求。如果在运行过程中,Pod的Ready状态变为False,那么它将会从Service后端Endpoint列表中去除(该Pod被Service管理)

StartupProbe探针:

如果容器启动较慢,可以使用该探针来延长对容器存活性的探测,可以通过将 failureThreshold * periodSeconds 参数设置为足够长的时间来应对糟糕情况下的启动时间

亲和性和反亲和性

NodeSelector定向调度

  • 当一个Pod被Scheduler服务调度的时候,它会执行一些列复杂的算法,最终将Pod调度到一个最佳的节点上

  • 如果想将Pod调度到指定的节点上,可以通过Node标签和nodeSelector属性相匹配,达到上述目的

    • 首先用kubectl label为一个节点打标签,然后在Pod的定义中加入nodeSelector
    kubectl label node k8s-node app=nginx
    

    pod的yaml文件

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:         
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
      nodeSelector:
        app=nginx
    
    • 在运行kubectl create -f pod-yaml创建Pod,scheduler就会将Pod调度到拥有app=nginx标签的Node上
    • 如果我们指定了Pod的nodeSelector,但是,集群中的node中没有包含对应的标签,则Pod将无法被调度

亲和性调度功能

节点亲和性(nodeAffinaity)
两种亲和性表达:

  • requiredDuringSchedulingIgnoredDuringExecution:硬限制,必须满足指定的规则才可以调度Pod到Node上
  • preferredDuringSchedulingIgnoredDuringExecution:软限制,强调优先满足指定规则,调度器会尝试将Pod调度到Node上,但并不强求
  • IgnoredDuringExecution:Pod所在节点在Pod运行期间标签发生了改变,并不会影响该Pod继续在此节点上运行
apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/os
            operator: In
            values:
            - linux
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
 - name: with-node-affinity
    image: k8s.gcr.io/xx:2.0

硬性要求:只能运行在有标签kubernetes.io/os:linux的节点上
软性要求:尽量运行在有标签another-node-label-key:another-node-label-value的节点上

NodeAffinity语法支持的操作符: In,NotIn(互斥)、Exists、DoesNotExist(互斥)、Gt、Lt
NodeAffinity设置的规则:

  • 如果同时设定了nodeSelector和NodeAffinity,则必须两者同时满足,Pod才能被调度到指定Node上
  • 如果NodeAffinity中指定了多个nodeSelectorTerms,则只要一个匹配成功就能将Pod调度到指定的Node上
  • 如果在一个nodeSelectorTerms指定了多个matchExpressions,则该节点需要满足所有的matchExpressions才能运行次Pod

Pod亲和性(PodAffinity)和反亲和性(PodAntiAffinity)
Pod亲和性:在生产环境中有些Pod相互依赖、频繁调用,他们就应该尽可能的部署在一个Node、机架、机房、网段或者区域中

在将一个Node加入Master中时,Node可能就会被加上默认的标签:
kubernetes.io/hostname;topology.kubernetes.io/region;topology.kubernetes.io/zone

Pod亲和和互斥的调度具体做法,就是通过Pod的定义上增加的topologyKey属性,来声明一些相关联的Pod是否要放在一个区域或节点上

Pod的亲和和互斥与节点亲和条件设置相同:requiredDuringSchedulingIgnoredDuringExecution
preferredDuringSchedulingIgnoredDuringExecution

举例说明Pod的亲和和反亲和性

apiVersion: v1
kind: Pod
metadata:
  name: pod-flag
  labels:
    security: "S1"
    app: "nginx"
spec:
  containers:
  - name: nginx
    image: nginx
---
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: topology.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: topology.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: k8s.gcr.io/pause:2.0

Pod将会被调度到有topology.kubernetes.io/zone标签,且Pod标签为security=S1,但是不与security=S2的Pod为同一个Node

Pod的亲和性操作符包括: In,NotIn(互斥)、Exists、DoesNotExist(互斥)、Gt、Lt
在原则上topologyKey可以使用任意合法的标签,但是出于安全考虑,topologyKey有如下限制:

  • Pod亲和性和带有硬性、软性限制,topologyKey不能为空
  • Pod反亲和性和带有硬性限制,topologyKey只能是 kubernetes.io/hostname
  • Pod亲和性除了设置Label Selector和topologyKey外,还可以指定Namespace列表进行限制
  • Pod被调度到某个Node上必须满足硬性限制和matchExpressions

污点(Taints)和容忍(Tolerations)

**Taint:**让Node拒绝Pod运行,标记了Taint的节点就是不希望Pod被调度过来,但此节点仍然是有效的节点;如果希望某些特定的Pod调度过来,则需要设置Tolerations
在节点上设置Taint

kubectl taint node k8s-node key=value:NoSchedule

在该节点上设置了key=value的污点,而且Pod中如果没有设置容忍该污点,则无法将Pod调度到该节点上

在Pod上声明容忍该污点:

tolerations:
 - key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
---
tolerations:
 - key: "key1"
  operator: "Exists"
  effect: "NoSchedule"

在设置容忍的时候,key和effect要和污点的设置保持一致,并且满足以下条件之一:

  • operator值是Exists,则无需指定value
  • operator值是Equal并且value相等
  • 如果不指定operator则默认是Equal

特例:
空的key匹配Exists操作能够匹配所有键和值
空的effect匹配所有的effect

effect类型:
NoSchedule:没有设置容忍该污点的Pod无法被调度到该节点
PreferNoSchedule:没有设置容忍该污点的Pod尽量避免调度到该节点
NoExecute:没有设置容忍该污点的Pod无法被调度到该节点,而且如果Pod已经在该节点上运行则会被驱逐

系统允许一个节点上有多个Taint和Tolerations,K8S处理的逻辑顺序为:

  • 列出节点中所有的Taint,忽略能够匹配Taint的Toleration;剩下没被忽略的Taint就起以下作用:
    • 剩余的Taint中存在effect=NoSchedule,调度器不会把该Pod调度到这一节点上
    • 剩余的Taint中没有NoSchedule,但是有PreferNoSchedule,调度器尝试不把这个Pod调度到该节点上
    • 剩余的Taint中有NoExecute,Pod无法被调度到该节点,如果Pod已经在该节点上运行,则会被驱逐

从K8S 1.6开始引入两个与Taint相关的新特性,新特性是用来改善异常情况下的Pod调度与驱逐问题(当节点有磁盘、内存、节点失联等问题时)

  • TaintNodesByCondition:
    • 不断地检查所有Node状态,设置对应的Condition
    • 根据Node Condition设置对应的Taint(添加的是NoSchedule的污点),主要有以下几种:
      • node.kubernetes.io/not-ready:节点未就绪
      • node.kubernetes.io/unreachable:节点不可触达(相当于失联的状态)
      • node.kubernetes.io/out-of-disk:节点磁盘空间已满
      • node.kubernetes.io/network-unavailable:节点网络不可用
      • node.kubernetes.io/unschedulable:节点不可调度
    • 根据Taint驱逐Node上的Pod
  • TaintBasedEvictions:添加的是NoExecute效果的污点
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐