Set up ArgoCD Image Updater to automatically monitor container registries and update Kubernetes deployments when new image versions are available. Configure GitOps workflows with automated Git commits and Prometheus monitoring for seamless CI/CD integration.
Prerequisites
- Kubernetes cluster with ArgoCD installed
- kubectl configured with cluster admin access
- Git repository for storing application manifests
- Container registry access (Docker Hub, GitHub, etc.)
- Basic understanding of Kubernetes and GitOps concepts
What this solves
ArgoCD Image Updater automatically monitors container registries for new image versions and updates your Kubernetes deployments through GitOps workflows. This eliminates manual image updates while maintaining Git as the single source of truth for your cluster state. You get automated deployment updates with full audit trails and rollback capabilities.
Prerequisites
Before starting, ensure you have a working ArgoCD installation in your Kubernetes cluster. You'll also need Git repository access for your application manifests and container registry credentials if using private repositories.
Step-by-step installation
Install ArgoCD Image Updater with Kubernetes manifests
Deploy ArgoCD Image Updater using the official Kubernetes manifests. This installs the controller and required RBAC permissions.
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml
Verify the installation
Check that the ArgoCD Image Updater pod is running and ready in the argocd namespace.
kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-image-updater
kubectl logs -n argocd deployment/argocd-image-updater
Alternative installation with Helm
If you prefer Helm charts, you can install ArgoCD Image Updater using the community Helm chart with custom values.
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
replicaCount: 1
image:
repository: quay.io/argoproj/argocd-image-updater
tag: v0.12.2
config:
argocd:
grpcWeb: true
serverAddress: "https://argocd-server.argocd.svc.cluster.local"
insecure: false
plaintext: false
metrics:
enabled: true
serviceMonitor:
enabled: true
helm install argocd-image-updater argo/argocd-image-updater -n argocd -f values.yaml
Configure registry authentication
Create a secret for private registry authentication. This example shows Docker Hub, but works with any registry.
kubectl create secret docker-registry regcred \
--docker-server=https://index.docker.io/v1/ \
--docker-username=your-username \
--docker-password=your-password \
--docker-email=your-email@example.com \
-n argocd
Create ArgoCD Image Updater configuration
Configure the image updater with registry settings and update policies. This ConfigMap defines how the updater connects to registries and Git.
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
ping: yes
credentials: pullsecret:argocd/regcred
- name: GitHub Container Registry
api_url: https://ghcr.io
prefix: ghcr.io
ping: yes
credentials: env:GITHUB_TOKEN
git.conf: |
git:
user: argocd-image-updater
email: argocd-image-updater@example.com
ssh_config: |
Host *
PubkeyAcceptedAlgorithms +ssh-rsa
HostkeyAlgorithms +ssh-rsa
kubectl apply -f argocd-image-updater-config.yaml
Configure Git repository access
Create SSH keys for Git repository access and configure the secret for automated commits.
ssh-keygen -t ed25519 -f /tmp/argocd-image-updater -N ""
kubectl create secret generic argocd-image-updater-secret \
--from-file=sshPrivateKey=/tmp/argocd-image-updater \
-n argocd
Add the public key to your Git repository's deploy keys with write access:
cat /tmp/argocd-image-updater.pub
Update ArgoCD Image Updater deployment
Modify the deployment to mount the Git SSH key and set environment variables for registry authentication.
spec:
template:
spec:
containers:
- name: argocd-image-updater
env:
- name: GITHUB_TOKEN
valueFrom:
secretKeyRef:
name: github-token
key: token
volumeMounts:
- name: ssh-key
mountPath: /app/config/ssh
readOnly: true
- name: known-hosts
mountPath: /app/config/ssh/known_hosts
subPath: known_hosts
readOnly: true
volumes:
- name: ssh-key
secret:
secretName: argocd-image-updater-secret
defaultMode: 0600
- name: known-hosts
configMap:
name: argocd-ssh-known-hosts-cm
defaultMode: 0644
kubectl patch deployment argocd-image-updater -n argocd --patch-file argocd-image-updater-patch.yaml
Configure automatic image updates
Annotate ArgoCD applications
Add annotations to your ArgoCD Application to enable automatic image updates. These annotations tell the updater which images to monitor and how to update them.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
annotations:
argocd-image-updater.argoproj.io/image-list: myapp=nginx:1.20
argocd-image-updater.argoproj.io/myapp.update-strategy: semver
argocd-image-updater.argoproj.io/myapp.allow-tags: regexp:^1\.[2-9][0-9]\.
argocd-image-updater.argoproj.io/write-back-method: git:secret:argocd/argocd-image-updater-secret
argocd-image-updater.argoproj.io/git-branch: main
spec:
project: default
source:
repoURL: git@github.com:example/my-app-config.git
targetRevision: main
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
kubectl apply -f application.yaml
Configure update strategies
Set up different update strategies for various environments. This example shows semantic versioning with different policies for staging and production.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-staging
namespace: argocd
annotations:
argocd-image-updater.argoproj.io/image-list: myapp=nginx
argocd-image-updater.argoproj.io/myapp.update-strategy: latest
argocd-image-updater.argoproj.io/myapp.allow-tags: regexp:^[0-9]+\.[0-9]+\.[0-9]+$
argocd-image-updater.argoproj.io/write-back-method: git
spec:
source:
repoURL: https://github.com/example/my-app-config.git
path: staging
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app-production
namespace: argocd
annotations:
argocd-image-updater.argoproj.io/image-list: myapp=nginx
argocd-image-updater.argoproj.io/myapp.update-strategy: semver:~1.20
argocd-image-updater.argoproj.io/myapp.ignore-tags: latest,main,dev
argocd-image-updater.argoproj.io/write-back-method: git
spec:
source:
repoURL: https://github.com/example/my-app-config.git
path: production
Configure polling intervals
Set custom polling intervals for different applications based on update frequency requirements.
kubectl patch configmap argocd-image-updater-config -n argocd --patch '{
"data": {
"config.yaml": "interval: 2m\ndefaultUpdateStrategy: semver\nregistryTimeout: 20s\ngitTimeout: 30s\nlogLevel: info"
}
}'
Set up GitOps workflows
Configure Git repository integration
Set up the image updater to automatically commit changes to your Git repository when new images are detected.
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-image-updater-git-config
namespace: argocd
data:
config: |
git:
user: ArgoCD Image Updater
email: argocd-image-updater@example.com
commitMessageTemplate: |
build: automatic update of {{ .AppName }}
{{ range .AppChanges -}}
{{ .Image }} -> {{ .NewTag }}
{{ end -}}
Updated by ArgoCD Image Updater
kubectl apply -f git-config.yaml
Configure commit automation
Set up branch protection and automatic pull request creation for production environments.
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-image-updater-pr-config
namespace: argocd
data:
pr-template: |
## Automatic Image Update
This PR was automatically created by ArgoCD Image Updater.
### Changes
{{ range .AppChanges -}}
- {{ .AppName }}: {{ .Image }} → {{ .NewTag }}
{{ end -}}
### Verification
- [ ] Security scan passed
- [ ] Integration tests passed
- [ ] Performance regression check
/cc @devops-team
kubectl apply -f pr-template.yaml
Configure webhook notifications
Set up Slack notifications for image updates and deployment changes.
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-image-updater-webhook-config
namespace: argocd
data:
webhooks.yaml: |
webhooks:
slack:
url: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
events:
- update
- error
template: |
{
"text": "ArgoCD Image Updater: {{ .AppName }} updated {{ .Image }} to {{ .NewTag }}",
"username": "ArgoCD Image Updater",
"icon_emoji": ":rocket:"
}
kubectl apply -f webhook-config.yaml
Monitor image updates
Enable Prometheus metrics
Configure ArgoCD Image Updater to expose metrics for monitoring with Prometheus and Grafana.
apiVersion: v1
kind: Service
metadata:
name: argocd-image-updater-metrics
namespace: argocd
labels:
app.kubernetes.io/name: argocd-image-updater
spec:
selector:
app.kubernetes.io/name: argocd-image-updater
ports:
- name: metrics
port: 8080
targetPort: 8080
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: argocd-image-updater
namespace: argocd
spec:
selector:
matchLabels:
app.kubernetes.io/name: argocd-image-updater
endpoints:
- port: metrics
path: /metrics
kubectl apply -f metrics-service.yaml
Create Grafana dashboard
Import a dashboard to visualize image update metrics, registry polling, and Git commit statistics.
{
"dashboard": {
"title": "ArgoCD Image Updater",
"panels": [
{
"title": "Applications Updated",
"type": "stat",
"targets": [{
"expr": "increase(argocd_image_updater_applications_updated_total[24h])"
}]
},
{
"title": "Registry Polling Errors",
"type": "stat",
"targets": [{
"expr": "argocd_image_updater_registry_requests_errors_total"
}]
},
{
"title": "Update Rate",
"type": "graph",
"targets": [{
"expr": "rate(argocd_image_updater_applications_updated_total[5m])"
}]
}
]
}
}
Set up alerting rules
Create Prometheus alerting rules for failed updates and registry connection issues.
groups:
- name: argocd-image-updater
rules:
- alert: ImageUpdaterRegistryError
expr: increase(argocd_image_updater_registry_requests_errors_total[5m]) > 0
for: 2m
labels:
severity: warning
annotations:
summary: "ArgoCD Image Updater registry errors"
description: "Image updater has {{ $value }} registry errors in the last 5 minutes"
- alert: ImageUpdaterGitError
expr: increase(argocd_image_updater_git_requests_errors_total[5m]) > 0
for: 2m
labels:
severity: warning
annotations:
summary: "ArgoCD Image Updater Git errors"
description: "Image updater has {{ $value }} Git errors in the last 5 minutes"
kubectl apply -f alerts.yaml
Verify your setup
Test the complete ArgoCD Image Updater workflow by checking application annotations, monitoring logs, and verifying Git commits.
# Check image updater pod status
kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-image-updater
View recent logs
kubectl logs -n argocd deployment/argocd-image-updater --tail=50
Check application annotations
kubectl get application my-app -n argocd -o jsonpath='{.metadata.annotations}'
Verify metrics endpoint
kubectl port-forward -n argocd service/argocd-image-updater-metrics 8080:8080
curl http://localhost:8080/metrics | grep argocd_image_updater
Check for recent Git commits
git log --oneline --grep="ArgoCD Image Updater" --since="1 day ago"
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Image updater pod crashlooping | Missing or invalid registry credentials | Check secret exists: kubectl get secret regcred -n argocd |
| No image updates detected | Incorrect application annotations | Verify annotation syntax and image list format |
| Git push failures | SSH key not added to repository | Add public key to repository deploy keys with write access |
| Registry connection timeout | Network policy blocking access | Allow egress to registry on port 443: kubectl apply -f network-policy.yaml |
| Metrics not appearing | ServiceMonitor not created | Ensure Prometheus operator is installed and ServiceMonitor applied |
| Webhook notifications failing | Invalid webhook URL or format | Test webhook URL manually and verify payload format |
Next steps
- Secure your registry credentials with Sealed Secrets
- Set up GitLab CI/CD integration with ArgoCD
- Configure advanced ArgoCD notifications
- Add policy enforcement with OPA Gatekeeper
- Secure your ArgoCD UI with automatic SSL certificates
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# Colors for output
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly NC='\033[0m' # No Color
# Default values
NAMESPACE="${NAMESPACE:-argocd}"
GIT_USER="${GIT_USER:-argocd-image-updater}"
GIT_EMAIL="${GIT_EMAIL:-argocd-image-updater@example.com}"
REGISTRY_USERNAME="${REGISTRY_USERNAME:-}"
REGISTRY_PASSWORD="${REGISTRY_PASSWORD:-}"
REGISTRY_EMAIL="${REGISTRY_EMAIL:-}"
# Progress tracking
STEP=0
TOTAL_STEPS=8
log() {
echo -e "${BLUE}[INFO]${NC} $1"
}
success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1" >&2
}
step() {
STEP=$((STEP + 1))
echo -e "${BLUE}[$STEP/$TOTAL_STEPS]${NC} $1"
}
usage() {
cat << EOF
Usage: $0 [OPTIONS]
Install and configure ArgoCD Image Updater for automatic Kubernetes deployments
OPTIONS:
-n, --namespace ArgoCD namespace (default: argocd)
-u, --git-user Git username for commits (default: argocd-image-updater)
-e, --git-email Git email for commits (default: argocd-image-updater@example.com)
--reg-user Registry username (optional)
--reg-pass Registry password (optional)
--reg-email Registry email (optional)
-h, --help Show this help message
EXAMPLES:
$0
$0 -n my-argocd --git-user "CI Bot" --git-email "ci@company.com"
$0 --reg-user myuser --reg-pass mypass --reg-email user@example.com
EOF
}
cleanup() {
error "Installation failed. Cleaning up..."
kubectl delete -n "$NAMESPACE" -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml 2>/dev/null || true
kubectl delete secret regcred -n "$NAMESPACE" 2>/dev/null || true
kubectl delete secret argocd-image-updater-secret -n "$NAMESPACE" 2>/dev/null || true
kubectl delete configmap argocd-image-updater-config -n "$NAMESPACE" 2>/dev/null || true
rm -f /tmp/argocd-image-updater* 2>/dev/null || true
}
trap cleanup ERR
check_prerequisites() {
step "Checking prerequisites"
# Check if running as root or with sudo
if [[ $EUID -ne 0 ]] && ! sudo -n true 2>/dev/null; then
error "This script requires root privileges or sudo access"
exit 1
fi
# Detect OS and package manager
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_INSTALL="apt install -y"
PKG_UPDATE="apt update"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_INSTALL="dnf install -y"
PKG_UPDATE="dnf check-update || true"
;;
amzn)
PKG_MGR="yum"
PKG_INSTALL="yum install -y"
PKG_UPDATE="yum check-update || true"
;;
*)
error "Unsupported distro: $ID"
exit 1
;;
esac
else
error "Cannot detect OS distribution"
exit 1
fi
# Check for kubectl
if ! command -v kubectl &> /dev/null; then
error "kubectl is required but not installed"
exit 1
fi
# Check cluster connection
if ! kubectl cluster-info &> /dev/null; then
error "Cannot connect to Kubernetes cluster"
exit 1
fi
# Check if ArgoCD namespace exists
if ! kubectl get namespace "$NAMESPACE" &> /dev/null; then
error "ArgoCD namespace '$NAMESPACE' does not exist. Please install ArgoCD first."
exit 1
fi
# Check if ArgoCD is running
if ! kubectl get deployment argocd-server -n "$NAMESPACE" &> /dev/null; then
error "ArgoCD server deployment not found in namespace '$NAMESPACE'"
exit 1
fi
success "Prerequisites check passed"
}
install_dependencies() {
step "Installing dependencies"
if [[ $EUID -eq 0 ]]; then
SUDO=""
else
SUDO="sudo"
fi
$SUDO $PKG_UPDATE
case "$PKG_MGR" in
apt)
$SUDO $PKG_INSTALL curl openssh-client
;;
dnf|yum)
$SUDO $PKG_INSTALL curl openssh-clients
;;
esac
success "Dependencies installed"
}
install_image_updater() {
step "Installing ArgoCD Image Updater"
kubectl apply -n "$NAMESPACE" -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml
# Wait for deployment to be ready
log "Waiting for ArgoCD Image Updater to be ready..."
kubectl wait --for=condition=available --timeout=300s deployment/argocd-image-updater -n "$NAMESPACE"
success "ArgoCD Image Updater installed"
}
create_registry_secret() {
step "Creating registry authentication secret"
if [[ -n "$REGISTRY_USERNAME" && -n "$REGISTRY_PASSWORD" && -n "$REGISTRY_EMAIL" ]]; then
kubectl create secret docker-registry regcred \
--docker-server=https://index.docker.io/v1/ \
--docker-username="$REGISTRY_USERNAME" \
--docker-password="$REGISTRY_PASSWORD" \
--docker-email="$REGISTRY_EMAIL" \
-n "$NAMESPACE" || true
success "Registry secret created"
else
warning "Registry credentials not provided. Skipping registry secret creation."
warning "You can create it later with: kubectl create secret docker-registry regcred ..."
fi
}
generate_ssh_keys() {
step "Generating SSH keys for Git access"
# Generate SSH key pair
ssh-keygen -t ed25519 -f /tmp/argocd-image-updater -N "" -C "$GIT_EMAIL"
chmod 600 /tmp/argocd-image-updater
chmod 644 /tmp/argocd-image-updater.pub
# Create Kubernetes secret
kubectl create secret generic argocd-image-updater-secret \
--from-file=sshPrivateKey=/tmp/argocd-image-updater \
-n "$NAMESPACE" || true
success "SSH keys generated and secret created"
warning "Add the following public key to your Git repository's deploy keys with write access:"
echo "----------------------------------------"
cat /tmp/argocd-image-updater.pub
echo "----------------------------------------"
}
create_config() {
step "Creating ArgoCD Image Updater configuration"
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-image-updater-config
namespace: $NAMESPACE
data:
registries.conf: |
registries:
- name: Docker Hub
api_url: https://registry-1.docker.io
ping: yes
credentials: pullsecret:$NAMESPACE/regcred
- name: GitHub Container Registry
api_url: https://ghcr.io
prefix: ghcr.io
ping: yes
git.conf: |
git:
user: $GIT_USER
email: $GIT_EMAIL
ssh_config: |
Host *
PubkeyAcceptedAlgorithms +ssh-rsa
HostkeyAlgorithms +ssh-rsa
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
EOF
success "Configuration created"
}
update_deployment() {
step "Updating ArgoCD Image Updater deployment"
# Patch deployment to mount SSH key
kubectl patch deployment argocd-image-updater -n "$NAMESPACE" --type='json' -p='[
{
"op": "add",
"path": "/spec/template/spec/volumes",
"value": [
{
"name": "ssh-key",
"secret": {
"secretName": "argocd-image-updater-secret",
"defaultMode": 256
}
}
]
},
{
"op": "add",
"path": "/spec/template/spec/containers/0/volumeMounts",
"value": [
{
"name": "ssh-key",
"mountPath": "/app/.ssh",
"readOnly": true
}
]
}
]'
# Wait for rollout to complete
kubectl rollout status deployment/argocd-image-updater -n "$NAMESPACE"
success "Deployment updated"
}
verify_installation() {
step "Verifying installation"
# Check pod status
if kubectl get pods -n "$NAMESPACE" -l app.kubernetes.io/name=argocd-image-updater | grep -q "Running"; then
success "ArgoCD Image Updater pod is running"
else
error "ArgoCD Image Updater pod is not running"
kubectl get pods -n "$NAMESPACE" -l app.kubernetes.io/name=argocd-image-updater
exit 1
fi
# Check logs for errors
log "Checking logs for any errors..."
if kubectl logs -n "$NAMESPACE" deployment/argocd-image-updater --tail=50 | grep -i error; then
warning "Found errors in logs. Please review the logs manually."
fi
success "Installation verification completed"
echo
success "ArgoCD Image Updater has been successfully installed!"
echo
log "Next steps:"
log "1. Add the SSH public key to your Git repository's deploy keys"
log "2. Annotate your ArgoCD applications to enable image updating:"
log " kubectl annotate application myapp -n $NAMESPACE \\"
log " argocd-image-updater.argoproj.io/image-list=myimage=myregistry/myimage"
log "3. For more configuration options, visit:"
log " https://argocd-image-updater.readthedocs.io/"
}
main() {
while [[ $# -gt 0 ]]; do
case $1 in
-n|--namespace)
NAMESPACE="$2"
shift 2
;;
-u|--git-user)
GIT_USER="$2"
shift 2
;;
-e|--git-email)
GIT_EMAIL="$2"
shift 2
;;
--reg-user)
REGISTRY_USERNAME="$2"
shift 2
;;
--reg-pass)
REGISTRY_PASSWORD="$2"
shift 2
;;
--reg-email)
REGISTRY_EMAIL="$2"
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
error "Unknown option: $1"
usage
exit 1
;;
esac
done
log "Starting ArgoCD Image Updater installation..."
check_prerequisites
install_dependencies
install_image_updater
create_registry_secret
generate_ssh_keys
create_config
update_deployment
verify_installation
# Cleanup temporary files
rm -f /tmp/argocd-image-updater*
}
main "$@"
Review the script before running. Execute with: bash install.sh