通过配置Readiness Gate确保Pod平滑更新

在使用LoadBalancer类型的Service暴露后端Pod时,当Pod进行滚动更新,可能会由于Pod更新速度快于负载均衡器后端服务器组的挂载速度而导致访问中断。您可以通过配置Readiness Gate来确保Pod的平滑更新。本文将介绍如何使用Pod Readiness Gate机制实现Pod平滑更新。

前提条件

使用说明

当您的Service通过LoadBalancer方式暴露后端Pod时,Pod进行滚动更新可能会导致服务短暂中断。

  • 问题原因

    在Pod进行滚动更新时,新Pod的启动速度可能快于LoadBalancer Service对后端Pod更新的速度。这可能导致请求流量仍然被导向正在逐步退出的Pod,从而造成短暂的访问失败。

  • 解决方案

    您可以在Pod的YAML配置中使用Pod Readiness Gate机制,通过自定义条件控制Pod的就绪状态。Readiness Gate允许您设置自定义条件(例如与LoadBalancer Service相关的service.readiness.alibabacloud.com/<Service Name>),当这些条件满足时,Pod才会被标记为Ready,从而能够接收流量。如果一个Pod挂载了多个负载均衡,您可以为其配置多个Readiness Gate。

  • 操作示例步骤

    image

步骤一:创建负载均衡服务

  1. 参见以下示例YAML内容,创建名为my-svc.yaml文件,按需创建传统型负载均衡CLB或网络型负载均衡NLB实例。

    CLB

    apiVersion: v1
    kind: Service
    metadata:
      name: my-svc
    spec:
      ports:
      - port: 80
        targetPort: 80
        protocol: TCP
      selector:
        app: nginx
      type: LoadBalancer

    NLB

    apiVersion: v1
    kind: Service
    metadata:
      name: my-svc
      annotations:
        service.beta.kubernetes.io/alibaba-cloud-loadbalancer-zone-maps: "${zone-A}:${vsw-A},${zone-B}:${vsw-B}" # 例如cn-hangzhou-k:vsw-i123456,cn-hangzhou-j:vsw-j654321。
    spec:
      loadBalancerClass: alibabacloud.com/nlb # 指定负载均衡类型为NLB。
      ports:
      - port: 80
        targetPort: 80
        protocol: TCP
      selector:
        app: nginx
      type: LoadBalancer
  2. 执行以下命令,创建示例Service。

    kubectl apply -f my-svc.yaml
  3. 执行以下命令,查看当前Service状态。

    kubectl get service my-svc

    等待出现<IP地址域名>后,即可确认对应的负载均衡实例已创建完成。

    NAME     TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE
    my-svc   LoadBalancer   192.XX.XX.215   <IP地址域名>     80:30493/TCP   8s

步骤二:创建示例Deployment

  1. 使用以下示例Pod的YAML内容,创建一个名为my-nginx.yaml的文件,且Readiness Gate的conditionType设置为service.readiness.alibabacloud.com/my-svc

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-nginx    # 示例名称。
      labels:
        app: nginx
    spec:
      replicas: 2       # 设置副本数量。
      selector:
        matchLabels:
          app: nginx     # 对应服务中Selector的值需要与其一致,才可以通过服务公开。
      template:
        metadata:
          labels:
            app: nginx
        spec:
          readinessGates:
          - conditionType: service.readiness.alibabacloud.com/my-svc # 设置my-svc服务的Readiness Gate
          containers:
          - name: nginx
            image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            ports:
            - containerPort: 80                                # 需要在服务中暴露该端口。
  2. 执行以下命令,部署示例Deployment。

    kubectl apply -f my-nginx.yaml
  3. 执行以下命令,查看Pod以及Readiness Gate状态。

    kubectl get pod -owide -l app=nginx

    预期输出:

    NAME                       READY   STATUS    RESTARTS   AGE   IP               NODE                         NOMINATED NODE   READINESS GATES
    my-nginx-d9f95dcf9-8dhwj   1/1     Running   0          14s   172.XX.XXX.188   cn-hangzhou.172.XX.XXX.174   <none>           0/1
    my-nginx-d9f95dcf9-z9hjm   1/1     Running   0          14s   172.XX.XXX.182   cn-hangzhou.172.XX.XXX.174   <none>           0/1

    多次执行该命令后,可以观察到Pod的Readiness Gate状态从0变为1,表明Pod已成功挂载到负载均衡服务器组中。

步骤三:滚动更新Deployment

  1. 执行以下命令,重新部署示例Deployment。

    kubectl rollout restart deployment my-nginx

    预期输出:

    deployment.apps/my-nginx restarted
  2. 执行以下命令,查看Pod以及Readiness Gate状态。

    kubectl get pod -owide -l app=nginx

    预期输出:

    NAME                       READY   STATUS    RESTARTS   AGE    IP               NODE                         NOMINATED NODE   READINESS GATES
    my-nginx-d9f95dcf9-8dhwj   1/1     Running   0          113s   172.XX.XXX.188   cn-hangzhou.172.XX.XXX.174   <none>           1/1
    my-nginx-df5c9cf7d-6p5jc   1/1     Running   0          6s     172.XX.XXX.182   cn-hangzhou.172.XX.XXX.174   <none>           0/1
    my-nginx-df5c9cf7d-7dh2v   1/1     Running   0          15s    172.XX.XXX.189   cn-hangzhou.172.XX.XXX.174   <none>           1/1

    多次执行该命令时,可以观察到在滚动更新过程中,Pod会等待就绪状态的Readiness Gate。只有当Readiness Gate就绪,表明Pod已成功挂载到负载均衡服务器组中,滚动更新才会继续进行。