Como migrar cargas de trabalho para tipos de máquina diferentes

Neste tutorial, demonstramos como migrar cargas de trabalho em execução em um cluster do GKE para um novo conjunto de nós no mesmo cluster sem incorrer em inatividade para o aplicativo. Isso é útil se você quiser migrar cargas de trabalho para nós com um tipo de máquina diferente.

Contexto

Um pool de nós é um subconjunto de máquinas que têm a mesma configuração, incluindo os escopos de autorização do tipo de máquina (CPU e memória). Os pools de nós representam um subconjunto de nodes em um cluster. Um cluster de contêineres pode conter um ou mais pools de nós.

Quando precisar alterar o perfil da máquina do cluster do Compute Engine, você poderá criar um pool de nós e migrar as cargas de trabalho para ele.

Para migrar as cargas de trabalho sem que ocorra inatividade, é preciso que você:

  • marque o pool de nós existente como não programável;
  • esvazie as cargas de trabalho em execução no pool de nós;
  • exclua o pool de nós.

O Kubernetes, que é o sistema de orquestração de clusters do GKE, reprograma automaticamente os pods removidos para o novo pool de nós à medida que esvazia o pool de nós atual.

Antes de começar

Siga estas etapas para ativar a API do Kubernetes Engine:
  1. Acesse a página do Kubernetes Engine no Console do Google Cloud.
  2. Crie ou selecione um projeto.
  3. Aguarde a ativação da API e dos serviços relacionados. Isso pode levar alguns minutos.
  4. Verifique se a cobrança está ativada para o seu projeto do Google Cloud. Saiba como confirmar se a cobrança está ativada para o seu projeto.

Instale as ferramentas de linha de comando a seguir usadas neste tutorial:

  • gcloud é usado para criar e excluir clusters do Kubernetes Engine. gcloud está incluído no SDK do Google Cloud.
  • O kubectl é usado para gerenciar o Kubernetes, o sistema de orquestração de cluster usado pelo Kubernetes Engine. É possível instalar kubectl usando gcloud:
    gcloud components install kubectl

Definir padrões para a ferramenta de linha de comando gcloud

Para poupar tempo, em vez de digitar o ID do projeto e as opções de zona do Compute Engine na ferramenta de linha de comando gcloud, defina os padrões:
gcloud config set project project-id
gcloud config set compute/zone compute-zone

Etapa 1: criar um cluster GKE

A primeira etapa é criar um cluster de contêiner para executar cargas de trabalho de aplicativo. O comando a seguir cria um novo cluster com cinco nós com o tipo de máquina padrão (e2-medium):

gcloud container clusters create migration-tutorial --num-nodes=5

Etapa 2: executar uma implantação de aplicativo replicado

O comando a seguir criará uma implantação de seis réplicas da imagem de contêiner de aplicativos da Web de exemplo:

kubectl run web --image=gcr.io/google-samples/hello-app:1.0 \
  --replicas=6 --limits='cpu=100m,memory=80Mi'

Para recuperar a lista de pods iniciados, execute:

kubectl get pods
Saída:
NAME                   READY     STATUS    RESTARTS   AGE
web-2212180648-80q72   1/1       Running   0          10m
web-2212180648-jwj0j   1/1       Running   0          10m
web-2212180648-pf67q   1/1       Running   0          10m
web-2212180648-pqz73   1/1       Running   0          10m
web-2212180648-rrd3b   1/1       Running   0          10m
web-2212180648-v3b18   1/1       Running   0          10m

Etapa 3: criar um pool de nós com um tipo de máquina grande

Por padrão, o GKE cria um pool de nós chamado default-pool para cada novo cluster:

gcloud container node-pools list --cluster migration-tutorial
Saída:
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
default-pool  e2-medium      100           1.5.7

Para introduzir instâncias com uma configuração diferente, como um tipo de máquina distinto ou outros escopos de autenticação, é necessário criar um novo pool de nós.

O comando a seguir cria um novo pool de nós chamado larger-pool com cinco instâncias de alta memória com o tipo de máquina n1-highmem-2:

gcloud container node-pools create larger-pool \
  --cluster=migration-tutorial \
  --machine-type=n1-highmem-2 \
  --num-nodes=5

