C
DevOps/CICD K8s/Lesson 03

CI/CD + Kubernetes — GitHub Actions · Pod · Deployment

60 min·theory

CI/CD + Kubernetes — GitHub Actions · Pod · Deployment

🎯 What you'll be able to do after this lesson

By the end of this lesson, you'll be confident doing all three of the following.

  • ✅ GitHub Actions / GitLab CI workflows
  • ✅ Kubernetes Pod · Deployment · Service · Ingress
  • ✅ Helm package manager + per-environment values.yml

Keep these goals as a checklist — when you can answer every item, close the lesson.

CI/CD Flow + GitHub Actions

CI/CD = Code → Production Automation:
1. Continuous Integration: Code push → automated build, test, and lint
2. Continuous Delivery: + automated staging deployment
3. Continuous Deployment: + automated production deployment

GitHub Actions (most common):

  • .github/workflows/*.yml files
  • push, PR, schedule, and manual triggers
  • Free for public repos; 2,000 minutes/month free for private repos

Example:

yaml
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20', cache: 'npm' }
      - run: npm ci
      - run: npm run lint
      - run: npm test
      - run: npm run build

Security best practices:

  • Use secrets.GITHUB_TOKEN (never paste a Personal Access Token directly)
  • Use OIDC for temporary AWS/GCP credentials (no long-lived keys)
  • Pin actions to a commit hash (not a version tag)
  • Use Dependabot to keep actions up to date automatically

Other CI/CD tools:

  • GitLab CI — built into GitLab
  • Jenkins — self-hosted, powerful but complex
  • CircleCI — quick to get started
  • ArgoCD — GitOps (Kubernetes-native)

Kubernetes — Pod · Service · Deployment

In one line: K8s = automated operations tool for containers. Born from Google's Borg → open-sourced in 2014 → now the de facto standard.

Core objects:

ObjectMeaning
PodSmallest unit of one or more containers — shares the same IP and volumes
ServiceStable entry point for Pods (stable even as Pod IPs change)
DeploymentManages the desired state of Pods (replicas, rolling updates)
StatefulSetPersistent, ordered Pods (DB, Kafka)
DaemonSetOne Pod per node (log collection, monitoring)
Job · CronJobOne-time or recurring tasks
ConfigMap · SecretConfiguration and secrets
IngressHTTP routing and TLS

Deployment example:

yaml
apiVersion: apps/v1
kind: Deployment
metadata: { name: web }
spec:
  replicas: 3
  selector: { matchLabels: { app: web } }
  template:
    metadata: { labels: { app: web } }
    spec:
      containers:
      - name: web
        image: myapp:1.0
        ports: [{ containerPort: 3000 }]
        resources:
          requests: { cpu: "100m", memory: "128Mi" }
          limits:   { cpu: "500m", memory: "512Mi" }

Rolling update (default strategy):

  • Gradually add new-version Pods → gradually remove old Pods
  • Guarantees zero-downtime deployment
  • Automatic rollback is possible on failure

Essential commands:

  • kubectl apply -f deploy.yaml — deploy
  • kubectl get pods,svc,deploy — check status
  • kubectl logs -f <pod> — stream logs
  • kubectl exec -it <pod> -- bash — enter the container
  • kubectl rollout undo deployment web — rollback
💻 📌 GitHub Actions + kubectl
# ============================================
# .github/workflows/deploy.yml
# Code push → Test → Build → Image push → K8s Deploy
# ============================================
name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write          # For OIDC

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with: { node-version: '20' }

      - run: npm ci
      - run: npm test
      - run: npm run build

      # Docker Image Build + Push
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.sha }}

      # AWS OIDC (without long-term keys)
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123:role/github-deploy
          aws-region: ap-northeast-2

      # K8s Deploy
      - uses: azure/setup-kubectl@v3
      - run: |
          aws eks update-kubeconfig --name prod-cluster
          kubectl set image deployment/web web=ghcr.io/myorg/web:${{ github.sha }}
          kubectl rollout status deployment/web --timeout=5m

# ============================================
# Practical kubectl Commands
# ============================================
# kubectl get all                          # All resources
# kubectl describe pod <name>              # Details (event·issue diagnosis)
# kubectl logs -f <pod> -c <container>     # Multi-container
# kubectl port-forward svc/web 8080:80     # Local → Cluster
# kubectl scale deployment web --replicas=5
# kubectl rollout history deployment web   # Deployment history
# kubectl rollout undo deployment web      # To previous
# kubectl top pods                         # CPU·MEM usage
# kubectl drain node-1 --ignore-daemonsets # Drain node

🤖 Try asking AI like this

Once you know the concepts in this lesson, you can give AI specific, precise instructions — not a vague 'fix this,' but a request with vocabulary — and that's where token savings begin.

  • 'Create a GitHub Actions workflow for this project (lint + test + deploy).'
  • 'Convert this app into Kubernetes deployment + service + ingress YAML.'

Why this reduces tokens

When you don't know the concepts, even after getting an AI response you have to ask 'What does that mean?' all over again. Those follow-up questions eat tokens. Learn the concepts once, and the conversation ends in a single round.

CI/CD + Kubernetes — GitHub Actions·Pod·Deployment - DevOps