Stay organized with collections Save and categorize content based on your preferences.

Sync OCI artifacts from Artifact Registry

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

From Anthos Config Management version 1.12.0 and later, you can configure Config Sync to sync from OCI images. This page uses Artifact Registry as an example, but you can also use Container 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.

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 download a public OCI image and push it to Artifact Registry. The commands in this section use crane to interact with remote images and registries.

  1. Download the crane tool:

    go install github.com/google/go-containerregistry/cmd/crane@latest
    
  2. Log in to Artifact Registry:

    crane auth login ${AR_REGION}-docker.pkg.dev  -u oauth2accesstoken -p "$(gcloud auth print-access-token)"
    
  3. Download the public OCI image:

    mkdir kustomize-components && cd kustomize-components && crane export \
    us-docker.pkg.dev/stolos-dev/config-sync-ci-public/kustomize-components:latest - | tar -xvf -
    
  4. Create and push the image to Artifact Registry:

    crane append -f <(tar -f - -c .) -t \
    ${AR_REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO_NAME}/kustomize-components
    

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}/kustomize-components
        dir: tenant-a
        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
    
  1. 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.
  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>   ${AR_REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO_NAME}/kustomize-components/tenant-a
       SYNCED   d2ba9708dc6f2573d13938d735ba6e1ed12988d50dec679d3e8a1e8885cf90e4
       Managed resources:
       NAMESPACE   NAME                                                             STATUS    SOURCEHASH
                   namespace/tenant-a                                               Current   d1ba970
       tenant-a    networkpolicy.networking.k8s.io/deny-all                         Current   d1ba970
       tenant-a    role.rbac.authorization.k8s.io/tenant-admin                      Current   d1ba970
       tenant-a    rolebinding.rbac.authorization.k8s.io/tenant-admin-rolebinding   Current   d1ba970
    

    You have now successfully synced your cluster to an image.

What's next