Implementações seguras com o Config Sync

Este documento mostra aos operadores de clusters e aos administradores da plataforma como implementar alterações em vários ambientes de forma segura através da sincronização de configuração. Esta abordagem pode ajudar a evitar erros que afetam todos os seus ambientes em simultâneo.

O Config Sync permite-lhe gerir clusters únicos, clusters multi-inquilinos e configurações do Kubernetes de vários clusters através de ficheiros armazenados num repositório Git.

As configurações podem representar várias coisas, incluindo o seguinte:

O Config Sync é especialmente adequado para implementar configurações, políticas e cargas de trabalho necessárias para executar a plataforma que cria com base no Google Kubernetes Engine, por exemplo, agentes de segurança, agentes de monitorização e gestores de certificados.

Embora possa implementar aplicações viradas para o utilizador com a sincronização de configuração, não recomendamos a associação do respetivo ciclo de vida de lançamento ao ciclo de vida de lançamento das cargas de trabalho administrativas mencionadas anteriormente. Em alternativa, recomendamos que use uma ferramenta dedicada à implementação de aplicações, como uma ferramenta de implementação contínua, para que as equipas de aplicações possam ser responsáveis pelo respetivo calendário de lançamento.

A sincronização de configuração é um produto poderoso que pode gerir muitos elementos, pelo que precisa de restrições para evitar erros com um grande impacto. Este documento descreve vários métodos para criar restrições. A primeira secção aborda as implementações faseadas e a segunda secção foca-se nos testes e validações. A terceira secção mostra como monitorizar as suas implementações.

Implementar implementações faseadas com o Config Sync

Num ambiente com vários clusters, não recomendamos que aplique uma alteração de configuração em todos os clusters ao mesmo tempo. Uma implementação faseada, cluster a cluster, é muito mais segura porque reduz o potencial impacto de qualquer erro.

Existem várias formas de implementar implementações faseadas com o Config Sync:

  • Use commits ou etiquetas do Git para aplicar manualmente as alterações que quer aos clusters.
  • Use ramificações do Git para aplicar automaticamente as alterações quando estas forem unidas. Pode usar ramos diferentes para diferentes grupos de clusters.
  • Use objetos ClusterSelector e NamespaceSelector para aplicar seletivamente alterações a subgrupos de clusters ou espaços de nomes.

Todos os métodos de implementações faseadas têm vantagens e desvantagens. A tabela seguinte mostra quais destes métodos pode usar em simultâneo:

Compatibilidade Commits ou etiquetas do Git Ramos do Git Seletores de clusters Seletores de espaço de nomes
Commits ou etiquetas do Git Não compatível Compatível Compatível
Ramos do Git Não compatível Compatível Compatível
Seletores de clusters Compatível Compatível Compatível
Seletores de espaço de nomes Compatível Compatível Compatível

A seguinte árvore de decisões pode ajudar a decidir quando usar um dos métodos de implementação faseada.

Árvore de decisões para métodos de implementação.

Use commits ou etiquetas Git

Em comparação com os outros métodos de implementação gradual, a utilização de commits ou etiquetas do Git oferece o maior controlo e é a mais segura. Pode usar a página de sincronização de configuração na Google Cloud consola na consola para atualizar vários clusters em simultâneo. Use este método se quiser aplicar alterações aos seus clusters um a um e controlar exatamente quando isto acontece.

Neste método, "fixa" cada cluster a uma versão específica (um commit ou uma etiqueta) do seu repositório. Este método é semelhante a usar a confirmação do Git como uma etiqueta de imagem do contentor. Implementa este método especificando a confirmação, a etiqueta ou o hash no campo spec.git.revision do RootSync ou do RepoSync recurso personalizado.

Se gerir os seus recursos personalizados RootSync ou RepoSync com uma ferramenta como o Kustomize, pode reduzir a quantidade de trabalho manual necessário para as implementações. Com esta ferramenta, só tem de alterar o parâmetro revision num único local e, em seguida, aplicar seletivamente o novo recurso personalizado RootSync ou RepoSync aos seus clusters na ordem e ao ritmo que escolher.

