BLOG POSTS
Deploying to Kubernetes Using Argo CD and GitOps

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.

Leave a reply

Your email address will not be published. Required fields are marked