DEV Community

leroykayanda
leroykayanda

Posted on

Using ArgoCD Image Updater with GCP Artifact Registry

We may want the updater to trigger a deployment when an image is pushed to Artifact Registry.

We install the updater in our cluster using terraform.

resource "helm_release" "image_updater" {
  name       = "argocd-image-updater"
  repository = "https://argoproj.github.io/argo-helm"
  chart      = "argocd-image-updater"
  namespace  = "argocd"
  version    = "0.9.6"

  values = [
    <<EOF
config:
  registries:
    - name: GCP Artifact Registry
      api_url: https://europe-west1-docker.pkg.dev
      prefix: europe-west1-docker.pkg.dev
      credentials: ext:/auth/auth.sh
      credsexpire: 30m
volumes:
- configMap:
    defaultMode: 0755
    name: auth-cm
  name: auth
volumeMounts:
- mountPath: /auth
  name: auth
EOF
  ]
}
Enter fullscreen mode Exit fullscreen mode

We authenticate to ECR using the script auth.sh. The process to do this is outlined here.

To enable argocd authenticate to Artifact Registry, we make use of GCP workload indentities. This is equivalent to IRSA (IAM Role for Service Accounts) in AWS. We set up a kubernetes service account which is annotated with a GCP service account.

resource "kubernetes_service_account" "ksa" {
  metadata {
    name      = "argocd-image-updater-sa"
    namespace = "argocd"
    annotations = {
      "iam.gke.io/gcp-service-account" = google_service_account.app_sa.email
    }
  }
}

resource "google_service_account" "app_sa" {
  account_id   = "argocd-image-updater-sa"
  display_name = "argocd-image-updater-sa"
}
Enter fullscreen mode Exit fullscreen mode

The GCP SA needs artifactregistry permissions.

resource "google_project_iam_member" "artifactregistry_repoAdmin" {
  project = var.project_id
  role    = "roles/artifactregistry.repoAdmin"
  member  = "serviceAccount:${google_service_account.app_sa.email}"
}
Enter fullscreen mode Exit fullscreen mode

Allow the Kubernetes service account to impersonate the GCP service account by adding an IAM policy binding between the two service accounts. This binding allows the Kubernetes service account to act as the GCP service account.

gcloud iam service-accounts add-iam-policy-binding GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"

resource "google_service_account_iam_binding" "argo_workload_identity_binding" {
  service_account_id = google_service_account.app_sa.name
  role               = "roles/iam.workloadIdentityUser"
  members            = ["serviceAccount:${var.project_id}.svc.id.goog[argocd/argocd-image-updater-sa]"]
}
Enter fullscreen mode Exit fullscreen mode

Set up a config map contaning the artifact registry authentication script. This config map is mounted to the argocd image updater deployment as a volume.

resource "kubernetes_config_map" "auth_cm" {
  metadata {
    name      = "auth-cm"
    namespace = "argocd"
  }

  data = {
    "auth.sh" = <<EOF
#!/bin/sh
ACCESS_TOKEN=$(wget --header 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token -q -O - | grep -Eo '"access_token":.*?[^\\]",' | cut -d '"' -f 4)
echo "oauth2accesstoken:$ACCESS_TOKEN"
EOF
  }
}
Enter fullscreen mode Exit fullscreen mode

We add these annotations to our ArgoCD application.

  annotations:
    argocd-image-updater.argoproj.io/image-list: repo=repo=europe-west1-docker.pkg.dev/tumahela/demo-app/demo-ap
    argocd-image-updater.argoproj.io/repo.update-strategy: latest
Enter fullscreen mode Exit fullscreen mode

To troubleshooot, we can log in to the argocd container.

When we push an image, after a short while argocd will trigger a deployment with this new image.

kubectl exec -n argocd -it argocd-image-updater-7fc87697d5-qtnhn -- ash

Test the connection to ECR.

argocd-image-updater test europe-west1-docker.pkg.dev/tumahela/demo-app/demo-app --credentials ext:/auth/auth.sh --update-strategy latest

Trigger a deploymemnt.

argocd-image-updater run --once --loglevel trace --argocd-namespace argocd --metrics-port 0

Top comments (0)