O cluster de contêineres agora tem dois pools de nós:

gcloud container node-pools list --cluster migration-tutorial
Saída:
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
default-pool  e2-medium      100           1.5.7
larger-pool   n1-highmem-2   100           1.5.7

Você pode ver as instâncias do novo pool de nós adicionado ao cluster do GKE:

kubectl get nodes
Saída:
NAME                                                STATUS    AGE       VERSION
gke-migration-tutorial-default-pool-56e3af9a-059q   Ready     40m       v1.5.7
gke-migration-tutorial-default-pool-56e3af9a-0ng4   Ready     40m       v1.5.7
gke-migration-tutorial-default-pool-56e3af9a-k6jm   Ready     40m       v1.5.7
gke-migration-tutorial-default-pool-56e3af9a-lkrv   Ready     40m       v1.5.7
gke-migration-tutorial-default-pool-56e3af9a-p9j4   Ready     40m       v1.5.7
gke-migration-tutorial-larger-pool-b8ec62a6-2rhk    Ready     4m        v1.5.7
gke-migration-tutorial-larger-pool-b8ec62a6-4bb2    Ready     4m        v1.5.7
gke-migration-tutorial-larger-pool-b8ec62a6-7fl0    Ready     4m        v1.5.7
gke-migration-tutorial-larger-pool-b8ec62a6-cx9q    Ready     4m        v1.5.7
gke-migration-tutorial-larger-pool-b8ec62a6-hs6p    Ready     4m        v1.5.7

Etapa 4: migrar as cargas de trabalho

Depois de criar um novo pool de nós, suas cargas de trabalho ainda estão em execução no default-pool. Os Pods não são reprogramados pelo Kubernetes, contanto que estejam em execução e disponíveis.

Execute o seguinte comando para ver em qual nó os pods são executados. Consulte a coluna NODE:

kubectl get pods -o=wide
Saída:
NAME                          READY     STATUS    IP         NODE
web-2212180648-80q72          1/1       Running   10.8.3.4   gke-migration-tutorial-default-pool-56e3af9a-k6jm
web-2212180648-jwj0j          1/1       Running   10.8.2.5   gke-migration-tutorial-default-pool-56e3af9a-0ng4
web-2212180648-pf67q          1/1       Running   10.8.4.4   gke-migration-tutorial-default-pool-56e3af9a-lkrv
web-2212180648-pqz73          1/1       Running   10.8.2.6   gke-migration-tutorial-default-pool-56e3af9a-0ng4
web-2212180648-rrd3b          1/1       Running   10.8.4.3   gke-migration-tutorial-default-pool-56e3af9a-lkrv
web-2212180648-v3b18          1/1       Running   10.8.1.4   gke-migration-tutorial-default-pool-56e3af9a-p9j4

Para migrar esses pods para o novo pool de nós, faça o seguinte:

  1. Demarque o pool de nós existente: esta operação marca os nós no pool de nós existente (default-pool) como não programáveis. O Kubernetes para de programar novos pods para esses nós quando você os marca como não programáveis.

  2. Drene o pool de nós existente: esta operação remove as cargas de trabalho em execução nos nós do pool de nós existente (default-pool) normalmente.

Com as etapas acima, os Pods em execução no pool de nós são encerrados, e o Kubernetes faz a reprogramação deles em outros nodes disponíveis. Nesse caso, os únicos nós disponíveis são aqueles no larger-pool criado na Etapa 3.

Para garantir que o Kubernetes encerre seus aplicativos normalmente, seus contêineres devem manipular o sinal SIGTERM. Use-o para fechar conexões ativas aos clientes e confirmar ou cancelar transações do banco de dados de maneira limpa. No manifesto do pod, você pode usar o campo spec.terminationGracePeriodSeconds para especificar quanto tempo o Kubernetes precisa aguardar antes de eliminar os contêineres no pod. O padrão é de 30 segundos. Leia mais sobre o encerramento de pods na documentação do Kubernetes.

Primeiro, demarque os nós no default-pool. Execute o comando a seguir para ver uma lista de nós nesse pool:

kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool

Em seguida, demarque cada nó executando um comando kubectl cordon NODE (substitua NODE pelos nomes do comando anterior). O comando a seguir itera em cada nó e os marca como não programáveis:

