
Implementing GitOps
- Published on
- Authors
- Author
- Ram Simran G
- twitter @rgarimella0124
In todayβs rapidly evolving DevOps landscape, GitOps has become a powerful approach to managing infrastructure and deployments. By treating your entire system configuration as code, stored in Git repositories, GitOps ensures consistency, traceability, and automated synchronization between your desired state (in Git) and the actual state (in production).
This differs from traditional DevOps pipelines, where deployments are often triggered and executed directly by CI/CD tools. With GitHub Actions and GitOps principles, you can automate builds, tests, and manifest updates while leveraging tools like ArgoCD or FluxCD for pull-based deployments to Kubernetes clusters.
This guide will walk you through implementing a GitOps pipeline using GitHub Actions for CI and ArgoCD for synchronization, complete with step-by-step instructions, sample workflows, and diagrams that clearly explain each process.
π Understanding GitOps vs. Traditional DevOps
Before diving into implementation, itβs essential to understand how GitOps differs from the conventional CI/CD pipelines.
β Traditional DevOps Pipeline
In a standard setup:
- Developers push code to a repository.
- CI runs unit tests and builds artifacts.
- A Docker image is created and pushed to a registry (e.g., v2.4).
- The deployment is pushed directly to the cluster using commands like
kubectl apply.
This is a push-based model where the CI/CD tool initiates deployment.
Diagram β Traditional DevOps
+-----------------+ +----------------+ +----------------+ +----------------+ +----------------+
| Developer Code | -> | Push to Repo | -> | Run Unit Tests | -> | Build Artifact | -> | Build Image |
+-----------------+ +----------------+ +----------------+ +----------------+ +----------------+
|
v
+----------------------+
| Push to Registry |
| Deploy to K8s |
| (kubectl apply v2.4) |
+----------------------+ β GitOps Pipeline
GitOps leverages Git as the source of truth:
- CI builds and tests as usual, creating an image (e.g., v6.7).
- Instead of directly deploying, a Pull Request (PR) is raised to update Kubernetes manifests in a separate repository.
- After approval and merge, a GitOps operator like ArgoCD pulls the updated manifest and synchronizes the cluster.
This is a pull-based model where the cluster reconciles with Git changes.
Diagram β GitOps Workflow
+-----------------+ +----------------+ +----------------+ +----------------+ +----------------+
| Developer Code | -> | Push to Repo | -> | Run Unit Tests | -> | Build Artifact | -> | Build Image |
+-----------------+ +----------------+ +----------------+ +----------------+ +----------------+
|
v
+----------------+ +----------------+ +----------------+
|Push to Registry| -> | Raise PR | -> |Update Manifests|
| | | Feature Branch | | (v6.7) |
+----------------+ +----------------+ +----------------+
|
v
+----------------+ +----------------+ +----------------+
| Approve & Merge| -> | ArgoCD Pulls | -> | Sync Cluster |
| PR | |Updated Manifests| | to Match v6.7 |
+----------------+ +----------------+ +----------------+ β Benefits of GitOps with GitHub Actions
- β Version Control for Infrastructure: All changes are tracked, auditable, and reversible.
- β Consistency Across Environments: Use the same manifests across dev, staging, and production.
- β Reduced Risk: PR reviews catch errors early, and reconciliation ensures stability.
- β Scalability: Teams collaborate using Git workflows without stepping on each otherβs changes.
- β Security: No direct access to clusters from CI tools.
Drawbacks:
- Requires extra setup and tooling (like ArgoCD).
- Involves more repositories and workflows.
- Requires understanding of GitOps concepts.
β Prerequisites
To implement this pipeline, youβll need:
β A GitHub account with two repositories:
app-repo: For application code.config-repo: For Kubernetes manifests.
β A Kubernetes cluster (Minikube for testing or EKS/AKS/GKE for production).
β A container registry like Docker Hub or GitHub Container Registry.
β ArgoCD installed in the cluster.
β GitHub secrets for authentication (registry tokens, kubeconfig).
β Familiarity with Docker, YAML, and Kubernetes basics.
Install ArgoCD with:
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml Create an Application in ArgoCD pointing to your config-repo.
π Step-by-Step Implementation
β Step 1 β Application Repository Setup
In app-repo, include:
- Your application code (e.g., Node.js server).
Dockerfile.- GitHub Actions workflow (
ci.yml).
Example Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"] β Step 2 β CI Workflow with GitHub Actions
Create .github/workflows/ci.yml for building, testing, and pushing the image.
name: CI - Build and Push Image
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push
uses: docker/build-push-action@v6
with:
push: true
tags: ghcr.io/${{ github.repository_owner }}/my-app:${{ github.sha }} β Step 3 β Automate Manifest Updates via PR
After the image is built, clone config-repo, update the manifest, and create a PR.
update-manifests:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
with:
repository: your-org/config-repo
path: config
token: ${{ secrets.CONFIG_REPO_TOKEN }}
- name: Update Image Tag
run: |
sed -i 's|image: ghcr.io/your-org/my-app:.*|image: ghcr.io/your-org/my-app:${{ github.sha }}|' config/deployment.yaml
cd config
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add deployment.yaml
git commit -m "Update image to ${{ github.sha }}"
git push origin main
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
path: config
commit-message: 'Update deployment image to ${{ github.sha }}'
title: 'Automated manifest update for commit ${{ github.sha }}'
body: 'This PR updates Kubernetes manifests with the latest image.'
branch: update-manifest-${{ github.sha }} β Step 4 β ArgoCD Synchronization
ArgoCD watches config-repo and applies changes automatically after a PR merge.
Sample ArgoCD Application YAML
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/config-repo.git
targetRevision: main
path: .
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true Diagram β ArgoCD Sync
+---------------+ +--------------+ +---------------+
| Merge PR | -> | Git Commit | -> |ArgoCD Detects |
| (Manifests) | | (v6.7) | | Change |
+---------------+ +--------------+ +---------------+
|
v
+--------------+
| Apply to K8s |
| Cluster Sync |
+--------------+ β Step 5 β Adding Tests and Security
Extend your pipeline by adding tests:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install
- run: npm test Use image scanning tools like Trivy to ensure your builds are secure.
β Step 6 β Supporting Multi-Environments
Manage environments by creating branches in config-repo:
dev,staging,prod.- Parameterize manifests using Helm or Kustomize.
- Use different ArgoCD applications for each environment.
β Best Practices
- π Security First: Use GitHub OIDC instead of static secrets.
- π Monitoring: Integrate ArgoCD with Prometheus.
- π§© Tooling Choices: Helm for complex deployments, FluxCD for simpler setups.
- β© Rollback: Use Git revert and let ArgoCD sync the change.
- β Automation: Add linting, format checks, and security scans.
- π§ Avoid Pitfalls: Ensure permissions and handle merge conflicts gracefully.
π Combined Workflow Visualization
CI + GitOps Flow
Developer Workflow (GitHub Actions)
+----------------+ +---------------+ +---------------+ +---------------+ +----------------+
| Developer Code | ->| Run Unit Test | ->| Build Image | ->| Push to Registry| ->| Update Manifest|
| Push to Repo | | | | v6.7 | | (ghcr.io) | | & Raise PR |
+----------------+ +---------------+ +---------------+ +----------------+ +----------------+
GitOps Workflow (ArgoCD)
+----------------+ +----------------+ +----------------+
| Merge PR | ->| Git Commit | ->| ArgoCD Sync |
| (Update Manifests)| | (v6.7) | | to Kubernetes |
+----------------+ +----------------+ +----------------+
β Conclusion
By combining GitHub Actions with ArgoCD, you can build a secure, scalable, and auditable GitOps pipeline for Kubernetes deployments. This approach empowers teams to collaborate efficiently while minimizing risks, ensuring reproducibility, and improving visibility into infrastructure changes.
Start by implementing this for a small test app, refine your workflows, and scale toward a production-ready deployment architecture. With the right tooling and best practices, GitOps can transform your deployment process into a reliable and developer-friendly workflow.
Happy GitOps-ing! π
Cheers,
Sim