Validar apps em relação às políticas da empresa em um pipeline de CI

Se sua organização usa o Policy Controller para gerenciar políticas nos clusters da edição Google Kubernetes Engine (GKE) Enterprise, é possível validar a configuração de implantação de um app no pipeline de integração contínua (CI). Neste tutorial, mostramos como alcançar esse resultado. A validação do app é útil quando você é um desenvolvedor que cria um pipeline de CI para um app ou um engenheiro de plataforma que cria um modelo de pipeline de CI para várias equipes de aplicativos.

As políticas são uma parte importante da segurança e da conformidade de uma organização. O Policy Controller permite que sua organização gerencie essas políticas de maneira centralizada e declarativa para todos os clusters. Como desenvolvedor, você consegue aproveitar a natureza centralizada e declarativa dessas políticas. É possível usar essas características para validar seu app em relação a essas políticas o mais cedo possível no seu fluxo de trabalho de desenvolvimento. Aprender sobre violações de políticas no pipeline de CI em vez de fazer isso durante a implantação tem duas vantagens principais: permite que você faça um processo de shift left na segurança e diminua o feedback loop, reduzindo o tempo e o custo necessários para corrigir essas violações.

Neste tutorial, o Cloud Build é usado como uma ferramenta de CI e um repositório do GitHub de amostra com políticas de demonstração.

Recursos

Neste tutorial, usamos várias ferramentas do Kubernetes. Esta seção explica quais são essas ferramentas, como elas interagem umas com as outras e se é possível substituí-las por outras.

As ferramentas usadas neste tutorial incluem o seguinte:

  • Policy Controller: é baseado no projeto de código aberto Open Policy Agent - Gatekeeper. O Policy Controller aplica políticas sobre os objetos criados em um cluster do Kubernetes (por exemplo, impedindo o uso de uma opção específica ou aplicação do uso de um rótulo específico). Essas políticas são chamadas de restrições. As restrições são definidas como recursos personalizados do Kubernetes. O Policy Controller está disponível como parte do Google Kubernetes Engine (GKE) Enterprise, mas é possível usar o Open Policy Agent - Gatekeeper em vez do Policy Controller para implementação.

  • GitHub: neste tutorial, usamos o GitHub para hospedar os repositórios Git: um para um app de exemplo e outro que contém as restrições do Policy Controller. Para simplificar, os dois repositórios são duas pastas diferentes em um único repositório Git. Na realidade, seriam repositórios diferentes. É possível usar qualquer solução Git.

  • Cloud Build: o Cloud Build é a solução de CI do Google Cloud. Neste tutorial, nós o usaremos para executar os testes de validação. Os detalhes da implementação podem variar de um sistema de CI para outro, mas os conceitos descritos neste tutorial podem ser usados com qualquer sistema de CI baseado em contêiner.

  • Kustomize: o Kustomize é uma ferramenta de personalização nas configurações do Kubernetes. Isso é feito por meio de configurações de "base" e da aplicação de personalizações. Ele permite, uma abordagem "Não se repita" (DRY, na sigla em inglês) para configurações do Kubernetes. Com o Kustomize, você mantém elementos comuns a todos os seus ambientes nas configurações básicas e cria personalizações por ambiente. Neste tutorial, manteremos as configurações do Kustomize no repositório de apps à medida que "criamos" as configurações no pipeline de CI (por exemplo, aplicando personalizações). Use os conceitos descritos neste tutorial com qualquer ferramenta que produz configurações do Kubernetes e que estão prontas para serem aplicadas a um cluster. Por exemplo, o comando do helm template.

  • Kpt: o Kpt é uma ferramenta para criar fluxos de trabalho para configurações do Kubernetes. O Kpt permite buscar, exibir, personalizar, atualizar, validar e aplicar configurações do Kubernetes. Como ele funciona com arquivos Git e YAML, é compatível com a maioria das ferramentas atuais do ecossistema do Kubernetes. Neste tutorial, usamos o kpt no pipeline de CI para buscar as restrições do repositório anthos-config-management-samples, além de validar as configurações do Kubernetes de acordo com essas restrições.

Pipeline

O pipeline de CI que usamos neste tutorial é mostrado no diagrama a seguir:

Pipeline de CI para o Policy Controller

O pipeline é executado no Cloud Build, e os comandos são executados em um diretório que contém uma cópia do repositório do app de amostra. O pipeline começa gerando as configurações finais do Kubernetes com o Kustomize. Em seguida, ele busca as restrições que queremos validar no repositório anthos-config-management-samples usando o kpt. Por fim, o kpt é usado para validar as configurações do Kubernetes de acordo com essas restrições. Para realizar essa última etapa, usamos uma função de configuração específica chamada gatekeeper, que realiza essa validação. Neste tutorial, você acionará o pipeline de CI manualmente. No entanto, na realidade, ele seria configurado para ser executado após um git push em seu repositório Git.

Objetivos

  • Executar um pipeline de CI para um aplicativo de amostra com o Cloud Build.
  • O pipeline falhou devido a uma violação da política.
  • Modificar o repositório do app de amostra para obedecer às políticas.
  • Executar o pipeline de CI novamente com êxito.

Custos

Neste tutorial, usamos o seguinte componente faturável do Google Cloud:

  • Cloud Build
  • Edição do Google Kubernetes Engine (GKE) Enterprise

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços.

Ao concluir o tutorial, exclua os recursos criados para evitar a continuidade do faturamento. Para mais detalhes, consulte a seção Como fazer a limpeza.

