Sincronizar artefatos do OCI no Artifact Registry

Nesta página, mostramos como criar e publicar sua imagem em um repositório do Artifact Registry com crane e oras.

É possível configurar o Config Sync para sincronizar a partir de imagens do OCI usando o Artifact Registry. Para usar esse recurso, você precisa ativar as APIs RootSync e RepoSync.

Sobre o Artifact Registry

O Artifact Registry é um serviço totalmente gerenciado compatível com imagens de contêiner e artefatos que não são contêineres. Recomendamos o Artifact Registry para armazenamento e gerenciamento de imagens de contêiner no Google Cloud. Há várias ferramentas disponíveis para enviar artefatos ao Artifact Registry. Por exemplo, é possível enviar uma imagem Docker ou usar a biblioteca go-containerregistry para trabalhar com os registros de contêiner. Escolha a ferramenta que funciona melhor para você.

Antes de começar

  1. Faça login na sua conta do Google Cloud . Se você começou a usar o Google Cloud, crie uma conta para avaliar o desempenho de nossos produtos em situações reais. Clientes novos também recebem US$ 300 em créditos para executar, testar e implantar cargas de trabalho.
  2. Instale a CLI do Google Cloud.

  3. Ao usar um provedor de identidade (IdP) externo, primeiro faça login na gcloud CLI com sua identidade federada.

  4. Para inicializar a gcloud CLI, execute o seguinte comando:

    gcloud init
  5. Crie ou selecione um Google Cloud projeto.

    Funções necessárias para selecionar ou criar um projeto

    • Selecionar um projeto: não é necessário um papel específico do IAM para selecionar um projeto. Você pode escolher qualquer projeto em que tenha recebido um papel.
    • Criar um projeto: para criar um projeto, é necessário ter o papel de Criador de projetos (roles/resourcemanager.projectCreator), que contém a permissão resourcemanager.projects.create. Saiba como conceder papéis.
    • Crie um projeto do Google Cloud :

      gcloud projects create PROJECT_ID

      Substitua PROJECT_ID por um nome para o projeto Google Cloud que você está criando.

    • Selecione o projeto Google Cloud que você criou:

      gcloud config set project PROJECT_ID

      Substitua PROJECT_ID pelo nome do projeto do Google Cloud .

  6. Verifique se o faturamento está ativado para o projeto do Google Cloud .

  7. Ative as APIs GKE, Config Sync e Artifact Registry:

    Funções necessárias para ativar APIs

    Para ativar as APIs, é necessário ter o papel do IAM de administrador do Service Usage (roles/serviceusage.serviceUsageAdmin), que contém a permissão serviceusage.services.enable. Saiba como conceder papéis.

    gcloud services enable container.googleapis.com  anthosconfigmanagement.googleapis.com  artifactregistry.googleapis.com
  8. Instale a CLI do Google Cloud.

  9. Ao usar um provedor de identidade (IdP) externo, primeiro faça login na gcloud CLI com sua identidade federada.

  10. Para inicializar a gcloud CLI, execute o seguinte comando:

    gcloud init
  11. Crie ou selecione um Google Cloud projeto.

    Funções necessárias para selecionar ou criar um projeto

    • Selecionar um projeto: não é necessário um papel específico do IAM para selecionar um projeto. Você pode escolher qualquer projeto em que tenha recebido um papel.
    • Criar um projeto: para criar um projeto, é necessário ter o papel de Criador de projetos (roles/resourcemanager.projectCreator), que contém a permissão resourcemanager.projects.create. Saiba como conceder papéis.
    • Crie um projeto do Google Cloud :

      gcloud projects create PROJECT_ID

      Substitua PROJECT_ID por um nome para o projeto Google Cloud que você está criando.

    • Selecione o projeto Google Cloud que você criou:

      gcloud config set project PROJECT_ID

      Substitua PROJECT_ID pelo nome do projeto do Google Cloud .

  12. Verifique se o faturamento está ativado para o projeto do Google Cloud .

  13. Ative as APIs GKE, Config Sync e Artifact Registry:

    Funções necessárias para ativar APIs

    Para ativar as APIs, é necessário ter o papel do IAM de administrador do Service Usage (roles/serviceusage.serviceUsageAdmin), que contém a permissão serviceusage.services.enable. Saiba como conceder papéis.

    gcloud services enable container.googleapis.com  anthosconfigmanagement.googleapis.com  artifactregistry.googleapis.com
  14. Crie ou tenha acesso a um cluster que atenda aos requisitos do Config Sync e esteja na versão mais recente do Config Sync.
  15. Instale ou faça upgrade da CLI nomos para a versão mais recente.
  16. (Opcional) Se você quiser usar o Cosign para verificar assinaturas de imagens OCI, instale o seguinte:
    • Cosign para assinar imagens OCI.
    • OpenSSL para gerar credenciais para o servidor webhook.
    • Docker para criar e enviar a imagem do servidor de webhook de admissão.

