Configure as sondas de prontidão, os readinessGates, os hooks preStop e o esvaziamento de conexões do Server Load Balancer (SLB) para garantir atualizações graduais sem tempo de inatividade no ACK.
Como funciona
A estratégia de atualização gradual (RollingUpdate) para Deployments substitui os Pods um a um para garantir a disponibilidade contínua. O processo possui três fases:
Fase de inicialização: O Kubernetes cria um novo Pod (v2) e aguarda a aprovação na sonda de prontidão antes de rotear qualquer tráfego do service para ele.
-
Fase de deslocamento de tráfego: Com os
readinessGatesativados, o novo Pod precisa passar na verificação de prontidão. Em seguida, o sistema registra o IP dele nos Endpoints do service e no grupo de servidores de backend do SLB, encerra o Pod antigo (v1) e remove o IP dele dos Endpoints.Consulte How readinessGates works .
Fase de desligamento graceful: Antes da exclusão, o Pod antigo executa seu hook preStop e usa o
terminationGracePeriodSecondspara concluir o processamento das conexões, enquanto o SLB esvazia as requisições em andamento. Isso garante a conclusão de todas as requisições, resultando em uma atualização sem tempo de inatividade.
Pré-requisitos
O cluster deve estar na versão 1.24 ou posterior. Atualize o cluster se necessário.
O componente cloud-controller-manager deve estar na versão v2.10.0 ou posterior. Consulte Cloud Controller Manager.
Implante um aplicativo de exemplo
Este exemplo implanta um aplicativo NGINX sem estado (stateless).
Console
Na página ACK Clusters, clique no nome do seu cluster. No painel de navegação à esquerda, clique em .
-
Na página Deployments, clique em Create from YAML. Cole o YAML a seguir e clique em Create.
Na janela pop-up, localize o aplicativo, clique em View e verifique se o status do Pod é
Running.
kubectl
Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster.
-
Salve o YAML a seguir como nginx-demo.yaml.
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment-demo spec: replicas: 1 # Set to 2 or more for production HA. Set to 1 for demonstration purposes. selector: matchLabels: app: nginx-demo # Rolling update strategy: ensures service availability during updates. # strategy: # type: RollingUpdate # Default strategy for Deployments. # rollingUpdate: # maxUnavailable: "25%" # Default. Max 25% of Pods can be unavailable during the update. # maxSurge: "25%" # Default. Max 25% extra Pods can be created above the desired replica count. template: metadata: labels: app: nginx-demo spec: # Pod-level graceful shutdown limit. Must be greater than the sum of preStop execution and app cleanup time. terminationGracePeriodSeconds: 60 readinessGates: - conditionType: service.readiness.alibabacloud.com/nginx-demo-service # Set the Readiness Gate for the nginx-demo-service Service. containers: - name: nginx image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6 ports: - containerPort: 80 resources: requests: cpu: 500m memory: 1Gi limits: cpu: 500m # --- Health check probes --- # startup probe: Ensures the application in the container has started. startupProbe: httpGet: path: / # Accessing the default NGINX root path indicates a successful startup. port: 80 # Allow sufficient time for startup. Total timeout = failureThreshold * periodSeconds. # Here: 30 * 10 = 300 seconds. failureThreshold: 30 periodSeconds: 10 # readiness probe: Determines whether the container is ready to receive traffic. readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 # Probing starts 5 seconds after the container starts. periodSeconds: 5 # Probe every 5 seconds. timeoutSeconds: 2 # Probe timeout duration. successThreshold: 1 # 1 success marks the Pod as ready. failureThreshold: 3 # 3 consecutive failures mark the Pod as not ready. # --- Pod graceful shutdown configuration --- lifecycle: preStop: exec: # For reliable graceful shutdown, define a custom hook that handles in-flight requests based on your application logic. # Using sleep alone is not recommended as it does not guarantee a clean exit. command: ["sh", "-c", "sleep 30 && /usr/sbin/nginx -s quit"] --- apiVersion: v1 kind: Service metadata: name: nginx-demo-service annotations: # Timeout for connection draining. This value should align with the application's preStop logic. Range: 10-900. service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain-timeout: "30" # Enable connection draining. service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain: "on" spec: type: LoadBalancer selector: app: nginx-demo ports: - protocol: TCP port: 80 -
Implante o aplicativo NGINX e crie o service.
kubectl apply -f nginx-demo.yaml -
Verifique se o Pod está
Running.kubectl get pod | grep nginx-deployment-demo
-
Verificações de prontidão do Pod
startupProbe(sonda de inicialização): Verifica se aplicativos de inicialização lenta, como aplicativos Java, iniciaram. Até que seja bem-sucedida, o sistema pausa as sondas de prontidão e de atividade (liveness) para evitar reinicializações prematuras do contêiner.readinessProbe(sonda de prontidão): Determina se um contêiner pode processar requisições. Em caso de sucesso, o Kubernetes adiciona o IP do Pod aos Endpoints do service, ativando o tráfego.readinessGates: O Pod só fica pronto após a aprovação tanto doreadinessProbequanto dosreadinessGates.
-
Desligamento graceful
-
Desligamento graceful do aplicativo
-
preStop: Hook executado antes do encerramento do contêiner. Configure-o para esvaziar as requisições em andamento e garantir um desligamento sem interrupções.Use um hook personalizado. O uso isolado do sleep pode não encerrar o processo corretamente.
terminationGracePeriodSeconds: Tempo máximo desde o encerramento do Pod até oSIGKILL. Padrão: 30 segundos. Deve exceder o tempo combinado do hookpreStope da limpeza do aplicativo.
-
-
Esvaziamento de conexões do SLB
Anotação
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain: Ative o esvaziamento de conexões do SLB.service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain-timeout: Tempo limite do esvaziamento de conexões em segundos. Defina este valor próximo ao tempo de processamento do hook preStop.
-
Estratégia de atualização gradual (rolling update)
strategy: A estratégia padrão do Deployment é a RollingUpdate. Cria novos Pods gradualmente e remove os antigos após a prontidão dos novos para garantir a disponibilidade do service.maxUnavailable: Número máximo de Pods indisponíveis durante uma atualização gradual. Padrão: 25%. Também aceita um número absoluto.maxSurge: Número máximo de Pods extras acima da contagem de réplicas desejada durante uma atualização gradual. Valores mais altos aceleram as atualizações, mas consomem mais recursos. Padrão: 25%. Também aceita um número absoluto.
Verifique a atualização gradual sem tempo de inatividade
Obtain the kubeconfig file of a cluster and use kubectl to connect to the cluster.
-
Obtenha a url do aplicativo de exemplo.
export NGINX_ENDPOINT=$(kubectl get service nginx-demo-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}{":"}{.spec.ports[0].port}') echo $NGINX_ENDPOINT -
Instale o hey. Execute um teste de carga com 200 conexões simultâneas e um total de 50.000 requisições. Uma única réplica conclui o teste em cerca de um minuto.
hey -c 200 -n 50000 -disable-keepalive http://$NGINX_ENDPOINTDurante a execução do teste, abra um novo terminal e reinicie o Deployment imediatamente.
kubectl rollout restart deployment nginx-deployment-demo -
Saídas esperadas:
Cenário de implantação
Saída esperada
Sem a configuração de tempo de inatividade zero
Ocorre perda de tráfego.
Status code distribution: [200] 49644 responses Error distribution: [320] Get "http://114.215.XXX.XXX": dial tcp 114.215.XXX.XXX:80: connect: connection refused [18] Get "http://114.215.XXX.XXX": dial tcp 114.215.XXX.XXX:80: connect: no route to host [18] Get "http://114.215.XXX.XXX": dial tcp 114.215.XXX.XXX:80: connect: operation timed outCom a configuração de tempo de inatividade zero
Não há perda de tráfego.
Status code distribution: [200] 50000 responses
Perguntas frequentes
Status do Pod: Running, mas não pronto
Causa: Geralmente, ocorre devido a uma falha na sonda de inicialização ou de prontidão.
Solução:
-
Configure a sonda de prontidão: Na página Edit dos Workloads de destino, verifique se o caminho da verificação de integridade (por exemplo, /healthz) e a porta correspondem ao aplicativo. Para aplicativos de inicialização lenta, aumente o Unhealthy Threshold para evitar falhas prematuras.
Desative temporariamente a verificação de Readiness , acesse o terminal do Pod e use um comando como
curle verifique se a verificação de integridade responde corretamente. Solução de problemas do aplicativo: Verifique os Events e Logs do Pod. Selecione Show the log of the last container exit.
Referências
-