Atualizando um cluster Kubernetes sem tempo de inatividade

Atualizando um cluster Kubernetes sem tempo de inatividade

Processo de upgrade para seu cluster Kubernetes

Em algum momento, ao usar um cluster Kubernetes, é necessário atualizar os nós em execução. Isso pode incluir atualizações de pacotes, atualizações de kernel ou implantação de novas imagens de máquinas virtuais. Na terminologia do Kubernetes, isso é chamado “Perturbação voluntária”.

Esta postagem faz parte de uma série de 4 postagens:

  1. Esta postagem.
  2. Desligamento correto de pods em um cluster Kubernetes
  3. Encerramento atrasado de um pod quando ele é excluído
  4. Como evitar o tempo de inatividade do cluster Kubernetes usando PodDisruptionBudgets

(aproximadamente espere traduções dos artigos restantes da série em um futuro próximo)

Neste artigo, descreveremos todas as ferramentas que o Kubernetes fornece para atingir zero tempo de inatividade para os nós em execução em seu cluster.

Definição do problema

Adotaremos inicialmente uma abordagem ingénua, identificaremos problemas e avaliaremos os riscos potenciais desta abordagem, e construiremos conhecimento para resolver cada um dos problemas que encontrarmos ao longo do ciclo. O resultado é uma configuração que usa ganchos de ciclo de vida, sondagens de prontidão e orçamentos de interrupção de pod para atingir nossa meta de tempo de inatividade zero.

Para iniciar nossa jornada, vamos dar um exemplo concreto. Digamos que temos um cluster Kubernetes de dois nós, no qual um aplicativo está sendo executado com dois pods localizados atrás Service:

Atualizando um cluster Kubernetes sem tempo de inatividade

Vamos começar com dois pods com Nginx e Service em execução em nossos dois nós de cluster Kubernetes.

Queremos atualizar a versão do kernel de dois nós de trabalho em nosso cluster. Como vamos fazer isso? Uma solução simples seria inicializar novos nós com a configuração atualizada e, em seguida, desligar os nós antigos enquanto inicia os novos. Embora isso funcione, haverá alguns problemas com esta abordagem:

  • Ao desativar nós antigos, os pods em execução neles também serão desativados. E se os pods precisarem ser limpos para um desligamento normal? O sistema de virtualização que você está usando pode não esperar a conclusão do processo de limpeza.
  • E se você desligar todos os nós ao mesmo tempo? Você terá um tempo de inatividade decente enquanto os pods são movidos para novos nós.

Precisamos de uma maneira de migrar pods de nós antigos sem problemas e, ao mesmo tempo, garantir que nenhum de nossos processos de trabalho esteja em execução enquanto fazemos alterações no nó. Ou quando fazemos uma substituição completa do cluster, como no exemplo (ou seja, substituímos imagens de VM), queremos transferir aplicativos em execução de nós antigos para novos. Em ambos os casos, queremos evitar que novos pods sejam agendados em nós antigos e, em seguida, remover todos os pods em execução deles. Para atingir esses objetivos podemos usar o comando kubectl drain.

Redistribuindo todos os pods de um nó

A operação de drenagem permite redistribuir todos os pods de um nó. Durante a execução da drenagem, o nó é marcado como não programável (sinalizador NoSchedule). Isso evita que novos pods apareçam nele. Em seguida, o dreno começa a expulsar os pods do nó, desliga os contêineres que estão atualmente em execução no nó, enviando um sinal TERM recipientes em um pod.

Embora kubectl drain fará um ótimo trabalho ao despejar os pods, há dois outros fatores que podem causar falha na operação de drenagem:

  • Sua inscrição deve poder ser encerrada normalmente após o envio TERM sinal. Quando os pods são removidos, o Kubernetes envia um sinal TERM contêineres e espera que eles parem por um determinado período de tempo, após o qual, se não pararem, ele os encerra à força. De qualquer forma, se o seu contêiner não perceber o sinal corretamente, você ainda poderá extinguir os pods incorretamente se eles estiverem em execução (por exemplo, uma transação de banco de dados estiver em andamento).
  • Você perde todos os pods que contêm seu aplicativo. Pode não estar disponível quando novos contêineres são iniciados em novos nós ou, se seus pods forem implantados sem controladores, eles poderão nem reiniciar.

Evitando tempo de inatividade

Para minimizar o tempo de inatividade causado por interrupções voluntárias, como uma operação de drenagem em um nó, o Kubernetes oferece as seguintes opções de tratamento de falhas:

No restante da série, usaremos esses recursos do Kubernetes para mitigar o impacto da migração de pod. Para facilitar o acompanhamento da ideia principal, utilizaremos nosso exemplo acima com a seguinte configuração de recursos:

---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
   app: nginx
spec:
 replicas: 2
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx:1.15
       ports:
       - containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
 name: nginx-service
spec:
 selector:
   app: nginx
 ports:
 - protocol: TCP
   targetPort: 80
   port: 80

Esta configuração é um exemplo mínimo Deployment, que gerencia pods nginx no cluster. Além disso, a configuração descreve o recurso Service, que pode ser usado para acessar pods nginx em um cluster.

Ao longo do ciclo, expandiremos iterativamente essa configuração para que ela inclua todos os recursos que o Kubernetes oferece para reduzir o tempo de inatividade.

Para obter uma versão totalmente implementada e testada de atualizações de cluster Kubernetes para tempo de inatividade zero na AWS e além, visite Gruntwork.io.

Leia também outros artigos em nosso blog:

Fonte: habr.com

Adicionar um comentário