Implantando aplicativos em vários clusters Kubernetes com o Helm


Como o Dailymotion usa o Kubernetes: implantação de aplicativos


No Dailymotion, começamos a usar o Kubernetes na produção há 3 anos. Mas a implantação de aplicativos em vários clusters ainda é um prazer. Por isso, nos últimos anos, tentamos melhorar nossas ferramentas e fluxos de trabalho.


Por onde começou


Aqui mostramos como implantamos nossos aplicativos em vários clusters Kubernetes em todo o mundo.


Para implantar vários objetos Kubernetes de uma só vez, usamos Helm e todos os nossos gráficos são armazenados em um repositório git. Para implantar a pilha completa de aplicativos de vários serviços, usamos o chamado gráfico generalizado. Em essência, este é um gráfico que declara dependências e permite inicializar a API e seus serviços com um único comando.


Também escrevemos um pequeno script Python em cima do Helm para fazer verificações, criar gráficos, adicionar segredos e implantar aplicativos. Todas essas tarefas são executadas na plataforma de IC central usando a imagem do docker.


Vamos direto ao ponto.


Nota Quando você lê isso, o primeiro candidato a lançamento do Helm 3 já foi anunciado. A versão principal contém todo um conjunto de aprimoramentos projetados para resolver alguns dos problemas que encontramos no passado.

Fluxo de trabalho de desenvolvimento de gráficos


Para aplicativos, usamos ramificação e decidimos aplicar a mesma abordagem aos gráficos.


  • O ramo dev é usado para criar gráficos que serão testados em clusters de desenvolvimento.
  • Quando a solicitação de pool é transferida para o mestre , eles são verificados na preparação.
  • Por fim, criamos uma solicitação de pool para enviar as alterações ao ramo de produtos e aplicá-las na produção.

Cada ambiente possui seu próprio repositório privado que armazena nossos gráficos e usamos o Chartmuseum com APIs muito úteis. Assim, garantimos um rigoroso isolamento entre os ambientes e verificamos os gráficos em condições reais antes de usá-los na produção.



Repositórios de gráficos em diferentes ambientes


É importante notar que, quando os desenvolvedores enviam a ramificação do desenvolvedor, uma versão de seu gráfico é automaticamente enviada ao Chartmuseum do desenvolvedor. Portanto, todos os desenvolvedores usam o mesmo repositório dev, e você precisa indicar cuidadosamente sua versão do gráfico para não usar acidentalmente as alterações de outras pessoas.


Além disso, nosso pequeno script Python verifica os objetos do Kubernetes com as especificações do Kubernetes OpenAPI com o Kubeval antes de publicá-los no Chartmusem.


Fluxo de trabalho de desenvolvimento de gráfico geral



  1. Configurando a tarefa de pipeline de acordo com a especificação gazr.io para controle de qualidade (fiapos, teste de unidade).
  2. Enviando uma imagem do docker com ferramentas Python que implantam nossos aplicativos.
  3. Configurando o ambiente pelo nome da ramificação.
  4. Verifique os arquivos yaml Kubernetes com o Kubeval.
  5. Aumente automaticamente a versão do gráfico e seus gráficos pai (gráficos que dependem da alteração do gráfico).
  6. Enviando um gráfico para o Chartmuseum que corresponde ao seu ambiente

Gerenciamento de diferenças de cluster


Federação de Cluster


Houve um tempo em que usamos a Federação de Cluster do Kubernetes , em que era possível declarar objetos do Kubernetes a partir de um ponto de extremidade da API. Mas houve problemas. Por exemplo, alguns objetos do Kubernetes não puderam ser criados no ponto de extremidade da federação, por isso era difícil manter os objetos combinados e outros objetos para clusters individuais.


Para resolver o problema, começamos a gerenciar clusters de forma independente, o que simplificou bastante o processo (usamos a primeira versão da federação; na segunda, algo poderia mudar).


Plataforma distribuída geograficamente


Agora, nossa plataforma está distribuída em 6 regiões - 3 localmente e 3 na nuvem.



Implantação distribuída


Valores globais do leme


4 valores globais de Helm permitem determinar as diferenças entre os clusters. Para todos os nossos gráficos, há padrões mínimos.


global: cloud: True env: staging region: us-central1 clusterName: staging-us-central1 