Além disso, pode usar a Google Cloud consola para atualizar o parâmetro revision para vários clusters pertencentes à mesma frota em simultâneo. No entanto, se tiver um sistema automatizado para atualizar as suas configurações, não recomendamos que use a consola para fazer alterações de configuração. Google Cloud

Por exemplo, a seguinte definição RootSync configura o Config Sync para usar a etiqueta 1.2.3:

apiVersion: configsync.gke.io/v1
kind: RootSync
metadata:
  name: root-sync
  namespace: config-sync-system
spec:
  sourceType: git
  sourceFormat: unstructured
  git:
    repo: git@example.com:gke/config-sync.git
    revision: 1.2.3
    auth: ssh

Se aplicar esta configuração ao seu cluster, o Config Sync usa a etiqueta 1.2.3 do repositório example.com:gke/config-sync.git.

Para atualizar um cluster, altere o campo spec.git.revision para o novo valor do cluster. Isto permite-lhe definir que clusters são atualizados e quando. Se precisar de reverter uma alteração, altere o campo spec.git.revision novamente para o respetivo valor anterior.

O diagrama seguinte ilustra o processo de implementação deste método. Primeiro, confirma as alterações ao repositório do Config Sync e, em seguida, atualiza as definições do RootSync em todos os clusters:

Processo de implementação para commits e etiquetas do Git.

Recomendamos que efetue as seguintes ações:

  • Use IDs de commits do Git em vez de etiquetas. Devido à forma como o Git funciona, tem uma garantia de que nunca vão mudar. Por exemplo, um git push --force não pode alterar o commit que o Config Sync está a usar. Esta abordagem é útil para fins de auditoria e para acompanhar a confirmação que está a usar nos registos. Além disso, ao contrário do que acontece com as etiquetas, não existe um passo adicional para confirmar os IDs.
  • Se preferir usar etiquetas Git em vez de IDs de consolidação do Git, pode proteger as suas etiquetas se estiver a usar uma solução Git que suporte proteção.
  • Se quiser atualizar vários clusters ao mesmo tempo, pode fazê-lo na Google Cloud consola. Para atualizar vários clusters de uma só vez, têm de fazer parte da mesma frota (e estar no mesmo projeto).

Use ramos Git

Se quiser que as alterações sejam aplicadas aos clusters assim que forem unidas no seu repositório Git, configure o Config Sync para usar ramificações Git em vez de commits ou etiquetas. Neste método, cria vários ramos de longa duração no seu repositório Git e configura o Config Sync em diferentes clusters para ler a respetiva configuração de ramos diferentes.

Por exemplo, um padrão simples tem dois ramos:

  • Um ramo staging para clusters de não produção.
  • Um ramo main para clusters de produção.

Para clusters de não produção, crie o objeto RootSync ou RepoSync com o campo spec.git.branch definido como staging. Para clusters de produção, crie o objeto RootSync ou RepoSync com o parâmetro spec.git.branch definido como main.

Por exemplo, a seguinte definição de RootSync configura o Config Sync para usar o ramo main:

apiVersion: configsync.gke.io/v1
kind: RootSync
metadata:
  name: root-sync
  namespace: config-sync-system
spec:
  git:
    repo: git@example.com:gke/config-sync.git
    branch: main
    auth: ssh

O diagrama seguinte ilustra o processo de implementação deste método:

Processo de implementação de ramos do Git.

Pode adaptar este padrão a necessidades específicas, usando mais de dois ramos ou usando ramos mapeados para algo que não sejam ambientes. Se precisar de reverter uma alteração, use o comando git revert para criar uma nova confirmação na mesma ramificação que reverta as alterações da confirmação anterior.

Recomendamos que efetue as seguintes ações:

  • Quando trabalhar com vários clusters, use, pelo menos, dois ramos do Git para ajudar a distinguir entre clusters de produção e não de produção.
  • A maioria das soluções Git permite-lhe usar a funcionalidade de ramos protegidos para impedir eliminações ou alterações não revistas desses ramos. Para mais informações, consulte a documentação do GitHub, GitLab e Bitbucket.

