[Repost] Primeiros passos do K8s | Orquestração de aplicativos com estado - StatefulSet

Iniciando do zero K8s | Orquestração de aplicativos com estado - StatefulSet

https: // www.kubernetes.org.cn/6724.html

 

Autor | Jiuzhu Alibaba Expert Técnico

Este artigo foi compilado na Aula 22 do "Curso Aberto de Tecnologia Nativa do CNCF x Alibaba Cloud".

Siga a conta pública "Alibaba Cloud Native" e responda à palavra-chave "Introdução" para baixar o PPT da série de artigos K8s do zero.

Introdução: A implantação e a entrega de aplicativos com estado sempre foram uma das dificuldades no campo de operação e manutenção de aplicativos. Requisitos de estado comuns, como o estado persistente do disco, cada máquina precisa de uma identificação de rede independente e estável e a certeza da ordem de liberação. Em resposta a esses problemas, o Kubernetes fornece um controlador StatefulSet como uma carga de trabalho para ajudar na implantação e no desembarque de aplicativos com estado no ambiente do K8s.

1. Requisitos "com estado"

Já falamos sobre a implantação como uma ferramenta de gerenciamento de orquestração de aplicativos.Que funções ela fornece para nós?

Como mostrado abaixo:

1.png

  • Primeiro, ele suporta a definição do número esperado de Pods. O Controlador manterá o número de Pods na versão desejada e o número esperado para nós;
  • Segundo, ele suporta a configuração do método de liberação do Pod. Após a conclusão da configuração, o Controlador atualizará o Pod de acordo com a estratégia que damos. Ao mesmo tempo, durante o processo de atualização, também garantirá que o número de Pods inutilizáveis ​​esteja dentro do intervalo que definimos;
  • Terceiro, se encontrarmos problemas durante o processo de lançamento, a Implantação também suportará a reversão de um clique.

Simplificando, o Deployment acredita que todas as mesmas versões dos Pods que gerencia são cópias idênticas. Em outras palavras, da perspectiva do Deployment Controller, todos os Pods da mesma versão, independentemente do aplicativo ou comportamento implantado dentro, são exatamente os mesmos.

Esse recurso é suportado para aplicativos sem estado.E se encontrarmos alguns aplicativos com estado?

Análise de necessidades

Por exemplo, alguns requisitos mostrados na figura abaixo:
2.png

Como todos os requisitos acima não podem ser atendidos pelo Deployment, a comunidade Kubernetes nos fornece um recurso chamado StatefluSet para gerenciar aplicativos com estado.

StatefulSet: controlador para gerenciamento de aplicativos com estado

De fato, muitos aplicativos sem estado na comunidade também são gerenciados pelo StatefulSet.Com o estudo deste artigo, todos também entenderão por que também gerenciamos alguns aplicativos sem estado através do StatefulSet.

3.png

Como mostrado no lado direito da figura acima, os Pods no StatefulSet são todos numerados, começando de 0 até o número de réplicas definidas diminuir em um. Cada Pod possui uma identificação de rede independente: um nome de host, um armazenamento pvc e pv independente. Nesse caso, diferentes Pods no mesmo StatefulSet têm identificações de rede diferentes e seus próprios discos de armazenamento exclusivos, que podem atender às necessidades da maioria dos aplicativos com estado.

Como mostrado no lado direito da imagem acima:

  • Primeiro, cada Pod terá um número de pedido, que será criado, excluído e atualizado de acordo com o número;
  • Em segundo lugar, configurando um serviço decapitado, cada Pod possui um identificador de rede exclusivo (nome do host);
  • Terceiro, configurando o modelo pvc, que é o modelo pvc, cada Pod possui um ou mais discos de armazenamento pv;
  • Finalmente, há suporte para um certo número de versões em escala de cinza. Por exemplo, agora existem três cópias do StatefulSet, podemos especificar para atualizar apenas uma ou duas delas, ou até três para a nova versão. Dessa forma, para atingir o objetivo de atualização da escala de cinza.

Segundo, interpretação de casos de uso

Criação de exemplo StatefulSet

4.png

O lado esquerdo da figura acima é uma configuração de Serviço. Ao configurar o Serviço sem cabeça, queremos atingir o objetivo: esperar que o Pod no StatefulSet tenha uma identificação de rede independente. O nome do serviço aqui é chamado nginx.

