🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

ArgoCD Image Updater Not Syncing — Fix Guide

ArgoCD Image Updater detects a new image tag but doesn't update the Application. Here's how to diagnose and fix annotation errors, registry auth issues, write-back problems, and sync failures.

DevOpsBoysMay 16, 20264 min read
Share:Tweet

ArgoCD Image Updater scans your container registry, finds a new tag, but the Application never updates. Or it updates internally but doesn't write back to Git. Here's how to find and fix it.


Understand What Image Updater Does

Image Updater watches registry every 2 minutes
  → Finds new tag matching your policy
  → Updates the Application's image parameter
  → Writes the new tag to Git (write-back mode)
  → ArgoCD syncs the change

Every step can fail silently. You need logs.


Step 1 — Check Image Updater Logs

bash
# Get the image updater pod
kubectl get pods -n argocd | grep image-updater
 
# Watch logs (most important first step)
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-image-updater -f
 
# Look for:
# "Waiting for image update" → polling is working
# "Found 0 applications with image update" → annotation not found
# "registry error" → registry auth issue
# "Failed to push" → Git write-back failing

Fix 1 — Annotation Errors on the Application

The most common issue. Wrong annotation format = Image Updater ignores the app.

bash
# Check your Application annotations
kubectl get application my-app -n argocd -o yaml | grep -A20 "annotations:"

Correct annotations format:

yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
  annotations:
    # List images to watch (namespace/name format)
    argocd-image-updater.argoproj.io/image-list: myapp=docker.io/myorg/my-app
 
    # Update strategy: latest, semver, digest, name
    argocd-image-updater.argoproj.io/myapp.update-strategy: semver
 
    # Version constraint (for semver strategy)
    argocd-image-updater.argoproj.io/myapp.allow-tags: regexp:^v[0-9]+\.[0-9]+\.[0-9]+$
 
    # Write-back method (git or argocd)
    argocd-image-updater.argoproj.io/write-back-method: git

Common annotation mistakes:

yaml
# WRONG - missing image alias
argocd-image-updater.argoproj.io/image-list: docker.io/myorg/my-app
# Must be: alias=docker.io/myorg/my-app
 
# WRONG - alias doesn't match in strategy annotation
argocd-image-updater.argoproj.io/image-list: myapp=docker.io/myorg/my-app
argocd-image-updater.argoproj.io/app.update-strategy: semver  # 'app' != 'myapp'
# Must match: myapp.update-strategy
 
# WRONG - private registry with no credentials
argocd-image-updater.argoproj.io/image-list: myapp=private-registry.com/org/app
# Need to add pull secret

Fix 2 — Registry Authentication Issues

If logs show 401 Unauthorized or manifest unknown:

bash
# Create registry credentials secret
kubectl create secret docker-registry registry-creds \
  --docker-server=docker.io \
  --docker-username=myusername \
  --docker-password=mypassword \
  -n argocd
 
# Or for ECR (use AWS credentials)
kubectl create secret generic ecr-creds \
  --from-literal=registries=123456789.dkr.ecr.ap-south-1.amazonaws.com \
  -n argocd

Configure Image Updater to use the secret:

yaml
# In image-updater configmap
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-image-updater-config
  namespace: argocd
data:
  registries.conf: |
    registries:
      - name: Docker Hub
        api_url: https://registry-1.docker.io
        credentials: secret:argocd/registry-creds#.dockerconfigjson
        defaultns: library
        default: true
      - name: Private ECR
        api_url: https://123456789.dkr.ecr.ap-south-1.amazonaws.com
        credentials: ext:/scripts/ecr-login.sh
        insecure: no

For ECR specifically — add IAM permissions to the Image Updater service account:

json
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": [
      "ecr:GetAuthorizationToken",
      "ecr:BatchGetImage",
      "ecr:DescribeImages"
    ],
    "Resource": "*"
  }]
}

Fix 3 — Write-Back to Git Not Working

Image Updater finds the update but fails to write it to Git.

bash
# Check logs for git errors
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-image-updater | grep -i "git\|write\|push"

Fix — create Git write-back credentials:

bash
# For HTTPS (GitHub token)
kubectl create secret generic git-creds \
  --from-literal=username=<github-username> \
  --from-literal=password=<github-token> \
  -n argocd

Add write-back annotations to your Application:

yaml
metadata:
  annotations:
    argocd-image-updater.argoproj.io/write-back-method: git:secret:argocd/git-creds
    argocd-image-updater.argoproj.io/git-branch: main
    # Optional: write to a specific branch
    argocd-image-updater.argoproj.io/write-back-target: "kustomization:./k8s/overlays/production"

For Helm-based apps (write to values file):

yaml
annotations:
  argocd-image-updater.argoproj.io/write-back-method: git
  argocd-image-updater.argoproj.io/myapp.helm.image-name: image.repository
  argocd-image-updater.argoproj.io/myapp.helm.image-tag: image.tag

Fix 4 — Semver Strategy Not Finding New Tags

bash
# Check what tags Image Updater sees
kubectl exec -n argocd <image-updater-pod> -- \
  argocd-image-updater test docker.io/myorg/my-app \
  --semver-constraint ">=1.0.0"

Common issues:

  • Tags use 1.0.0 format but constraint is v1.0.0 (or vice versa)
  • Registry rate limiting causing tag list failures
  • Tags are not semver-compatible
yaml
# More flexible constraint
argocd-image-updater.argoproj.io/myapp.update-strategy: semver
argocd-image-updater.argoproj.io/myapp.allow-tags: regexp:^[0-9]+\.[0-9]+\.[0-9]+$
# Matches: 1.2.3, 2.0.0, etc. (without 'v' prefix)

Fix 5 — Application Not Syncing After Image Update

Image Updater updates the tag but ArgoCD doesn't sync:

yaml
# Check Application sync policy
spec:
  syncPolicy:
    automated:
      prune: true
      selfHeal: true   # This is needed for auto-sync to work

If automated is not set, Image Updater updates the parameter but ArgoCD waits for manual sync.

bash
# Manually trigger sync to test
argocd app sync my-app

Debug Command: Test Image Updater Directly

bash
# Run a test scan against a specific image
kubectl exec -n argocd \
  $(kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-image-updater -o name) \
  -- argocd-image-updater test \
  --registries-conf /app/config/registries.conf \
  docker.io/myorg/my-app:latest \
  --semver-constraint ">=1.0.0" \
  --update-strategy semver
 
# Expected output:
# INFO[...] Fetching available tags and metadata from registry
# INFO[...] Found 5 tags
# INFO[...] Latest tag: 1.2.3

For hands-on GitOps labs with ArgoCD, KodeKloud has courses covering ArgoCD setup, ApplicationSets, and Image Updater configuration.

Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments