Sync OCI artifacts from Artifact Registry

This page shows you how to sync an OCI artifact from Artifact Registry.

You can configure Config Sync to sync from OCI images by using Artifact Registry. To use this feature, you must enable the RootSync and RepoSync APIs.

Since Artifact Registry is a fully-managed service with support for both container images and non-container artifacts, we recommend that you use it for your container image storage and management on Google Cloud. There are multiple tools available to push artifacts to Artifact Registry. For example, you can push a Docker image, push a Helm chart, or use the go-containerregistry library to work with container registries. Choose the tool that works best for you. This page shows how to create and publish your image to a repository in Artifact Registry with crane and oras.

Create an Artifact Registry repository

In this section, you create an Artifact Registry repository. To learn more about creating Artifact Registry repositories, see Create repositories.

  1. Enable the Artifact Registry API:

    gcloud services enable artifactregistry.googleapis.com --project=PROJECT_ID
    
  2. Create an Artifact Registry repository:

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

Replace the following:

  • PROJECT_ID: the organization's project ID.
  • AR_REPO_NAME: the ID of the repository.
  • AR_REGION: the regional or multi-regional location of the repository.

Variables used in the following sections:

  • FLEET_HOST_PROJECT_ID: if you're using GKE Workload Identity Federation for GKE, this is the same as PROJECT_ID. If you're using fleet Workload Identity Federation for GKE, this is the project ID of the fleet that your cluster is registered to.
  • GSA_NAME: the name of the custom Google service account that you want to use to connect to Artifact Registry.
  • KSA_NAME: the Kubernetes service account for the reconciler.
    • For root repositories, if the RootSync name is root-sync, add root-reconciler. Otherwise, add root-reconciler-ROOT_SYNC_NAME.
    • For namespace repositories, if the RepoSync name is repo-sync, add ns-reconciler-NAMESPACE. Otherwise, add ns-reconciler-NAMESPACE-REPO_SYNC_NAME-REPO_SYNC_NAME_LENGTH where REPO_SYNC_NAME_LENGTH is the number of characters in REPO_SYNC_NAME.

Grant reader permission

If the Config Sync version is 1.17.2 or later on your cluster, you can use the Kubernetes service account to authenticate to Artifact Registry. Otherwise, use the Google service account for authentication.

Using Kubernetes service account

Grant the Artifact Registry Reader (roles/artifactregistry.reader) IAM role to the Kubernetes service account with the Workload Identity Federation for GKE pool:

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

Using Google service account

  1. Grant the Artifact Registry Reader (roles/artifactregistry.reader) IAM role to the Google service account:

    gcloud artifacts repositories add-iam-policy-binding AR_REPO_NAME \
       --location=AR_REGION \
       --member=serviceAccount:GSA_NAME@PROJECT_ID.iam.gserviceaccount.com \
       --role=roles/artifactregistry.reader \
       --project=PROJECT_ID
    
  2. Create an IAM policy binding between the Kubernetes service account and Google service account:

    gcloud iam service-accounts add-iam-policy-binding \
       --role roles/iam.workloadIdentityUser \
       --member "serviceAccount:FLEET_HOST_PROJECT_ID.svc.id.goog[config-management-system/KSA_NAME]" \
       GSA_NAME@PROJECT_ID.iam.gserviceaccount.com \
       --project=PROJECT_ID
    

Push an image to the Artifact Registry repository

In this section, you create an OCI image and push it to Artifact Registry.

  1. Create a Namespace manifest file:

    cat <<EOF> test-namespace.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: test
    EOF
    
  2. Log in to Artifact Registry:

    gcloud auth configure-docker AR_REGION-docker.pkg.dev
    
  3. Package and push the image to Artifact Registry:

    crane

    The commands in this section use crane to interact with remote images and registries.

    1. Package the file:

      tar -cf test-namespace.tar test-namespace.yaml
      
    2. Install the crane tool.

    3. Push the image to Artifact Registry:

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

    oras

    The commands in this section use oras to interact with remote images and registries.

    1. Package the file:

      tar -czf test-namespace.tar.gz test-namespace.yaml
      
    2. Install the oras tool.

    3. Push the image to Artifact Registry:

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

Configure Config Sync to sync from your image

In this section, you'll create a RootSync object and configure Config Sync to sync from the OCI image.

  1. Create a RootSync object with a unique name:

    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: .
        # The k8sserviceaccount auth type is available in version 1.17.2 and
        # later. Use `gcpserviceaccount` if using an older version.
        # auth: gcpserviceaccount
        # gcpServiceAccountEmail: GSA_NAME@PROJECT_ID.iam.gserviceaccount.com
        auth: k8sserviceaccount
    EOF
    

    Replace ROOT_SYNC_NAME with the name of your RootSync object. The name should be unique in the cluster and have no more than 26 characters. For the full list of options when configuring RootSync objects, see RootSync and RepoSync fields.

  2. Apply the RootSync object:

    kubectl apply -f ROOT_SYNC_NAME.yaml
    
  3. Verify that Config Sync is syncing from the image:

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

    You should see output similar to the following example:

    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
    

    You have now successfully synced an image to your cluster.

What's next