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 you a simple way 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'll create an Artifact Registry repository. To learn more about creating Artifact Registry repositories, see Create repositories.

  1. Create environment variables:

    export PROJECT_ID=PROJECT_ID
    export AR_REPO_NAME=AR_REPO_NAME
    export GSA_NAME=GSA_NAME
    export AR_REGION=AR_REGION
    

    Replace the following:

    • PROJECT_ID: your project ID
    • AR_REPO_NAME: the name that you want to give your Artifact Registry repository.
    • GSA_NAME: the name of the custom Google service account that you want to use to connect to Artifact Registry.
    • AR_REGION: the region where you want to locate the Artifact Registry repository. You can use regions such as us-central1 or multi-regions such as us.
  2. Enable the Artifact Registry API:

    gcloud services enable artifactregistry.googleapis.com \
       --project=${PROJECT_ID}
    
  3. Create an Artifact Registry repository:

    gcloud artifacts repositories create ${AR_REPO_NAME} \
          --repository-format=docker \
          --location=${AR_REGION} \
          --description="Config Sync OCI repo" \
          --project=${PROJECT_ID}
    
  4. 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
    

Push an image to the Artifact Registry repository

In this section, you'll 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: .
        auth: gcpserviceaccount
        gcpServiceAccountEmail: ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
    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. Grant the Workload Identity User (roles/iam.workloadIdentityUser) IAM role to the Google service account:

    gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:$PROJECT_ID.svc.id.goog[config-management-system/root-reconciler-${ROOT_SYNC_NAME}]" \
          ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
    
  3. Create IAM policy binding between the Google service account and Kubernetes service account:

    gcloud iam service-accounts add-iam-policy-binding \
          --role roles/iam.workloadIdentityUser \
          --member "serviceAccount:${PROJECT_ID}.svc.id.goog[config-management-system/KSA_NAME]" \
          ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
    
    • KSA_NAME: the Kubernetes service account for the reconciler. For root repositories, if the RootSync name is root-sync, KSA_NAME is root-reconciler. Otherwise, it is root-reconciler-ROOT_SYNC_NAME.
  4. Apply the RootSync object:

    kubectl apply -f ROOT_SYNC_NAME.yaml
    
  5. 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