O lado direito da figura acima é uma configuração StatefulSet.Há um serviceName na especificação também chamado nginx. Use este serviceName para especificar a qual serviço este StatefulSet corresponde.

Existem vários outros campos familiares nessa especificação, como seletor e modelo. selector é um seletor de rótulo.A lógica de seleção de rótulo definida pelo seletor deve corresponder aos rótulos nos metadados no modelo, incluindo app: nginx. Defina um contêiner nginx no modelo, a versão da imagem usada por esse contêiner é a versão alpina e a porta exposta 80 é usada como um serviço da web.

Finalmente, um volumeMounts é definido em template.spec, esse volumeMounts não é de um Volumes na especificação, mas de volumeClaimTemplates, que é o modelo de pvc. Definimos um nome de pvc chamado www-storage no modelo de pvc. Este nome de pvc, também escreveremos volumeMounts como um nome de volume, montado no diretório / usr / share / nginx / html. Dessa forma, cada pod possui um pvc independente e é montado no diretório correspondente no contêiner.

Serviço, estado StatefulSet

5.png

Depois de criar os dois objetos acima, podemos ver que o recurso Service nginx foi criado com sucesso por meio do comando get.

Ao mesmo tempo, é possível ver, examinando os pontos de extremidade, que esse back-end registrou três IPs e portas, que correspondem aos IPs do Pod e as portas correspondem às 80 portas configuradas na especificação anterior.

Por fim, obtenha sts (abreviação de StatefulSet) nginx-web. Como você pode ver no resultado, há uma coluna chamada PRONTA com um valor de 3/3. O denominador 3 é o número desejado no StatefulSet e o numerador 3 indica que o Pod alcançou o número desejado de estados em READY.

Pod, status de PVC

O pod de obtenção na figura abaixo mostra que os três Pods estão no estado Em execução e estão PRONTOS. Seu IP é o endereço do terminal visto anteriormente.

6.png

Você pode ver o nome de NAME através de get pvc, o prefixo é www-storage, o meio é nginx-web e o sufixo é um número de série. Por meio da análise, podemos saber que www-storage é o nome definido em volumeClaimTemplates, o nome definido no meio é StatefulSet e o número de série no final corresponde ao número de série do Pod, ou seja, os três PVCs são vinculados por três Pods. Dessa forma, diferentes pods desfrutam de diferentes PVCs; o PVC também ligará um PV correspondente para atingir o objetivo de vincular diferentes PVs a diferentes Pods.

Versão do pod

7.png

Aprendemos anteriormente que o Deployment usa o ReplicaSet para gerenciar a versão do Pod e o número esperado de Pods, mas no StatefulSet, o StatefulSet Controller gerencia os Pods subordinados; portanto, o StatefulSet usa o rótulo do Pod para identificar a versão desse Pod, chamada aqui controlador-revisão-hash. Esse rótulo é semelhante ao hash do modelo do Pod injetado pelo Deployment e StatefulSet no Pod.

Conforme mostrado na figura acima, o controller-revision-hash é visualizado no get pod. O hash aqui é a versão do modelo correspondente à primeira criação do Pod. Você pode ver que o sufixo é 677759c9b8. Vamos gravar aqui primeiro e, em seguida, fazer a atualização do Pod e, em seguida, ver se o controlador-revisão-hash será alterado.

Espelho de atualização

8.png

Executando o comando acima, você pode ver que na configuração StatefulSet abaixo da imagem acima, a imagem no StatefulSet foi atualizada para a nova versão da linha principal.

Ver o status da nova versão

9.png

Ao consultar o hash de revisão por meio do comando get pod, é possível ver que o controlador-revisão-hash por trás dos três pods foi atualizado para o novo hash de revisão, que mais tarde se tornará 7c55499668. Durante o tempo de criação desses três Pods, pode-se descobrir que o Pod com o número de série 2 é o mais antigo e, em seguida, os números de série são 1 e 0. Isso significa que, durante o processo de atualização, a sequência de atualização real é 2-1-0, e o Pod é atualizado gradualmente para a nova versão por uma ordem inversa, e o Pod atualizado também reutiliza o PVC usado pelo Pod anterior. Portanto, os dados no disco de armazenamento PV ainda serão montados no novo Pod.