Antes de começar

  1. Selecione ou crie um projeto do Google Cloud. No Console do Google Cloud, acesse a página Gerenciar recursos.

    Acessar "Gerenciar recursos"

  2. Ative o faturamento do projeto.

  3. Para executar os comandos listados neste tutorial, abra o Cloud Shell e siga estas etapas:

    Acesse o Cloud Shell

  4. No Cloud Shell, execute gcloud config get-value project.

    Se o comando não retornar o ID do projeto que foi selecionado, configure o Cloud Shell para usar seu projeto.

    gcloud config set project PROJECT_ID
    

    Substitua PROJECT_ID pela ID do seu projeto.

  5. No Cloud Shell, ative a API Cloud Build necessária:

    gcloud services enable cloudbuild.googleapis.com
    

Validar as configurações de aplicativos de amostra

Nesta seção, você executará um pipeline de CI com o Cloud Build para um repositório de app de amostra que fornecemos. Esse pipeline valida a configuração do Kubernetes disponível nesse repositório de aplicativos de amostra em relação às restrições disponíveis em um repositório antos-config-management-samples.

Para validar as configurações do app, siga estas etapas:

  1. No Cloud Shell, clone o repositório do app de amostra.

    git clone https://github.com/GoogleCloudPlatform/anthos-config-management-samples.git
    
  2. Execute o pipeline de CI com o Cloud Build Os registros do build são exibidos diretamente no Cloud Shell.

    cd anthos-config-management-samples/ci-app/app-repo
    gcloud builds submit .
    

    O pipeline que você executa é definido no arquivo a seguir.

    steps:
    - id: 'Prepare config'
      # This step builds the final manifests for the app
      # using kustomize and the configuration files
      # available in the repository.
      name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
      entrypoint: '/bin/sh'
      args: ['-c', 'mkdir hydrated-manifests && kubectl kustomize config/prod > hydrated-manifests/prod.yaml']
    - id: 'Download policies'
      # This step fetches the policies from the Anthos Config Management repository
      # and consolidates every resource in a single file.
      name: 'gcr.io/kpt-dev/kpt'
      entrypoint: '/bin/sh'
      args: ['-c', 'kpt pkg get https://github.com/GoogleCloudPlatform/anthos-config-management-samples.git/ci-app/acm-repo/cluster@main constraints
                      && kpt fn source constraints/ hydrated-manifests/ > hydrated-manifests/kpt-manifests.yaml']
    - id: 'Validate against policies'
      # This step validates that all resources comply with all policies.
      name: 'gcr.io/kpt-fn/gatekeeper:v0.2'
      args: ['--input', 'hydrated-manifests/kpt-manifests.yaml']

    No Policy Controller, as restrições são instâncias de modelos de restrição. Os modelos de restrição contêm o código Rego atual usado para implementar a restrição. A função gcr.io/kpt-fn/gatekeeper precisa do modelo de restrição e das definições de restrição para funcionar. O repositório de políticas de amostra contém ambos, mas, na realidade, eles podem ser armazenados em lugares diferentes. Use o comando kpt pkg get conforme necessário para fazer o download de modelos de restrição e restrições.

    Neste tutorial, usamos gcr.io/kpt-fn/gatekeeper com o Cloud Build para validar recursos, mas há duas outras alternativas que podem ser usadas:

    kpt fn eval hydrated-manifests/kpt-manifests.yaml --image gcr.io/kpt-fn/gatekeeper:v0.2
    
    gator test -f hydrated-manifests/kpt-manifests.yaml
    
  3. Após alguns minutos, observe que o pipeline falha com o seguinte erro:

    [...]
    Step #2 - "Validate against policies": [error] apps/v1/Deployment/nginx-deployment : Deployment objects should have an 'owner' label indicating who created them.
    Step #2 - "Validate against policies": violatedConstraint: deployment-must-have-owner
    Finished Step #2 - "Validate against policies"
    2022/05/11 18:55:18 Step Step #2 - "Validate against policies" finished
    2022/05/11 18:55:19 status changed to "ERROR"
    ERROR
    ERROR: build step 2 "gcr.io/kpt-fn/gatekeeper:v0.2" failed: exit status 1
    2022/05/11 18:55:20 Build finished with ERROR status
    

    A restrição que a configuração viola é definida no arquivo a seguir. É um recurso personalizado do Kubernetes chamado K8sRequiredLabels.

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sRequiredLabels
    metadata:
      name: deployment-must-have-owner
    spec:
      match:
        kinds:
          - apiGroups: ["apps"]
            kinds: ["Deployment"]
      parameters:
        labels:
          - key: "owner"
        message: "Deployment objects should have an 'owner' label indicating who created them."

    Para o modelo de restrição correspondente a essa restrição, consulte requiredlabels.yaml no GitHub.

  4. Crie a configuração completa do Kubernetes e observe que o rótulo owner está realmente ausente. Para criar a configuração, faça o seguinte:

    kubectl kustomize config/prod
    

Corrija o app para estar em conformidade com as políticas da empresa

Nesta seção, você corrige a violação da política usando o Kustomize:

  1. No Cloud Shell, adicione uma seção commonLabels ao arquivo base do Kustomize:

    cat <<EOF >> config/base/kustomization.yaml
    commonLabels:
      owner: myself
    EOF
    
  2. Crie a configuração completa do Kubernetes e observe que o rótulo owner está presente:

    kubectl kustomize config/prod
    
  3. Execute novamente o pipeline de CI com o Cloud Build:

    gcloud builds submit .
    

    O pipeline agora é bem-sucedido com a seguinte saída:

    [...]
    Step #2 - "Validate against policies": [RUNNING] "gcr.io/kpt-fn/gatekeeper:v0"
    Step #2 - "Validate against policies": [PASS] "gcr.io/kpt-fn/gatekeeper:v0"
    [...]
    

Limpar

  1. No Console do Google Cloud, acesse a página Gerenciar recursos.

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

A seguir