GitOps Workflow
Complete guide to implementing declarative, Git-based continuous delivery for Kubernetes using ArgoCD or Flux CD, following OpenGitOps principles.
When to Use
- Setting up GitOps for Kubernetes clusters
- Automating application deployments from Git
- Implementing progressive delivery strategies (canary, blue-green)
- Managing multi-cluster deployments
- Configuring automated sync policies
- Setting up secret management in GitOps
Do not use this skill when:
- You need a one-off manual deployment
- You cannot manage cluster access or repo permissions
- You are not deploying to Kubernetes
Prerequisites
- A running Kubernetes cluster with
kubectlconfigured and cluster-admin access - A Git repository (GitHub, GitLab, or other) with push permissions
kubectlinstalled and authenticated (kubectl get nodesmust succeed)- For ArgoCD: network access to apply manifests from
raw.githubusercontent.com - For Flux:
fluxCLI installed (see Procedure step for installation) - For Windows/PowerShell hosts:
kubectlworks identically in PowerShell; useSelect-Stringinstead ofgrepand$env:VARinstead of$VARfor environment variables
Procedure
1. Define Repository Layout and Desired-State Conventions
Establish a clear repo structure separating applications, infrastructure, and GitOps controller configs:
gitops-repo/
├── apps/
│ ├── production/
│ │ ├── app1/
│ │ │ ├── kustomization.yaml
│ │ │ └── deployment.yaml
│ │ └── app2/
│ └── staging/
├── infrastructure/
│ ├── ingress-nginx/
│ ├── cert-manager/
│ └── monitoring/
└── argocd/
├── applications/
└── projects/
For Flux, use a clusters/ directory layout:
gitops-repo/
├── clusters/
│ ├── production/
│ │ ├── flux-system/
│ │ ├── apps/
│ │ └── infrastructure/
│ └── staging/
└── apps/
└── base/
2. Install ArgoCD
# 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
Load
references/argocd-setup.mdwhen the user needs detailed ArgoCD installation, ingress configuration, SSO setup, or RBAC customization beyond the basic install above.
3. Create an ArgoCD Application
# argocd/applications/my-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/gitops-repo
targetRevision: main
path: apps/production/my-app
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Apply it:
kubectl apply -f argocd/applications/my-app.yaml
4. App of Apps Pattern (ArgoCD)
For managing many applications from a single root Application:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: applications
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/org/gitops-repo
targetRevision: main
path: argocd/applications
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated: {}
5. Install Flux CD
# Install Flux CLI (macOS)
brew install fluxcd/tap/flux
# Alternative: download the official installer, inspect it, then execute it
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
curl -fsSLo "$tmpdir/flux-install.sh" https://fluxcd.io/install.sh
cat "$tmpdir/flux-install.sh" # review the full installer before sudo
sudo bash "$tmpdir/flux-install.sh"
# Bootstrap Flux
flux bootstrap github \
--owner=org \
--repository=gitops-repo \
--branch=main \
--path=clusters/production \
--personal
6. Create Flux GitRepository Source
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: my-app
namespace: flux-system
spec:
interval: 1m
url: https://github.com/org/my-app
ref:
branch: main
7. Create Flux Kustomization
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: my-app
namespace: flux-system
spec:
interval: 5m
path: ./deploy
prune: true
sourceRef:
kind: GitRepository
name: my-app
8. Configure Sync Policies
ArgoCD auto-sync:
syncPolicy:
automated:
prune: true # Delete resources not in Git
selfHeal: true # Reconcile manual changes
allowEmpty: false
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
Flux sync:
spec:
interval: 1m
prune: true
wait: true
timeout: 5m
Load
references/sync-policies.mdwhen the user needs advanced sync configuration: retry/backoff tuning, health assessments, wave sync, or multi-environment promotion flows.
9. Progressive Delivery
Canary deployment with ArgoCD Rollouts:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
replicas: 5
strategy:
canary:
steps:
- setWeight: 20
- pause: {duration: 1m}
- setWeight: 50
- pause: {duration: 2m}
- setWeight: 100
Blue-green deployment:
strategy:
blueGreen:
activeService: my-app
previewService: my-app-preview
autoPromotionEnabled: false
10. Secret Management
Option A — External Secrets Operator (recommended):
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
target:
name: db-credentials
data:
- secretKey: password
remoteRef:
key: prod/db/password
Option B — Sealed Secrets:
# Encrypt secret
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
# Commit sealed-secret.yaml to Git
HARD RULE: Never commit plaintext Kubernetes Secrets to Git. Always use sealed secrets or an external secret manager (External Secrets Operator, Vault, cloud KMS).
Pitfalls
- Auto-sync to production without approvals — Avoid enabling
automated.syncon production Applications without a prior approval gate. UseautoPromotionEnabled: falsefor blue-green or manual sync for production. - Secrets in Git — Never store raw Kubernetes Secret manifests in Git. Use Sealed Secrets or External Secrets Operator.
- Missing
prune: true— Without prune, deleted Git resources remain in the cluster, causing drift between Git and cluster state. selfHeal: trueon namespaces with manual operators — Self-heal will revert manual changes made by operators (e.g., HPA scaling), causing conflicts.- Flux bootstrap with wrong
--path— The--pathflag determines where Flux stores its manifests in the repo. Changing it later requires manual cleanup. - ArgoCD
argocd-initial-admin-secretnot deleted — After changing the admin password, delete the initial secret:kubectl -n argocd delete secret argocd-initial-admin-secret. Leaving it is a security risk. - No RBAC on Git repo — Anyone with push access can deploy anything. Implement branch protection and required reviews.
- No notifications on sync failure — Without alerts, drift or sync failures go unnoticed. Enable ArgoCD notifications or Flux alert providers.
- Windows PowerShell line-continuation — In PowerShell, use backtick
`instead of\for line continuation in multi-line commands. YAML files are unaffected. - Flux installer not inspected before execution — Always review the downloaded
flux-install.shbefore running withsudo, as shown in the procedure.
Verification
ArgoCD
# Check ArgoCD server is running
kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server
# Verify application sync status
argocd app get my-app
# Check for out-of-sync resources
argocd app diff my-app
# Force sync if needed
argocd app sync my-app --prune
argocd app sync my-app --force
Expected output: Health: Healthy and Sync Status: Synced.
Flux
# Check Flux controllers are running
kubectl get pods -n flux-system
# Verify GitRepository is ready
flux get sources git
# Verify Kustomization is reconciling
flux get kustomizations
# Check reconciliation logs
flux logs --all-namespaces
Expected output: Ready: True for all sources and kustomizations.
General Cluster Verification
# Confirm deployed resources match Git state
kubectl get all -n production
# Verify no orphaned resources (prune working)
kubectl get deployments -n production
Related Skills
k8s-manifest-generator— For creating Kubernetes manifestshelm-chart-scaffolding— For packaging applications as Helm charts
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.