Use objetos ClusterSelector e NamespaceSelector

As ramificações do Git são uma boa forma de fazer uma implementação faseada de alterações em vários clusters que, eventualmente, vão ter todos as mesmas políticas. No entanto, se quiser implementar uma alteração apenas num subconjunto de clusters ou de espaços de nomes, use os objetos ClusterSelector e NamespaceSelector. Estes objetos têm um objetivo semelhante: permitem-lhe aplicar objetos apenas a clusters ou espaços de nomes que tenham etiquetas específicas.

Por exemplo:

  • Ao usar objetos ClusterSelector, pode aplicar políticas diferentes a clusters, consoante o país em que se encontram, para vários regimes de conformidade.
  • Ao usar objetos NamespaceSelector, pode aplicar políticas diferentes a espaços de nomes usados por uma equipa interna e por um fornecedor externo.

Os objetos ClusterSelector e NamespaceSelector também lhe permitem implementar metodologias de teste e lançamento avançadas, como as seguintes:

  • Lançamentos canary de políticas, em que implementa uma nova política num pequeno subconjunto de clusters e espaços de nomes durante um longo período para estudar o impacto da política.
  • Testes A/B, em que implementa diferentes versões da mesma política em diferentes clusters para estudar a diferença do impacto das versões da política e, em seguida, escolhe a melhor para implementar em todos os locais.

Por exemplo, imagine uma organização com vários clusters de produção. A equipa da plataforma já criou duas categorias de clusters de produção, denominadas canary-prod e prod, através de objetos Cluster e ClusterSelector (consulte o artigo Use ClusterSelectors).

A equipa da plataforma quer implementar uma política com o Policy Controller para aplicar a presença de uma etiqueta de equipa nos espaços de nomes, de modo a identificar a que equipa pertence cada espaço de nomes. Já implementaram uma versão desta política no modo de teste e agora querem aplicá-la a um pequeno número de clusters. Usando objetos ClusterSelector, criam dois recursos K8sRequiredLabels diferentes que são aplicados a diferentes clusters.

  • O recurso K8sRequiredLabels é aplicado a clusters do tipo prod, com um parâmetro enforcementAction definido como dryrun:

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sRequiredLabels
    metadata:
      name: ns-must-have-team
      annotations:
        configmanagement.gke.io/cluster-selector: prod
    Spec:
      enforcementAction: dryrun
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Namespace"]
      parameters:
        labels:
          - key: "team"
    
  • O recurso K8sRequiredLabels é aplicado a clusters do tipo canary-prod, sem o parâmetro enforcementAction, o que significa que a política é efetivamente aplicada:

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sRequiredLabels
    metadata:
      name: ns-must-have-team
      annotations:
        configmanagement.gke.io/cluster-selector: canary-prod
    spec:
      match:
        kinds:
          - apiGroups: [""]
        kinds: ["Namespace"]
      parameters:
        labels:
          - key: "team"
    

A anotação configmanagement.gke.io/cluster-selector permite à equipa aplicar a política apenas em clusters do tipo canary-prod, impedindo que quaisquer efeitos secundários não intencionais se propaguem a toda a frota de produção. Para mais informações sobre a funcionalidade de teste de execução do Policy Controller, consulte o artigo sobre a criação de restrições.

Recomendamos que efetue as seguintes ações:

  • Use objetos ClusterSelector e NamespaceSelector se precisar de aplicar uma alteração de configuração apenas a um subconjunto de clusters ou espaços de nomes indefinidamente ou durante muito tempo.
  • Se implementar uma alteração através de seletores, tenha muito cuidado. Se usar commits do Git, qualquer erro afeta apenas um cluster de cada vez, porque está a implementar cluster a cluster. No entanto, se usar ramificações do Git, qualquer erro pode afetar todos os clusters que usam essa ramificação. Se usar seletores, o erro pode afetar todos os clusters de uma só vez.