Custos

Neste documento, você vai usar os seguintes componentes faturáveis do Google Cloud:

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

Novos usuários do Google Cloud podem estar qualificados para um teste sem custo financeiro.

Crie um repositório do Artifact Registry

Nesta seção, você criará um repositório do Artifact Registry. Para saber mais sobre como criar repositórios do Artifact Registry, consulte Criar repositórios.

  1. Crie um repositório do Artifact Registry:

    gcloud artifacts repositories create AR_REPO_NAME \
       --repository-format=docker \
       --location=AR_REGION \
       --description="Config Sync repo" \
       --project=PROJECT_ID
    

Substitua:

  • PROJECT_ID: ID do projeto da organização.
  • AR_REPO_NAME: o ID do repositório.
  • AR_REGION é o local regional ou multirregional do repositório.

Variáveis usadas nas seguintes seções:

  • FLEET_HOST_PROJECT_ID: se você estiver usando a federação de identidade da carga de trabalho do GKE, será igual a PROJECT_ID. Se você estiver usando a federação de identidade da carga de trabalho da frota para o GKE, esse será o ID do projeto da frota em que o cluster está registrado.
  • GSA_NAME: o nome da conta de serviço personalizada do Google que você quer usar para se conectar ao Artifact Registry.
  • KSA_NAME: a conta de serviço do Kubernetes do reconciliador.
    • Para repositórios raiz, se o nome RootSync for root-sync, adicione root-reconciler. Caso contrário, adicione root-reconciler-ROOT_SYNC_NAME.
    • Para repositórios de namespace, se o nome RepoSync for repo-sync, adicione ns-reconciler-NAMESPACE. Caso contrário, adicione ns-reconciler-NAMESPACE-REPO_SYNC_NAME-REPO_SYNC_NAME_LENGTH, em que REPO_SYNC_NAME_LENGTH é o número de caracteres em REPO_SYNC_NAME.

Conceder permissão de leitor

Use uma conta de serviço do Kubernetes para autenticar no Artifact Registry seguindo estas etapas:

Conceda o papel do IAM de leitor do Artifact Registry (roles/artifactregistry.reader) à conta de serviço do Kubernetes que tem o pool da Federação de Identidade da Carga de Trabalho para GKE:

gcloud artifacts repositories add-iam-policy-binding AR_REPO_NAME \
   --location=AR_REGION \
   --member="serviceAccount:FLEET_HOST_PROJECT_ID.svc.id.goog[config-management-system/KSA_NAME]" \
   --role=roles/artifactregistry.reader \
   --project=PROJECT_ID

Enviar uma imagem para o repositório do Artifact Registry

Nesta seção, você vai criar uma imagem OCI e enviá-la para o Artifact Registry.

  1. Crie um arquivo de manifesto Namespace:

    cat <<EOF> test-namespace.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: test
    EOF
    
  2. Faça login no Artifact Registry:

    gcloud auth configure-docker AR_REGION-docker.pkg.dev
    
  3. Empacote e envie a imagem para o Artifact Registry:

    crane

    Os comandos nesta seção usam crane para interagir com imagens e registros remotos.

    1. Empacote o arquivo:

      tar -cf test-namespace.tar test-namespace.yaml
      
    2. Instale a ferramenta crane.

    3. Envie a imagem para o Artifact Registry:

      crane append -f test-namespace.tar -t AR_REGION-docker.pkg.dev/PROJECT_ID/AR_REPO_NAME/test-namespace:v1
      

    oras

    Os comandos nesta seção usam oras para interagir com imagens e registros remotos.

    1. Empacote o arquivo:

      tar -czf test-namespace.tar.gz test-namespace.yaml
      
    2. Instale a ferramenta oras.

    3. Envie a imagem para o Artifact Registry:

      oras push AR_REGION-docker.pkg.dev/PROJECT_ID/AR_REPO_NAME/test-namespace:v1 test-namespace.tar.gz
      

Configurar o Config Sync para sincronizar usando a imagem

