Kubernetes: a vida de uma lareira

Nota perev. : Este artigo pequeno (mas espaçoso!), Escrito por Michael Hausenblas, da equipe OpenShift da Red Hat, gostou tanto que foi adicionado Ă  nossa base de conhecimento interna do Kubernetes quase imediatamente apĂłs sua descoberta. E como as informaçÔes apresentadas serĂŁo obviamente Ășteis para a comunidade de TI de lĂ­ngua russa, estamos felizes em publicar sua tradução.



Como vocĂȘ pode imaginar, o tĂ­tulo desta publicação Ă© uma referĂȘncia ao desenho animado da Pixar de 1998, “A Bug's Life” (nas bilheterias russas, era chamado de “Adventures of Flick” ou “Life of an Insect” - aproximadamente tradução ) . Kubernetes tem muito em comum com trabalhadores e lares. Analisaremos cuidadosamente o ciclo de vida completo da lareira do ponto de vista prĂĄtico - em particular, as maneiras pelas quais vocĂȘ pode influenciar o comportamento na inicialização e desligamento, bem como as abordagens corretas para verificar o status do aplicativo.

Independentemente de vocĂȘ ter criado sob vocĂȘ mesmo ou, melhor ainda, atravĂ©s de um controlador como Deployment , DaemonSet ou StatefulSet , under pode estar em uma das seguintes fases:

  • Pendente : o servidor da API criou um recurso de pod e o salvou no etcd, mas ainda nĂŁo foi planejado e as imagens de seus contĂȘineres nĂŁo foram recebidas do registro;
  • Em execução (em funcionamento): under foi atribuĂ­do ao nĂł e todos os contĂȘineres foram criados pelo kubelet ;
  • Sucedido (concluĂ­do com sucesso): a operação de todos os contĂȘineres da lareira foi concluĂ­da com ĂȘxito e eles nĂŁo serĂŁo reiniciados;
  • Falha : todos os contĂȘineres na lareira pararam de funcionar e pelo menos um dos contĂȘineres falhou;
  • Desconhecido : o servidor de API nĂŁo conseguiu consultar o status da lareira, geralmente devido a um erro ao interagir com o kubelet .

Ao executar o kubectl get pod , observe que a coluna STATUS pode mostrar outras (exceto essas cinco) mensagens - por exemplo, Init:0/1 ou CrashLoopBackOff . Isso ocorre porque a fase Ă© apenas parte do estado geral da lareira. Uma boa maneira de descobrir o que exatamente aconteceu Ă© executar o kubectl describe pod/$PODNAME e veja a entrada kubectl describe pod/$PODNAME Events: abaixo. Ela exibe uma lista de açÔes relevantes: que a imagem do contĂȘiner foi recebida, foi planejada, o contĂȘiner estĂĄ em um estado "Ă­ntegro" .

Agora dĂȘ uma olhada em um exemplo especĂ­fico do ciclo de vida de uma lareira do inĂ­cio ao fim, conforme mostrado no diagrama a seguir:



O que aconteceu aqui? Os passos sĂŁo os seguintes:

  1. Isso nĂŁo Ă© mostrado no diagrama, mas, no inĂ­cio, um infra-contĂȘiner especial Ă© iniciado e configura os espaços de nomes aos quais os contĂȘineres restantes se unem.
  2. O primeiro contĂȘiner definido pelo usuĂĄrio que inicia Ă© o contĂȘiner init ; pode ser usado para tarefas de inicialização.
  3. Em seguida, o contĂȘiner principal e o gancho pĂłs-partida sĂŁo lançados simultaneamente; no nosso caso, isso acontece apĂłs 4 segundos. Ganchos sĂŁo definidos para cada contĂȘiner.
  4. EntĂŁo, no sĂ©timo segundo, os testes de vivacidade e prontidĂŁo entram em cena novamente para cada contĂȘiner.
  5. No 11Âș segundo, quando o abate Ă© eliminado, um gancho de parada Ă© acionado e o contĂȘiner principal Ă© eliminado apĂłs um perĂ­odo de carĂȘncia . Observe que, na realidade, o processo de conclusĂŁo do pod Ă© um pouco mais complicado.