Implementar revisões, testes e validações

Uma vantagem do Config Sync é que gere tudo de forma declarativa: recursos do Kubernetes, recursos da nuvem e políticas. Isto significa que os ficheiros num sistema de gestão de controlo de origem representam os recursos (ficheiros Git, no caso da sincronização de configuração). Esta característica permite-lhe implementar fluxos de trabalho de desenvolvimento que já usa para o código-fonte de uma aplicação: revisões e testes automatizados.

Implemente críticas

Uma vez que o Config Sync se baseia no Git, pode usar a sua solução Git preferida para alojar o repositório do Config Sync. A sua solução Git tem provavelmente uma funcionalidade de revisão de código que pode usar para rever as alterações feitas ao repositório do Config Sync.

As práticas recomendadas para rever as alterações ao seu repositório são as mesmas que as de uma revisão de código normal, como se segue:

Devido à sensibilidade da base de código do Config Sync, também recomendamos que, se possível com a sua solução Git, faça as seguintes configurações:

Ao usar estas funcionalidades diferentes, pode aplicar aprovações para cada pedido de alteração à sua base de código. Por exemplo, pode garantir que cada alteração é aprovada, pelo menos, por um membro da equipa da plataforma (que opera a frota de clusters) e por um membro da equipa de segurança (que é responsável por definir e implementar políticas de segurança).

Recomendamos a seguinte ação:

  • Aplique revisões por pares no seu repositório e proteja os ramos Git usados pelos seus clusters.

Implemente testes automatizados

Uma prática recomendada comum quando trabalha num código base é implementar a integração contínua. Isto significa que configura testes automatizados para serem executados quando um pedido de alteração é criado ou atualizado. Os testes automatizados podem detetar muitos erros antes de um humano rever o pedido de alteração. Isto melhora o ciclo de feedback para o programador. Pode implementar a mesma ideia, usando as mesmas ferramentas, para o repositório do Config Sync.

Por exemplo, um bom ponto de partida é executar o comando nomos vet automaticamente em novas alterações. Este comando valida se a sintaxe do repositório do Config Sync é válida. Pode implementar este teste através do Cloud Build seguindo o tutorial de validação de configurações. Pode integrar o Cloud Build com as seguintes opções:

  • Bitbucket, usando acionadores de compilação.
  • GitHub, através da aplicação GitHub do Google Cloud Build. Os acionadores de compilação também estão disponíveis para o GitHub, mas a aplicação GitHub é o método de integração preferencial.

Como pode ver no tutorial de validação de configurações, o teste é feito através de uma imagem de contentor. Por conseguinte, pode implementar o teste em qualquer solução de integração contínua que execute contentores e não apenas no Cloud Build.

Para reforçar ainda mais o ciclo de feedback, pode pedir aos utilizadores que executem o comando nomos vet como um Git pre-commit hook. Uma ressalva é que alguns utilizadores podem não ter acesso aos clusters do Kubernetes geridos pelo Config Sync e podem não conseguir executar a validação completa a partir da respetiva estação de trabalho. Execute o comando nomos vet --clusters "" para restringir a validação a verificações semânticas e sintáticas.

Recomendamos a seguinte ação:

  • Implemente testes num pipeline de integração contínua.
  • Execute, pelo menos, o comando nomos vet em todas as alterações sugeridas.

Monitorização de implementações

Mesmo que implemente todas as salvaguardas abordadas neste documento, podem ocorrer erros. Seguem-se dois tipos comuns de erros:

  • Erros que não representam um problema para a sincronização de configuração em si, mas impedem que as suas cargas de trabalho funcionem corretamente, como uma NetworkPolicy excessivamente restritiva que impede a comunicação dos componentes da sua carga de trabalho.
  • Erros que impossibilitam a aplicação de alterações por parte da Config Sync a um cluster, como um manifesto do Kubernetes inválido ou um objeto rejeitado por um controlador de admissão. Os métodos explicados anteriormente devem detetar a maioria destes erros.

