9.14 CI/CD Integration

Continuous Integration and Deployment with Kubernetes

This chapter covers integrating Kubernetes with modern CI/CD pipelines, focusing on GitHub Actions and security best practices.

GitHub Actions for Kubernetes

Why GitHub Actions with Kubernetes?

  • Native integration with GitHub repositories

  • Kubernetes-specific actions available in marketplace

  • Matrix builds for multi-environment deployments

  • Security scanning integration

  • Cost-effective for open source projects

Basic Workflow Structure

# .github/workflows/k8s-deploy.yml
name: Deploy to Kubernetes

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3

    - name: Log in to 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 }}
        cache-from: type=gha
        cache-to: type=gha,mode=max

Multi-Environment Deployment

# .github/workflows/multi-env-deploy.yml
name: Multi-Environment Deploy

on:
  push:
    branches: [main, develop]

jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        environment: [development, staging, production]
        include:
        - environment: development
          branch: develop
          cluster: dev-cluster
        - environment: staging
          branch: main
          cluster: staging-cluster
        - environment: production
          branch: main
          cluster: prod-cluster
          manual_approval: true

    environment:
      name: ${{ matrix.environment }}
      url: https://${{ matrix.environment }}.example.com

    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Configure kubectl
      uses: azure/setup-kubectl@v3
      with:
        version: 'v1.28.0'

    - name: Set up Kustomize
      run: |
        curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
        sudo mv kustomize /usr/local/bin/

    - name: Deploy to Kubernetes
      run: |
        echo "${{ secrets.KUBECONFIG }}" | base64 -d > kubeconfig
        export KUBECONFIG=kubeconfig

        # Update image tag in kustomization
        cd k8s/overlays/${{ matrix.environment }}
        kustomize edit set image app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

        # Apply with kubectl
        kubectl apply -k .
        kubectl rollout status deployment/app -n ${{ matrix.environment }}

Image Scanning Pipeline

Trivy Security Scanning

# .github/workflows/security-scan.yml
name: Security Scan

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    - name: Build Docker image
      run: docker build -t test-image .

    - name: Run Trivy vulnerability scanner
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: 'test-image'
        format: 'sarif'
        output: 'trivy-results.sarif'

    - name: Upload Trivy scan results
      uses: github/codeql-action/upload-sarif@v2
      with:
        sarif_file: 'trivy-results.sarif'

    - name: Fail on critical vulnerabilities
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: 'test-image'
        format: 'table'
        exit-code: '1'
        severity: 'CRITICAL,HIGH'

Advanced Security Pipeline

# .github/workflows/advanced-security.yml
name: Advanced Security Pipeline

on:
  push:
    branches: [main]

jobs:
  security-pipeline:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v4

    # Dockerfile security scanning
    - name: Scan Dockerfile
      uses: hadolint/hadolint-action@v3.1.0
      with:
        dockerfile: Dockerfile
        format: sarif
        output-file: hadolint-results.sarif

    # Build image
    - name: Build image
      run: docker build -t security-test .

    # Container image scanning
    - name: Container image scan
      uses: anchore/scan-action@v3
      with:
        image: security-test
        fail-build: true
        severity-cutoff: high

    # Kubernetes manifest scanning
    - name: Scan Kubernetes manifests
      uses: stackrox/kube-linter-action@v1
      with:
        directory: k8s/
        format: sarif
        output-file: kube-linter-results.sarif

    # SBOM generation
    - name: Generate SBOM
      uses: anchore/sbom-action@v0
      with:
        image: security-test
        format: spdx-json
        output-file: sbom.spdx.json

    # Sign container image
    - name: Install Cosign
      uses: sigstore/cosign-installer@v3

    - name: Sign container image
      run: |
        cosign sign --yes ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
      env:
        COSIGN_EXPERIMENTAL: 1

GitOps Integration with GitHub Actions

ArgoCD Sync with GitHub Actions

# .github/workflows/gitops-sync.yml
name: GitOps Sync

on:
  push:
    branches: [main]

jobs:
  update-manifests:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout config repo
      uses: actions/checkout@v4
      with:
        repository: company/k8s-config
        token: ${{ secrets.GITOPS_TOKEN }}
        path: config-repo

    - name: Update image tags
      run: |
        cd config-repo

        # Update image tag using yq
        yq eval '.spec.template.spec.containers[0].image = "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}"' \
          -i environments/production/app-deployment.yaml

        # Commit changes
        git config user.name "GitHub Actions"
        git config user.email "actions@github.com"
        git add .
        git commit -m "Update image to ${{ github.sha }}"
        git push

    - name: Trigger ArgoCD sync
      run: |
        curl -X POST \
          -H "Authorization: Bearer ${{ secrets.ARGOCD_TOKEN }}" \
          -H "Content-Type: application/json" \
          "${{ secrets.ARGOCD_URL }}/api/v1/applications/app-production/sync" \
          -d '{"revision": "HEAD"}'

Pipeline Best Practices

Security Best Practices

# Security-focused pipeline structure
jobs:
  security-checks:
    runs-on: ubuntu-latest
    steps:
    # 1. Static code analysis
    - name: CodeQL Analysis
      uses: github/codeql-action/analyze@v2

    # 2. Dependency scanning
    - name: Dependency Review
      uses: actions/dependency-review-action@v3

    # 3. Secret scanning
    - name: TruffleHog Secret Scan
      uses: trufflesecurity/trufflehog@main
      with:
        path: ./
        base: main
        head: HEAD

    # 4. Infrastructure as Code scanning
    - name: Checkov IaC scan
      uses: bridgecrewio/checkov-action@master
      with:
        directory: k8s/
        framework: kubernetes

Performance and Optimization

# Optimized pipeline with caching
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Cache Docker layers
      uses: actions/cache@v3
      with:
        path: /tmp/.buildx-cache
        key: ${{ runner.os }}-buildx-${{ github.sha }}
        restore-keys: |
          ${{ runner.os }}-buildx-

    - name: Build with cache
      uses: docker/build-push-action@v5
      with:
        context: .
        cache-from: type=local,src=/tmp/.buildx-cache
        cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max

    - name: Move cache
      run: |
        rm -rf /tmp/.buildx-cache
        mv /tmp/.buildx-cache-new /tmp/.buildx-cache

Essential Commands

# GitHub CLI for workflow management
gh workflow list
gh workflow run deploy.yml
gh run list --workflow=deploy.yml
gh run watch

# ArgoCD CLI integration
argocd login argocd.example.com
argocd app sync myapp
argocd app wait myapp

# Image signing verification
cosign verify $IMAGE_NAME
cosign verify-attestation $IMAGE_NAME

# Security scanning locally
trivy image myapp:latest
grype myapp:latest
syft myapp:latest

What’s Next?

Next, we’ll explore Service Mesh for advanced traffic management and security in microservices architectures.