Synchroniser les artefacts OCI à partir d'Artifact Registry

Cette page vous explique comment créer et publier votre image dans un dépôt Artifact Registry avec crane et oras.

Vous pouvez configurer Config Sync pour qu'il se synchronise à partir d'images OCI à l'aide d'Artifact Registry. Pour utiliser cette fonctionnalité, vous devez activer les API RootSync et RepoSync.

À propos d'Artifact Registry

Artifact Registry est un service entièrement géré compatible avec les images de conteneurs et les artefacts non issus de conteneurs. Nous vous recommandons d'utiliser Artifact Registry pour stocker et gérer vos images de conteneurs sur Google Cloud. De nombreux outils permettent de transférer des artefacts vers Artifact Registry. Par exemple, vous pouvez transférer une image Docker,transférer un chart Helm ou utiliser la bibliothèque go-containerregistry pour travailler avec des registres de conteneurs. Choisissez l'outil qui vous convient le mieux.

Avant de commencer

  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. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  4. To initialize the gcloud CLI, run the following command:

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

    • 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. Make sure that billing is enabled for your Google Cloud project.

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

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

  9. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  10. To initialize the gcloud CLI, run the following command:

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

    • 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. Make sure that billing is enabled for your Google Cloud project.

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

    gcloud services enable anthos.googleapis.com  anthosconfigmanagement.googleapis.com  artifactregistry.googleapis.com
  14. Créez un cluster répondant aux exigences de Config Sync et utilisant la dernière version de Config Sync, ou assurez-vous d'y avoir accès.
  15. Installez la CLI nomos ou mettez-la à niveau vers la dernière version.
  16. (Facultatif) Si vous souhaitez utiliser Cosign pour valider les signatures d'images OCI, installez les éléments suivants :
    • Cosign pour signer les images OCI.
    • OpenSSL pour générer des identifiants pour le serveur de webhook.
    • Docker pour créer et transmettre l'image du serveur Admission Webhook.

    Coûts

    Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

    Pour obtenir une estimation des coûts en fonction de votre utilisation prévue, utilisez le simulateur de coût.

    Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

    Créer un dépôt Artifact Registry

    Dans cette section, vous allez créer un dépôt Artifact Registry. Pour en savoir plus sur la création de dépôts Artifact Registry, consultez la section Créer des dépôts.

    1. Créer un dépôt Artifact Registry :

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

    Remplacez les éléments suivants :

    • PROJECT_ID : ID de projet de l'organisation.
    • AR_REPO_NAME : ID du dépôt.
    • AR_REGION : emplacement régional ou multirégional du dépôt.

    Variables utilisées dans les sections suivantes :

    • FLEET_HOST_PROJECT_ID : si vous utilisez la fédération d'identité de charge de travail GKE pour GKE, cette valeur est identique à PROJECT_ID. Si vous utilisez la Workload Identity Federation pour GKE pour votre parc, il s'agit de l'ID du projet dans lequel votre cluster est enregistré.
    • GSA_NAME : nom du compte de service Google personnalisé que vous souhaitez utiliser pour vous connecter à Artifact Registry.
    • KSA_NAME : compte de service Kubernetes pour le rapprochement.
      • Pour les dépôts racine, si le nom RootSync est root-sync, ajoutez root-reconciler. Sinon, ajoutez root-reconciler-ROOT_SYNC_NAME.
      • Pour les dépôts d'espaces de noms, si le nom RepoSync est repo-sync, ajoutez ns-reconciler-NAMESPACE. Sinon, ajoutez ns-reconciler-NAMESPACE-REPO_SYNC_NAME-REPO_SYNC_NAME_LENGTH, où REPO_SYNC_NAME_LENGTH correspond au nombre de caractères dans REPO_SYNC_NAME.

    Accorder l'autorisation de lecture

    Pour vous authentifier auprès d'Artifact Registry à l'aide d'un compte de service Kubernetes, procédez comme suit :

    Attribuez le rôle IAM de lecteur Artifact Registry (roles/artifactregistry.reader) au compte de service Kubernetes qui possède le pool Workload Identity Federation for 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
    

    Transférer une image vers le dépôt Artifact Registry

    Dans cette section, vous allez créer une image OCI et la transférer dans Artifact Registry.

    1. Créez un fichier manifeste Namespace :

      cat <<EOF> test-namespace.yaml
      apiVersion: v1
      kind: Namespace
      metadata:
        name: test
      EOF
      
    2. Connectez-vous à Artifact Registry :

      gcloud auth configure-docker AR_REGION-docker.pkg.dev
      
    3. Empaquetez et transférez l'image vers Artifact Registry :

      crane

      Les commandes de cette section utilisent crane pour interagir avec les images et registres distants.

      1. Empaquetez le fichier :

        tar -cf test-namespace.tar test-namespace.yaml
        
      2. Installez l'outil crane.

      3. Transférez l'image vers Artifact Registry :

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

      oras

      Les commandes de cette section utilisent oras pour interagir avec les images et registres distants.

      1. Empaquetez le fichier :

        tar -czf test-namespace.tar.gz test-namespace.yaml
        
      2. Installez l'outil oras.

      3. Transférez l'image vers Artifact Registry :

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

    Configurer Config Sync pour la synchronisation à partir de votre image

    Dans cette section, vous allez créer un objet RootSync et configurer Config Sync pour la synchronisation à partir de l'image OCI.

    1. Créez un objet RootSync avec un nom unique :

      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
      

      Remplacez ROOT_SYNC_NAME par le nom de votre objet RootSync. Le nom doit être unique dans le cluster et ne pas dépasser 26 caractères. Pour obtenir la liste complète des options de configuration des objets RootSync, consultez les champs RootSync et RepoSync.

    2. Appliquez l'objet RootSync :

      kubectl apply -f ROOT_SYNC_NAME.yaml
      
    3. Vérifiez que Config Sync est synchronisé à partir de l'image :

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

      Un résultat semblable aux lignes suivantes doit s'afficher :

      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
      

      Vous venez de synchroniser une image avec votre cluster.

    (Facultatif) Valider les signatures de la source OCI

    À partir de la version 1.20.0 de Config Sync, Config Sync permet de vérifier l'authenticité des images sources OCI avant que les configurations ne soient appliquées à vos clusters. Cette méthode utilise un objet ValidatingWebhookConfiguration et un serveur de webhook de validation pour intercepter les demandes de mise à jour des objets RootSync et RepoSync. Config Sync met à jour l'annotation configsync.gke.io/image-to-sync des objets RootSync et RepoSync après avoir récupéré un nouveau résumé d'image. Le serveur de webhook de validation compare les valeurs entre l'ancienne et la nouvelle annotation, et exécute la validation avec un outil de validation tel que Cosign lorsqu'une modification est détectée.

    Configurer un serveur de validation de signature

    Pour garantir l'authenticité de vos sources OCI, vous avez besoin d'un serveur HTTP pour valider les signatures. Vous pouvez utiliser les exemples du dépôt d'exemples Config Sync ou votre propre image Docker.

    1. Si vous souhaitez utiliser l'exemple fourni, procédez comme suit :

      1. Clonez l'exemple de dépôt :

        git clone https://github.com/GoogleCloudPlatform/anthos-config-management-samples/
        
      2. Accédez au répertoire contenant les exemples de serveur de validation de signature :

        cd anthos-config-management-samples/tree/main/pre-sync/oci-image-verification
        
    2. Pour créer une image Docker pour le serveur de validation de signature et la transférer vers un registre d'images, exécutez la commande suivante :

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

      Remplacez SIGNATURE_VERIFICATION_SERVER_IMAGE_URL par l'URL de l'image de votre serveur de validation de signature.

    S'authentifier auprès des services

    Pour configurer votre serveur de validation de signature, vous devez vous authentifier auprès d'Artifact Registry, du client Cosign et du serveur de webhook.

    1. Créez un espace de noms :

      kubectl create ns signature-verification
      
    2. Pour vous authentifier auprès d'Artifact Registry avec un compte de service Kubernetes, procédez comme suit :

      1. Créez un ServiceAccount Kubernetes dans l'espace de noms que vous avez créé :

        kubectl create sa signature-verification-sa -n signature-verification
        
      2. Ajoutez la liaison de stratégie IAM pour le rôle Lecteur 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
        

        Remplacez les éléments suivants :

        • REPOSITORY_NAME : nom de votre dépôt Artifact Registry dans lequel vous stockez vos images OCI.
        • REPOSITORY_LOCATION : emplacement de votre dépôt Artifact Registry.
    3. Pour vous authentifier auprès du client Cosign, procédez comme suit :

      1. Générez une paire de clés Cosign. Cette commande génère une clé publique et une clé privée :

        cosign generate-key-pair
        
      2. Stockez la clé publique dans un secret Kubernetes dans l'espace de noms que vous avez créé :

        kubectl create secret generic cosign-key --from-file=cosign.pub -n signature-verification
        
    4. Pour authentifier le serveur de validation des signatures, procédez comme suit :

      1. Pour chiffrer la communication au sein du serveur de validation des signatures, générez un certificat TLS et une clé privée avec 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. Stockez les identifiants que vous avez générés dans un secret Kubernetes :

        kubectl create secret tls webhook-tls --cert=tls.crt --key=tls.key -n signature-verification
        
      3. Obtenez le contenu encodé en base64 de tls.cert. Cette étape est requise pour la configuration du webhook de validation que vous allez créer dans la section suivante :

        cat tls.crt | base64 -w 0.
        

    Déployer le webhook d'admission

    Vous pouvez utiliser les exemples suivants pour créer un déploiement pour le serveur de validation de signature et une configuration de webhook de validation.

    1. Créez un déploiement pour le serveur de validation de signature en enregistrant le fichier suivant :

      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

      Remplacez SIGNATURE_VERIFICATION_SERVER_IMAGE_URL par l'URL complète de l'image du serveur de validation de la signature.

    2. Appliquez le déploiement au cluster :

      kubectl apply -f signature-verification-deployment.yaml -n signature-verification
      
    3. Créez une configuration de webhook de validation en enregistrant le fichier suivant :

      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

      Remplacez CA_BUNDLE par le contenu encodé en base64 de tls.cert.

    4. Appliquez la configuration du webhook de validation au cluster :

      kubectl apply -f signature-verification-validatingwebhookconfiguration.yaml
      

    Vérifier les journaux pour détecter les erreurs de validation des images

    Une fois que vous avez configuré votre serveur de validation d'images, toute tentative de synchronisation à partir d'images OCI non signées devrait échouer.

    Pour rechercher les erreurs de validation de la signature, consultez les journaux du serveur de validation de la signature en exécutant les commandes suivantes :

    1. Consultez les journaux kubectl :

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

      Les erreurs de kubectl liées à la validation de la signature ressemblent à ce qui suit :

      main.go:69: error during command execution: no signatures found
      
    2. Vérifiez les journaux Config Sync :

      nomos status
      

      Les erreurs de Config Sync liées à la validation de la signature ressemblent à ce qui suit :

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

    Si aucune erreur ne s'affiche, vous pouvez confirmer que l'image signée est l'objet synchronisé en inspectant votre configuration RootSync ou RepoSync :

    RootSync

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

    Remplacez ROOTSYNC_NAME par le nom de votre RootSync.

    RepoSync

     kubectl get reposync REPOSYNC_NAME -n REPOSYNC_NAMESPACE -oyaml
    

    Remplacez les éléments suivants :

    • REPOSYNC_NAME : nom de votre RepoSync.
    • REPOSYNC_NAMESPACE : nom de l'espace de noms associé à votre RepoSync.

    L'annotation configsync.gke.io/image-to-sync doit être ajoutée à votre objet RootSync ou RepoSync. L'annotation contient l'URL de l'image OCI source et le dernier condensé récupéré par Config Sync.

    Étapes suivantes