首页 > 解决方案 > 滚动更新策略不会在实时流量中提供零停机时间

问题描述

我正在使用滚动更新策略进行部署,使用这两个命令:

kubectl patch deployment.apps/<deployment-name> -n <namespace> -p '{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}' 
kubectl apply -f ./kube.deploy.yml -n <namespace>
kubectl apply -f ./kube_service.yml -n <namespace>

滚动更新的 YAML 属性:

 apiVersion: extensions/v1beta1

kind: Deployment

metadata:

  name: "applyupui-persist-service-deployment"

spec:

  # this replicas value is default

  # modify it according to your case

  replicas: 2

  strategy:

    type: RollingUpdate

    rollingUpdate:

      maxSurge: 1

      maxUnavailable: 20%

  template:

    metadata:

      labels:

        app: "applyupui-persist-service-selector"

    spec:

      hostAliases:
        - ip: "xx.xx.xx.xxx"

          hostnames:

          - "kafka02.prod.fr02.bat.cloud"


      imagePullSecrets:

        - name: tpdservice-devops-image-pull-secret

      containers:

        - name: applyupui-persist-service

          image: gbs-bat-devops-preprod-docker-local.artifactory.swg-devops.com:443/applyupui-msg-persist-service:latest

          imagePullPolicy: Always

          env:

          - name: KAFKA_BROKER

            value: "10.194.6.221:9092,10.194.6.221:9093,10.194.6.203:9092"

          - name: SCYLLA_DB

            value: "scylla01.fr02.bat.cloud,scylla02.fr02.bat.cloud,scylla03.fr02.bat.cloud"

          - name: SCYLLA_PORT

            value: "9042"            

          - name: SCYLLA_DB_USER_ID

            value: "kafcons"

          - name: SCYLLA_DB_PASSWORD

            value: "@%$lk*&we@45"

          - name: SCYLLA_LOCAL_DC_NAME

            value: "Frankfurt-DC"

          - name: DC_LOCATION

            value: "FRA"

          - name: kafka.consumer.retry.topic.timeout.interval            

            value: "100"

          - name: kafka.consumer.retry.topic.max.retry.count

            value: "5"

          - name: kafka.consumer.dlq.topic.timeout.interval

            value: "100"

          - name: kafka.producer.timeout.interval

            value: "100"             

          - name: debug.log.enabled

            value: "false"

          - name: is-application-intransition-phase

            value: "false"

          - name: is-grace-period

            value: "false"             

          - name: SCYLLA_KEYSPACE

            value: "bat_tpd_pri_msg"

          readinessProbe:

            httpGet:

             path: /greeting

             port: 8080

            initialDelaySeconds: 3

            periodSeconds: 10

            successThreshold: 1

            timeoutSeconds: 1

      nodeSelector:

        deployment: frankfurt

        # resources:

        #   requests:

        #     cpu: 100m

        #     memory: 100Mi

我尝试更改参数maxsurgemaxunavailable不同的initialdelayseconds参数。另外,我尝试给出livelinessprobe参数

 livenessprobe:
            tcpSocket:
              port: 8080
            initialDelaySeconds: 15
            periodSeconds: 20  

,但都没有奏效。它给出了连接错误,表明某些 pod 已关闭,因此存在停机时间。

标签: kubernetesdevopskubernetes-deploymentdowntimerolling-updates

解决方案


首先,您需要确保您的 yaml 文件正确且所有缩进都已到位。之后,您需要正确设置值以实现零停机更新。下面的示例显示了正确定义RollingUpdate的 s:

spec:
  replicas: 2
  strategy:
   type: RollingUpdate
   rollingUpdate:
     maxSurge: 1
     maxUnavailable: 0

在此示例中,将maxSurge: 1在所需数量 2 之上增加一个 Pod ( ),并且可用 Pod 的数量不能低于该数量 ( maxUnavailable: 0)。

选择这个配置,Kubernetes 将启动一个额外的 Pod,然后停止一个“旧的”。如果有另一个节点可用于部署此 Pod,系统将能够在部署期间处理相同的工作负载。如果没有,该 Pod 将部署在已使用的节点上,代价是来自同一节点上托管的其他 Pod 的资源。

你也可以尝试这样的事情:

spec:
  replicas: 2
  strategy:
   type: RollingUpdate
   rollingUpdate:
     maxSurge: 0
     maxUnavailable: 1

对于上面的示例,将没有额外的 Pod ( maxSurge: 0),并且一次只有一个 Pod 不可用 ( maxUnavailable: 1)。

在这种情况下,Kubernetes 会先停止一个 Pod,然后再启动一个新的 Pod。这样做的好处是基础架构不需要扩展,但最大工作负载会更少。

如果您选择使用百分比值maxSurge并且maxUnavailable您需要记住:

  • maxSurge- 绝对数字是通过四舍五入的百分比计算得出的

  • maxUnavailable- 绝对数字是通过四舍五入的百分比计算得出的

正确定义后,RollingUpdate您还必须确保您的应用程序提供端点以供 Kubernetes 查询并返回应用程序的状态。下面是一个/greeting端点,当它准备好处理请求时返回 HTTP 200 状态,而不是返回 HTTP 500:

readinessProbe:
  httpGet:
    path: /greeting
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5
  successThreshold: 1
  timeoutSeconds: 1
  • initialDelaySeconds- 完成第一次就绪检查之前的时间(以秒为单位)。

  • periodSeconds- 第一次之后的两次就绪检查之间的时间(以秒为单位)。

  • successThreshold- 探测失败后被视为成功的最小连续成功次数。默认为 1。活性必须为 1。最小值为 1。

  • timeoutSeconds- 探测超时的秒数。默认为 1 秒。最小值为 1。

我已经成功地测试了上述场景。

请让我知道这是否有帮助。


推荐阅读