ArgoCD GitOps
Implement declarative continuous delivery for Kubernetes with ArgoCD.
When to Use This Skill
Use this skill when:
-
Implementing GitOps workflows for Kubernetes
-
Automating deployments from Git repositories
-
Managing multiple environments declaratively
-
Implementing progressive delivery strategies
-
Synchronizing cluster state with Git
Prerequisites
-
Kubernetes cluster with ArgoCD installed
-
kubectl configured
-
Git repository for manifests
-
ArgoCD CLI (optional)
Installation
Create namespace
kubectl create namespace argocd
Install ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Get admin password
kubectl -n argocd get secret argocd-initial-admin-secret
-o jsonpath="{.data.password}" | base64 -d
Port forward to access UI
kubectl port-forward svc/argocd-server -n argocd 8080:443
Login with CLI
argocd login localhost:8080
Application Definition
Basic Application
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: myapp namespace: argocd spec: project: default source: repoURL: https://github.com/org/myapp-manifests.git targetRevision: main path: environments/production destination: server: https://kubernetes.default.svc namespace: myapp syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespace=true
Helm Application
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: myapp-helm namespace: argocd spec: project: default source: repoURL: https://github.com/org/myapp-chart.git targetRevision: main path: charts/myapp helm: valueFiles: - values.yaml - values-production.yaml parameters: - name: replicaCount value: "3" - name: image.tag value: "2.0.0" destination: server: https://kubernetes.default.svc namespace: myapp syncPolicy: automated: prune: true selfHeal: true
Kustomize Application
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: myapp-kustomize namespace: argocd spec: project: default source: repoURL: https://github.com/org/myapp-manifests.git targetRevision: main path: overlays/production kustomize: images: - myapp=myregistry/myapp:2.0.0 destination: server: https://kubernetes.default.svc namespace: myapp
Projects
apiVersion: argoproj.io/v1alpha1 kind: AppProject metadata: name: myproject namespace: argocd spec: description: My Project sourceRepos: - https://github.com/org/* destinations: - namespace: myapp-* server: https://kubernetes.default.svc clusterResourceWhitelist: - group: '' kind: Namespace namespaceResourceWhitelist: - group: '' kind: '' roles: - name: developer description: Developer role policies: - p, proj:myproject:developer, applications, get, myproject/, allow - p, proj:myproject:developer, applications, sync, myproject/, allow groups: - developers
Application Sets
Git Generator
apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: myapp-environments namespace: argocd spec: generators: - git: repoURL: https://github.com/org/myapp-manifests.git revision: main directories: - path: environments/* template: metadata: name: 'myapp-{{path.basename}}' spec: project: default source: repoURL: https://github.com/org/myapp-manifests.git targetRevision: main path: '{{path}}' destination: server: https://kubernetes.default.svc namespace: 'myapp-{{path.basename}}' syncPolicy: automated: prune: true selfHeal: true
List Generator
apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: myapp-clusters namespace: argocd spec: generators: - list: elements: - cluster: production url: https://prod-cluster.example.com - cluster: staging url: https://staging-cluster.example.com template: metadata: name: 'myapp-{{cluster}}' spec: project: default source: repoURL: https://github.com/org/myapp-manifests.git targetRevision: main path: 'environments/{{cluster}}' destination: server: '{{url}}' namespace: myapp
Matrix Generator
apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: myapp-matrix namespace: argocd spec: generators: - matrix: generators: - git: repoURL: https://github.com/org/myapp-manifests.git revision: main directories: - path: apps/* - list: elements: - env: staging - env: production template: metadata: name: '{{path.basename}}-{{env}}' spec: project: default source: repoURL: https://github.com/org/myapp-manifests.git targetRevision: main path: '{{path}}/overlays/{{env}}' destination: server: https://kubernetes.default.svc namespace: '{{path.basename}}-{{env}}'
Sync Policies
Automated Sync
syncPolicy: automated: prune: true # Delete resources not in Git selfHeal: true # Revert manual changes allowEmpty: false # Don't sync empty directories syncOptions: - CreateNamespace=true - PrunePropagationPolicy=foreground - PruneLast=true retry: limit: 5 backoff: duration: 5s factor: 2 maxDuration: 3m
Sync Waves
In Kubernetes manifests
apiVersion: v1 kind: ConfigMap metadata: name: myconfig annotations: argocd.argoproj.io/sync-wave: "-1" # Sync first
apiVersion: apps/v1 kind: Deployment metadata: name: myapp annotations: argocd.argoproj.io/sync-wave: "0" # Sync second
Sync Hooks
apiVersion: batch/v1 kind: Job metadata: name: migration annotations: argocd.argoproj.io/hook: PreSync argocd.argoproj.io/hook-delete-policy: HookSucceeded spec: template: spec: containers: - name: migrate image: myapp:latest command: ["./migrate.sh"] restartPolicy: Never
CLI Commands
List applications
argocd app list
Get application details
argocd app get myapp
Sync application
argocd app sync myapp
Force sync (ignore differences)
argocd app sync myapp --force
View diff
argocd app diff myapp
Rollback
argocd app rollback myapp
Delete application
argocd app delete myapp
View logs
argocd app logs myapp
Hard refresh (clear cache)
argocd app get myapp --hard-refresh
Repository Configuration
apiVersion: v1 kind: Secret metadata: name: private-repo namespace: argocd labels: argocd.argoproj.io/secret-type: repository stringData: url: https://github.com/org/private-repo.git username: git password: ghp_xxxx
SSH key
apiVersion: v1 kind: Secret metadata: name: private-repo-ssh namespace: argocd labels: argocd.argoproj.io/secret-type: repository stringData: url: git@github.com:org/private-repo.git sshPrivateKey: | -----BEGIN OPENSSH PRIVATE KEY----- ... -----END OPENSSH PRIVATE KEY-----
Notifications
apiVersion: v1 kind: ConfigMap metadata: name: argocd-notifications-cm namespace: argocd data: service.slack: | token: $slack-token template.app-deployed: | message: Application {{.app.metadata.name}} is now {{.app.status.sync.status}}. trigger.on-deployed: | - when: app.status.operationState.phase in ['Succeeded'] send: [app-deployed]
Common Issues
Issue: Sync Fails with Diff
Problem: Resources show differences but are correct Solution: Configure ignore differences
spec: ignoreDifferences: - group: apps kind: Deployment jsonPointers: - /spec/replicas
Issue: Repository Not Accessible
Problem: ArgoCD cannot clone repository Solution: Check repository secret, verify URL and credentials
Issue: Application Stuck OutOfSync
Problem: Application never becomes synced Solution: Check resource status, review events, verify manifests
Issue: Health Check Failing
Problem: Application shows degraded health Solution: Check custom health checks, verify probe configurations
Best Practices
-
Use ApplicationSets for multi-environment deployments
-
Implement sync waves for ordered deployments
-
Use projects to isolate applications
-
Configure notifications for deployment events
-
Implement proper RBAC with projects
-
Use health checks for deployment verification
-
Enable auto-pruning to remove deleted resources
-
Keep manifests in dedicated repositories
Related Skills
-
kubernetes-ops - K8s fundamentals
-
helm-charts - Helm deployments
-
kustomize - Kustomize overlays