
Deploying to Kubernetes Using Argo CD and GitOps
Kubernetes deployment just got a massive upgrade with Argo CD and GitOps workflows. This powerful combo transforms how we push code to production by treating infrastructure as code and using Git as the single source of truth for your entire deployment pipeline. You’ll learn how to set up Argo CD from scratch, configure GitOps workflows that sync automatically, and troubleshoot the most common deployment headaches that’ll save you hours of debugging.
How Argo CD and GitOps Actually Work
Argo CD is a declarative continuous delivery tool that lives inside your Kubernetes cluster and constantly watches your Git repositories for changes. When you push updates to your manifests, it automatically syncs those changes to your cluster without any manual intervention.
The GitOps model flips traditional CI/CD on its head. Instead of pushing deployments from your CI system, Argo CD pulls changes from Git and applies them. This creates an audit trail, makes rollbacks trivial, and ensures your cluster state always matches what’s in version control.
Here’s the flow: you commit Kubernetes manifests to Git → Argo CD detects changes → it compares desired state (Git) with actual state (cluster) → applies necessary changes → your app is deployed. The beauty is that Argo CD runs inside Kubernetes, so it has direct API access and can make changes instantly.
Traditional CI/CD | GitOps with Argo CD |
---|---|
Push-based deployments | Pull-based deployments |
CI system needs cluster credentials | No external access needed |
Manual rollback processes | Git revert = instant rollback |
Limited deployment visibility | Full Git history and UI dashboard |
Complex multi-environment setup | One Argo CD per cluster, simple config |
Complete Argo CD Setup Guide
First, you need a running Kubernetes cluster. If you’re looking for reliable infrastructure, check out VPS services or dedicated servers that can handle your Kubernetes workloads.
Install Argo CD in your cluster with these commands:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
Wait for all pods to be ready:
kubectl wait --for=condition=available --timeout=300s deployment/argocd-server -n argocd
Get the initial admin password:
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
Access the Argo CD UI by port-forwarding:
kubectl port-forward svc/argocd-server -n argocd 8080:443
Now you can access the dashboard at https://localhost:8080 with username admin
and the password from the previous step.
For production setups, you’ll want to expose Argo CD through an ingress controller. Here’s a basic nginx ingress configuration:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
spec:
rules:
- host: argocd.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 443
Setting Up Your First GitOps Application
Create a Git repository with your Kubernetes manifests. Here’s a simple example structure:
my-app/
├── deployment.yaml
├── service.yaml
└── ingress.yaml
Sample deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: nginx:1.21
ports:
- containerPort: 80
Create an Argo CD application using the CLI:
argocd app create my-app \
--repo https://github.com/yourusername/your-repo.git \
--path my-app \
--dest-server https://kubernetes.default.svc \
--dest-namespace default \
--sync-policy automated
Or create it declaratively with YAML:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/yourusername/your-repo.git
targetRevision: HEAD
path: my-app
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
The automated
sync policy means Argo CD will automatically deploy changes when it detects them in Git. The prune: true
option removes resources that are no longer in Git, and selfHeal: true
corrects any manual changes made to the cluster.
Multi-Environment Configuration
Real-world deployments need multiple environments. Here’s how to structure your repository for dev, staging, and production:
environments/
├── base/
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
├── dev/
│ ├── kustomization.yaml
│ └── patch-replicas.yaml
├── staging/
│ ├── kustomization.yaml
│ └── patch-replicas.yaml
└── production/
├── kustomization.yaml
└── patch-replicas.yaml
Base kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
Environment-specific kustomization.yaml (production example):
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../base
patchesStrategicMerge:
- patch-replicas.yaml
images:
- name: nginx
newTag: 1.21-alpine
Create separate Argo CD applications for each environment:
argocd app create my-app-prod \
--repo https://github.com/yourusername/your-repo.git \
--path environments/production \
--dest-server https://kubernetes.default.svc \
--dest-namespace production \
--sync-policy automated
Helm Charts Integration
Argo CD works seamlessly with Helm charts. You can deploy charts directly from Git repositories or Helm registries:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: prometheus
namespace: argocd
spec:
project: default
source:
chart: prometheus
repoURL: https://prometheus-community.github.io/helm-charts
targetRevision: 15.10.1
helm:
values: |
server:
persistentVolume:
size: 10Gi
alertmanager:
enabled: false
destination:
server: https://kubernetes.default.svc
namespace: monitoring
syncPolicy:
automated: {}
syncOptions:
- CreateNamespace=true
For Helm charts stored in Git, use this approach:
spec:
source:
repoURL: https://github.com/yourusername/helm-charts.git
path: charts/my-app
targetRevision: HEAD
helm:
valueFiles:
- values-production.yaml
Common Issues and Troubleshooting
Here are the most frequent problems you’ll encounter and how to fix them:
- Application stuck in “OutOfSync” state: Usually caused by manual changes to the cluster. Enable auto-sync with selfHeal or manually sync to override.
- Permission denied errors: Check your repository access. For private repos, add SSH keys or access tokens to Argo CD.
- CRD installation issues: Argo CD can’t create CRDs by default. Use sync waves or install CRDs separately.
- Resource hooks not working: Ensure your hook annotations are correct:
argocd.argoproj.io/hook: PreSync
- Large applications timing out: Increase timeout in application spec or break down into smaller apps.
Debug applications with these commands:
# Check application status
argocd app get my-app
# View application logs
argocd app logs my-app
# Force refresh from Git
argocd app get my-app --refresh
# Manual sync if needed
argocd app sync my-app
For sync hook debugging, check the application events:
kubectl describe application my-app -n argocd
Advanced GitOps Patterns
Implement progressive delivery with Argo Rollouts for canary and blue-green deployments:
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app-rollout
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 20
- pause: {duration: 10m}
- setWeight: 50
- pause: {duration: 10m}
- setWeight: 100
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: nginx:1.21
Use ApplicationSets for managing applications across multiple clusters:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: multi-cluster-app
namespace: argocd
spec:
generators:
- clusters: {}
template:
metadata:
name: '{{name}}-my-app'
spec:
project: default
source:
repoURL: https://github.com/yourusername/your-repo.git
targetRevision: HEAD
path: my-app
destination:
server: '{{server}}'
namespace: default
syncPolicy:
automated: {}
Security Best Practices
Lock down your Argo CD installation with these security measures:
- Use RBAC to restrict access:
argocd proj role create myproject read-only --description "Read-only access"
- Enable OIDC integration for authentication instead of local users
- Set up repository credentials with minimal required permissions
- Use sealed secrets or external secret operators for sensitive data
- Enable audit logging to track all changes
Configure RBAC policies:
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
policy.default: role:readonly
policy.csv: |
p, role:admin, applications, *, */*, allow
p, role:admin, clusters, *, *, allow
p, role:readonly, applications, get, */*, allow
g, argocd-admins, role:admin
Performance Optimization
Argo CD performance depends heavily on repository size and number of applications. Here are optimization strategies:
Issue | Solution | Performance Impact |
---|---|---|
Large Git repositories | Use shallow clones and sparse checkout | 50-80% faster sync times |
Many applications | Increase controller replicas | Linear scaling improvement |
Resource-heavy manifests | Use server-side apply | 30-40% less network overhead |
Frequent sync operations | Tune refresh intervals | Reduced API server load |
Configure performance settings in argocd-cm ConfigMap:
data:
timeout.reconciliation: 180s
timeout.hard.reconciliation: 0s
application.instanceLabelKey: argocd.argoproj.io/instance
server.rbac.log.enforce.enable: false
reposerver.parallelism.limit: 10
Monitor Argo CD performance with these metrics:
- Application sync duration:
argocd_app_reconcile_bucket
- Repository access time:
argocd_git_request_duration_seconds
- Controller memory usage:
process_resident_memory_bytes
- API server request rate:
argocd_server_api_request_total
This GitOps approach with Argo CD creates a rock-solid deployment pipeline that scales with your team and infrastructure. The initial setup investment pays off quickly when you need to manage multiple applications across different environments. Check out the official Argo CD documentation for more advanced configuration options and the GitHub repository for community examples and troubleshooting guides.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.