Valores globais


Esses valores ajudam a determinar o contexto de nossos aplicativos e são usados ​​para diferentes tarefas: monitoramento, rastreamento, registro, realização de chamadas externas, dimensionamento etc.


  • "Cloud": temos uma plataforma híbrida Kubernetes. Por exemplo, nossa API é implantada nas zonas GCP e em nossos data centers.
  • "Env": alguns valores podem variar para ambientes não funcionais. Por exemplo, definições de recursos e configurações de dimensionamento automático.
  • “Região”: essas informações ajudam a determinar a localização do cluster e podem ser usadas para determinar os pontos de extremidade mais próximos para serviços externos.
  • “ClusterName”: se e quando queremos determinar o valor para um cluster individual.

Aqui está um exemplo concreto:


 {{/* Returns Horizontal Pod Autoscaler replicas for GraphQL*/}} {{- define "graphql.hpaReplicas" -}} {{- if eq .Values.global.env "prod" }} {{- if eq .Values.global.region "europe-west1" }} minReplicas: 40 {{- else }} minReplicas: 150 {{- end }} maxReplicas: 1400 {{- else }} minReplicas: 4 maxReplicas: 20 {{- end }} {{- end -}} 

Exemplo de modelo de leme


Essa lógica é definida no modelo auxiliar para não entupir o Kubernetes YAML.


Anúncio do aplicativo


Nossas ferramentas de implantação são baseadas em vários arquivos YAML. A seguir, é apresentado um exemplo de como declaramos um serviço e sua topologia de escala (número de réplicas) em um cluster.


 releases: - foo.world foo.world: # Release name services: # List of dailymotion's apps/projects foobar: chart_name: foo-foobar repo: git@github.com:dailymotion/foobar contexts: prod-europe-west1: deployments: - name: foo-bar-baz replicas: 18 - name: another-deployment replicas: 3 

Definição de Serviço


Este é um diagrama de todas as etapas que definem nosso fluxo de trabalho de implantação. A etapa final implementa o aplicativo em vários clusters de trabalho simultaneamente.



Etapas de implantação do Jenkins


E os segredos?


Em termos de segurança, mantemos o controle de todos os segredos de vários lugares e os armazenamos no repositório exclusivo do Vault em Paris.


Nossas ferramentas de implantação extraem os valores dos segredos do Vault e, quando chegar a hora da implantação, insira-os no Helm.


Para isso, determinamos o mapeamento entre os segredos no Vault e os segredos que nossos aplicativos precisam:


 secrets: - secret_id: "stack1-app1-password" contexts: - name: "default" vaultPath: "/kv/dev/stack1/app1/test" vaultKey: "password" - name: "cluster1" vaultPath: "/kv/dev/stack1/app1/test" vaultKey: "password" 

  • Identificamos as regras gerais que você deve seguir ao escrever segredos no Vault.
  • Se o segredo se referir a um contexto ou cluster específico , você precisará adicionar uma entrada específica. (Aqui, o contexto do cluster1 tem seu próprio valor para a pilha secreta-app1-senha).
  • Caso contrário, o valor padrão é usado.
  • Para cada item desta lista, um par de valores-chave é inserido no segredo do Kubernetes . Portanto, o padrão secreto em nossos gráficos é muito simples.

 apiVersion: v1 data: {{- range $key,$value := .Values.secrets }} {{ $key }}: {{ $value | b64enc | quote }} {{ end }} kind: Secret metadata: name: "{{ .Chart.Name }}" labels: chartVersion: "{{ .Chart.Version }}" tillerVersion: "{{ .Capabilities.TillerVersion.SemVer }}" type: Opaque 

Problemas e limitações


Trabalhar com vários repositórios


Agora, compartilhamos o desenvolvimento de gráficos e aplicativos. Isso significa que os desenvolvedores precisam trabalhar em dois repositórios git: um para o aplicativo e o segundo para determinar sua implantação no Kubernetes. 2 repositórios git são 2 fluxos de trabalho e é fácil para um novato ficar confuso.


Gerenciar gráficos resumidos é problemático


Como já dissemos, gráficos genéricos são muito convenientes para definir dependências e implantar rapidamente vários aplicativos. Mas usamos --reuse-values para evitar passar todos os valores toda vez que implementamos o aplicativo incluído neste gráfico generalizado.


