Using ArgoCD Image Updater with GCP Artifact Registry
leroykayanda
Posted on March 25, 2024
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
]
}
We authenticate to Artifact Registry 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"
}
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}"
}
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]"]
}
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
}
}
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
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
Posted on March 25, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024