在使用LoadBalancer类型的Service暴露后端Pod时,当Pod进行滚动更新,可能会由于Pod更新速度快于负载均衡器后端服务器组的挂载速度而导致访问中断。您可以通过配置Readiness Gate来确保Pod的平滑更新。本文将介绍如何使用Pod Readiness Gate机制实现Pod平滑更新。
前提条件
已创建ACK托管集群或ACK Serverless集群,且符合以下要求。具体操作请参见创建ACK托管集群、创建ACK Serverless集群。
若集群类型为ACK托管集群,网络插件需为Terway。
集群版本为1.24及以上,请参见升级集群。
cloud-controller-manager组件为v2.10.0或更高版本,请参见Cloud Controller Manager。
已通过kubectl工具连接集群。具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群。
使用说明
当您的Service通过LoadBalancer方式暴露后端Pod时,Pod进行滚动更新可能会导致服务短暂中断。当使用 LoadBalancer
类型的 Service 暴露应用,并在进行滚动更新(Rolling Update)时,可能会遇到短暂的服务中断或连接失败。
问题原因
新 Pod 的启动速度通常快于负载均衡更新后端服务器列表的速度。在新 Pod 容器已就绪、但其 IP 尚未被添加到负载均衡后端时,滚动更新机制可能已经开始终止旧 Pod。这导致部分请求流量仍被导向正在终止或已从负载均衡移除的旧 Pod,从而引发访问失败。
解决方案
可在Pod YAML配置中Pod Readiness Gate机制,通过自定义条件控制Pod的就绪状态。Readiness Gate允许设置自定义条件(例如与LoadBalancer Service相关的
service.readiness.alibabacloud.com/<Service Name>
)。只有当这些条件满足时,Pod才会被标记为Ready
,并开始正式接收流量。操作示例步骤
工作原理
当 Pod 配置
后,其就绪流程如下:readinessGates
容器探针就绪 kubelet运行容器的
readinessProbe
。探针成功后,Pod 的ContainersReady
状态变为True
。此时,Pod 整体仍为非就绪状态,等待其它Readiness Gate状态的确认。CCM添加后端 CCM 监测到容器就绪后,将该 Pod 的 IP 地址添加到指定负载均衡的后端服务器组中。添加成功后,CCM 会为Pod添加对应Service的Condition(如
service.readiness.alibabacloud.com/my-svc
),并将其状态设置为True
。Pod 最终就绪 kubelet确认所有 Readiness Gate 条件均为
True
后,将 Pod 的最终Ready
状态设置为True
。至此,Pod 才被正式视为就绪,同时滚动更新流程可以安全地终止旧 Pod。
注意事项
Service 必须存在: 确保
readinessGates
中引用的 Service 名称正确无误,并且该 Service 真实存在于集群中。如果 Service 名称错误或在 Pod 启动期间被删除,CCM 无法完成添加后端的操作,Pod 将永远无法达到Ready
状态,导致部署流程卡住。支持多个 Service: 一个 Pod 需要配置多个
readinessGates
,对应挂载到多个不同的LoadBalancer
Service。此时,Pod 必须被成功添加到所有 Service 的后端后,才会最终变为就绪状态。
步骤一:创建负载均衡服务
参见以下示例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
执行以下命令,创建示例Service。
kubectl apply -f my-svc.yaml
执行以下命令,查看当前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
使用以下示例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 # 需要在服务中暴露该端口。
执行以下命令,部署示例Deployment。
kubectl apply -f my-nginx.yaml
执行以下命令,查看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
执行以下命令,重新部署示例Deployment。
kubectl rollout restart deployment my-nginx
预期输出:
deployment.apps/my-nginx restarted
执行以下命令,查看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已成功挂载到负载均衡服务器组中,滚动更新才会继续进行。