Sincronize artefactos OCI do Artifact Registry

Esta página mostra como criar e publicar a sua imagem num repositório no Artifact Registry com crane e oras.

Pode configurar o Config Sync para sincronizar a partir de imagens OCI através do Artifact Registry. Para usar esta funcionalidade, tem de ativar as APIs RootSync e RepoSync.

Acerca do Artifact Registry

O Artifact Registry é um serviço totalmente gerido com suporte para imagens de contentores e artefactos que não sejam contentores. Recomendamos o Artifact Registry para o armazenamento e a gestão de imagens de contentores no Google Cloud. Existem muitas ferramentas disponíveis para enviar artefactos para o Artifact Registry. Por exemplo, pode enviar uma imagem do Docker ou usar a biblioteca go-containerregistry para trabalhar com registos de contentores. Escolha a ferramenta que funciona melhor para si.

Antes de começar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. Se estiver a usar um fornecedor de identidade (IdP) externo, tem primeiro de iniciar sessão na CLI gcloud com a sua identidade federada.

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

    gcloud init
  5. Create or select a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.
    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the GKE, Config Sync, Artifact Registry APIs:

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    gcloud services enable container.googleapis.com  anthosconfigmanagement.googleapis.com  artifactregistry.googleapis.com
  8. Install the Google Cloud CLI.

  9. Se estiver a usar um fornecedor de identidade (IdP) externo, tem primeiro de iniciar sessão na CLI gcloud com a sua identidade federada.

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

    gcloud init
  11. Create or select a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.
    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Verify that billing is enabled for your Google Cloud project.

  13. Enable the GKE, Config Sync, Artifact Registry APIs:

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    gcloud services enable container.googleapis.com  anthosconfigmanagement.googleapis.com  artifactregistry.googleapis.com
  14. Criar ou ter acesso a um cluster que cumpra os requisitos do Config Sync e que esteja na versão mais recente do Config Sync.
  15. Instale a CLI nomos ou atualize-a para a versão mais recente.
  16. (Opcional) Se quiser usar o Cosign para validar as assinaturas de imagens OCI, instale o seguinte:
    • Cosign para assinar imagens OCI.
    • OpenSSL para gerar credenciais para o servidor de webhook.
    • Docker para criar e enviar a imagem do servidor do webhook de admissão.

    Custos

    Neste documento, usa os seguintes componentes faturáveis do Google Cloud:

    Para gerar uma estimativa de custos com base na sua utilização prevista, use a calculadora de preços.

    Os novos Google Cloud utilizadores podem ser elegíveis para uma avaliação sem custo financeiro.

    Crie um repositório do Artifact Registry

    Nesta secção, cria um repositório do Artifact Registry. Para saber como criar repositórios do Artifact Registry, consulte o artigo Crie 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 o seguinte:

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

    Variáveis usadas nas seguintes secções:

    • FLEET_HOST_PROJECT_ID: se estiver a usar a Workload Identity Federation do GKE para o GKE, é igual a PROJECT_ID. Se estiver a usar a Federação de identidades de carga de trabalho da frota para o GKE, este é o ID do projeto da frota no qual o seu cluster está registado.
    • GSA_NAME: o nome da conta de serviço Google personalizada que quer usar para estabelecer ligação ao Artifact Registry.
    • KSA_NAME: a conta de serviço do Kubernetes para o 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 espaço de nomes, 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 onde REPO_SYNC_NAME_LENGTH é o número de carateres em REPO_SYNC_NAME.

    Conceda autorização de leitor

    Use uma conta de serviço do Kubernetes para fazer a autenticação no Artifact Registry concluindo os seguintes passos:

    Conceda a função de IAM de leitor do Artifact Registry (roles/artifactregistry.reader) à conta de serviço do Kubernetes que tem a federação de identidades da carga de trabalho para o pool do 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
    

    Envie uma imagem para o repositório do Artifact Registry

    Nesta secção, cria uma imagem OCI e envia-a para o Artifact Registry.

    1. Crie um Namespaceficheiro de manifesto:

      cat <<EOF> test-namespace.yaml
      apiVersion: v1
      kind: Namespace
      metadata:
        name: test
      EOF
      
    2. Inicie sessão 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 secção usam crane para interagir com imagens remotas e registos.

      1. Empacote o ficheiro:

        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 secção usam oras para interagir com imagens remotas e registos.

      1. Empacote o ficheiro:

        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
        

    Configure o Config Sync para sincronizar a partir da sua imagem

    Nesta secção, vai criar um objeto RootSync e configurar o Config Sync para sincronizar a partir da 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 seu objeto RootSync. O nome deve ser exclusivo no cluster e não ter mais de 26 carateres. 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á a sincronizar a partir da imagem:

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

      Deverá ver uma saída semelhante ao seguinte exemplo:

      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
      

      Sincronizou com êxito uma imagem com o seu cluster.

    (Opcional) Valide as assinaturas de origem da OCI

    Pode validar a autenticidade das imagens de origem da OCI antes de as configurações serem aplicadas aos seus clusters. Este método usa um objeto ValidatingWebhookConfiguration e um servidor webhook de validação para intercetar pedidos de atualização para objetos RootSync e RepoSync. O Config Sync atualiza a anotação configsync.gke.io/image-to-sync dos objetos RootSync e RepoSync depois de obter com êxito um novo resumo da imagem. O servidor webhook de validação compara os valores entre a anotação antiga e a nova anotação e executa a validação com uma ferramenta de validação, como o Cosign, quando é detetada uma alteração.

    Configure um servidor de validação de assinaturas

    Para garantir a autenticidade das suas origens OCI, precisa de um servidor HTTP para validar as assinaturas. Pode usar os exemplos no repositório de exemplos do Config Sync ou usar a sua própria imagem do Docker.

    1. Se quiser usar o exemplo fornecido, conclua os seguintes passos:

      1. Clone o repositório de exemplo:

        git clone https://github.com/GoogleCloudPlatform/anthos-config-management-samples/
        
      2. Altere para o diretório que contém os exemplos do servidor de validação de assinaturas:

        cd anthos-config-management-samples/tree/main/pre-sync/oci-image-verification
        
    2. Para criar uma imagem do Docker para o servidor de validação de assinaturas e enviá-la para um registo 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 validação de assinatura.

    Autentique-se nos serviços

    Para configurar o servidor de validação de assinaturas, tem de se autenticar no Artifact Registry, no cliente Cosign e no servidor webhook.

    1. Crie um espaço de nomes:

      kubectl create ns signature-verification
      
    2. Para autenticar no Artifact Registry com uma conta de serviço do Kubernetes, conclua os seguintes passos:

      1. Crie uma ServiceAccount do Kubernetes no espaço de nomes que criou:

        kubectl create sa signature-verification-sa -n signature-verification
        
      2. Adicione a associação da Política IAM para a função 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 o seguinte:

        • REPOSITORY_NAME: o nome do seu repositório do Artifact Registry onde armazena as suas imagens OCI.
        • REPOSITORY_LOCATION: a localização do seu repositório do Artifact Registry.
    3. Para se autenticar no cliente Cosign, conclua os seguintes passos:

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

        cosign generate-key-pair
        
      2. Armazene a chave pública num secret do Kubernetes no espaço de nomes que criou:

        kubectl create secret generic cosign-key --from-file=cosign.pub -n signature-verification
        
    4. Para autenticar o servidor de validação de assinaturas, conclua os seguintes passos:

      1. Para encriptar a comunicação no servidor de validação de assinaturas, 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 que gerou num segredo do Kubernetes:

        kubectl create secret tls webhook-tls --cert=tls.crt --key=tls.key -n signature-verification
        
      3. Obtenha o conteúdo codificado em base64 de tls.cert. Isto é necessário para a configuração do webhook de validação que cria na secção seguinte:

        cat tls.crt | base64 -w 0.
        

    Implemente o webhook de admissão

    Pode usar os seguintes exemplos para criar uma implementação para o servidor de validação de assinaturas e uma configuração de webhook de validação.

    1. Crie uma implementação para o servidor de validação de assinaturas guardando o seguinte ficheiro:

      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 validação de assinatura.

    2. Aplique a implementação ao cluster:

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

      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 do webhook de validação ao cluster:

      kubectl apply -f signature-verification-validatingwebhookconfiguration.yaml
      

    Verifique os registos para ver se existem erros de validação de imagens

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

    Para verificar se existem erros de validação de assinatura, veja os registos do servidor de validação de assinatura executando os seguintes comandos:

    1. Verifique os registos do kubectl:

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

      Os erros do kubectl relacionados com a validação da assinatura são semelhantes aos seguintes:

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

      nomos status
      

      Os erros do Config Sync relacionados com a validação de assinaturas são semelhantes aos seguintes:

      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 receber erros, pode confirmar que a imagem assinada é o objeto que está a ser sincronizado inspecionando a configuração do RootSync ou do 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 o seguinte:

    • REPOSYNC_NAME: o nome do seu RepoSync.
    • REPOSYNC_NAMESPACE: o nome do espaço de nomes associado ao seu RepoSync.

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

    O que se segue?