Como cheguei Ă  sequĂȘncia acima e ao seu tempo? Para fazer isso, usamos a seguinte implantação , criada especificamente para rastrear a ordem dos eventos (nĂŁo Ă© muito Ăștil por si sĂł):

 kind: Deployment apiVersion: apps/v1beta1 metadata: name: loap spec: replicas: 1 template: metadata: labels: app: loap spec: initContainers: - name: init image: busybox command: ['sh', '-c', 'echo $(date +%s): INIT >> /loap/timing'] volumeMounts: - mountPath: /loap name: timing containers: - name: main image: busybox command: ['sh', '-c', 'echo $(date +%s): START >> /loap/timing; sleep 10; echo $(date +%s): END >> /loap/timing;'] volumeMounts: - mountPath: /loap name: timing livenessProbe: exec: command: ['sh', '-c', 'echo $(date +%s): LIVENESS >> /loap/timing'] readinessProbe: exec: command: ['sh', '-c', 'echo $(date +%s): READINESS >> /loap/timing'] lifecycle: postStart: exec: command: ['sh', '-c', 'echo $(date +%s): POST-START >> /loap/timing'] preStop: exec: command: ['sh', '-c', 'echo $(date +%s): PRE-HOOK >> /loap/timing'] volumes: - name: timing hostPath: path: /tmp/loap 

Observe que, para desligar o pod com força quando o contĂȘiner principal estava funcionando, executei o seguinte comando:

 $ kubectl scale deployment loap --replicas=0 

Observamos uma sequĂȘncia especĂ­fica de eventos em ação e agora estamos prontos para seguir em frente - para prĂĄticas no campo do gerenciamento do ciclo de vida da lareira. Eles sĂŁo os seguintes:

  • Use recipientes init para preparar a lareira para a operação normal. Por exemplo, para obter dados externos, crie tabelas no banco de dados ou aguarde a disponibilidade do serviço do qual depende. Se necessĂĄrio, vocĂȘ pode criar muitos contĂȘineres init e todos eles devem ser concluĂ­dos com ĂȘxito antes do lançamento de contĂȘineres regulares.
  • Sempre adicione livenessProbe e readinessProbe . O primeiro Ă© usado pelo kubelet 'ohm para entender se e quando reiniciar o contĂȘiner e a implantação ' ohm para decidir se a atualização sem interrupção foi bem-sucedida. O segundo Ă© usado pelo serviço para decidir a direção do trĂĄfego para o submarino. Se essas amostras nĂŁo forem definidas, o kubelet para ambas assume que elas foram concluĂ­das com ĂȘxito. Isso leva a duas consequĂȘncias: a) a polĂ­tica de reinicialização nĂŁo pode ser aplicada; b) os contĂȘineres na lareira recebem instantaneamente o trĂĄfego do serviço que estĂŁo enfrentando e mesmo se ainda estiverem ocupados com o processo de inicialização.
  • Use ganchos para inicializar adequadamente o contĂȘiner e destruĂ­-lo completamente. Por exemplo, isso Ă© Ăștil no caso de funcionamento de um aplicativo cujo cĂłdigo fonte vocĂȘ nĂŁo tem acesso ou nĂŁo pode modificar, mas que requer alguma inicialização ou preparação para a conclusĂŁo - por exemplo, limpando as conexĂ”es com o banco de dados. Observe que, ao usar o serviço , o desligamento do servidor de API, do controlador de terminal e do kube-proxy pode levar algum tempo (por exemplo, excluindo as entradas correspondentes das tabelas de ip). Portanto, o tĂ©rmino do seu trabalho pode afetar as solicitaçÔes de aplicativos. FreqĂŒentemente, para resolver esse problema, basta um gancho simples com uma chamada de suspensĂŁo.
  • Para necessidades de depuração e para entender em geral por que parou de funcionar, o aplicativo pode gravar em /dev/termination-log , e vocĂȘ pode ver as mensagens usando o kubectl describe pod 
 Essas configuraçÔes padrĂŁo sĂŁo alteradas por meio de terminationMessagePath e / ou usando terminationMessagePolicy na subespecificação - consulte a referĂȘncia da API para obter mais detalhes.

Esta publicação nĂŁo discute inicializadores (alguns detalhes sobre eles podem ser encontrados no final deste material - aprox. Transl. ) . Este Ă© um conceito completamente novo introduzido no Kubernetes 1.7. Os inicializadores trabalham dentro do plano de controle (API Server) em vez de estarem no contexto kubelet e podem ser usados ​​para enriquecer os lares, por exemplo, com contĂȘineres laterais ou imposição de polĂ­ticas de segurança. AlĂ©m disso, os PodPresets nĂŁo foram considerados, que no futuro podem ser substituĂ­dos por um conceito mais flexĂ­vel de inicializadores.

PS do tradutor


Leia também em nosso blog:

Source: https://habr.com/ru/post/pt415393/


All Articles