Nesta seção, você vai criar um objeto RootSync e configurar o Config Sync para fazer a sincronização com a imagem OCI.

  1. Crie um objeto RootSync com um nome exclusivo:

    cat <<EOF>> ROOT_SYNC_NAME.yaml
    apiVersion: configsync.gke.io/v1beta1
    kind: RootSync
    metadata:
      name: ROOT_SYNC_NAME
      namespace: config-management-system
    spec:
      sourceFormat: unstructured
      sourceType: oci
      oci:
        image: AR_REGION-docker.pkg.dev/PROJECT_ID/AR_REPO_NAME/test-namespace:v1
        dir: .
        auth: k8sserviceaccount
    EOF
    

    Substitua ROOT_SYNC_NAME pelo nome do objeto RootSync. O nome precisa ser exclusivo no cluster e ter no máximo 26 caracteres. Para ver a lista completa de opções ao configurar objetos RootSync, consulte os campos RootSync e RepoSync.

  2. Aplique o objeto RootSync:

    kubectl apply -f ROOT_SYNC_NAME.yaml
    
  3. Verifique se o Config Sync está sincronizando com a imagem:

    nomos status --contexts=$(kubectl config current-context)
    

    O resultado será semelhante a:

    Connecting to clusters...
    
    *publish-config-registry
       --------------------
       <root>:root-sync-test   AR_REGION-docker.pkg.dev/PROJECT_ID/AR_REPO_NAME/test-namespace:v1   
       SYNCED                  05e6a6b77de7a62286387cfea833d45290105fe84383224938d7b3ab151a55a1
       Managed resources:
          NAMESPACE   NAME             STATUS    SOURCEHASH
                      namespace/test   Current   05e6a6b
    

    Você sincronizou uma imagem com o cluster com êxito.

(Opcional) Verificar assinaturas de origem do OCI

É possível verificar a autenticidade das imagens de origem do OCI antes que as configurações sejam aplicadas aos clusters. Esse método usa um objeto ValidatingWebhookConfiguration e um servidor webhook de validação para interceptar solicitações de atualização de objetos RootSync e RepoSync. O Config Sync atualiza a anotação configsync.gke.io/image-to-sync dos objetos RootSync e RepoSync depois de buscar um novo resumo de imagem. O servidor webhook de validação compara os valores entre a anotação antiga e a nova e executa a validação com uma ferramenta de validação, como o Cosign, quando uma mudança é detectada.

Configurar um servidor de verificação de assinatura

Para garantir a autenticidade das suas fontes OCI, você precisa de um servidor HTTP para verificar as assinaturas. É possível usar as amostras no repositório de amostras do Config Sync ou usar sua própria imagem Docker.

  1. Se quiser usar a amostra fornecida, siga estas etapas:

    1. Clone o repositório de amostra:

      git clone https://github.com/GoogleCloudPlatform/anthos-config-management-samples/
      
    2. Mude para o diretório que contém as amostras do servidor de verificação de assinatura:

      cd anthos-config-management-samples/tree/main/pre-sync/oci-image-verification
      
  2. Para criar uma imagem Docker para o servidor de verificação de assinatura e enviá-la para um registro de imagens, execute o seguinte comando:

    docker build -t SIGNATURE_VERIFICATION_SERVER_IMAGE_URL:latest . && docker push SIGNATURE_VERIFICATION_SERVER_IMAGE_URL:latest
    

    Substitua SIGNATURE_VERIFICATION_SERVER_IMAGE_URL pelo URL da imagem do servidor de verificação de assinatura.

Autenticar em serviços

Para configurar o servidor de verificação de assinatura, autentique-se no Artifact Registry, no cliente Cosign e no servidor de webhook.

  1. Para criar um namespace:

    kubectl create ns signature-verification
    
  2. Para autenticar no Artifact Registry com uma ServiceAccount do Kubernetes, siga estas etapas:

    1. Crie uma conta de serviço do Kubernetes no namespace que você criou:

      kubectl create sa signature-verification-sa -n signature-verification
      
    2. Adicione a vinculação de política do IAM para o papel de leitor do Artifact Registry (roles/artifactregistry.reader):

      gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \
         --location=REPOSITORY_LOCATION \
         --member="serviceAccount:PROJECT_ID.svc.id.goog[signature-verification/signature-verification-sa]" \
         --role=roles/artifactregistry.reader \
         --project=PROJECT_ID
      

      Substitua:

      • REPOSITORY_NAME: o nome do repositório do Artifact Registry onde você armazena as imagens OCI.
      • REPOSITORY_LOCATION: o local do repositório do Artifact Registry.
  3. Para autenticar no cliente Cosign, siga estas etapas:

    1. Gere um par de chaves do Cosign. Esse comando gera uma chave pública e uma privada:

      cosign generate-key-pair
      
    2. Armazene a chave pública em um Secret do Kubernetes no namespace que você criou:

      kubectl create secret generic cosign-key --from-file=cosign.pub -n signature-verification
      
  4. Para autenticar o servidor de verificação de assinatura, siga estas etapas:

    1. Para criptografar a comunicação no servidor de verificação de assinatura, gere um certificado TLS e uma chave privada com o OpenSSL:

      openssl req -nodes -x509 -sha256 -newkey rsa:4096 \
      -keyout tls.key \
      -out tls.crt \
      -days 356 \
      -subj "/CN=signature-verification-service.signature-verification.svc"  \
      -addext "subjectAltName = DNS:signature-verification-service,DNS:signature-verification-service.signature-verification.svc,DNS:signature-verification-service.signature-verification"
      
    2. Armazene as credenciais geradas em um Secret do Kubernetes:

      kubectl create secret tls webhook-tls --cert=tls.crt --key=tls.key -n signature-verification
      
    3. Receba o conteúdo codificado em base64 do tls.cert. Isso é necessário para a configuração de webhook de validação que você vai criar na próxima seção:

      cat tls.crt | base64 -w 0.
      

