Docker dan Kubernetes

Docker dan Kubernetes adalah tools penting untuk containerization dan orchestration aplikasi Go. Tutorial ini akan menjelaskan cara menggunakan keduanya.

Contoh Masalah

Bagaimana cara:

  1. Membuat Docker image
  2. Deploy ke Kubernetes
  3. Scale aplikasi
  4. Manage secrets

Penyelesaian

1. Struktur Project

myapp/
├── Dockerfile
├── k8s/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── configmap.yaml
├── main.go
└── go.mod

2. Aplikasi Go Sederhana

main.go:

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
)

func main() {
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    http.HandleFunc("/", func(w http.ResponseWriter,
        r *http.Request) {
        hostname, _ := os.Hostname()
        fmt.Fprintf(w, "Hello from %s!", hostname)
    })

    http.HandleFunc("/health", func(w http.ResponseWriter,
        r *http.Request) {
        fmt.Fprintf(w, "OK")
    })

    log.Printf("Server starting on :%s", port)
    log.Fatal(http.ListenAndServe(":"+port, nil))
}

3. Dockerfile

# Build stage
FROM golang:1.21-alpine AS builder

WORKDIR /app
COPY go.* ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp

# Run stage
FROM alpine:3.18

WORKDIR /app
COPY --from=builder /app/myapp .

EXPOSE 8080
CMD ["./myapp"]

4. Kubernetes Manifests

k8s/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
        env:
        - name: PORT
          value: "8080"
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "200m"
            memory: "256Mi"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10

k8s/service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer

k8s/configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-config
data:
  config.json: |
    {
      "environment": "production",
      "logLevel": "info"
    }    

5. Build dan Push Docker Image

# Build image
docker build -t myapp:latest .

# Test locally
docker run -p 8080:8080 myapp:latest

# Tag dan push ke registry (contoh menggunakan Docker Hub)
docker tag myapp:latest username/myapp:latest
docker push username/myapp:latest

6. Deploy ke Kubernetes

# Apply manifests
kubectl apply -f k8s/

# Check status
kubectl get pods
kubectl get services
kubectl get deployments

# Scale aplikasi
kubectl scale deployment myapp --replicas=5

# Lihat logs
kubectl logs -l app=myapp

# Port forward untuk testing
kubectl port-forward service/myapp 8080:80

Penjelasan

  1. Docker

    • Multi-stage build untuk image yang lebih kecil
    • Alpine base image untuk security
    • Proper layering untuk caching
  2. Kubernetes

    • Deployment untuk manage replicas
    • Service untuk load balancing
    • ConfigMap untuk konfigurasi
    • Health checks
    • Resource limits

Best Practices

  1. Docker

    • Use multi-stage builds
    • Minimize image size
    • Cache dependencies
    • Don’t run as root
    • Set resource limits
  2. Kubernetes

    • Use namespaces
    • Set resource quotas
    • Implement health checks
    • Use ConfigMaps/Secrets
    • Scale appropriately

Contoh Output

Build Docker image:

=> [1/8] FROM golang:1.21-alpine@sha256:123...
=> [2/8] WORKDIR /app
=> [3/8] COPY go.* ./
=> [4/8] RUN go mod download
=> [5/8] COPY . .
=> [6/8] RUN CGO_ENABLED=0 GOOS=linux go build -o myapp
=> [7/8] FROM alpine:3.18@sha256:456...
=> [8/8] COPY --from=builder /app/myapp .
=> exporting to image
=> => writing image sha256:789...
=> => naming to docker.io/library/myapp:latest

Kubernetes deployment:

NAME                     READY   STATUS    RESTARTS   AGE
myapp-6f7b9d5f7-2nlzx   1/1     Running   0          5m
myapp-6f7b9d5f7-7k9qj   1/1     Running   0          5m
myapp-6f7b9d5f7-x4g9p   1/1     Running   0          5m

NAME         TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)
myapp        LoadBalancer   10.0.0.1       <pending>     80:30000/TCP

Tips

  1. Development

    • Use docker-compose for local development
    • Implement hot reload
    • Mount volumes for code changes
  2. Production

    • Use proper monitoring
    • Implement CI/CD
    • Regular security scans
    • Backup strategies
  3. Scaling

    • Horizontal vs Vertical scaling
    • Load testing
    • Resource monitoring
    • Cost optimization

Troubleshooting

  1. Docker Issues

    • Check logs: docker logs <container>
    • Inspect container: docker inspect <container>
    • Check resource usage: docker stats
  2. Kubernetes Issues

    • Check pod logs: kubectl logs <pod>
    • Describe resources: kubectl describe pod/service/deployment
    • Check events: kubectl get events

Security

  1. Docker

    • Scan images
    • Use minimal base images
    • Don’t run as root
    • Update regularly
  2. Kubernetes

    • Use RBAC
    • Network policies
    • Pod security policies
    • Regular updates

Monitoring

  1. Metrics

    • CPU/Memory usage
    • Request latency
    • Error rates
    • Container health
  2. Tools

    • Prometheus
    • Grafana
    • Kubernetes Dashboard
    • ELK Stack