O canto superior direito da figura acima são os dados vistos no status do StatefulSet.Existem vários campos importantes:

  • currentReplica: indica o número da versão atual
  • currentRevision: indica o número da versão atual
  • updateReplicas: indica o número de novas versões
  • updateRevision: indica o número da versão a ser atualizada

Obviamente, você também pode ver que currentReplica e updateReplica, assim como currentRevision e updateRevision, são os mesmos, o que significa que todos os Pods foram atualizados para a versão necessária.

3. Demonstração da operação

Arquivo de orquestração StatefulSet

Primeiro de tudo, aqui foi conectado a um cluster do Alibaba Cloud, existem três nós no cluster.
10.png

Agora, para criar um StatefulSet e o Serviço correspondente, primeiro observe o arquivo de layout correspondente.
11.png

Como mostra o exemplo na figura acima, o nginx correspondente ao serviço expõe a porta 80 ao mundo externo. Os metadados na configuração StatefulSet definem o nome como nginx-web; os contêineres no modelo definem as informações da imagem e, finalmente, definem um volumeClaimTemplates como o modelo PVC.

Comece a criar

12.png

Após executar o comando acima, criamos com êxito Service e StatefulSet. Através do get pod, você pode ver que o pod criado primeiro tem um número de série 0; através do get pvc, você pode ver que o PVC com número de série 0 foi vinculado ao PV.

13.png

O Pod com o número de sequência 0 já foi criado e o status é ContainerCreating.

14.png

Quando o Pod com o número de série 0 é criado, o Pod com o número de série 1 começa a ser criado e, em seguida, verifica se o novo PVC também foi criado com sucesso, seguido pelo Pod com o número de série 2.

15.png

Você pode ver que antes de cada Pod ser criado, um PVC é criado. Depois que o PVC é criado, o Pod se liga ao PV a partir do estado Pendente, torna-se ContainerCreating e, finalmente, atinge Running.

Exibir status

Em seguida, verifique o estado de StatefulSet através do kubectl get sts nginx-web -o yaml.

16.png

Conforme mostrado na figura acima, o número esperado de réplicas é 3, o número disponível atualmente é 3 e a versão mais recente é alcançada.

17.png

Em seguida, observe Serviço e terminais, você pode ver que a Porta de serviço é 80 e o terminal possui três endereços IP correspondentes.

18.png

Venha para obter pod novamente, você pode ver que os três pod correspondem aos endereços IP dos pontos de extremidade acima.

Os resultados das operações acima são: três PVCs e três Pods atingiram o estado desejado e, no status relatado pelo StatefulSet, há três réplicas e currentReplicas.

Operação de atualização

19.png

Aqui, novamente, kubectl set image é uma expressão fixa para declarar imagens; StatefulSet indica um tipo voluntário; nginx-web é o nome do recurso; nginx = nginx: mainline, nginx antes do sinal de igual é o nome do contêiner que definimos no modelo e o último nginx: mainline é a versão da imagem que você deseja atualizar.

Por meio do comando acima, a imagem no StatefulSet foi atualizada com êxito para a nova versão.

20.png

Observando o status por meio do pod pod, nginx-web-1 e nginx-web-2 entraram no estado Em execução. O controlador-revisão-hash correspondente já é uma nova versão. Em seguida, o pod de nginx-web-0, o pod antigo foi excluído e o novo pod ainda está no estado Criando.

21.png

Verifique o status novamente, todos os Pods já estão no status Running.

22.png

Observando as informações do StatefulSet, a currentRevision definida no status no StatefulSet foi atualizada para uma nova versão, indicando que os três Pods que o StatefulSet adquiriu entraram na nova versão.

23.png

Como verificar se esses três Pods ainda reutilizam o logotipo da rede e o disco de armazenamento anteriores?

De fato, o nome do host configurado pelo serviço sem cabeçalho é vinculado apenas ao nome do Pod, portanto, desde que o nome do Pod atualizado seja o mesmo que o antigo nome do Pod, a ID da rede usada pelo Pod anterior pode ser usada.

Com relação aos discos de armazenamento, você pode ver o status dos PVCs na figura acima. O tempo de criação deles não mudou. É o momento em que o Pod foi criado pela primeira vez, agora o Pod atualizado usa o PVC usado no Pod antigo.

