CI/CD Pipelines
A comprehensive guide to Kubernetes CI/CD pipelines covering Jenkins, GitHub Actions, GitLab CI, Argo Workflows, Tekton, and practical implementation strategies for automating builds, tests, and deployments.
CI/CD (Continuous Integration and Continuous Delivery) is essential for modern Kubernetes deployments. It automates the build, test, and deployment process, enabling teams to deliver software faster and more reliably [citation:4].
A well-designed CI/CD pipeline for Kubernetes should:
- Build and Test: Compile code, run unit tests, and perform security scans [citation:1]
- Containerize: Build and push container images to a registry
- Deploy: Deploy manifests or Helm charts to Kubernetes clusters [citation:3]
- Validate: Run integration tests and health checks
- Rollback: Enable quick rollbacks in case of failures [citation:4]
- CI (Continuous Integration): Automates building and testing code changes
- CD (Continuous Delivery/Deployment): Automates deploying validated code to environments [citation:1]
- GitOps: Uses Git as the single source of truth for deployments [citation:3]
Jenkins
GitHub Actions
GitLab CI
Argo Workflows
Tekton
Jenkins is the most widely used CI/CD tool in enterprises. It integrates with Git, Docker, Kubernetes, cloud providers, and more through a rich plugin ecosystem [citation:1].
# Jenkins Kubernetes Plugin - Dynamic Agents
apiVersion: v1
kind: Pod
metadata:
name: jenkins-agent
spec:
containers:
- name: docker
image: docker:latest
command:
- sleep
- infinity
volumeMounts:
- name: dockersock
mountPath: /var/run/docker.sock
- name: kubectl
image: bitnami/kubectl:latest
command:
- sleep
- infinity
volumes:
- name: dockersock
hostPath:
path: /var/run/docker.sock
# Jenkinsfile (Declarative Pipeline)
pipeline {
agent {
kubernetes {
yamlFile 'jenkins-agent.yaml'
}
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
container('docker') {
sh 'docker build -t myapp:${BUILD_NUMBER} .'
sh 'docker tag myapp:${BUILD_NUMBER} registry/myapp:latest'
}
}
}
stage('Test') {
steps {
container('docker') {
sh 'docker run --rm myapp:${BUILD_NUMBER} npm test'
}
}
}
stage('Push') {
steps {
container('docker') {
withCredentials([string(credentialsId: 'docker-hub-password', variable: 'DOCKER_PASS')]) {
sh 'echo $DOCKER_PASS | docker login -u myuser --password-stdin'
sh 'docker push registry/myapp:${BUILD_NUMBER}'
}
}
}
}
stage('Deploy') {
steps {
container('kubectl') {
sh 'kubectl set image deployment/myapp myapp=registry/myapp:${BUILD_NUMBER}'
sh 'kubectl rollout status deployment/myapp'
}
}
}
}
post {
failure {
slackSend(
channel: '#alerts',
message: "Pipeline failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}"
)
}
}
}
- Use Jenkins Kubernetes Plugin for dynamic agents [citation:1]
- Define pipelines as code (Jenkinsfile) [citation:1]
- Use shared libraries for reusable pipeline code
- Integrate SonarQube for code quality gates [citation:1]
- Store credentials securely using Jenkins Credentials Store
GitHub Actions provides deep integration with GitHub repositories, a large marketplace of reusable actions, and strong support for public repos [citation:3].
# .github/workflows/build-deploy.yml
name: Build and Deploy
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
- name: Scan image for vulnerabilities
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy results to GitHub
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
deploy:
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up kubectl
uses: azure/setup-kubectl@v4
with:
version: 'latest'
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/myapp myapp=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
kubectl rollout status deployment/myapp
- Use GitHub Container Registry for storing images
- Integrate security scanning (Trivy, Snyk)
- Use environment protections for production deployments
- Store secrets in GitHub Secrets
- Use reusable workflows for shared logic
GitLab CI/CD provides a tightly integrated DevOps platform where code, pipelines, security scans, and monitoring live in one place [citation:1].
# .gitlab-ci.yml
stages:
- build
- test
- security
- deploy
variables:
REGISTRY: registry.gitlab.com
IMAGE_TAG: $CI_COMMIT_SHORT_SHA
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker build -t $REGISTRY/$CI_PROJECT_PATH:$IMAGE_TAG .
- docker push $REGISTRY/$CI_PROJECT_PATH:$IMAGE_TAG
only:
- main
test:
stage: test
image: node:18
script:
- npm install
- npm run test
- npm run coverage
coverage: '/Coverage: \d+\.\d+%/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/coverage.xml
security:
stage: security
image: aquasec/trivy:latest
script:
- trivy image --severity HIGH,CRITICAL $REGISTRY/$CI_PROJECT_PATH:$IMAGE_TAG
only:
- main
deploy:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl set image deployment/myapp myapp=$REGISTRY/$CI_PROJECT_PATH:$IMAGE_TAG
- kubectl rollout status deployment/myapp
only:
- main
environment:
name: production
url: https://myapp.example.com
- Use Auto DevOps for automated pipeline generation [citation:1]
- Leverage built-in security scanning (SAST, DAST, Dependency Scanning)
- Use environments for deployment tracking
- Store CI/CD variables securely
- Use pipeline caching to speed up builds
Kubernetes-native CI/CD tools like Tekton and Argo Workflows run entirely on Kubernetes, treating pipeline components as Kubernetes resources [citation:5].
Tekton
# Tekton Task
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: build-and-push
spec:
params:
- name: image
type: string
steps:
- name: build
image: docker:latest
script: |
docker build -t $(params.image) .
docker push $(params.image)
# Tekton Pipeline
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: ci-pipeline
spec:
params:
- name: image
type: string
workspaces:
- name: source
tasks:
- name: build
taskRef:
name: build-and-push
params:
- name: image
value: $(params.image)
workspaces:
- name: source
workspace: source
- name: deploy
taskRef:
name: deploy
params:
- name: image
value: $(params.image)
runAfter:
- build
# Tekton PipelineRun
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: ci-pipeline-run
spec:
pipelineRef:
name: ci-pipeline
params:
- name: image
value: registry/myapp:latest
workspaces:
- name: source
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Argo Workflows
# Argo Workflow
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
name: ci-workflow
spec:
entrypoint: ci
templates:
- name: ci
steps:
- - name: build
template: build
- - name: test
template: test
- - name: deploy
template: deploy
- name: build
container:
image: docker:latest
command: ["/bin/sh", "-c"]
args: ["docker build -t myapp:latest . && docker push myapp:latest"]
- name: test
container:
image: node:18
command: ["/bin/sh", "-c"]
args: ["npm install && npm test"]
- name: deploy
container:
image: bitnami/kubectl:latest
command: ["/bin/sh", "-c"]
args: ["kubectl set image deployment/myapp myapp=myapp:latest"]
- Builds run in ephemeral pods, not persistent VMs [citation:5]
- Use PVCs for caching (Docker layers, npm packages) [citation:5]
- Tekton has a higher learning curve but is extremely flexible [citation:3]
- Argo Workflows is ideal for complex, parallel workflows
- Both are open-source and Kubernetes-native
ArgoCD is the leading GitOps tool for Kubernetes. It monitors Git repositories and automatically synchronizes the cluster state with declared manifests [citation:3].
# ArgoCD Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp
targetRevision: HEAD
path: kubernetes/
helm:
valueFiles:
- values-prod.yaml
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
# CI Pipeline with ArgoCD
# GitHub Actions: Build image and update Git
- name: Update Git for ArgoCD
run: |
git clone https://github.com/myorg/myapp-config
cd myapp-config
yq eval -i '.image.tag = "${{ github.sha }}"' values-prod.yaml
git config user.email "ci@example.com"
git config user.name "CI Bot"
git add .
git commit -m "Update image to ${{ github.sha }}"
git push
- CI builds image and pushes to registry
- CI updates Git repository with new image tag
- ArgoCD detects the change and deploys [citation:3]
- ArgoCD continuously reconciles to maintain desired state
- Rollback is a simple Git revert [citation:4]
| Tool | Model | Kubernetes Native | GitOps | Complexity | Best For |
|---|---|---|---|---|---|
| Jenkins | Push-based | Partial | No | Medium | Complex pipelines, enterprises |
| GitHub Actions | Push-based | Partial | No | Low | GitHub-based workflows |
| GitLab CI | Push-based | Partial | No | Low | All-in-one DevOps |
| Tekton | Cloud-native | Yes | Partial | High | Cloud-native pipelines |
| Argo Workflows | Cloud-native | Yes | Partial | High | Complex workflows, ML |
| ArgoCD | Pull-based (GitOps) | Yes | Yes | Low | Kubernetes CD |
- Jenkins: Best for enterprises with existing Jenkins infrastructure
- GitHub Actions: Best for GitHub-based workflows
- GitLab CI: Best for all-in-one DevOps platform
- Tekton: Best for cloud-native, Kubernetes-centric teams
- ArgoCD: Best for GitOps-driven Kubernetes deployments [citation:3]
A well-designed CI/CD pipeline is essential for fast, reliable Kubernetes deployments. Choose the right tools for your needs and implement security scanning and GitOps practices for production-grade delivery.