A deteção dos erros descritos no primeiro ponto anterior é quase impossível ao nível do Config Sync, porque isto requer a compreensão do estado de cada uma das suas cargas de trabalho. Por este motivo, a melhor forma de detetar estes erros é através do seu sistema de monitorização existente que envia alertas quando uma aplicação tem um comportamento incorreto.

A deteção dos erros descritos no segundo ponto anterior, que devem ser raros se tiver implementado todas as salvaguardas, requer uma configuração específica. Por predefinição, o Config Sync escreve erros nos respetivos registos (que encontra, por predefinição, no Cloud Logging). Os erros também são apresentados na página da consola de sincronização de configuração Google Cloud . Normalmente, os registos nem a consola são suficientes para detetar erros, porque provavelmente não os monitoriza em todos os momentos. A forma mais simples de automatizar a deteção de erros é executar o nomos status comando, que indica se existe um erro num cluster.

Também pode configurar uma solução mais avançada com alertas automáticos para erros. O Config Sync expõe métricas no formato Prometheus. Para mais informações, consulte o artigo Monitorizar a sincronização de configuração.

Depois de ter as métricas de sincronização da configuração no seu sistema de monitorização, crie um alerta para receber uma notificação quando a métrica gkeconfig_monitor_errors for superior a 0. Para mais informações, consulte o artigo sobre a gestão de políticas de alerta para o Cloud Monitoring ou as regras de alerta para o Prometheus.

Resumo dos mecanismos para implementações seguras com o Config Sync

A tabela seguinte resume os vários mecanismos descritos anteriormente neste documento. Nenhum destes mecanismos é exclusivo. Pode optar por usar algumas ou todas as funcionalidades para diferentes fins.

Mecanismo Para que é útil Para que não é adequado Exemplo de utilização
Tags e IDs de commits do Git Use IDs de commits do Git ou etiquetas específicos para controlar com precisão as alterações de cluster que são aplicadas. Não use IDs de consolidação nem etiquetas do Git para diferenças duradouras entre clusters. Use seletores de clusters. Todos os seus clusters estão configurados para aplicar o 12345 Git commit. Faz uma alteração com uma nova confirmação, abcdef, que quer testar. Altera a configuração de um único cluster para usar esta nova confirmação para validar a alteração.
Ramos do Git Use várias ramificações do Git quando quiser implementar a mesma alteração em vários ambientes, um após o outro. Não use várias ramificações do Git para diferenças duradouras entre clusters. As ramificações vão divergir significativamente e vai ser difícil juntá-las novamente. Primeiro, combine a alteração no ramo de preparação, onde vai ser recolhida pelos clusters de preparação.
Em seguida, combine a alteração na ramificação principal, onde será recolhida pelos clusters de produção.
Seletores de clusters e seletores de namespaces Use seletores para diferenças duradouras entre clusters e espaços de nomes. Não use seletores para uma implementação faseada em vários ambientes. Se quiser testar primeiro uma modificação na preparação e, em seguida, implementá-la na produção, use ramos Git separados. Se as equipas de aplicações precisarem de acesso total aos clusters de desenvolvimento, mas acesso só de leitura aos clusters de produção, use o objeto ClusterSelector para aplicar as políticas de RBAC corretas apenas aos clusters relevantes.
Revisões de pares Use revisões por pares para garantir que as equipas relevantes aprovam as alterações. Os revisores humanos não detetam todos os erros, especialmente itens como erros de sintaxe. A sua organização exige que a equipa de segurança reveja as alterações de configuração que afetam vários sistemas. Faça com que um membro da equipa de segurança reveja as alterações.
Testes automatizados no pipeline de integração contínua Use testes automatizados para detetar erros nas alterações sugeridas. Os testes automatizados não podem substituir totalmente um revisor humano. Use ambas. A execução de um comando nomos vet em todas as alterações sugeridas confirma que o repositório é uma configuração válida do Config Sync.
Monitorize erros de sincronização Certifique-se de que a sincronização de configuração aplica efetivamente as alterações aos seus clusters. Os erros de sincronização ocorrem apenas se o Config Sync tentar aplicar um repositório inválido ou se o servidor da API Kubernetes rejeitar alguns dos objetos. Um utilizador ignora todos os seus testes e revisões e confirma uma alteração inválida no repositório do Config Sync. Não é possível aplicar esta alteração aos seus clusters. Se estiver a monitorizar erros de sincronização, recebe um alerta se for cometido um erro.

