1. 探针机制

Kubernetes 中客户端通过 Service 访问容器服务时,kube-proxy 根据同名 Endpoints 中 subsets 列表随机选择一个后端 Pod 进行流量转发。

下图展示了 Service 到 Pod IP 的映射关系:

image-20230516115224919

当 Pod 副本异常退出时,可以看到 Endpoints 的 subsets 列表被 Kubernetes 的管理服务更新。此时外部通过 ClusterIP 或 NodePort 访问容器服务时,流量不会路由到发生异常的容器:

image-20230516115729430

Kubernetes 还通过探针机制检查 Pod 的运行状况检查,动态更新 Endpoints 的 subsets 列表,因此用户需要小心设置 Pod 中探针的相关配置,才能保证在部署、升级等过程中服务持续可用。

Kubernetes 中可以配置以下三种类型的探针:

  • Liveness Probe: 用于检测容器是否存活,如果探测失败,kubelet 会重启容器(PS:重启不会触发重新调度)。
  • Readiness Probe: 用于检测容器是否准备好接收流量,如果探测失败,端点控制器会从与 Pod 匹配的 Service 的 Endpoints 列表中移除该 Pod。
  • Startup Probe: 用于检测容器是否启动成功,在容器启动成功之前,其他的探针不会生效,如果探测失败,kubelet 会重启容器

每种探针都支持三种方式进行探测:

  • HTTP GET Probe: 向容器的 IP 地址、端口和路径发送一个 HTTP GET 请求,如果响应的状态码在 200 到 399 之间,就认为探测成功。
  • TCP Socket Probe: 尝试建立一个 TCP 连接到容器的指定端口,如果连接成功,就认为探测成功。
  • Exec Probe: 在容器内执行一个指定的命令,如果命令返回 0,就认为探测成功。
  • gRPC Probe:在容器中通过 gRPC 命令进行健康检查(PS:要求 Kubernetes 1.24 以上版本)。

通常用户需要配置 Readiness Probe 和 Liveness Probe 探针以提高应用程序的可靠性和可用性,下图仅有一个容器的 readinessProbe 正常工作,因此 Service 后端仅指向一个 PodIP。

image-20230516143946587

参考资料

  • Kubernetes 探针 官方文档

  • Kubernetes 相关源码目录:

    • Probe 探针控制器:pkg/kubelet/prober

    • Probe 探针实现类:pkg/probe

    • EndPoint 控制器:pkg/controller/endpoint

2. 控制器升级策略

Kubernetes 主要负载控制器 Deployment、DaemonSet、Statefulset 都支持配置滚动更新。

在满足以下条件后,可以不中断业务的情况下对容器进行平滑更新。

  • 业务部署为多副本

  • 业务容器合理设置了 readinessProbe

  • 合理设置了这些控制器的更新策略

Deployment

Deployment 支持以下两种方式更新容器:

  • Recreate:同时终止所有容器副本,当旧副本完全结束后,同时拉起新的副本。
  • RollingUpdate:滚动升级副本容器,用户可以通过额外的参数控制滚动的过程。

默认情况下 Deployment 通过 RollingUpdate 的方式,用户可以控制参数包含以下两个:

  • maxSurge(默认配置 25%):可以创建的最大Pod数,即新旧 Pod 之和不能超过 replicas + maxSure,该值可以是绝对数或百分比。
  • maxUnavailable(默认配置 25%):在更新过程中可能不可用的最大Pod数,该值可以是绝对数或百分比。

下面配置中,maxSurge 和 maxUnavailable 均被设置为 1,此时 Kubernetes 将逐个更新 Pod 副本。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
spec:
  replicas: 3
  selector:
    matchLabels:
      app: whoami
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
      - command: ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]
        image: registry.lqingcloud.cn/library/whoami:v1.5.0-centos
        imagePullPolicy: IfNotPresent
        name: whoami
        readinessProbe:
          httpGet:
            path: /
            port: 33333
          failureThreshold: 1
          periodSeconds: 10

DaemonSet

DaemonSet 支持以下两种方式更新容器:

  • OnDelete:在更新 DaemonSet 后,只有在手动删除旧的 DaemonSet Pod 时才会创建新的DaemonSet Pod。
  • RollingUpdate:滚动升级每个节点上的容器,用户可以通过额外的参数控制滚动的过程。

默认情况下 DaemonSet 通过 RollingUpdate 的方式更新,用户可以调整的参数和 Deployment 相同,但对应的默认值不同。

  • maxSurge(默认配置 0):maxSurge 配置为 0 时,可以保证任意时刻、任意节点上只有 Pod 在运行。
  • maxUnavailable(默认配置 1): maxUnavailable 配置为 1 时,可以保证任意时刻只有一个节点在更新容器。

Statefulset

Statefulset 支持以下两种方式更新容器:

  • OnDelete:含义和 DaemonSet 一致。
  • RollingUpdate:滚动升级每个节点上的容器,用户可以通过额外的参数控制滚动的过程。

Statefulset 的滚动升级比较复杂,以下先说明默认配置下 Statefulset 的更新策略。

默认配置

默认配置下 Statefulset 通过 RollingUpdate 的方式更新,此时 kubernetes 如何更新 Pod 取决于用户在 Statefulset 中定义的 spec.podManagementPolicy 参数。该参数有以下两种取值:

  • OrderedReady(默认):从编号最大的 Pod 开始,逐个滚动更新 Pod
  • Parallel:同时更新所有 Pod,等价于 Deployment 的 ReCreate。

默认配置下,Statefulset 更新策略实际上和 Deployment 一致。

分区滚动

Statefulset 中我们可以配置以下参数,实现分区滚动升级:

  • partition(默认值 0):在更新 StatefulSet 时,序号大于或等于该 partition 的所有Pod都将被更新。序号小于 partition 的所有 Pod 将不会被更新,即使它们被删除,它们也将在以前的版本中重新创建。

v1.24 以上版本,Statefulset 还支持 maxUnavailable 参数,其含义和 Deployment 一致。

以下 Statefulset 定义了一个 5 副本的容器服务,并且将分区参数设置为 3 :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: whoami
spec:
  selector:
    matchLabels:
      app: whoami
  serviceName: "whoami"
  replicas: 5
  updateStrategy:
    rollingUpdate:
      partition: 3
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
      - command: ["/bin/sh", "-c", "trap : TERM INT; sleep infinity & wait"]
        image: registry.lqingcloud.cn/library/whoami:v1.5.0-centos
        imagePullPolicy: IfNotPresent
        name: whoami

Statefulset 控制器将创建以下容器:

image-20230516171431411

此时手工编辑 Statefulset 变更容器使用的镜像,由于我们定义了分区更新此时只用 whoami-3 和 whoami-4 发生更新,如下图:

image-20230516172039188

总结:基于 Statefulset 的分区更新机制,业务可以自行设计金丝雀部署蓝绿部署灰度发布等策略。