Set up ArgoCD Image Updater to automatically detect and deploy new container image versions in your GitOps workflow. Includes Git repository integration, webhook configuration, and monitoring setup.
Prerequisites
- Existing Kubernetes cluster
- ArgoCD already installed
- Git repository with Kubernetes manifests
- kubectl configured for cluster access
What this solves
ArgoCD Image Updater automatically monitors container registries for new image versions and updates your Kubernetes manifests in Git repositories. This eliminates manual image version updates while maintaining GitOps principles and audit trails.
Step-by-step installation
Update system packages
Ensure your package manager has the latest package information before installing dependencies.
sudo apt update && sudo apt upgrade -y
Install kubectl and required tools
Install kubectl for Kubernetes cluster interaction and curl for API calls.
sudo apt install -y curl git
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
Verify ArgoCD installation
Confirm that ArgoCD is already running in your cluster. ArgoCD Image Updater requires an existing ArgoCD installation.
kubectl get pods -n argocd
kubectl get svc -n argocd
Create ArgoCD Image Updater namespace and RBAC
Set up the namespace and service account with appropriate permissions for the Image Updater to function.
apiVersion: v1
kind: ServiceAccount
metadata:
name: argocd-image-updater
namespace: argocd
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: argocd-image-updater
rules:
- apiGroups:
- ""
resources:
- secrets
- configmaps
verbs:
- get
- list
- watch
- apiGroups:
- argoproj.io
resources:
- applications
- appprojects
verbs:
- get
- list
- update
- patch
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argocd-image-updater
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argocd-image-updater
subjects:
- kind: ServiceAccount
name: argocd-image-updater
namespace: argocd
kubectl apply -f /tmp/argocd-image-updater-rbac.yaml
Deploy ArgoCD Image Updater
Install the Image Updater deployment with the latest stable version from the official repository.
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml
Configure Image Updater settings
Create a ConfigMap with global configuration settings for the Image Updater behavior and logging.
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
prefix: docker.io
ping: yes
credentials: secret:argocd/docker-registry#creds
credsexpire: 10h
- name: Quay
api_url: https://quay.io
prefix: quay.io
ping: yes
- name: GitHub Container Registry
api_url: https://ghcr.io
prefix: ghcr.io
ping: yes
git.conf: |
git:
user: argocd-image-updater
email: argocd-image-updater@example.com
log.conf: |
log:
level: info
kubectl apply -f /tmp/argocd-image-updater-config.yaml
Create Git repository access secret
Configure credentials for the Image Updater to commit changes back to your Git repository.
kubectl create secret generic git-credentials \
--from-literal=username=your-git-username \
--from-literal=password=your-git-token \
-n argocd
kubectl label secret git-credentials \
"argocd.argoproj.io/secret-type=repo-creds" \
-n argocd
your-git-username and your-git-token with your actual Git credentials. Use a personal access token, not your password, for better security.Configure container registry credentials
Set up authentication for private container registries that require credentials.
kubectl create secret generic docker-registry \
--from-literal=creds=username:password \
-n argocd
kubectl label secret docker-registry \
"argocd.argoproj.io/secret-type=repository" \
-n argocd
Configure image update automation
Annotate ArgoCD Application for automatic updates
Add annotations to your existing ArgoCD Application to enable automatic image updates.
kubectl patch application my-app -n argocd --type merge --patch '{
"metadata": {
"annotations": {
"argocd-image-updater.argoproj.io/image-list": "myapp=docker.io/myuser/myapp:latest",
"argocd-image-updater.argoproj.io/write-back-method": "git",
"argocd-image-updater.argoproj.io/git-branch": "main"
}
}
}'
Configure update strategy
Define how the Image Updater should determine which new versions to deploy.
kubectl patch application my-app -n argocd --type merge --patch '{
"metadata": {
"annotations": {
"argocd-image-updater.argoproj.io/myapp.update-strategy": "semver",
"argocd-image-updater.argoproj.io/myapp.allow-tags": "regexp:^v[0-9]+\\.[0-9]+\\.[0-9]+$",
"argocd-image-updater.argoproj.io/myapp.ignore-tags": "latest,dev,staging"
}
}
}'
Enable Helm chart image updates
For Helm-based applications, configure the Image Updater to modify Helm values.
kubectl patch application my-helm-app -n argocd --type merge --patch '{
"metadata": {
"annotations": {
"argocd-image-updater.argoproj.io/image-list": "myapp=docker.io/myuser/myapp",
"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"
}
}
}'
Set up Git repository integration
Configure Git write-back settings
Set up how the Image Updater commits changes back to your Git repository with proper commit messages.
kubectl patch configmap argocd-image-updater-config -n argocd --patch '{
"data": {
"git.conf": "git:\n user: argocd-image-updater\n email: argocd-image-updater@example.com\n commit_user: ArgoCD Image Updater\n commit_email: argocd-image-updater@example.com\n commit_message_template: |\n build: automatic update of {{ .AppName }}\n \n {{ range .AppChanges -}}\n updates image {{ .Image }} tag '{{ .OldTag }}' to '{{ .NewTag }}'\n {{ end -}}"
}
}'
Configure webhook notifications
Set up webhook notifications to receive updates when images are automatically updated.
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-image-updater-config
namespace: argocd
data:
webhooks.conf: |
webhooks:
- name: slack
url: https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
method: POST
headers:
Content-Type: application/json
template: |
{
"text": "Image updated: {{ .AppName }}",
"attachments": [
{
"color": "good",
"fields": [
{{ range .AppChanges -}}
{
"title": "{{ .Image }}",
"value": "{{ .OldTag }} → {{ .NewTag }}",
"short": true
}{{ if not (last .) }},{{ end }}
{{ end -}}
]
}
]
}
kubectl patch configmap argocd-image-updater-config -n argocd --patch-file /tmp/webhook-config.yaml
Configure update schedules
Set up cron-based schedules for when the Image Updater should check for new images.
kubectl patch application my-app -n argocd --type merge --patch '{
"metadata": {
"annotations": {
"argocd-image-updater.argoproj.io/myapp.update-schedule": "0 2 *",
"argocd-image-updater.argoproj.io/myapp.platforms": "linux/amd64,linux/arm64"
}
}
}'
Monitor and troubleshoot deployments
Enable detailed logging
Configure verbose logging to help with troubleshooting and monitoring update activities.
kubectl patch deployment argocd-image-updater -n argocd --patch '{
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "argocd-image-updater",
"args": [
"--interval", "2m",
"--loglevel", "debug",
"--metrics-port", "8080",
"--health-probe-port", "8081",
"--argocd-server-addr", "argocd-server.argocd.svc.cluster.local:443",
"--insecure"
]
}
]
}
}
}
}'
Set up Prometheus metrics
Enable metrics collection for monitoring the Image Updater performance and activity.
apiVersion: v1
kind: Service
metadata:
name: argocd-image-updater-metrics
namespace: argocd
labels:
app.kubernetes.io/component: image-updater
app.kubernetes.io/name: argocd-image-updater
app.kubernetes.io/part-of: argocd
spec:
ports:
- name: metrics
port: 8080
protocol: TCP
targetPort: 8080
selector:
app.kubernetes.io/name: argocd-image-updater
kubectl apply -f /tmp/metrics-service.yaml
Create ServiceMonitor for Prometheus
Set up automatic metrics scraping if you have Prometheus Operator installed.
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: argocd-image-updater
namespace: argocd
labels:
app.kubernetes.io/component: image-updater
app.kubernetes.io/name: argocd-image-updater
spec:
endpoints:
- interval: 30s
path: /metrics
port: metrics
namespaceSelector:
matchNames:
- argocd
selector:
matchLabels:
app.kubernetes.io/name: argocd-image-updater
kubectl apply -f /tmp/servicemonitor.yaml
Verify your setup
kubectl get pods -n argocd | grep image-updater
kubectl logs -n argocd deployment/argocd-image-updater
kubectl get applications -n argocd -o json | jq '.items[].metadata.annotations | select(. != null) | to_entries[] | select(.key | contains("argocd-image-updater"))'
curl -s http://localhost:8080/metrics | grep argocd_image_updater
Check that your application has the correct annotations:
kubectl describe application my-app -n argocd | grep -A 10 Annotations
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| Image Updater pod not starting | Missing RBAC permissions | Verify ClusterRole and ClusterRoleBinding are applied correctly |
| No image updates happening | Incorrect application annotations | Check annotation syntax and ensure image-list matches your container registry |
| Git commits failing | Invalid Git credentials | Verify git-credentials secret has correct username and token |
| Registry authentication errors | Missing or invalid registry credentials | Create proper docker-registry secret with valid credentials |
| Webhook notifications not working | Incorrect webhook URL or format | Test webhook URL manually and verify JSON template syntax |
| Metrics not available | Metrics port not exposed | Ensure deployment args include --metrics-port 8080 and service is created |
Next steps
- Set up comprehensive Kubernetes monitoring to track your automated deployments
- Configure ArgoCD notifications for deployment status updates
- Implement Vault integration for secure credential management
- Set up security scanning in your GitOps pipeline
- Configure advanced RBAC policies for better security
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# ArgoCD Image Updater Production Installation Script
# Supports: Ubuntu, Debian, AlmaLinux, Rocky Linux, CentOS, RHEL, Fedora, Amazon Linux
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Configuration
GIT_USERNAME=""
GIT_TOKEN=""
GIT_EMAIL="argocd-image-updater@example.com"
ARGOCD_NAMESPACE="argocd"
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -u, --git-username Git username for repository access"
echo " -t, --git-token Git token/password for repository access"
echo " -e, --git-email Git email (default: argocd-image-updater@example.com)"
echo " -n, --namespace ArgoCD namespace (default: argocd)"
echo " -h, --help Show this help message"
echo ""
echo "Example:"
echo " $0 -u myuser -t ghp_token123 -e user@company.com"
exit 1
}
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
cleanup() {
log_error "Installation failed. Cleaning up..."
rm -f /tmp/kubectl
rm -f /tmp/argocd-image-updater-*.yaml
exit 1
}
trap cleanup ERR
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-u|--git-username)
GIT_USERNAME="$2"
shift 2
;;
-t|--git-token)
GIT_TOKEN="$2"
shift 2
;;
-e|--git-email)
GIT_EMAIL="$2"
shift 2
;;
-n|--namespace)
ARGOCD_NAMESPACE="$2"
shift 2
;;
-h|--help)
usage
;;
*)
log_error "Unknown option: $1"
usage
;;
esac
done
# Check if running as root or with sudo
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root or with sudo"
exit 1
fi
# Detect distribution and set package manager
log_info "[1/8] Detecting operating system..."
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_UPGRADE="apt upgrade -y"
PKG_INSTALL="apt install -y"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf check-update || true"
PKG_UPGRADE="dnf update -y"
PKG_INSTALL="dnf install -y"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum check-update || true"
PKG_UPGRADE="yum update -y"
PKG_INSTALL="yum install -y"
;;
*)
log_error "Unsupported distribution: $ID"
exit 1
;;
esac
log_info "Detected: $PRETTY_NAME (Package manager: $PKG_MGR)"
else
log_error "Cannot detect operating system"
exit 1
fi
# Update system packages
log_info "[2/8] Updating system packages..."
$PKG_UPDATE
$PKG_UPGRADE
# Install required tools
log_info "[3/8] Installing required tools..."
$PKG_INSTALL curl git
# Install kubectl
log_info "[4/8] Installing kubectl..."
KUBECTL_VERSION=$(curl -L -s https://dl.k8s.io/release/stable.txt)
curl -Lo /tmp/kubectl "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl"
install -o root -g root -m 0755 /tmp/kubectl /usr/local/bin/kubectl
rm -f /tmp/kubectl
# Verify kubectl installation
if ! kubectl version --client &>/dev/null; then
log_error "kubectl installation failed"
exit 1
fi
# Verify ArgoCD installation
log_info "[5/8] Verifying ArgoCD installation..."
if ! kubectl get namespace "$ARGOCD_NAMESPACE" &>/dev/null; then
log_error "ArgoCD namespace '$ARGOCD_NAMESPACE' not found. Please install ArgoCD first."
exit 1
fi
if ! kubectl get pods -n "$ARGOCD_NAMESPACE" -l app.kubernetes.io/name=argocd-server &>/dev/null; then
log_warn "ArgoCD server pods not found in namespace '$ARGOCD_NAMESPACE'"
fi
# Create RBAC configuration
log_info "[6/8] Creating ArgoCD Image Updater RBAC..."
cat > /tmp/argocd-image-updater-rbac.yaml << 'EOF'
apiVersion: v1
kind: ServiceAccount
metadata:
name: argocd-image-updater
namespace: argocd
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: argocd-image-updater
rules:
- apiGroups: [""]
resources:
- secrets
- configmaps
verbs:
- get
- list
- watch
- apiGroups: ["argoproj.io"]
resources:
- applications
- appprojects
verbs:
- get
- list
- update
- patch
- watch
- apiGroups: [""]
resources:
- events
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argocd-image-updater
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argocd-image-updater
subjects:
- kind: ServiceAccount
name: argocd-image-updater
namespace: argocd
EOF
sed -i "s/namespace: argocd/namespace: $ARGOCD_NAMESPACE/g" /tmp/argocd-image-updater-rbac.yaml
kubectl apply -f /tmp/argocd-image-updater-rbac.yaml
# Deploy ArgoCD Image Updater
log_info "[7/8] Deploying ArgoCD Image Updater..."
kubectl apply -n "$ARGOCD_NAMESPACE" -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/manifests/install.yaml
# Create configuration
cat > /tmp/argocd-image-updater-config.yaml << EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-image-updater-config
namespace: $ARGOCD_NAMESPACE
data:
registries.conf: |
registries:
- name: Docker Hub
api_url: https://registry-1.docker.io
prefix: docker.io
ping: yes
- name: Quay
api_url: https://quay.io
prefix: quay.io
ping: yes
- name: GitHub Container Registry
api_url: https://ghcr.io
prefix: ghcr.io
ping: yes
git.conf: |
git:
user: argocd-image-updater
email: $GIT_EMAIL
log.conf: |
log:
level: info
EOF
kubectl apply -f /tmp/argocd-image-updater-config.yaml
# Create Git credentials if provided
if [[ -n "$GIT_USERNAME" && -n "$GIT_TOKEN" ]]; then
log_info "Creating Git repository access credentials..."
kubectl create secret generic git-credentials \
--from-literal=username="$GIT_USERNAME" \
--from-literal=password="$GIT_TOKEN" \
-n "$ARGOCD_NAMESPACE" \
--dry-run=client -o yaml | kubectl apply -f -
kubectl label secret git-credentials \
"argocd.argoproj.io/secret-type=repo-creds" \
-n "$ARGOCD_NAMESPACE" --overwrite
fi
# Verification
log_info "[8/8] Verifying installation..."
sleep 10
# Check if Image Updater pod is running
if kubectl get pods -n "$ARGOCD_NAMESPACE" -l app.kubernetes.io/name=argocd-image-updater --field-selector=status.phase=Running | grep -q argocd-image-updater; then
log_info "ArgoCD Image Updater pod is running"
else
log_warn "ArgoCD Image Updater pod may still be starting up"
fi
# Check ConfigMap
if kubectl get configmap argocd-image-updater-config -n "$ARGOCD_NAMESPACE" &>/dev/null; then
log_info "Configuration ConfigMap created successfully"
fi
# Cleanup temporary files
rm -f /tmp/argocd-image-updater-*.yaml
log_info "ArgoCD Image Updater installation completed successfully!"
echo ""
echo "Next steps:"
echo "1. Configure your applications with image updater annotations"
echo "2. Example annotation: argocd-image-updater.argoproj.io/image-list=myapp=docker.io/myorg/myapp:latest"
echo "3. Monitor logs: kubectl logs -n $ARGOCD_NAMESPACE -l app.kubernetes.io/name=argocd-image-updater -f"
echo ""
if [[ -z "$GIT_USERNAME" || -z "$GIT_TOKEN" ]]; then
log_warn "Git credentials not provided. Create them manually if needed:"
echo "kubectl create secret generic git-credentials --from-literal=username=USER --from-literal=password=TOKEN -n $ARGOCD_NAMESPACE"
echo "kubectl label secret git-credentials 'argocd.argoproj.io/secret-type=repo-creds' -n $ARGOCD_NAMESPACE"
fi
Review the script before running. Execute with: bash install.sh