| 1 | --- |
| 2 | title: "Kubernetes (K8s)" |
| 3 | term: "apa-itu-kubernetes" |
| 4 | category: "Cloud & Infrastructure" |
| 5 | tags: ["container", "orchestration", "devops", "cloud-native", "microservices", "k8s"] |
| 6 | description: "Platform orchestration open-source untuk automasi deployment, scaling, dan management aplikasi berbasis container di production scale." |
| 7 | englishTerm: "Kubernetes" |
| 8 | acronym: "K8s" |
| 9 | relatedTerms: ["apa-itu-docker", "apa-itu-container", "apa-itu-devops", "apa-itu-microservices", "apa-itu-cloud-computing"] |
| 10 | difficulty: "lanjut" |
| 11 | lastmod: 2024-01-15 |
| 12 | published: true |
| 13 | --- |
| 14 | |
| 15 | ## Apa itu Kubernetes? |
| 16 | |
| 17 | **Kubernetes** (sering disingkat **K8s**) adalah platform open-source untuk mengatur deployment, scaling, dan manajemen aplikasi berbasis container. Kubernetes banyak dipakai saat aplikasi tidak lagi cukup dijalankan sebagai beberapa container terpisah di satu atau dua server. |
| 18 | |
| 19 | Awalnya Kubernetes dikembangkan oleh Google, lalu dikelola lebih lanjut oleh Cloud Native Computing Foundation (CNCF). |
| 20 | |
| 21 | **Asal nama**: "Kubernetes" berasal dari bahasa Yunani yang berarti "helmsman" atau "pilot". Singkatan **K8s** berarti huruf `K`, lalu delapan huruf di tengah, lalu `s`. |
| 22 | |
| 23 | ## Mengapa Kubernetes Diperlukan? |
| 24 | |
| 25 | ### Masalah jika Hanya Mengandalkan Docker |
| 26 | |
| 27 | Docker sangat berguna untuk menjalankan container, tetapi saat jumlah service dan server mulai bertambah, pekerjaan operasional ikut membesar. |
| 28 | |
| 29 | **Tanpa Kubernetes, tim biasanya harus menangani hal-hal berikut secara manual:** |
| 30 | - Menjalankan dan menghentikan container di banyak server |
| 31 | - Merestart container yang crash |
| 32 | - Membagi traffic ke beberapa instance aplikasi |
| 33 | - Menambah kapasitas saat traffic naik |
| 34 | - Mengatur komunikasi antarservice |
| 35 | - Mengembalikan deployment saat versi baru bermasalah |
| 36 | |
| 37 | **Kubernetes membantu merapikan semua itu dengan fitur seperti:** |
| 38 | - **Auto-healing** - Pod yang gagal bisa dijalankan ulang |
| 39 | - **Auto-scaling** - Jumlah instance bisa disesuaikan dengan beban |
| 40 | - **Load balancing** - Traffic dibagi ke beberapa pod |
| 41 | - **Rolling updates** - Versi baru dirilis bertahap |
| 42 | - **Service discovery** - Service saling menemukan lewat DNS internal |
| 43 | - **Secret management** - Credential dan konfigurasi sensitif bisa dipisahkan dari kode |
| 44 | |
| 45 | ## Arsitektur Kubernetes |
| 46 | |
| 47 | ### Control Plane (Master Node) |
| 48 | |
| 49 | Brain dari cluster yang manage semua operations: |
| 50 | |
| 51 | **1. API Server** |
| 52 | - Entry point untuk semua commands |
| 53 | - Handle REST operations |
| 54 | - Validate dan process requests |
| 55 | |
| 56 | **2. etcd** |
| 57 | - Key-value store untuk cluster state |
| 58 | - Distributed dan highly-available |
| 59 | |
| 60 | **3. Scheduler** |
| 61 | - Assign pods ke nodes |
| 62 | - Consider resource requirements dan constraints |
| 63 | |
| 64 | **4. Controller Manager** |
| 65 | - Run controllers (Deployment, ReplicaSet, etc.) |
| 66 | - Ensure desired state = actual state |
| 67 | |
| 68 | ### Worker Nodes |
| 69 | |
| 70 | Machines yang run aplikasi Anda: |
| 71 | |
| 72 | **1. kubelet** |
| 73 | - Agent di setiap node |
| 74 | - Manage pods dan containers |
| 75 | - Report status ke control plane |
| 76 | |
| 77 | **2. kube-proxy** |
| 78 | - Network proxy di setiap node |
| 79 | - Maintain network rules |
| 80 | - Handle load balancing |
| 81 | |
| 82 | **3. Container Runtime** |
| 83 | - Docker, containerd, atau CRI-O |
| 84 | - Actually run containers |
| 85 | |
| 86 | ``` |
| 87 | ┌─────────────────────────────────────┐ |
| 88 | │ Control Plane │ |
| 89 | │ ┌──────────┐ ┌────────┐ │ |
| 90 | │ │API Server│ │ etcd │ │ |
| 91 | │ └──────────┘ └────────┘ │ |
| 92 | │ ┌──────────┐ ┌─────────────────┐ │ |
| 93 | │ │Scheduler │ │Controller Manager│ │ |
| 94 | │ └──────────┘ └─────────────────┘ │ |
| 95 | └─────────────────────────────────────┘ |
| 96 | │ |
| 97 | ┌─────┴─────┐ |
| 98 | │ │ |
| 99 | ┌────▼────┐ ┌────▼────┐ |
| 100 | │ Node 1 │ │ Node 2 │ |
| 101 | │┌───────┐│ │┌───────┐│ |
| 102 | ││kubelet││ ││kubelet││ |
| 103 | │└───────┘│ │└───────┘│ |
| 104 | │┌───────┐│ │┌───────┐│ |
| 105 | ││kube- ││ ││kube- ││ |
| 106 | ││proxy ││ ││proxy ││ |
| 107 | │└───────┘│ │└───────┘│ |
| 108 | │ Pods... │ │ Pods... │ |
| 109 | └─────────┘ └─────────┘ |
| 110 | ``` |
| 111 | |
| 112 | ## Konsep Penting Kubernetes |
| 113 | |
| 114 | ### 1. Pod |
| 115 | |
| 116 | Unit deployment terkecil di K8s. Bisa berisi 1+ containers yang share network dan storage. |
| 117 | |
| 118 | ```yaml |
| 119 | apiVersion: v1 |
| 120 | kind: Pod |
| 121 | metadata: |
| 122 | name: myapp-pod |
| 123 | labels: |
| 124 | app: myapp |
| 125 | spec: |
| 126 | containers: |
| 127 | - name: myapp |
| 128 | image: myapp:v1 |
| 129 | ports: |
| 130 | - containerPort: 3000 |
| 131 | ``` |
| 132 | |
| 133 | ### 2. Deployment |
| 134 | |
| 135 | Manage ReplicaSets dan Pods. Untuk stateless applications. |
| 136 | |
| 137 | ```yaml |
| 138 | apiVersion: apps/v1 |
| 139 | kind: Deployment |
| 140 | metadata: |
| 141 | name: myapp-deployment |
| 142 | spec: |
| 143 | replicas: 3 |
| 144 | selector: |
| 145 | matchLabels: |
| 146 | app: myapp |
| 147 | template: |
| 148 | metadata: |
| 149 | labels: |
| 150 | app: myapp |
| 151 | spec: |
| 152 | containers: |
| 153 | - name: myapp |
| 154 | image: myapp:v1 |
| 155 | ports: |
| 156 | - containerPort: 3000 |
| 157 | resources: |
| 158 | requests: |
| 159 | memory: "128Mi" |
| 160 | cpu: "250m" |
| 161 | limits: |
| 162 | memory: "256Mi" |
| 163 | cpu: "500m" |
| 164 | ``` |
| 165 | |
| 166 | ### 3. Service |
| 167 | |
| 168 | Expose pods ke network. Provide stable IP dan DNS. |
| 169 | |
| 170 | ```yaml |
| 171 | apiVersion: v1 |
| 172 | kind: Service |
| 173 | metadata: |
| 174 | name: myapp-service |
| 175 | spec: |
| 176 | type: LoadBalancer |
| 177 | selector: |
| 178 | app: myapp |
| 179 | ports: |
| 180 | - protocol: TCP |
| 181 | port: 80 |
| 182 | targetPort: 3000 |
| 183 | ``` |
| 184 | |
| 185 | **Service Types:** |
| 186 | - **ClusterIP** - Internal only (default) |
| 187 | - **NodePort** - Expose pada port di setiap node |
| 188 | - **LoadBalancer** - External load balancer (cloud) |
| 189 | - **ExternalName** - Map to external DNS |
| 190 | |
| 191 | ### 4. ConfigMap |
| 192 | |
| 193 | Store configuration data as key-value pairs. |
| 194 | |
| 195 | ```yaml |
| 196 | apiVersion: v1 |
| 197 | kind: ConfigMap |
| 198 | metadata: |
| 199 | name: myapp-config |
| 200 | data: |
| 201 | DATABASE_HOST: postgres.default.svc.cluster.local |
| 202 | DATABASE_PORT: "5432" |
| 203 | ENVIRONMENT: production |
| 204 | ``` |
| 205 | |
| 206 | ### 5. Secret |
| 207 | |
| 208 | Store sensitive data (encrypted at rest). |
| 209 | |
| 210 | ```yaml |
| 211 | apiVersion: v1 |
| 212 | kind: Secret |
| 213 | metadata: |
| 214 | name: myapp-secret |
| 215 | type: Opaque |
| 216 | data: |
| 217 | # base64 encoded |
| 218 | database-password: cGFzc3dvcmQxMjM= |
| 219 | api-key: c2VjcmV0a2V5MTIz |
| 220 | ``` |
| 221 | |
| 222 | ### 6. Ingress |
| 223 | |
| 224 | HTTP/HTTPS routing ke services. Provide SSL termination. |
| 225 | |
| 226 | ```yaml |
| 227 | apiVersion: networking.k8s.io/v1 |
| 228 | kind: Ingress |
| 229 | metadata: |
| 230 | name: myapp-ingress |
| 231 | annotations: |
| 232 | cert-manager.io/cluster-issuer: letsencrypt-prod |
| 233 | spec: |
| 234 | tls: |
| 235 | - hosts: |
| 236 | - myapp.example.com |
| 237 | secretName: myapp-tls |
| 238 | rules: |
| 239 | - host: myapp.example.com |
| 240 | http: |
| 241 | paths: |
| 242 | - path: / |
| 243 | pathType: Prefix |
| 244 | backend: |
| 245 | service: |
| 246 | name: myapp-service |
| 247 | port: |
| 248 | number: 80 |
| 249 | ``` |
| 250 | |
| 251 | ### 7. StatefulSet |
| 252 | |
| 253 | Untuk stateful applications (databases, etc.). Provide stable network identity. |
| 254 | |
| 255 | ```yaml |
| 256 | apiVersion: apps/v1 |
| 257 | kind: StatefulSet |
| 258 | metadata: |
| 259 | name: postgres |
| 260 | spec: |
| 261 | serviceName: postgres |
| 262 | replicas: 3 |
| 263 | selector: |
| 264 | matchLabels: |
| 265 | app: postgres |
| 266 | template: |
| 267 | metadata: |
| 268 | labels: |
| 269 | app: postgres |
| 270 | spec: |
| 271 | containers: |
| 272 | - name: postgres |
| 273 | image: postgres:15 |
| 274 | volumeMounts: |
| 275 | - name: data |
| 276 | mountPath: /var/lib/postgresql/data |
| 277 | volumeClaimTemplates: |
| 278 | - metadata: |
| 279 | name: data |
| 280 | spec: |
| 281 | accessModes: ["ReadWriteOnce"] |
| 282 | resources: |
| 283 | requests: |
| 284 | storage: 10Gi |
| 285 | ``` |
| 286 | |
| 287 | ### 8. Namespace |
| 288 | |
| 289 | Virtual clusters untuk isolasi resources. |
| 290 | |
| 291 | ```bash |
| 292 | # Create namespace |
| 293 | kubectl create namespace production |
| 294 | kubectl create namespace staging |
| 295 | |
| 296 | # Deploy to namespace |
| 297 | kubectl apply -f deployment.yaml -n production |
| 298 | ``` |
| 299 | |
| 300 | ## kubectl: Kubernetes CLI |
| 301 | |
| 302 | ### Basic Commands |
| 303 | |
| 304 | ```bash |
| 305 | # Get cluster info |
| 306 | kubectl cluster-info |
| 307 | kubectl get nodes |
| 308 | |
| 309 | # Get resources |
| 310 | kubectl get pods |
| 311 | kubectl get deployments |
| 312 | kubectl get services |
| 313 | kubectl get all |
| 314 | |
| 315 | # Describe resource (detail info) |
| 316 | kubectl describe pod myapp-pod |
| 317 | |
| 318 | # Logs |
| 319 | kubectl logs myapp-pod |
| 320 | kubectl logs -f myapp-pod # Follow logs |
| 321 | kubectl logs myapp-pod -c container-name # Multi-container pod |
| 322 | |
| 323 | # Execute command in pod |
| 324 | kubectl exec -it myapp-pod -- /bin/sh |
| 325 | kubectl exec myapp-pod -- env |
| 326 | |
| 327 | # Port forward (local testing) |
| 328 | kubectl port-forward pod/myapp-pod 8080:3000 |
| 329 | kubectl port-forward service/myapp-service 8080:80 |
| 330 | ``` |
| 331 | |
| 332 | ### Apply & Delete |
| 333 | |
| 334 | ```bash |
| 335 | # Create/update resources |
| 336 | kubectl apply -f deployment.yaml |
| 337 | kubectl apply -f ./k8s-manifests/ |
| 338 | |
| 339 | # Delete resources |
| 340 | kubectl delete -f deployment.yaml |
| 341 | kubectl delete pod myapp-pod |
| 342 | kubectl delete deployment myapp-deployment |
| 343 | |
| 344 | # Delete all in namespace |
| 345 | kubectl delete all --all -n staging |
| 346 | ``` |
| 347 | |
| 348 | ### Scaling |
| 349 | |
| 350 | ```bash |
| 351 | # Manual scaling |
| 352 | kubectl scale deployment myapp-deployment --replicas=5 |
| 353 | |
| 354 | # Auto-scaling |
| 355 | kubectl autoscale deployment myapp-deployment \ |
| 356 | --cpu-percent=70 \ |
| 357 | --min=2 \ |
| 358 | --max=10 |
| 359 | ``` |
| 360 | |
| 361 | ### Updates & Rollback |
| 362 | |
| 363 | ```bash |
| 364 | # Update image |
| 365 | kubectl set image deployment/myapp-deployment \ |
| 366 | myapp=myapp:v2 |
| 367 | |
| 368 | # Rollout status |
| 369 | kubectl rollout status deployment/myapp-deployment |
| 370 | |
| 371 | # Rollout history |
| 372 | kubectl rollout history deployment/myapp-deployment |
| 373 | |
| 374 | # Rollback |
| 375 | kubectl rollout undo deployment/myapp-deployment |
| 376 | kubectl rollout undo deployment/myapp-deployment --to-revision=2 |
| 377 | ``` |
| 378 | |
| 379 | ## Deployment Strategies |
| 380 | |
| 381 | ### 1. Rolling Update (Default) |
| 382 | |
| 383 | Update pods secara bertahap. |
| 384 | |
| 385 | ```yaml |
| 386 | spec: |
| 387 | strategy: |
| 388 | type: RollingUpdate |
| 389 | rollingUpdate: |
| 390 | maxSurge: 1 |
| 391 | maxUnavailable: 0 |
| 392 | ``` |
| 393 | |
| 394 | ### 2. Recreate |
| 395 | |
| 396 | Terminate semua pods lama, baru start yang baru. Brief downtime. |
| 397 | |
| 398 | ```yaml |
| 399 | spec: |
| 400 | strategy: |
| 401 | type: Recreate |
| 402 | ``` |
| 403 | |
| 404 | ### 3. Blue-Green (Manual) |
| 405 | |
| 406 | Run dua versions simultaneously, switch traffic. |
| 407 | |
| 408 | ```bash |
| 409 | # Deploy green version |
| 410 | kubectl apply -f green-deployment.yaml |
| 411 | |
| 412 | # Test green |
| 413 | kubectl port-forward service/myapp-green 8080:80 |
| 414 | |
| 415 | # Switch traffic (update service selector) |
| 416 | kubectl patch service myapp -p '{"spec":{"selector":{"version":"green"}}}' |
| 417 | ``` |
| 418 | |
| 419 | ### 4. Canary |
| 420 | |
| 421 | Gradual rollout ke subset users. |
| 422 | |
| 423 | ```yaml |
| 424 | # Stable deployment: 90% traffic |
| 425 | apiVersion: apps/v1 |
| 426 | kind: Deployment |
| 427 | metadata: |
| 428 | name: myapp-stable |
| 429 | spec: |
| 430 | replicas: 9 |
| 431 | # ... |
| 432 | |
| 433 | --- |
| 434 | # Canary deployment: 10% traffic |
| 435 | apiVersion: apps/v1 |
| 436 | kind: Deployment |
| 437 | metadata: |
| 438 | name: myapp-canary |
| 439 | spec: |
| 440 | replicas: 1 |
| 441 | # ... |
| 442 | ``` |
| 443 | |
| 444 | ## Resource Management |
| 445 | |
| 446 | ### Resource Requests & Limits |
| 447 | |
| 448 | ```yaml |
| 449 | resources: |
| 450 | requests: |
| 451 | memory: "128Mi" # Minimum guaranteed |
| 452 | cpu: "250m" # 0.25 CPU core |
| 453 | limits: |
| 454 | memory: "256Mi" # Maximum allowed |
| 455 | cpu: "500m" # 0.5 CPU core |
| 456 | ``` |
| 457 | |
| 458 | ### Quality of Service (QoS) |
| 459 | |
| 460 | 1. **Guaranteed** - requests = limits |
| 461 | 2. **Burstable** - requests < limits |
| 462 | 3. **BestEffort** - no requests/limits |
| 463 | |
| 464 | ## Health Checks |
| 465 | |
| 466 | ### Liveness Probe |
| 467 | |
| 468 | Check if container is alive. Restart if fails. |
| 469 | |
| 470 | ```yaml |
| 471 | livenessProbe: |
| 472 | httpGet: |
| 473 | path: /health |
| 474 | port: 3000 |
| 475 | initialDelaySeconds: 30 |
| 476 | periodSeconds: 10 |
| 477 | timeoutSeconds: 3 |
| 478 | failureThreshold: 3 |
| 479 | ``` |
| 480 | |
| 481 | ### Readiness Probe |
| 482 | |
| 483 | Check if container ready to accept traffic. |
| 484 | |
| 485 | ```yaml |
| 486 | readinessProbe: |
| 487 | httpGet: |
| 488 | path: /ready |
| 489 | port: 3000 |
| 490 | initialDelaySeconds: 5 |
| 491 | periodSeconds: 5 |
| 492 | failureThreshold: 3 |
| 493 | ``` |
| 494 | |
| 495 | ### Startup Probe |
| 496 | |
| 497 | For slow-starting containers. |
| 498 | |
| 499 | ```yaml |
| 500 | startupProbe: |
| 501 | httpGet: |
| 502 | path: /startup |
| 503 | port: 3000 |
| 504 | initialDelaySeconds: 0 |
| 505 | periodSeconds: 10 |
| 506 | failureThreshold: 30 # 300s total |
| 507 | ``` |
| 508 | |
| 509 | ## Persistent Storage |
| 510 | |
| 511 | ### PersistentVolume (PV) |
| 512 | |
| 513 | Cluster-level storage resource. |
| 514 | |
| 515 | ```yaml |
| 516 | apiVersion: v1 |
| 517 | kind: PersistentVolume |
| 518 | metadata: |
| 519 | name: pv-data |
| 520 | spec: |
| 521 | capacity: |
| 522 | storage: 10Gi |
| 523 | accessModes: |
| 524 | - ReadWriteOnce |
| 525 | persistentVolumeReclaimPolicy: Retain |
| 526 | storageClassName: standard |
| 527 | hostPath: |
| 528 | path: /data |
| 529 | ``` |
| 530 | |
| 531 | ### PersistentVolumeClaim (PVC) |
| 532 | |
| 533 | Request for storage by pod. |
| 534 | |
| 535 | ```yaml |
| 536 | apiVersion: v1 |
| 537 | kind: PersistentVolumeClaim |
| 538 | metadata: |
| 539 | name: pvc-data |
| 540 | spec: |
| 541 | accessModes: |
| 542 | - ReadWriteOnce |
| 543 | resources: |
| 544 | requests: |
| 545 | storage: 5Gi |
| 546 | storageClassName: standard |
| 547 | ``` |
| 548 | |
| 549 | ### Use in Pod |
| 550 | |
| 551 | ```yaml |
| 552 | spec: |
| 553 | containers: |
| 554 | - name: myapp |
| 555 | volumeMounts: |
| 556 | - mountPath: /app/data |
| 557 | name: data |
| 558 | volumes: |
| 559 | - name: data |
| 560 | persistentVolumeClaim: |
| 561 | claimName: pvc-data |
| 562 | ``` |
| 563 | |
| 564 | ## Helm: Kubernetes Package Manager |
| 565 | |
| 566 | Package K8s applications sebagai "charts". |
| 567 | |
| 568 | ```bash |
| 569 | # Install Helm |
| 570 | curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash |
| 571 | |
| 572 | # Add repository |
| 573 | helm repo add bitnami https://charts.bitnami.com/bitnami |
| 574 | |
| 575 | # Search charts |
| 576 | helm search repo postgres |
| 577 | |
| 578 | # Install chart |
| 579 | helm install my-postgres bitnami/postgresql |
| 580 | |
| 581 | # List releases |
| 582 | helm list |
| 583 | |
| 584 | # Uninstall |
| 585 | helm uninstall my-postgres |
| 586 | ``` |
| 587 | |
| 588 | ### Create Custom Chart |
| 589 | |
| 590 | ```bash |
| 591 | # Create chart structure |
| 592 | helm create myapp |
| 593 | |
| 594 | myapp/ |
| 595 | ├── Chart.yaml |
| 596 | ├── values.yaml |
| 597 | ├── templates/ |
| 598 | │ ├── deployment.yaml |
| 599 | │ ├── service.yaml |
| 600 | │ └── ingress.yaml |
| 601 | ``` |
| 602 | |
| 603 | ## Managed Kubernetes Services |
| 604 | |
| 605 | ### Google Kubernetes Engine (GKE) |
| 606 | |
| 607 | ```bash |
| 608 | gcloud container clusters create mycluster \ |
| 609 | --num-nodes=3 \ |
| 610 | --zone=asia-southeast1-a |
| 611 | ``` |
| 612 | |
| 613 | ### Amazon EKS |
| 614 | |
| 615 | ```bash |
| 616 | eksctl create cluster \ |
| 617 | --name mycluster \ |
| 618 | --region ap-southeast-1 \ |
| 619 | --nodes 3 |
| 620 | ``` |
| 621 | |
| 622 | ### Azure AKS |
| 623 | |
| 624 | ```bash |
| 625 | az aks create \ |
| 626 | --resource-group mygroup \ |
| 627 | --name mycluster \ |
| 628 | --node-count 3 |
| 629 | ``` |
| 630 | |
| 631 | ### DigitalOcean Kubernetes |
| 632 | |
| 633 | ```bash |
| 634 | doctl kubernetes cluster create mycluster \ |
| 635 | --region sgp1 \ |
| 636 | --node-pool "name=worker;size=s-2vcpu-4gb;count=3" |
| 637 | ``` |
| 638 | |
| 639 | ## Best Practices |
| 640 | |
| 641 | ### 1. Resource Limits |
| 642 | |
| 643 | Always set requests dan limits untuk predictable behavior. |
| 644 | |
| 645 | ### 2. Health Checks |
| 646 | |
| 647 | Implement liveness dan readiness probes. |
| 648 | |
| 649 | ### 3. Use Namespaces |
| 650 | |
| 651 | Isolate environments (dev, staging, prod). |
| 652 | |
| 653 | ### 4. ConfigMaps & Secrets |
| 654 | |
| 655 | Never hardcode configuration. |
| 656 | |
| 657 | ### 5. Labels & Annotations |
| 658 | |
| 659 | Organize dan document resources. |
| 660 | |
| 661 | ```yaml |
| 662 | metadata: |
| 663 | labels: |
| 664 | app: myapp |
| 665 | version: v1 |
| 666 | environment: production |
| 667 | team: backend |
| 668 | annotations: |
| 669 | description: "Main application deployment" |
| 670 | contact: "team@example.com" |
| 671 | ``` |
| 672 | |
| 673 | ### 6. Pod Security |
| 674 | |
| 675 | ```yaml |
| 676 | securityContext: |
| 677 | runAsNonRoot: true |
| 678 | runAsUser: 1000 |
| 679 | fsGroup: 1000 |
| 680 | capabilities: |
| 681 | drop: |
| 682 | - ALL |
| 683 | readOnlyRootFilesystem: true |
| 684 | ``` |
| 685 | |
| 686 | ### 7. Network Policies |
| 687 | |
| 688 | Restrict traffic between pods. |
| 689 | |
| 690 | ```yaml |
| 691 | apiVersion: networking.k8s.io/v1 |
| 692 | kind: NetworkPolicy |
| 693 | metadata: |
| 694 | name: api-policy |
| 695 | spec: |
| 696 | podSelector: |
| 697 | matchLabels: |
| 698 | app: api |
| 699 | policyTypes: |
| 700 | - Ingress |
| 701 | ingress: |
| 702 | - from: |
| 703 | - podSelector: |
| 704 | matchLabels: |
| 705 | app: frontend |
| 706 | ports: |
| 707 | - protocol: TCP |
| 708 | port: 8080 |
| 709 | ``` |
| 710 | |
| 711 | ## Kubernetes untuk Developer Indonesia |
| 712 | |
| 713 | ### Kapan Perlu K8s? |
| 714 | |
| 715 | **Kubernetes biasanya masuk akal jika:** |
| 716 | - Aplikasi sudah berbentuk microservices |
| 717 | - High availability memang dibutuhkan |
| 718 | - Auto-scaling mulai penting |
| 719 | - Anda mengelola beberapa environment sekaligus |
| 720 | - Tim dan jumlah service sudah cukup besar |
| 721 | |
| 722 | **Kubernetes sering belum perlu jika:** |
| 723 | - Aplikasinya masih monolith sederhana |
| 724 | - Traffic masih rendah |
| 725 | - Anda bekerja sendiri atau di tim kecil |
| 726 | - Budget dan waktu operasional terbatas |
| 727 | |
| 728 | ### Alternatif Lebih Sederhana |
| 729 | |
| 730 | Untuk banyak startup atau SMB di Indonesia, platform yang lebih sederhana sering lebih realistis untuk tahap awal: |
| 731 | - **smbCloud** - PaaS dengan setup yang lebih ringan |
| 732 | - **Heroku** - PaaS yang mudah dipakai |
| 733 | - **Railway** - Cukup ramah untuk developer |
| 734 | - **Fly.io** - Cocok untuk deployment yang dekat ke edge |
| 735 | - **Render** - Opsi cloud yang relatif sederhana |
| 736 | |
| 737 | ## Troubleshooting Common Issues |
| 738 | |
| 739 | ### Pod Stuck in Pending |
| 740 | |
| 741 | ```bash |
| 742 | kubectl describe pod myapp-pod |
| 743 | # Check: Insufficient resources, PVC not bound, node selector issues |
| 744 | ``` |
| 745 | |
| 746 | ### CrashLoopBackOff |
| 747 | |
| 748 | ```bash |
| 749 | kubectl logs myapp-pod --previous |
| 750 | # Check: Application errors, missing dependencies, misconfiguration |
| 751 | ``` |
| 752 | |
| 753 | ### ImagePullBackOff |
| 754 | |
| 755 | ```bash |
| 756 | kubectl describe pod myapp-pod |
| 757 | # Check: Wrong image name, authentication issues, network problems |
| 758 | ``` |
| 759 | |
| 760 | ### Service Not Accessible |
| 761 | |
| 762 | ```bash |
| 763 | kubectl get endpoints myapp-service |
| 764 | # Check: Label selector, port configuration, pod readiness |
| 765 | ``` |
| 766 | |
| 767 | ## Learning Path |
| 768 | |
| 769 | ### Beginner (1-2 bulan) |
| 770 | - Understand containers (Docker) |
| 771 | - K8s architecture basics |
| 772 | - Deploy simple app with Deployment + Service |
| 773 | - kubectl basic commands |
| 774 | |
| 775 | ### Intermediate (3-6 bulan) |
| 776 | - ConfigMaps & Secrets |
| 777 | - Health checks |
| 778 | - Ingress & networking |
| 779 | - Persistent storage |
| 780 | - Helm charts |
| 781 | |
| 782 | ### Advanced (6+ bulan) |
| 783 | - StatefulSets |
| 784 | - Custom Resource Definitions (CRDs) |
| 785 | - Operators |
| 786 | - Service mesh (Istio/Linkerd) |
| 787 | - Multi-cluster management |
| 788 | |
| 789 | ## Kesimpulan |
| 790 | |
| 791 | Kubernetes sangat berguna saat aplikasi containerized sudah cukup besar dan operasionalnya mulai sulit ditangani manual. Dengan Kubernetes, tim bisa mengatur deployment, scaling, networking, dan pemulihan service dengan cara yang lebih konsisten. |
| 792 | |
| 793 | Tetap ada konsekuensinya: Kubernetes menambah lapisan kompleksitas. Karena itu, pilih Kubernetes saat kebutuhan sistem memang mengarah ke sana, bukan hanya karena sedang populer. |
| 794 | |
| 795 | Kalau Anda baru belajar, mulai saja dari dasar-dasarnya dulu: pahami container, pod, deployment, service, dan `kubectl`. Setelah itu, baru lanjut ke topik seperti ingress, Helm, autoscaling, dan observability. |