# Application Deployment

> Panduan lengkap untuk deployment aplikasi di Kubernetes, dari pods hingga services, dengan praktik terbaik dan contoh production-ready.

## 📋 Daftar Isi

* [📦 Pods & Containers](#pods--containers)
* [🚀 Deployments](#deployments)
* [🌐 Services](#services)
* [⚙️ ConfigMaps & Secrets](#configmaps--secrets)
* [📊 Scaling](#scaling)
* [🔄 Rollouts & Updates](#rollouts--updates)
* [🏗️ Application Architecture](#application-architecture)
* [🎯 Best Practices](#best-practices)

***

## 📦 Pods & Containers

### **Pod Fundamentals**

Pod adalah unit terkecil dan paling dasar dari aplikasi yang di-deploy di Kubernetes. Pod dapat berisi satu atau beberapa containers yang berbagi network namespace dan storage.

#### **Basic Pod Example**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
    version: v1.21
  annotations:
    description: "Basic Nginx web server pod"
spec:
  containers:
  - name: nginx
    image: nginx:1.21
    ports:
    - containerPort: 80
      name: http
      protocol: TCP
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 500m
        memory: 512Mi
    livenessProbe:
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 5
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 3
      failureThreshold: 3
    env:
    - name: APP_ENV
      value: "production"
    - name: LOG_LEVEL
      value: "info"
  restartPolicy: Always
  terminationGracePeriodSeconds: 30
```

#### **Multi-Container Pod**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: web-app-pod
  labels:
    app: web-app
spec:
  containers:
  - name: web-server
    image: nginx:1.21
    ports:
    - containerPort: 80
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
    resources:
      requests:
        cpu: 200m
        memory: 256Mi
      limits:
        cpu: 500m
        memory: 512Mi

  - name: content-generator
    image: busybox:1.35
    command: ["/bin/sh"]
    args:
      - -c
      - |
        while true; do
          echo "<h1>Time: $(date)</h1>" > /shared/index.html
          echo "<p>Container: $(hostname)</p>" >> /shared/index.html
          echo "<p>Pod IP: $POD_IP</p>" >> /shared/index.html
          sleep 10
        done
    env:
    - name: POD_IP
      valueFrom:
        fieldRef:
          fieldPath: status.podIP
    volumeMounts:
    - name: shared-data
      mountPath: /shared
    resources:
      requests:
        cpu: 50m
        memory: 32Mi
      limits:
        cpu: 100m
        memory: 64Mi

  volumes:
  - name: shared-data
    emptyDir: {}
  restartPolicy: Always
```

#### **Init Containers**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-with-init
spec:
  initContainers:
  - name: setup-database
    image: busybox:1.35
    command: ['sh', '-c']
    args:
      - |
        echo "Setting up database connection..."
        echo "DB_HOST=database.default.svc.cluster.local" > /app/.env
        echo "DB_PORT=5432" >> /app/.env
        echo "DB_NAME=myapp" >> /app/.env
    volumeMounts:
    - name: config-volume
      mountPath: /app
    resources:
      requests:
        cpu: 50m
        memory: 32Mi

  - name: wait-for-database
    image: postgres:13
    command: ['sh', '-c']
    args:
      - |
        until pg_isready -h $DB_HOST -p $DB_PORT -U postgres; do
          echo "Waiting for database..."
          sleep 2
        done
    env:
    - name: DB_HOST
      value: "database.default.svc.cluster.local"
    - name: DB_PORT
      value: "5432"
    resources:
      requests:
        cpu: 100m
        memory: 128Mi

  containers:
  - name: app
    image: myapp:latest
    ports:
    - containerPort: 8080
    envFrom:
    - configMapRef:
        name: app-config
    volumeMounts:
    - name: config-volume
      mountPath: /app
      readOnly: true
    resources:
      requests:
        cpu: 200m
        memory: 256Mi
      limits:
        cpu: 500m
        memory: 512Mi

  volumes:
  - name: config-volume
    emptyDir: {}
```

### **Pod Lifecycle Management**

#### **Pod Lifecycle**

```bash
# Create pod
kubectl apply -f pod.yaml

# Get pod status
kubectl get pod nginx-pod

# Get detailed pod information
kubectl describe pod nginx-pod

# Get pod logs
kubectl logs nginx-pod
kubectl logs -f nginx-pod  # Follow logs

# Execute command in pod
kubectl exec -it nginx-pod -- /bin/bash
kubectl exec nginx-pod -- ls -la /usr/share/nginx/html

# Port forwarding
kubectl port-forward nginx-pod 8080:80

# Delete pod
kubectl delete pod nginx-pod
```

***

## 🚀 Deployments

### **Deployment Fundamentals**

Deployment menyediakan deklaratif update untuk Pods dan ReplicaSets dengan fitur rolling update, rollback, dan scaling.

#### **Basic Deployment**

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
    version: v1.0.0
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
        version: v1.0.0
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
          name: http
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 3
          successThreshold: 1
          failureThreshold: 3
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi
        env:
        - name: NGINX_HOST
          value: "localhost"
        - name: NGINX_PORT
          value: "80"
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
```

#### **Advanced Deployment with Environment Variables**

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
  labels:
    app: my-app
    environment: production
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        environment: production
    spec:
      containers:
      - name: app
        image: myapp:latest
        ports:
        - containerPort: 8080
          name: http
        env:
        - name: NODE_ENV
          value: "production"
        - name: APP_VERSION
          value: "v1.2.0"
        - name: DATABASE_URL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: database_url
        - name: API_KEY
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: api_key
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: SERVICE_ACCOUNT
          valueFrom:
            fieldRef:
              fieldPath: spec.serviceAccountName
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 500m
            memory: 512Mi
        volumeMounts:
        - name: config-volume
          mountPath: /app/config
          readOnly: true
        - name: logs-volume
          mountPath: /app/logs
        - name: tmp-volume
          mountPath: /tmp
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
        startupProbe:
          httpGet:
            path: /startup
            port: 8080
          failureThreshold: 30
          periodSeconds: 10
      volumes:
      - name: config-volume
        configMap:
          name: app-config
      - name: logs-volume
        emptyDir: {}
      - name: tmp-volume
        emptyDir: {}
```

### **Deployment Management**

#### **Basic Deployment Commands**

```bash
# Create deployment
kubectl apply -f deployment.yaml

# Get deployments
kubectl get deployments
kubectl get deployment nginx-deployment

# Get detailed deployment info
kubectl describe deployment nginx-deployment

# Scale deployment
kubectl scale deployment nginx-deployment --replicas=5
kubectl scale deployment nginx-deployment --replicas=3

# Update deployment image
kubectl set image deployment/nginx-deployment nginx=nginx:1.22
kubectl set image deployment/nginx-deployment nginx=nginx:1.22 --record

# Edit deployment
kubectl edit deployment nginx-deployment

# Delete deployment
kubectl delete deployment nginx-deployment
```

#### **Deployment Rollout Management**

```bash
# Check rollout status
kubectl rollout status deployment/nginx-deployment

# Get rollout history
kubectl rollout history deployment/nginx-deployment

# Undo to previous revision
kubectl rollout undo deployment/nginx-deployment

# Undo to specific revision
kubectl rollout undo deployment/nginx-deployment --to-revision=2

# Restart deployment
kubectl rollout restart deployment/nginx-deployment

# Pause rollout
kubectl rollout pause deployment/nginx-deployment

# Resume rollout
kubectl rollout resume deployment/nginx-deployment
```

***

## 🌐 Services

### **Service Fundamentals**

Service menyediakan stable network endpoint untuk Pods dengan load balancing dan service discovery.

#### **ClusterIP Service**

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    app: nginx
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: nginx
```

#### **NodePort Service**

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport
  labels:
    app: nginx
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
    protocol: TCP
    name: http
  selector:
    app: nginx
```

#### **LoadBalancer Service**

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-loadbalancer
  labels:
    app: nginx
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "tcp"
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: nginx
  externalTrafficPolicy: Local
```

#### **Headless Service**

```yaml
apiVersion: v1
kind: Service
metadata:
  name: database-headless
  labels:
    app: database
spec:
  type: ClusterIP
  clusterIP: None
  ports:
  - port: 5432
    targetPort: 5432
    protocol: TCP
    name: postgres
  selector:
    app: database
```

#### **ExternalName Service**

```yaml
apiVersion: v1
kind: Service
metadata:
  name: external-dns
spec:
  type: ExternalName
  externalName: google.com
```

### **Service Discovery**

#### **DNS Resolution**

```bash
# Service DNS format
<service-name>.<namespace>.svc.cluster.local

# Examples:
nginx-service.default.svc.cluster.local
database.production.svc.cluster.local

# Test DNS resolution
kubectl run dns-test --image=busybox:1.35 --rm -it --restart=Never -- nslookup nginx-service.default.svc.cluster.local
```

#### **Environment Variables**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    env:
    - name: DB_HOST
      value: "database.default.svc.cluster.local"
    - name: DB_PORT
      value: "5432"
    - name: REDIS_HOST
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: redis_host
    - name: SERVICE_URL
      value: "http://$(DB_HOST):$(DB_PORT)"
```

### **Service Management**

#### **Service Commands**

```bash
# Get services
kubectl get services
kubectl get svc
kubectl get svc -o wide

# Get detailed service info
kubectl describe service nginx-service

# Get service endpoints
kubectl get endpoints nginx-service

# Test service connectivity
kubectl port-forward service/nginx-service 8080:80
kubectl run curl-test --image=curlimages/curl --rm -it --restart=Never -- curl -I http://nginx-service.default.svc.cluster.local
```

***

## ⚙️ ConfigMaps & Secrets

### **ConfigMaps**

ConfigMeny digunakan untuk menyimpan data konfigurasi non-sensitif.

#### **Basic ConfigMap**

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  labels:
    app: my-app
data:
  database_url: "postgresql://localhost:5432/myapp"
  debug_mode: "true"
  log_level: "INFO"
  app_port: "8080"
  cache_ttl: "300"
  max_connections: "100"
  config.yaml: |
    app:
      name: my-application
      version: 1.0.0
      environment: production
      debug: false
    database:
      host: localhost
      port: 5432
      name: myapp
      pool_size: 10
      ssl_mode: require
    logging:
      level: info
      format: json
      output: stdout
      max_size: 100MB
      max_files: 5
    security:
      allowed_hosts: ["localhost", "example.com"]
      csrf_protection: true
      session_timeout: 3600
  nginx.conf: |
    user nginx;
    worker_processes auto;
    error_log /var/log/nginx/error.log warn;
    pid /var/run/nginx.pid;

    events {
        worker_connections 1024;
    }

    http {
        include /etc/nginx/conf.d/*.conf;

        server {
            listen 80;
            server_name localhost;

            location / {
                root /usr/share/nginx/html;
                index index.html index.htm;
            }

            location /api {
                proxy_pass http://backend:8080;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            }
        }
    }
```

#### **ConfigMap from Files**

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-files
data:
  # Single file content
  app.properties: |
    spring.application.name=MyApplication
    server.port=8080
    spring.datasource.url=jdbc:postgresql://localhost:5432/myapp
    spring.datasource.username=postgres
    logging.level.root=INFO

  # JSON configuration
  config.json: |
    {
      "app": {
        "name": "MyApp",
        "version": "1.0.0",
        "environment": "production"
      },
      "services": {
        "database": {
          "host": "localhost",
          "port": 5432,
          "name": "myapp"
        },
        "cache": {
          "type": "redis",
          "host": "redis.default.svc.cluster.local",
          "port": 6379
        }
      }
    }

  # XML configuration
  spring-config.xml: |
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <appSettings>
            <add key="AppSettings:Environment" value="Production" />
            <add key="AppSettings:Version" value="1.0.0" />
        </appSettings>
        <connectionStrings>
            <add name="DefaultConnection"
                 connectionString="Server=localhost;Database=myapp;User Id=postgres;Password=secret;" />
        </connectionStrings>
    </configuration>
```

### **Secrets**

Secrets digunakan untuk menyimpan data sensitif seperti password, API keys, dan certificates.

#### **Opaque Secret**

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
  labels:
    app: my-app
type: Opaque
data:
  database_password: c2VjcmV0X3Bhc3N3b3Jk  # "secretpassword" in base64
  api_key: YXBpa2V5dmFsdWU=              # "apikeyvalue" in base64
  jwt_secret: bXlKd1RTZWNyZXRLZXk=          # "myJWTSecretKey" in base64
  tls_cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCkVJRU5HQ2...  # Certificate
  tls_key: LS0tLS1CRUdJTiBFRU5FQlJDUkVTWVRZ...    # Private key
stringData:
  # Plain text values (automatically base64 encoded)
  jwt_secret_plain: "my-jwt-secret-key-2024"
  database_username: "app_user"
  environment: "production"
```

#### **Service Account Token Secret**

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: service-account-token
  annotations:
    kubernetes.io/service-account.name: my-service-account
type: kubernetes.io/service-account-token
data:
  token: <base64-encoded-token>
```

#### **Docker Registry Secret**

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: docker-registry-secret
  annotations:
    kubernetes.io/dockerconfigjson: "true"
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: |
    {
      "auths": {
        "https://index.docker.io/v1/": {
          "auth": "dXNlcm5hbWU6cGFzc3dvcmQ="
        },
        "https://gcr.io": {
          "auth": "_json_key_"
        }
      }
    }
```

### **Using ConfigMaps and Secrets**

#### **Environment Variables**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    env:
    - name: DATABASE_URL
      value: "postgresql://localhost:5432/myapp"
    - name: LOG_LEVEL
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: log_level
    - name: API_KEY
      valueFrom:
        secretKeyRef:
          name: app-secrets
          key: api_key
    - name: JWT_SECRET
      valueFrom:
        secretKeyRef:
          name: app-secrets
          key: jwt_secret_plain
    envFrom:
    - configMapRef:
        name: app-config
    - secretRef:
        name: app-secrets
```

#### **Volume Mounts**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: config-volume
      mountPath: /app/config
      readOnly: true
    - name: secrets-volume
      mountPath: /app/secrets
      readOnly: true
    - name: certificates-volume
      mountPath: /app/certs
      readOnly: true
    - name: logs-volume
      mountPath: /app/logs
    resources:
      requests:
        cpu: 200m
        memory: 256Mi
      limits:
        cpu: 500m
        memory: 512Mi
  volumes:
  - name: config-volume
    configMap:
      name: app-config
  - name: secrets-volume
    secret:
      secretName: app-secrets
  - name: certificates-volume
    secret:
      secretName: tls-certificates
  - name: logs-volume
    emptyDir: {}
```

***

## 📊 Scaling

### **Manual Scaling**

#### **Deployment Scaling**

```bash
# Scale deployment
kubectl scale deployment/nginx-deployment --replicas=5

# Scale statefulset
kubectl scale statefulset/database-statefulset --replicas=3

# Scale daemonset
kubectl scale daemonset/node-exporter --replicas=10
```

### **Horizontal Pod Autoscaler (HPA)**

#### **Basic HPA**

```yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: app-hpa
  labels:
    app: my-app
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
```

#### **Advanced HPA with Custom Metrics**

```yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app-deployment
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  - type: Pods
    pods:
      metric:
        name: packets_per_second
      target:
        type: AverageValue
        averageValue: 1k
  - type: External
    external:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: 500
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
      - type: Pods
        value: 4
        periodSeconds: 15
      selectPolicy: Max
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60
```

### **Vertical Pod Autoscaler (VPA)**

#### **Basic VPA**

```yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: app-vpa
  labels:
    app: my-app
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app-deployment
  updatePolicy:
    updateMode: "Auto"
  resourcePolicy:
    containerPolicies:
    - containerName: app
      maxAllowed:
        cpu: 2
        memory: 4Gi
      minAllowed:
        cpu: 100m
        memory: 128Mi
      controlledResources: ["cpu", "memory"]
```

#### **VPA with Update Modes**

```yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app-deployment
  updatePolicy:
    updateMode: "Recreate"  # Auto, Initial, Recreate, Off
    recreationMode: "PodTemplate" # PodTemplate, ControllerRevision
  resourcePolicy:
    containerPolicies:
    - containerName: app
      maxAllowed:
        cpu: 4
        memory: 8Gi
      minAllowed:
        cpu: 100m
        memory: 64Mi
      controlledValues: RequestsAndLimits
    - containerName: sidecar
      maxAllowed:
        cpu: 500m
        memory: 1Gi
      minAllowed:
        cpu: 50m
        memory: 32Mi
      controlledResources: ["cpu", "memory"]
```

***

## 🔄 Rollouts & Updates

### **Rolling Update Strategy**

#### **Rolling Update Configuration**

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1              # Maximum additional pods during update
      maxUnavailable: 1        # Maximum unavailable pods during update
      progressDeadlineSeconds: 600
  selector:
    matchLabels:
      app: my-app
  template:
    spec:
      containers:
      - name: app
        image: myapp:latest
```

#### **Recreate Strategy**

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 3
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: my-app
  template:
    spec:
      containers:
      - name: app
        image: myapp:latest
```

### **Update Management**

#### **Image Updates**

```bash
# Update image with automatic rollback
kubectl set image deployment/app-deployment app=myapp:v2.0

# Update image with record
kubectl set image deployment/app-deployment app=myapp:v2.0 --record

# Check rollout status
kubectl rollout status deployment/app-deployment

# Undo last update
kubectl rollout undo deployment/app-deployment

# Undo to specific revision
kubectl rollout undo deployment/app-deployment --to-revision=3
```

#### **Configuration Updates**

```bash
# Update environment variables
kubectl set env deployment/app-deployment ENV=production
kubectl set env deployment/app-deployment LOG_LEVEL=info

# Update resources
kubectl patch deployment/app-deployment -p '{"spec":{"template":{"spec":{"containers":[{"name":"app","resources":{"limits":{"memory":"1Gi"}}}]}}}'

# Update annotations
kubectl annotate deployment/app-deployment description="Production deployment v2.0"
```

### **Rollback Strategies**

#### **Rollback Configuration**

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
  annotations:
    kubernetes.io/change-cause: "Updated to v2.0 for performance improvements"
spec:
  replicas: 3
  revisionHistoryLimit: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      annotations:
        kubernetes.io/change-cause: "Initial deployment"
    spec:
      containers:
      - name: app
        image: myapp:latest
```

#### **Rollback Commands**

```bash
# Get rollout history
kubectl rollout history deployment/app-deployment

# Check revision details
kubectl rollout history deployment/app-deployment --revision=3

# Rollback to previous version
kubectl rollout undo deployment/app-deployment

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

# Pause rollout
kubectl rollout pause deployment/app-deployment

# Resume rollout
kubectl rollout resume deployment/app-deployment

# Cancel rollout
kubectl rollout undo deployment/app-deployment --to-current
```

***

## 🏗️ Application Architecture

### **Microservices Architecture**

#### **Web Application Architecture**

```yaml
# Frontend Service
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: myapp-frontend:latest
        ports:
        - containerPort: 80
        env:
        - name: API_URL
          value: "http://backend-service:8080"
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi
---
# Backend Service
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: backend
        image: myapp-backend:latest
        ports:
        - containerPort: 8080
        env:
        - name: DATABASE_URL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: database_url
        - name: REDIS_URL
          value: "redis://redis-service:6379"
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 1
            memory: 1Gi
---
# Database Service
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: database-statefulset
spec:
  serviceName: database
  replicas: 1
  selector:
    matchLabels:
      app: database
  template:
    metadata:
      labels:
        app: database
    spec:
      containers:
      - name: database
        image: postgres:13
        ports:
        - containerPort: 5432
        env:
        - name: POSTGRES_DB
          value: myapp
        - name: POSTGRES_USER
          valueFrom:
            secretKeyRef:
              name: database-credentials
              key: username
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: database-credentials
              key: password
        volumeMounts:
        - name: postgres-storage
          mountPath: /var/lib/postgresql/data
        resources:
          requests:
            cpu: 500m
          memory: 1Gi
          limits:
            cpu: 1
            memory: 2Gi
  volumeClaimTemplates:
  - metadata:
      name: postgres-storage
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: fast-ssd
      resources:
        requests:
          storage: 10Gi
```

### **Multi-Tier Architecture**

#### **Nginx Configuration**

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  nginx.conf: |
    user nginx;
    worker_processes auto;
    error_log /var/log/nginx/error.log warn;
    pid /var/run/nginx.pid;

    events {
        worker_connections 1024;
    }

    http {
        include /etc/nginx/conf.d/*.conf;

        # Rate limiting
        limit_req_zone $binary_remote_addr $limit_req_zone:10m rate=10r/s;

        upstream backend {
            server backend-service:8080;
            keepalive 32;
        }

        server {
            listen 80;
            server_name _;

            # Security headers
            add_header X-Frame-Options "SAMEORIGIN" always;
            add_header X-Content-Type-Options "nosniff" always;
            add_header X-XSS-Protection "1; mode=block" always;

            # Rate limiting
            limit_req zone=$limit_req_zone burst=20 nodelay;

            location / {
                root /usr/share/nginx/html;
                index index.html index.htm;
                try_files $uri $uri/ =404;
            }

            location /api/ {
                proxy_pass http://backend;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;

                # CORS headers
                add_header Access-Control-Allow-Origin "*" always;
                add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
                add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;

                # Timeout settings
                proxy_connect_timeout 30s;
                proxy_send_timeout 30s;
                proxy_read_timeout 30s;
            }

            # Health check
            location /health {
                access_log off;
                return 200 "healthy\n";
                add_header Content-Type text/plain;
            }
        }
    }
```

***

## 🎯 Best Practices

### **Resource Management**

#### **Resource Requests and Limits**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    resources:
      requests:
        cpu: 100m          # Minimum guaranteed CPU
        memory: 128Mi      # Minimum guaranteed memory
        ephemeral-storage: 1Gi  # Temporary storage
      limits:
        cpu: 500m          # Maximum CPU allowed
        memory: 512Mi      # Maximum memory allowed
        ephemeral-storage: 2Gi # Maximum temporary storage
```

#### **Quality of Service Classes**

```yaml
# Guaranteed QoS (high priority)
apiVersion: v1
kind: Pod
metadata:
  name: guaranteed-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    resources:
      requests:
        cpu: 500m
        memory: 512Mi
      limits:
        cpu: 1
        memory: 1Gi

# Burstable QoS (medium priority)
apiVersion: v1
kind: Pod
metadata:
  name: burstable-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 500m
        memory: 512Mi

# BestEffort QoS (low priority)
apiVersion: v1
kind: Pod
metadata:
  name: besteffort-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    resources: {}  # No requests or limits
```

### **Security Best Practices**

#### **Security Context**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 2000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
    readOnlyRootFilesystem: true
  containers:
  - name: app
    image: myapp:latest
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop:
        - ALL
      readOnlyRootFilesystem: true
      volumeMounts:
      - name: tmp
        mountPath: /tmp
```

#### **Network Security**

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-network-policy
spec:
  podSelector:
    matchLabels:
      app: my-app
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
  - ports:
    - protocol: TCP
      port: 80
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
  - to: []
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
  - to: []
    ports:
    - protocol: TCP
      port: 443
```

### **Health Checks**

#### **Liveness and Readiness Probes**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: healthy-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    ports:
    - containerPort: 8080
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
        scheme: HTTP
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 5
      successThreshold: 1
      failureThreshold: 3
      terminationGracePeriodSeconds: 30
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
        scheme: HTTP
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 3
      successThreshold: 1
      failureThreshold: 3
    startupProbe:
      httpGet:
        path: /startup
        port: 8080
        scheme: HTTP
      failureThreshold: 30
      periodSeconds: 10
      timeoutSeconds: 5
      successThreshold: 1
```

### **Monitoring and Logging**

#### **Application Logging**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-pod
spec:
  containers:
  - name: app
    image: myapp:latest
    env:
    - name: LOG_LEVEL
      value: "INFO"
    - name: LOG_FORMAT
      value: "json"
    volumeMounts:
    - name: logs
      mountPath: /app/logs
  - name: log-shipper
    image: fluent/fluentd:latest
    env:
    - name: FLUENTD_CONF
      value: |
        <source>
          @type tail
          path /app/logs/app.log
          pos_file /var/log/fluentd.pos
          tag app.logs
        </source>
        <match app.**>
          @type elasticsearch
          host elasticsearch.logging.svc.cluster.local
          port 9200
          index_name app-logs
        </match>
    volumeMounts:
    - name: logs
      mountPath: /app/logs
      readOnly: true
    - name: fluentd-pos
      mountPath: /var/log/fluentd
    - name: fluentd-config
      mountPath: /fluentd/etc
    volumes:
    - name: logs
      emptyDir: {}
    - name: fluentd-pos
      emptyDir: {}
    - name: fluentd-config
      configMap:
        name: fluentd-config
```

***

## 📋 **Quick Reference**

### **Common Deployment Patterns**

```bash
# Basic deployment
kubectl create deployment myapp --image=myapp:latest --replicas=3

# Expose as service
kubectl expose deployment myapp --port=80 --type=LoadBalancer

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

# Update image
kubectl set image deployment/myapp myapp=v2.0

# Check rollout status
kubectl rollout status deployment/myapp
```

### **Troubleshooting Commands**

```bash
# Check pod issues
kubectl describe pod <pod-name>
kubectl logs <pod-name>
kubectl exec -it <pod-name> -- /bin/bash

# Check service issues
kubectl describe service <service-name>
kubectl get endpoints <service-name>

# Check deployment issues
kubectl describe deployment <deployment-name>
kubectl rollout history deployment/<deployment-name>
```

***

*📅 **Last Updated**: November 2024* *🔗 **Related**:* [*Setup & Installation*](https://mahbubzulkarnain.gitbook.io/catatan-seekor-the-series/catatan-seekor-devops/kubernetes/setup-installation) *|* [*Advanced Topics*](https://mahbubzulkarnain.gitbook.io/catatan-seekor-the-series/catatan-seekor-devops/kubernetes/advanced-topics) *|* [*Cheatsheets*](https://mahbubzulkarnain.gitbook.io/catatan-seekor-the-series/catatan-seekor-devops/kubernetes/cheatsheets)
