Back to Blog
Tutorial January 8, 2025 10 min read

GitOps with ArgoCD on KubeBid

Set up continuous deployment with ArgoCD. Automatic rollbacks, drift detection, and policy enforcement for your clusters.

MJ
Michael Johnson
Senior DevOps Engineer

GitOps is the practice of using Git as the single source of truth for declarative infrastructure and applications. With ArgoCD on KubeBid, you can automate deployments, detect configuration drift, and roll back changes automatically. This tutorial walks you through the setup.

Why GitOps?

Traditional deployment pipelines push changes to clusters. GitOps flips this model: the cluster pulls its desired state from Git. This provides several benefits:

Prerequisites

Step 1: Install ArgoCD

KubeBid offers ArgoCD as a one-click add-on, or you can install it manually:

# Option 1: One-click install via KubeBid CLI
kubebid addons install argocd --cluster my-cluster

# Option 2: Manual install
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Wait for ArgoCD to be ready
kubectl wait --for=condition=available deployment/argocd-server -n argocd --timeout=300s

Step 2: Access the ArgoCD UI

Get the initial admin password and expose the UI:

# Get the initial admin password
ARGO_PWD=$(kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d)
echo "ArgoCD Password: $ARGO_PWD"

# Port forward to access the UI
kubectl port-forward svc/argocd-server -n argocd 8080:443

# Or create an Ingress for permanent access
cat <

Step 3: Set Up Your Git Repository

Create a repository structure for your Kubernetes manifests:

my-app-config/
├── apps/
│   ├── production/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   └── kustomization.yaml
│   └── staging/
│       ├── deployment.yaml
│       ├── service.yaml
│       └── kustomization.yaml
├── base/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
└── argocd/
    └── applications.yaml

Example base deployment:

# base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: myorg/my-app:latest
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml
# apps/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: production
resources:
  - ../../base
replicas:
  - name: my-app
    count: 5
images:
  - name: myorg/my-app
    newTag: v1.2.3

Step 4: Create ArgoCD Applications

Define your applications in ArgoCD:

# argocd/applications.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-production
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/my-app-config.git
    targetRevision: main
    path: apps/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true        # Delete resources removed from Git
      selfHeal: true     # Revert manual changes
    syncOptions:
      - CreateNamespace=true
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-staging
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/my-app-config.git
    targetRevision: main
    path: apps/staging
  destination:
    server: https://kubernetes.default.svc
    namespace: staging
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

Apply the applications:

kubectl apply -f argocd/applications.yaml

Step 5: Connect Your Git Repository

If your repository is private, add credentials:

# Using the CLI
argocd login argocd.your-domain.com

# Add repository with SSH key
argocd repo add git@github.com:myorg/my-app-config.git \
  --ssh-private-key-path ~/.ssh/id_rsa

# Or with HTTPS and token
argocd repo add https://github.com/myorg/my-app-config.git \
  --username git \
  --password $GITHUB_TOKEN

Step 6: Deploy with GitOps

Now deployment is as simple as pushing to Git:

# Update the image tag in your config repo
cd my-app-config
sed -i 's/newTag: v1.2.3/newTag: v1.2.4/' apps/production/kustomization.yaml

# Commit and push
git add .
git commit -m "Deploy v1.2.4 to production"
git push origin main

# ArgoCD will automatically detect the change and deploy

Advanced: Rollback and History

View deployment history and rollback:

# View sync history
argocd app history my-app-production

# Rollback to previous version
argocd app rollback my-app-production 2

# Or via Git
git revert HEAD
git push origin main

Advanced: Sync Waves and Hooks

Control deployment order with sync waves:

# Deploy database migration before app
apiVersion: batch/v1
kind: Job
metadata:
  name: db-migration
  annotations:
    argocd.argoproj.io/sync-wave: "-1"  # Run before wave 0
    argocd.argoproj.io/hook: PreSync
spec:
  template:
    spec:
      containers:
      - name: migrate
        image: myorg/migrations:latest
        command: ["./migrate.sh"]
      restartPolicy: Never
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  annotations:
    argocd.argoproj.io/sync-wave: "0"  # Default wave
spec:
  # ...

Integrating with KubeBid Bid Strategies

Combine GitOps with KubeBid's bid strategies for cost-optimized deployments:

# Include bid strategy in your deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ml-training
  annotations:
    kubebid.io/bid-strategy: cost-optimized
spec:
  replicas: 10
  template:
    spec:
      containers:
      - name: trainer
        image: myorg/trainer:v1
        resources:
          requests:
            nvidia.com/gpu: 1

Best Practices

  1. Separate config from code: Keep your Kubernetes manifests in a dedicated repository
  2. Use Kustomize or Helm: Don't duplicate YAML across environments
  3. Enable auto-sync carefully: Start with manual sync in production, enable auto-sync once confident
  4. Set up notifications: Alert on sync failures via Slack/PagerDuty
  5. Use ApplicationSets: Manage multiple clusters from a single definition

Next Steps

Now that you have GitOps set up, explore:

Michael Johnson is a Senior DevOps Engineer at KubeBid, specializing in CI/CD and platform engineering.