文档首页/ 云容器实例 CCI/ 最佳实践/ 负载管理/ CCI 2.0应用进行优雅滚动升级
更新时间:2025-08-12 GMT+08:00

CCI 2.0应用进行优雅滚动升级

应用场景

用户在云容器实例 CCI 2.0中部署工作负载时,应用发布为LoadBalancer类型的Service且对接的独享型ELB,经过ELB的访问流量支持直通到容器中,应用进行滚动升级或者弹性扩缩容时,可以配置容器探针、最短就绪时间等实现优雅升级和优雅弹性扩缩容,避免升级或扩缩容过程中出现5xx的错误响应。

表1 应用场景

场景

措施

Deployment升级

滚动升级+存活/就绪探针+优雅终止

Deployment缩容

存活/就绪探针+优雅终止

  • 滚动升级

    Deployment可以采用滚动升级的升级方式,会对各个实例逐步进行更新,并非同时对所有实例进行全部更新,可以控制Pod的更新速度和并发数,从而确保了升级过程中业务不中断。例如,可以设置maxSurge和maxUnavailable参数,控制同时创建的新Pod数量和同时删除的旧Pod数量。确保升级过程中始终有工作负载能够提供服务。

    示例:配置最大浪涌(maxSurge)为25%,最大无效实例数(maxUnavailable)为25%,假设Deployment的副本数为2,那实际升级过程中,maxSurge允许最多3个Pod存在(向上取整,2*1.25=2.5,取整为3),而maxUnavailable则不允许有Pod Unavailable(向下取整,2*0.25=0.5,取整为0),也就是说在升级过程中,不允许有Pod处于非运行状态,每次新建一个Pod,待新的Pod创建成功后再删掉一个旧的Pod,直至Pod全部为新Pod。

  • 设置存活/就绪探针

    存活探针可以用来确定什么时候需要重启容器,如果容器的存活检查的结果为失败,云容器实例会对该容器执行重启操作,有利于提高应用的可用性。

    就绪探针可以知道容器何时准备好接口请求流量,若Pod尚未就绪,将会被从负载均衡器后端服务器组中剔除。

  • 优雅终止

    负载升级或缩容过程中,负载均衡器会将正在终止的pod从后端服务器组中移除,但会保持还在处理的请求的连接。如果后端服务Pod在收到结束信号后立即退出,可能会导致正在处理的请求失败或部分流量仍被转发到已经退出的Pod中,导致流量损失和服务中断。为了避免这种情况,建议在后端服务的Pod中配置优雅删除时间(terminationGracePeriodSeconds)和preStop Hook。

    优雅删除时间(terminationGracePeriodSeconds):默认为30秒,删除Pod时发送SIGTERM终止信号,然后等待容器中的应用程序终止执行。如果在terminationGracePeriodSeconds时间内未能终止,则发送SIGKILL的系统信号强行终止。

    如果用户的业务代码中没有处理SIGTERM信号,也可以尝试为Pod配置preStop Hook,在Pod被移除后继续工作一段时间,以解决流量中断的问题。

    建议用户在业务代码中对SIGTERM信号进行处理,实现优雅终止,同时也可以利用preStop先sleep一会,等待 kube-proxy 完成规则同步再开始停止容器内进程。用户可根据实际情况自定义优雅删除时间(preStop + 业务进程停止可能超过30s),避免过早被SIGKILL信号强行终止。

操作步骤

部署nginx无状态工作负载为例,在云容器实例 CCI 2.0中进行优雅滚动升级或者弹性扩缩容。

  1. 在云容器实例 CCI2.0控制台,单击左侧导航栏中的“负载管理 > 无状态负载”,单击左上角“YAML创建”。

  2. 参考以下yaml示例创建负载:

    kind: Deployment
    apiVersion: cci/v2
    metadata:
      name: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
            - name: nginx
              image: nginx:latest
              ports:
              - containerPort: 80
              resources:
                limits:
                  cpu: 500m
                  memory: 1Gi
                requests:
                  cpu: 500m
                  memory: 1Gi
              livenessProbe:            # 存活探针
                httpGet:                # 以HTTP请求检查为例
                  path: /               # HTTP检查路径为/
                  port: 80              # 检查端口为80
                initailDelySeconds: 5
                periodSeconds: 5
              readinessProbe:           # 就绪探针,该配置是检查用户业务是否就绪,不就绪则不转发流量到当前实例。
                httpGet:
                  path: /
                  port: 80
                initialDelaySeconds: 5
                periodSeconds: 5
              lifecycle:
                preStop:               # 停止前处理,该配置是保证业务容器在退出过程中能够对外提供服务。
                  exec:
                    command:
                    - /bin/bash
                    - '-c'
                    - sleep 30
          dnsPolicy: Default
          imagePullSecrets:
            - name: imagepull-secret
      strategy:
        type: RollingUpdate
        rollingUpdate:
          maxUnavailable: 0           # 滚动升级期间最多容忍的不可用的pod数量
          maxSurge: 100%              # 滚动升级期间可冗余的pod比例
      minReadySeconds: 10             # 最小就绪时间,用于指定新创建的Pod在没有任意容器崩溃情况下的最小就绪时间,只有超出这个时间Pod才被视为可用。
    • 推荐的配置minReadySeconds时长,为业务容器的启动预期时间加上ELB服务下发member到生效的时间。
    • minReadySeconds的时长需要小于sleep时长,保证旧的容器停止并退出之前,新的容器已经准备就绪。

  3. 配置完成后,对应用进行升级和弹性扩缩容的测试。

    准备一台集群外的客户端节点,预置检测脚本detection_script.sh,内容如下,其中100.85.125.90:80为service的公网访问地址:

    #! /bin/bash 
    for (( ; ; ))
    do
             curl -I 100.85.125.90:80 | grep "200 OK"
             if [ $? -ne 0 ]; then
                      echo "response error!"
                      exit 1
             fi 
    done

  4. 运行检测脚本:bash detection_script.sh,并在云容器实例 CCI2.0控制台,单击左侧导航栏中的“负载管理 > 无状态负载”,选择相关工作负载,单击“YAML编辑”,来触发应用的滚动升级。

    滚动升级的过程中,应用的访问并未中断,并且返回的请求都是“200 OK”,说明升级过程是优雅升级,无中断。