24.png

Por exemplo, você pode visualizar um dos Pods. Este Pod também possui um volume declarado.O nome www-storage-nginx-web-0 no persistentVolumeClaim corresponde ao PVC com o número de série 0 visto na lista de PVC. Usado por vagens antigos. Durante o processo de atualização, o Controlador exclui o antigo Pod e cria um novo Pod com o mesmo nome.O novo Pod ainda reutiliza o PVC usado pelo antigo Pod.

Dessa maneira, o objetivo do armazenamento em rede pode ser reutilizado antes e após a atualização.

Quatro, projeto de arquitetura

Modo de Gerenciamento

StatefulSet pode criar três tipos de recursos.

  • O primeiro recurso: ControllerRevision

Por meio desse recurso, o StatefulSet pode gerenciar facilmente diferentes versões dos modelos de modelo.

Por exemplo: Para o nginx mencionado acima, a primeira versão do modelo no início da criação criará uma ControllerRevision correspondente. Quando a versão da imagem é modificada, o StatefulSet Controller cria uma nova ControllerRevision.Você pode entender que cada ControllerRevision corresponde a cada versão do Template e também a cada versão do hash ControllerRevision. De fato, o hash ControllerRevision definido no rótulo do Pod é o nome de ControllerRevision. Através deste recurso, o StatefulSet Controller para gerenciar diferentes versões dos recursos do modelo.

  • O segundo recurso: PVC

Se volumeClaimTemplates for definido no StatefulSet, o StatefulSet criará um PVC com base nesse modelo antes de criar o Pod e adicionará o PVC ao volume do Pod.

Se o usuário definir volumeClaimTemplates no modelo de pvc da especificação, StatefulSet cria um PVC de acordo com o modelo antes de criar o Pod e o adiciona ao volume correspondente ao Pod. Obviamente, você não pode definir o modelo de pvc na especificação; o Pod criado não montará um único pv.

  • O terceiro recurso: Pod

StatefulSet cria, exclui e atualiza os Pods em sequência, e cada Pod possui um número de série exclusivo.
25.png

Conforme mostrado na figura acima, o StatefulSet Controller possui três recursos: ControllerRevision, Pod, PVC.

A diferença aqui é que a versão atual do StatefulSet adicionará apenas OwnerReference em ControllerRevision e Pod, mas não adicionará OwnerReference em PVC. Conforme mencionado na série anterior de artigos, o recurso com OwnerReference excluirá os recursos subordinados em cascata por padrão quando o recurso sob gerenciamento for excluído. Portanto, depois que o StatefulSet for excluído por padrão, o ControllerRevision e o Pod criados pelo StatefulSet serão excluídos, mas o PVC não será excluído em cascata porque o OwnerReference não será gravado no PVC.

Controlador StatefulSet

26.png

A figura acima mostra o fluxo de trabalho do controlador StatefulSet.Vamos apresentar brevemente o fluxo de trabalho inteiro.

Primeiro, registre o manipulador de eventos do Informer para lidar com as alterações de StatefulSet e Pod. Na lógica do controlador, toda vez que um StatefulSet ou Pod muda, ele encontra o StatefulSet correspondente e o coloca na fila. Imediatamente após ser retirada da fila para processamento, a primeira operação é Revisão de Atualização, ou seja, verifique primeiro o modelo no StatefulSet atual, se há uma ControllerRevision correspondente. Caso contrário, significa que o modelo foi atualizado e o Controller criará uma nova versão da Revisão, e haverá um novo número de versão do hash ControllerRevision.

Em seguida, o controlador retira todos os números de versão e os classifica de acordo com o número de série. Durante esse processo de classificação, se houver um Pod ausente, ele será criado de acordo com o número de série; se houver excesso de Pod, ele será excluído de acordo com o número de série. Quando é garantido que o número de Pods e números de série do Pod atenda ao número de réplicas, o Controlador verificará se o Pod precisa ser atualizado. Em outras palavras, a diferença entre essas duas etapas é que os pods do Manger podem verificar se todos os pods atendem ao número de série; e a última atualização para verificar se a versão desejada do pod atende aos requisitos e a atualização por número de série.