Exemplo de estratégia de implementação

Esta secção usa os conceitos apresentados no resto deste artigo para ajudar a criar uma estratégia de implementação integral em todos os clusters da sua organização. Esta estratégia pressupõe que tem frotas separadas para desenvolvimento, preparação e produção (conforme mostrado no Exemplo de frota 1 – Abordagem 1).

Neste cenário, configura cada cluster para sincronizar com o seu repositório Git através de uma consolidação do Git específica. A implementação de uma alteração numa determinada frota é um processo de 4 passos:

  1. Atualiza um único cluster (o "canário") na frota para usar primeiro a nova confirmação.
  2. Valida se tudo funciona como esperado executando testes e monitorizando a implementação.
  3. Atualiza o resto dos clusters na frota.
  4. Valida novamente se tudo funciona conforme esperado.

Para implementar uma alteração em todos os seus clusters, repita este processo para cada frota. Tecnicamente, pode aplicar este método com qualquer commit do Git, a partir de qualquer ramificação. No entanto, sugerimos que adote o seguinte processo para identificar problemas numa fase inicial do processo de revisão:

  1. Quando alguém abre um pedido de alteração no repositório Git do Config Sync, implemente essa alteração num dos clusters de desenvolvimento.
  2. Se o pedido de alteração for aceite e incorporado na ramificação principal, execute a implementação completa em todas as frotas, conforme descrito anteriormente.

Embora algumas alterações possam segmentar apenas uma frota específica, recomendamos que implemente todas as alterações em todas as frotas. Esta estratégia elimina o problema de acompanhar que frota deve ser sincronizada com que confirmação. Preste especial atenção às alterações que têm como destino apenas a frota de produção, uma vez que não foi possível fazer testes adequados nas frotas anteriores. Por exemplo, isto significa esperar mais tempo para que os problemas surjam entre a implementação nos clusters canary e no resto dos clusters.

Em resumo, uma implementação ponto a ponto completa tem o seguinte aspeto:

  1. Alguém abre um pedido de alteração.
  2. São executados testes e validações automáticos, e é feita uma revisão manual.
  3. Aciona uma tarefa manualmente para implementar a alteração no cluster de teste canary na frota de desenvolvimento. Os testes ponto a ponto automatizados são executados neste cluster.
  4. Se estiver tudo bem, junta o pedido de alteração no ramo principal.
  5. A união aciona uma tarefa automatizada para implementar a nova confirmação da ponta do ramo principal no cluster de testes beta na frota de desenvolvimento. Testes ponto a ponto automatizados executados neste cluster (para detetar potenciais incompatibilidades entre dois pedidos de alteração criados e unidos aproximadamente ao mesmo tempo).
  6. As seguintes tarefas são executadas sucessivamente (são acionadas manualmente ou após um período predefinido para permitir relatórios de regressões por parte dos utilizadores):
    1. Implemente em todos os clusters da frota de desenvolvimento.
    2. Executar testes e validações nos clusters da frota de desenvolvimento.
    3. Implemente no cluster de testes do grupo de preparação.
    4. Execute testes e validações no cluster de testes beta da frota de preparação.
    5. Implemente em todos os clusters da frota de preparação.
    6. Executar testes e validações nos clusters da frota de preparação.
    7. Implemente no cluster de testes do conjunto de produção.
    8. Executar testes e validações no cluster canary da frota de produção.
    9. Implemente em todos os clusters da frota de produção.
    10. Executar testes e validações nos clusters da frota de produção.

Processo de implementação completa.

O que se segue?