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 do 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. 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. 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. 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 (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. 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. 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 (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. 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 sua projeção de uso, utilize 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

    A partir da versão 1.20.0, o Config Sync oferece suporte à verificação da 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 do 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 do 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 se 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 você não receber erros, confirme se a imagem assinada é o objeto sendo sincronizado inspecionando sua 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