Atualização em ordem O processo de atualização é mostrado na figura acima.De fato, esse processo é relativamente simples, ou seja, a exclusão do Pod. Depois de excluir o Pod, na verdade, é o próximo evento de acionamento.Depois que o Controlador obtém esse sucesso, ele descobre que o Pod está faltando e, em seguida, cria um novo Pod a partir do pod do Manger da etapa anterior em ordem. Depois disso, o Controlador fará um status de atualização, que é a informação de status que foi vista através da linha de comando antes.

Durante todo esse processo, o StatefulSet alcança a capacidade de gerenciar aplicativos com estado.

Simulação de expansão de capacidade

27

Suponha que a configuração inicial das réplicas StatefulSet seja 1, existe um Pod0. Depois de modificar as réplicas de 1 a 3., na verdade, criamos o Pod1 primeiro. Por padrão, aguardamos o status do Pod1 READY antes de criar o Pod2.

Como você pode ver na figura acima, os Pods em cada StatefulSet são criados a partir do número de sequência 0. Portanto, um StatefulSet com réplicas N é criado com um número de sequência de Pod [0, N), 0 é uma curva aberta e N é uma curva fechada, ou seja, quando N> 0, os números de sequência são de 0 a N-1.

Estratégia de gerenciamento de expansão

28.png

Alguns alunos podem ter perguntas: se eu não quiser criar e excluir de acordo com o número de série, o StatefulSet também suporta outra lógica de criação e exclusão, e é por isso que algumas pessoas na comunidade também gerenciam aplicativos sem estado por meio do StatefulSet. Sua vantagem é que ele pode ter uma identificação e armazenamento de rede exclusivos e também pode ser expandido e reduzido de maneira simultânea.

Existe um campo no StatefulSet.spec chamado campo podMangementPolicy.As estratégias opcionais desse campo são OrderedReady e Parallel, que é o primeiro por padrão.

Como no exemplo que acabamos de criar, podMangementPolicy não está definido na especificação. Em seguida, o controlador assume como padrão OrderedReady como estratégia e, no caso de OrderedReady, a expansão e a contração são estritamente executadas na ordem de Order. Você deve aguardar o estado do Pod anterior estar Pronto antes de expandir o próximo Pod. Ao diminuir, exclua na ordem inversa e exclua o número da sequência de grande para pequeno.

Por exemplo, ao expandir de Pod0 para Pod0, Pod1 e Pod2 no lado direito da figura acima, você deve primeiro criar o Pod1 e aguardar o Pod1 Pronto para criar o Pod2. De fato, existe uma possibilidade: por exemplo, ao criar o Pod1, o Pod0 pode se tornar o estado NotReady por algum motivo, que pode ser a causa da máquina host ou o motivo do próprio aplicativo. No momento, o Controlador não criará o Pod2, portanto, não apenas o Pod anterior que criamos precisa estar Pronto, mas todos os Pods anteriores devem estar Prontos e, em seguida, o próximo Pod será criado. No exemplo acima, se você deseja criar o Pod2, o Pod0 e o Pod1 devem estar prontos.

Outra estratégia é chamada Parallel. Como o nome indica, é expandir e encolher em paralelo.Você não precisa esperar o Pod anterior estar pronto ou excluí-lo antes de processar o próximo.

Pós-simulação

29.png

Supondo que o StatefulSet template1 aqui corresponda à Revisão1 lógica, os três Pods no StatefulSet pertencem à versão Revision1. Depois de modificarmos o modelo, como a imagem, o Controlador atualizou os Pods um por um na ordem inversa. Na figura acima, você pode ver que o Controller criou pela primeira vez uma Revisão2, correspondente à criação de um recurso como ControllerRevision2, e o nome do Resource ControllerRevision2 como um novo hash de Revisão. Depois de atualizar o Pod2 para a nova versão, exclua o Pod0 e o Pod1 um por um e, em seguida, crie o Pod0 e o Pod1.

Sua lógica é realmente muito simples. Durante o processo de atualização, o Controlador excluirá o Pod com o número de série mais alto e atenderá às condições. Em seguida, após a exclusão, na próxima vez em que o Controlador se reconciliar, ele descobrirá que o Pod com esse número de série está ausente e seguirá a nova versão. Crie o Pod.

Análise de campo de especificação

30.png