for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool -o=name); do
  kubectl cordon "$node";
done
Saída:
node "gke-migration-tutorial-default-pool-56e3af9a-059q" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-0ng4" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-k6jm" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-lkrv" cordoned
node "gke-migration-tutorial-default-pool-56e3af9a-p9j4" cordoned

Agora, você verá que os nós default-pool têm o status SchedulingDisabled na lista de nós:

kubectl get nodes
Saída:
NAME                                                STATUS                     AGE       VERSION
gke-migration-tutorial-default-pool-56e3af9a-059q   Ready,SchedulingDisabled   1h        v1.5.7
gke-migration-tutorial-default-pool-56e3af9a-0ng4   Ready,SchedulingDisabled   1h        v1.5.7
gke-migration-tutorial-default-pool-56e3af9a-k6jm   Ready,SchedulingDisabled   1h        v1.5.7
gke-migration-tutorial-default-pool-56e3af9a-lkrv   Ready,SchedulingDisabled   1h        v1.5.7
gke-migration-tutorial-default-pool-56e3af9a-p9j4   Ready,SchedulingDisabled   1h        v1.5.7
gke-migration-tutorial-larger-pool-b8ec62a6-2rhk    Ready                      1h        v1.5.7
gke-migration-tutorial-larger-pool-b8ec62a6-4bb2    Ready                      1h        v1.5.7
gke-migration-tutorial-larger-pool-b8ec62a6-7fl0    Ready                      1h        v1.5.7
gke-migration-tutorial-larger-pool-b8ec62a6-cx9q    Ready                      1h        v1.5.7
gke-migration-tutorial-larger-pool-b8ec62a6-hs6p    Ready                      1h        v1.5.7

Em seguida, drene os Pods em cada nó. Para executar a drenagem, use o comando kubectl drain que remove os pods em cada nó.

Você pode executar kubectl drain --force NODE substituindo NODE pela mesma lista de nomes transmitidos ao comando kubectl cordon.

O comando shell a seguir itera cada nó em default-pool e os esvazia removendo pods com um período de encerramento de 10 segundos:

for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=default-pool -o=name); do
  kubectl drain --force --ignore-daemonsets --delete-local-data --grace-period=10 "$node";
done

Quando esse comando for concluído, você verá que os pods estão sendo executados nos nós de larger-pool:

kubectl get pods -o=wide
Saída:
NAME                   READY     STATUS    IP         NODE
web-2212180648-3n9hz   1/1       Running   10.8.9.4   gke-migration-tutorial-larger-pool-b8ec62a6-cx9q
web-2212180648-88q1c   1/1       Running   10.8.7.4   gke-migration-tutorial-larger-pool-b8ec62a6-2rhk
web-2212180648-dlmjc   1/1       Running   10.8.9.3   gke-migration-tutorial-larger-pool-b8ec62a6-cx9q
web-2212180648-hcv46   1/1       Running   10.8.5.4   gke-migration-tutorial-larger-pool-b8ec62a6-hs6p
web-2212180648-n0nht   1/1       Running   10.8.6.4   gke-migration-tutorial-larger-pool-b8ec62a6-7fl0
web-2212180648-s51jb   1/1       Running   10.8.8.4   gke-migration-tutorial-larger-pool-b8ec62a6-4bb2

Etapa 5: excluir o pool de nós antigo

Depois que o Kubernetes reagendar todos os pods em Deployment de web para larger-pool, será seguro excluir default-pool porque ele não será mais necessário. Execute o comando a seguir para excluir o default-pool:

gcloud container node-pools delete default-pool --cluster migration-tutorial

Quando esta operação for concluída, você terá um único pool de nós para seu cluster de contêiner, que é o larger-pool:

gcloud container node-pools list --cluster migration-tutorial
Saída:
NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
larger-pool   n1-highmem-2   100           1.5.7

Como fazer a limpeza

Para evitar cobranças dos recursos usados neste tutorial na conta do Google Cloud Platform:

  • Exclua o cluster de contêiner: nessa etapa, são excluídos os recursos que compõem o cluster de contêiner, como instâncias de computação, discos e recursos de rede.

    gcloud container clusters delete migration-tutorial

A seguir