cloud-kubernetes-deployment

Deploy and manage applications on Kubernetes with production best practices

Kubernetes Deployment

Deploy and manage containerized applications on Kubernetes with production best practices for high availability, security, and scalability.

Hanzo Production Reality (read first)

For Hanzo/Lux services this generic skill is background knowledge only — deployment is prescribed by HIP-0117 (one binary, three modes) and the operator. See skills/hanzo-cloud-architecture/SKILL.md.

  1. cloud serve — single process, NO Kubernetes. The whole cloud

(IAM, KMS, o11y, tasks, console, ...) in one binary with per-tenant SQLite. This is local dev and single-node/edge production.

  1. cloud cluster init — the binary fetches k3s, bootstraps the

cluster, installs the operator, and hands reconciliation to services.hanzo.ai CRs. Devs do NOT hand-write Deployments; the operator reconciles CRs. (Decided per HIP-0117; staged.)

  1. helm install cloud ./helm/cloud — BYO Kubernetes, same image.

Rules that override the generic advice below:

never by kubectl create deployment.

our runners); GitHub is the OSS mirror. Never build images locally.

providers (BYO provider).

Overview

This skill covers Kubernetes deployment strategies, including:

When to Use

Prerequisites

Key Concepts

Kubernetes Resources

Workloads:

Services:

Configuration:

Security:

Deployment Strategies

Rolling Update (Default):

Recreate:

Canary:

Blue-Green:

Basic Usage

Create Deployment

# From command line
kubectl create deployment web --image=nginx:1.25 --replicas=3

# From YAML
kubectl apply -f deployment.yaml

deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 256Mi

Expose with Service

# Create service
kubectl expose deployment web --port=80 --type=LoadBalancer

# From YAML
kubectl apply -f service.yaml

service.yaml:

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

Update Deployment

# Update image
kubectl set image deployment/web nginx=nginx:1.26

# Edit deployment
kubectl edit deployment/web

# Apply changes from file
kubectl apply -f deployment.yaml

# Monitor rollout
kubectl rollout status deployment/web

Rollback Deployment

# View history
kubectl rollout history deployment/web

# Rollback to previous version
kubectl rollout undo deployment/web

# Rollback to specific revision
kubectl rollout undo deployment/web --to-revision=2

Advanced Patterns

Production-Ready Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
  labels:
    app: api
    version: v1
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
        version: v1
    spec:
      serviceAccountName: api
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 2000

      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - api
              topologyKey: kubernetes.io/hostname

      containers:
      - name: api
        image: myapp/api:v1.0.0
        ports:
        - name: http
          containerPort: 8080

        env:
        - name: DB_HOST
          valueFrom:
            configMapKeyRef:
              name: api-config
              key: db.host
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: api-secrets
              key: db.password

        resources:
          requests:
            cpu: 500m
            memory: 512Mi
          limits:
            cpu: 2
            memory: 2Gi

        startupProbe:
          httpGet:
            path: /healthz/startup
            port: http
          periodSeconds: 10
          failureThreshold: 30

        livenessProbe:
          httpGet:
            path: /healthz/live
            port: http
          periodSeconds: 10
          failureThreshold: 3

        readinessProbe:
          httpGet:
            path: /healthz/ready
            port: http
          periodSeconds: 5
          failureThreshold: 3

        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          capabilities:
            drop:
            - ALL

        volumeMounts:
        - name: tmp
          mountPath: /tmp

      volumes:
      - name: tmp
        emptyDir: {}

Horizontal Pod Autoscaler

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

ConfigMap and Secret

# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: api-config
data:
  db.host: "postgres.default.svc.cluster.local"
  db.port: "5432"
  app.yaml: |
    server:
      port: 8080
      timeout: 30s
---
# Secret
# ❌ BAD: Hardcoded credentials - example only, never do this in production
# In production, use sealed-secrets, external-secrets-operator, or your cloud provider's secret management
apiVersion: v1
kind: Secret
metadata:
  name: api-secrets
type: Opaque
stringData:
  db.password: "changeme123"  # Example only - use secret management in production
  api.key: "secret-api-key"  # Example only - use secret management in production

Common Commands

# Get resources
kubectl get deployments
kubectl get pods
kubectl get services
kubectl get all

# Describe resource
kubectl describe deployment web
kubectl describe pod web-abc123

# View logs
kubectl logs deployment/web
kubectl logs -f pod/web-abc123  # Follow logs
kubectl logs pod/web-abc123 --previous  # Previous container

# Execute commands in pod
kubectl exec -it pod/web-abc123 -- /bin/sh

# Port forwarding
kubectl port-forward deployment/web 8080:80

# Scale deployment
kubectl scale deployment/web --replicas=5

# Delete resources
kubectl delete deployment web
kubectl delete -f deployment.yaml

Troubleshooting

Pod Not Starting

# Check pod status
kubectl get pods
kubectl describe pod <pod-name>

# Common issues:
# - ImagePullBackOff: Check image name and registry credentials
# - CrashLoopBackOff: Check logs for application errors
# - Pending: Check resource availability and node constraints

# View events
kubectl get events --sort-by='.lastTimestamp'

# Check logs
kubectl logs <pod-name>

Service Not Accessible

# Check service and endpoints
kubectl get service web
kubectl get endpoints web

# Test DNS
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup web

# Test connectivity
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- curl http://web

Deployment Not Rolling Out

# Check rollout status
kubectl rollout status deployment/web

# View deployment events
kubectl describe deployment web

# Check replica sets
kubectl get rs -l app=web

# Pause and resume
kubectl rollout pause deployment/web
kubectl rollout resume deployment/web

Best Practices

Resource Management

Health Checks

Security

High Availability

Configuration

Deployment

Related Skills

Level 3: Resources

Comprehensive resources for Kubernetes deployment are available in the resources/ directory:

Reference Material

resources/REFERENCE.md (1,800+ lines) Complete reference covering:

Executable Scripts

resources/scripts/validate_manifests.py Validate Kubernetes YAML manifests for correctness and best practices:

# Validate single file
./validate_manifests.py deployment.yaml

# Validate directory
./validate_manifests.py --strict manifests/

# JSON output
./validate_manifests.py --json deployment.yaml

resources/scripts/analyze_deployment.py Analyze deployments for issues and optimization opportunities:

# Analyze file
./analyze_deployment.py deployment.yaml

# Analyze live cluster
./analyze_deployment.py --cluster --namespace production

# JSON output
./analyze_deployment.py --json --cluster

resources/scripts/test_deployment.sh Test deployments in local Kubernetes cluster:

# Test with kind
./test_deployment.sh deployment.yaml

# Test with minikube
./test_deployment.sh --provider minikube manifests/

# Keep cluster for debugging
./test_deployment.sh --no-cleanup deployment.yaml

Examples

resources/examples/manifests/basic-deployment/ Simple deployment example:

resources/examples/manifests/production-deployment/ Production-ready deployment:

resources/examples/helm/sample-chart/ Complete Helm chart structure:

resources/examples/kustomize/ Kustomize overlays for environments:

resources/examples/cicd/github-actions-deploy.yml Complete GitHub Actions workflow:

Learning Path

  1. Start: Basic deployment and service creation
  2. Intermediate: Add health checks, resource limits, ConfigMaps
  3. Advanced: Implement autoscaling, GitOps, production patterns
  4. Expert: Multi-cluster, service mesh, advanced networking

See Also