Implantar o webhook de admissão

Use as amostras a seguir para criar um deployment para o servidor de verificação de assinatura e uma configuração de webhook de validação.

  1. Crie uma implantação para o servidor de verificação de assinatura salvando o arquivo a seguir:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: signature-verification-server
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: signature-verification-server
      template:
        metadata:
          labels:
            app: signature-verification-server
        spec:
          serviceAccountName: signature-verification-sa
          containers:
          - name: signature-verification-server
            command:
            - /signature-verification-server
            image: SIGNATURE_VERIFICATION_SERVER_IMAGE_URL
            imagePullPolicy: Always
            ports:
            - containerPort: 10250
            volumeMounts:
            - name: tls-certs
              mountPath: "/tls"
            - name: cosign-key
              mountPath: "/cosign-key"
          volumes:
          - name: cosign-key
            secret:
              secretName: cosign-key
          - name: tls-certs
            secret:
              secretName: webhook-tls
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: signature-verification-service
    spec:
      ports:
      - port: 10250
        targetPort: 10250
      selector:
        app: signature-verification-server

    Substitua SIGNATURE_VERIFICATION_SERVER_IMAGE_URL pelo URL completo da imagem do servidor de verificação de assinatura.

  2. Aplique a implantação ao cluster:

    kubectl apply -f signature-verification-deployment.yaml -n signature-verification
    
  3. Crie uma configuração de webhook de validação salvando o seguinte arquivo:

    apiVersion: admissionregistration.k8s.io/v1
    kind: ValidatingWebhookConfiguration
    metadata:
      name: image-verification-webhook
    webhooks:
    - name: imageverification.webhook.com
      clientConfig:
        service:
          name: signature-verification-service
          namespace: signature-verification
          path: "/validate"
          port: 10250
        caBundle: CA_BUNDLE
      rules:
      - apiGroups:
        - configsync.gke.io
        apiVersions:
        - v1beta1
        - v1alpha1
        operations:
        - UPDATE
        resources:
        - 'rootsyncs'
        - 'reposyncs'
        scope: '*'
      admissionReviewVersions: ["v1", "v1beta1"]
      sideEffects: None

    Substitua CA_BUNDLE pelo conteúdo codificado em base64 do tls.cert.

  4. Aplique a configuração de validação do webhook ao cluster:

    kubectl apply -f signature-verification-validatingwebhookconfiguration.yaml
    

Verificar se há erros de verificação de imagem nos registros

Depois de configurar o servidor de verificação de imagens, todas as tentativas de sincronização de imagens OCI não assinadas vão falhar.

Para verificar se há erros de verificação de assinatura, consulte os registros do servidor de verificação de assinatura executando os seguintes comandos:

  1. Verifique os registros do kubectl:

    kubectl logs deployment  signature-verification-server -n  signature-verification
    

    Erros de kubectl relacionados à verificação de assinatura são semelhantes a este:

    main.go:69: error during command execution: no signatures found
    
  2. Verifique os registros do Config Sync:

    nomos status
    

    Os erros do Config Sync relacionados à verificação de assinatura são semelhantes a este:

    Error:   KNV2002: admission webhook "imageverification.webhook.com" denied the request: Image validation failed: cosign verification failed: exit status 10, output: Error: no signatures found
    

Se não houver erros, confirme se a imagem assinada é o objeto sendo sincronizado inspecionando a configuração RootSync ou RepoSync:

RootSync

 kubectl get rootsync ROOTSYNC_NAME -n config-management-system -oyaml

Substitua ROOTSYNC_NAME pelo nome do seu RootSync.

RepoSync

 kubectl get reposync REPOSYNC_NAME -n REPOSYNC_NAMESPACE -oyaml

Substitua:

  • REPOSYNC_NAME: o nome do seu RepoSync.
  • REPOSYNC_NAMESPACE: o nome do namespace associado ao seu RepoSync.

A anotação configsync.gke.io/image-to-sync será adicionada ao objeto RootSync ou RepoSync. A anotação contém o URL da imagem OCI de origem e o resumo mais recente buscado pelo Config Sync.

A seguir