No fluxo de trabalho de entrega contínua, temos apenas dois valores que mudam regularmente: o número de réplicas e a tag da imagem (versão). Outros valores mais estáveis ​​são alterados manualmente, e isso é bastante complicado. Além disso, um erro na implantação de um gráfico generalizado pode levar a falhas graves, como vimos em nossa própria experiência.


Atualizando vários arquivos de configuração


Quando um desenvolvedor adiciona um novo aplicativo, ele precisa alterar vários arquivos: o anúncio do aplicativo, a lista de segredos, adicionando o aplicativo dependendo se ele está incluído no gráfico generalizado.


Permissões Jenkins muito estendidas no Vault


Agora, temos um AppRole que lê todos os segredos do Vault.


O processo de reversão não é automatizado


Para reverter, você precisa executar o comando em vários clusters, e isso está repleto de erros. Executamos essa operação manualmente para garantir que o identificador de versão correto seja especificado.


Estamos nos movendo em direção ao GitOps


Nosso objetivo


Queremos retornar o gráfico ao repositório do aplicativo que ele implanta.


O fluxo de trabalho será o mesmo do desenvolvimento. Por exemplo, quando uma ramificação é enviada ao assistente, a implantação será iniciada automaticamente. A principal diferença entre essa abordagem e o fluxo de trabalho atual será que tudo será gerenciado no git (o próprio aplicativo e como implantá-lo no Kubernetes).


Existem várias vantagens:


  • Muito mais claro para o desenvolvedor. É mais fácil aprender como aplicar alterações no gráfico local.
  • Uma definição de implantação de serviço pode ser especificada onde está o código de serviço.
  • Gerenciamento da remoção de gráficos generalizados . O serviço terá seu próprio lançamento do Helm. Isso permitirá que você gerencie o ciclo de vida do aplicativo (reversão, atualização) no menor nível, para não afetar outros serviços.
  • Os benefícios do git para gerenciar gráficos são: desfazendo alterações, trilha de auditoria etc. Se você precisar desfazer uma alteração em um gráfico, poderá fazê-lo com o git. A implantação inicia automaticamente.
  • Você pode melhorar o fluxo de trabalho de desenvolvimento com ferramentas como o Skaffold , com as quais os desenvolvedores podem testar alterações em um contexto semelhante à produção.

Migração em dois estágios


Nossos desenvolvedores usam esse fluxo de trabalho há 2 anos, por isso precisamos da migração mais indolor. Portanto, decidimos adicionar um estágio intermediário no caminho para a meta.
O primeiro passo é simples:


  • Mantemos uma estrutura semelhante para configurar a implantação do aplicativo, mas no mesmo objeto denominado DailymotionRelease.

 apiVersion: "v1" kind: "DailymotionRelease" metadata: name: "app1.ns1" environment: "dev" branch: "mybranch" spec: slack_channel: "#admin" chart_name: "app1" scaling: - context: "dev-us-central1-0" replicas: - name: "hermes" count: 2 - context: "dev-europe-west1-0" replicas: - name: "app1-deploy" count: 2 secrets: - secret_id: "app1" contexts: - name: "default" vaultPath: "/kv/dev/ns1/app1/test" vaultKey: "password" - name: "dev-europe-west1-0" vaultPath: "/kv/dev/ns1/app1/test" vaultKey: "password" 

  • 1 release por aplicativo (sem gráficos generalizados).
  • Gráficos no repositório de aplicativos git.

Conversamos com todos os desenvolvedores, então o processo de migração já começou. A primeira fase ainda é controlada usando a plataforma de IC. Em breve irei escrever outro post sobre o segundo estágio: como mudamos para o fluxo de trabalho do GitOps com o Flux . Eu vou lhe contar como nos configuramos e quais dificuldades encontramos (vários repositórios, segredos etc.). Acompanhe as novidades.


Aqui, tentamos descrever nosso progresso no fluxo de trabalho de implantação de aplicativos nos últimos anos, o que levou a pensamentos sobre a abordagem GitOps. Ainda não atingimos a meta e apresentaremos relatórios sobre os resultados, mas agora estamos convencidos de que fizemos isso corretamente quando decidimos simplificar tudo e aproximar os hábitos dos desenvolvedores.

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


All Articles