Primeiro, observe os primeiros campos da especificação: Replica e Selector são os campos com os quais estamos mais familiarizados.

  • A réplica é principalmente a quantidade esperada;
  • Selector é um seletor de eventos e deve corresponder às condições definidas em spec.template.metadata.labels;
  • Modelo: modelo de pod, que define o modelo de informações básicas do pod a ser criado;
  • VolumeClaimTemplates: lista de modelos de PVC. Se isso for definido na especificação, o PVC será criado antes do modelo de Pod. Após a criação do PVC, o nome do PVC criado é injetado no Pod criado de acordo com o Modelo como um volume.

31.png

  • ServiceName: o nome correspondente ao serviço sem cabeça. Obviamente, se alguém não precisar dessa função, o Serviço receberá um valor inexistente e o Controlador não fará a verificação, para que você possa escrever um NomeDoServiço falso. No entanto, é recomendável configurar um serviço sem cabeça para cada serviço, independentemente de o Pod no StatefulSet exigir uma identificação de rede;
  • PodMangementPolicy: Estratégia de gerenciamento de pod. Como mencionado anteriormente, as estratégias opcionais para este campo são OrderedReady e Parallel, que é a primeira por padrão;
  • UpdataStrategy: Estratégia de atualização do pod. Esta é uma estrutura, descrita em detalhes abaixo;
  • RevisionHistoryLimit: limite o número de ControllerRevisions para manter o histórico (o padrão é 10). Deve-se observar que, na versão clara aqui, não deve haver Pod relacionado a essas versões; se ainda houver Pods nesta versão, este ControllerRevision não pode ser excluído.

Análise de campo da estratégia de atualização

32.png

No lado direito da imagem acima, você pode ver que StatefulSetUpdateStrategy possui um campo de tipo, que define dois tipos: um é RollingUpdate e outro é OnDelete.

  • RollingUpdate é realmente um pouco semelhante à atualização em Implantação, que é atualizar de acordo com o método de atualização sem interrupção;
  • O OnDelete é atualizado quando é excluído e é chamado para proibir a atualização ativa.O Controlador não atualiza ativamente os Pods sobreviventes, mas através do OnDelete. Por exemplo, atualmente existem três Pods antigos, mas a estratégia de atualização é OnDelete; portanto, ao atualizar o espelho nas especificações, o Controller não atualizará os três Pods para a nova versão, um por um, mas quando reduzirmos a réplica, o Controller primeiro Exclua o Pod. Quando expandirmos a capacidade da próxima vez, o Controlador expandirá a nova versão do Pod.

No RollingUpdateStatefulSetSetStrategy, você pode ver que há um campo chamado Partition. Esta partição significa que o número de pods na versão antiga é mantido durante a atualização sem interrupção. Muitos estudantes que acabaram de concluir o StatefulSet podem pensar que esse é o número de novas versões da escala de cinza, o que está errado.

Por exemplo: suponha que atualmente exista um StatefulSet com réplicas de 10. Quando atualizamos a versão, se a Partição for 8, isso não significa que precisamos atualizar os 8 Pods para a nova versão, mas que precisamos manter os 8 Pods como a versão antiga. , Atualize apenas 2 novas versões como escala de cinza. Quando a réplica é 10, o número de série do Pod a seguir é [0,9); portanto, quando configuramos a Partição para 8, na verdade mantemos [0,7) esses 8 Pods são versões antigas, apenas [8,9) Digite a nova versão.

Para resumir, suponha réplicas = N, Partição = M (M

V. Resumo desta seção

Este é o final do conteúdo principal deste artigo, aqui está um breve resumo para todos:

    • StatefulSet é uma carga de trabalho comum no Kubernetes, cujo objetivo inicial é implantar aplicativos com estado, mas também suporta a implantação de aplicativos sem estado;
    • Diferentemente da implantação, o StatefulSet opera diretamente o Pod para expandir / contratar / publicar e não é controlado por outras cargas de trabalho como o ReplicaSet;
    • As características do StatefulSet são: suporte para cada PVC exclusivo do Pod, ter uma identificação de rede exclusiva e também pode reutilizar o PVC e a identificação de rede após o lançamento da atualização;

Acho que você gosta

Origin www.cnblogs.com/jinanxiaolaohu/p/12503531.html
Recomendado
Clasificación