Ebook Syafi
Koleksi
Admin
← DevOps Dari Homelab ke Production
Edit Bab
💾 Simpan
Batal
Syarat
Mukadimah
Bab
Penutup
B
I
H2
H3
List
1.
Quote
Code
Link
Img
Table
Edit
Split
Preview
0 perkataan
# Bab 5: Kubernetes Asas Ada satu titik dalam perjalanan DevOps anda di mana Docker Compose mula terasa tidak cukup. Mungkin anda perlu deploy ke multiple servers. Mungkin anda perlu auto-scaling. Mungkin anda perlu zero-downtime deployment tanpa perlu tulis skrip yang rumit. Di situlah Kubernetes masuk. Kubernetes (atau K8s, kerana ada 8 huruf antara K dan s) pada mulanya mungkin nampak menakutkan. Banyak terminologi baru, banyak YAML files, banyak moving parts. Tapi kalau anda sudah faham Docker, anda sebenarnya sudah mempunyai 60% daripada pengetahuan yang diperlukan. Bab ini akan bawa anda melalui 40% yang tinggal. Kita tak akan cover semuanya. Kubernetes adalah ecosystem yang sangat luas. Tapi selepas habis bab ini, anda akan mempunyai pemahaman yang kukuh tentang core concepts dan boleh deploy aplikasi pertama anda ke K8s cluster. ## Apa yang anda akan belajar: - Kenapa Kubernetes wujud dan masalah apa yang ia selesaikan - Arsitektur K8s: control plane, worker nodes, pods, services - Setup K3s di homelab anda (step by step) - Kubectl commands yang anda perlu tahu - Deploy aplikasi pertama ke K8s - Services dan Ingress untuk expose aplikasi - ConfigMaps dan Secrets - Persistent storage - Scaling aplikasi - Asas Helm - Bila guna K8s vs Docker Compose ## Kenapa Kubernetes? Sebelum kita terjun ke technical details, mari faham masalah yang Kubernetes selesaikan. Bayangkan anda ada 5 aplikasi microservices, setiap satu memerlukan 2 replicas, dan anda ada 3 servers. Dengan Docker Compose, anda perlu manually decide: service A dan B di server 1, service C di server 2, dan seterusnya. Kalau server 2 mati, anda perlu manually pindahkan services ke server lain. Kalau traffic meningkat, anda perlu manually tambah replicas. Kubernetes automate semua ini. Anda cuma perlu cakap: "Saya nak 2 replicas untuk service A." Kubernetes akan decide di mana nak letak, dan kalau satu replica mati, ia akan automatically create yang baru. Ini dipanggil **declarative configuration**. Anda declare apa yang anda nak, bukan bagaimana nak achieve ia. Selain itu, Kubernetes memberikan anda beberapa superpower yang Docker Compose tidak ada: - **Self-healing**: Kalau container crash, K8s automatically restart. Kalau node mati, K8s pindahkan workload ke node lain. - **Auto-scaling**: K8s boleh tambah atau kurangkan replicas berdasarkan CPU/memory usage secara automatik. - **Rolling updates**: Deploy version baru tanpa downtime. K8s akan slowly replace pods lama dengan pods baru. - **Service discovery**: Setiap service dapat DNS name secara automatik. Tak perlu hardcode IP addresses. - **Load balancing**: Traffic diagihkan secara automatik antara semua replicas. > **Nota Beginner:** K8s bukan penyelesaian untuk semua masalah. Ia menambah complexity yang significant. Pastikan anda benar-benar perlukan features di atas sebelum adopt K8s. Banyak aplikasi berjaya dengan Docker Compose sahaja. ## Arsitektur Kubernetes Untuk faham K8s, anda perlu faham beberapa komponen utama. ### Control Plane Control plane adalah "otak" K8s. Ia terdiri daripada beberapa komponen. **API Server** adalah pintu masuk utama. Semua arahan kepada K8s melalui API server, termasuk arahan dari `kubectl`. **etcd** adalah database yang simpan semua state cluster. Ia tahu berapa replicas setiap service ada, di mana ia running, dan apa configuration mereka. **Scheduler** bertanggungjawab untuk decide di mana nak run pods baru. Ia mempertimbangkan resource availability, constraints, dan affinity rules. **Controller Manager** menjalankan pelbagai controllers yang memastikan actual state cluster sepadan dengan desired state. Kalau anda kata nak 3 replicas tapi hanya 2 yang running, controller manager akan buat satu lagi. ### Worker Nodes Worker nodes adalah machines yang actually run containers anda. Setiap worker node mempunyai beberapa komponen penting. **kubelet** adalah agent yang run di setiap node. Ia menerima arahan dari control plane dan memastikan containers running seperti yang dikehendaki. **kube-proxy** menguruskan network rules supaya traffic boleh sampai ke pods yang betul. **Container Runtime** (biasanya containerd) adalah software yang actually run containers. ### Pods Pod adalah unit terkecil dalam Kubernetes. Satu pod boleh mengandungi satu atau lebih containers. Dalam kebanyakan kes, satu pod mengandungi satu container sahaja. > **Nota Beginner:** Fikirkan pod macam wrapper di sekeliling container anda. Kenapa perlu wrapper? Kerana K8s perlu tempat untuk letak metadata, health check info, restart policy, dan networking config. Pod menyediakan semua ini. ### Services Service dalam K8s bukan service dalam Docker Compose. Di sini, service adalah abstraksi yang menyediakan stable network endpoint untuk satu set pods. Pods boleh datang dan pergi (dihapus, dicipta semula), tetapi service address kekal sama. ## Setting Up K3s di Homelab K3s adalah lightweight Kubernetes distribution dari Rancher. Ia sesuai untuk homelab kerana ia menggunakan kurang resources berbanding full K8s, tetapi masih production-ready. ### Keperluan - Satu atau lebih machines (boleh VMs) dengan minimum 2GB RAM dan 2 CPU cores - Ubuntu 22.04 atau mana-mana Linux distribution yang supported - Network connectivity antara semua nodes ### Install K3s Server (Control Plane) ```bash # Di server utama (control plane) curl -sfL https://get.k3s.io | sh - # Check status sudo systemctl status k3s # Dapatkan kubeconfig sudo cat /etc/rancher/k3s/k3s.yaml ``` Itu sahaja. Serius. K3s boleh di-install dalam satu command. Selepas install, anda sudah ada functional Kubernetes cluster dengan satu node. ### Tambah Worker Nodes ```bash # Di server utama, dapatkan token sudo cat /var/lib/rancher/k3s/server/node-token # Di worker node, join cluster curl -sfL https://get.k3s.io | K3S_URL=https://CONTROL_PLANE_IP:6443 \ K3S_TOKEN=TOKEN_DARI_SERVER sh - ``` ### Setup kubectl di Local Machine ```bash # Copy kubeconfig dari server scp user@server:/etc/rancher/k3s/k3s.yaml ~/.kube/config # Edit server address (tukar 127.0.0.1 ke server IP) # Dalam ~/.kube/config, cari line "server:" dan tukar ke IP server # Test connection kubectl get nodes ``` Output yang anda sepatutnya nampak: ``` NAME STATUS ROLES AGE VERSION server-01 Ready control-plane,master 10m v1.28.5+k3s1 worker-01 Ready
5m v1.28.5+k3s1 worker-02 Ready
3m v1.28.5+k3s1 ``` > **Nota Beginner:** Kalau anda cuma ada satu machine, tak perlu risau. K3s boleh run semua workloads di control plane node juga. Untuk belajar, satu node sudah cukup. ## Kubectl Commands yang Anda Perlu Tahu `kubectl` adalah CLI tool untuk interact dengan Kubernetes cluster. Ini commands yang paling kerap digunakan. ```bash # Lihat semua resources kubectl get pods # Senarai pods kubectl get services # Senarai services kubectl get deployments # Senarai deployments kubectl get all # Senarai semua resources kubectl get all -n kube-system # Resources dalam namespace tertentu # Maklumat terperinci kubectl describe pod POD_NAME # Detail sesuatu pod kubectl describe service SVC_NAME # Detail sesuatu service # Logs kubectl logs POD_NAME # Lihat logs kubectl logs -f POD_NAME # Follow logs (live) kubectl logs POD_NAME -c CONTAINER # Logs dari specific container # Debug kubectl exec -it POD_NAME -- /bin/sh # Shell ke dalam pod kubectl port-forward POD_NAME 8080:80 # Forward port ke local # Apply configuration kubectl apply -f manifest.yaml # Create atau update resource kubectl delete -f manifest.yaml # Delete resource ``` Tips berguna: set alias supaya hidup lebih mudah. ```bash # Tambah dalam ~/.bashrc atau ~/.zshrc alias k='kubectl' alias kgp='kubectl get pods' alias kgs='kubectl get services' alias kgd='kubectl get deployments' alias kd='kubectl describe' alias kl='kubectl logs' alias ka='kubectl apply -f' ``` ## Deploy Aplikasi Pertama Mari deploy satu aplikasi web yang simple. Dalam K8s, anda define apa yang anda nak dalam YAML files yang dipanggil **manifests**. ### Deployment ```yaml # app-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: my-web-app labels: app: my-web-app spec: replicas: 3 selector: matchLabels: app: my-web-app template: metadata: labels: app: my-web-app spec: containers: - name: web image: ghcr.io/username/my-app:v1.0.0 ports: - containerPort: 3000 resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 256Mi readinessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 15 periodSeconds: 20 ``` YAML ini memberitahu K8s: "Saya nak 3 replicas aplikasi saya, setiap satu guna image ini, expose port 3000, dan ini resource limits yang saya nak." ```bash # Apply deployment kubectl apply -f app-deployment.yaml # Check status kubectl get deployments kubectl get pods # Tunggu sehingga semua pods Ready kubectl rollout status deployment/my-web-app ``` Perhatikan dua jenis probes. **readinessProbe** menentukan sama ada pod sedia menerima traffic. Kalau fail, pod akan dikeluarkan dari service (tak terima traffic baru, tapi tidak di-kill). **livenessProbe** menentukan sama ada pod masih hidup. Kalau fail beberapa kali berturut-turut, K8s akan restart pod tersebut. ## Services dan Ingress Pods sudah running, tapi bagaimana nak access mereka? Di sinilah Services dan Ingress masuk. ### ClusterIP Service ```yaml # app-service.yaml apiVersion: v1 kind: Service metadata: name: my-web-app spec: selector: app: my-web-app ports: - port: 80 targetPort: 3000 type: ClusterIP ``` ClusterIP service hanya boleh diakses dari dalam cluster. Ia menyediakan stable IP address dan DNS name (`my-web-app.default.svc.cluster.local`). Sesuai untuk internal services seperti API yang diakses oleh services lain. ### NodePort Service ```yaml apiVersion: v1 kind: Service metadata: name: my-web-app-nodeport spec: selector: app: my-web-app ports: - port: 80 targetPort: 3000 nodePort: 30080 type: NodePort ``` NodePort expose service pada setiap node di port tertentu (30080 dalam contoh ini). Anda boleh access aplikasi melalui `http://NODE_IP:30080`. Sesuai untuk testing, tetapi bukan untuk production. ### Ingress Untuk production, gunakan Ingress. Ia menyediakan HTTP routing, SSL termination, dan virtual hosting. ```yaml # app-ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-web-app annotations: cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - myapp.example.com secretName: myapp-tls rules: - host: myapp.example.com http: paths: - path: / pathType: Prefix backend: service: name: my-web-app port: number: 80 ``` K3s datang dengan Traefik sebagai Ingress controller secara default. Anda cuma perlu create Ingress resource dan point DNS ke cluster anda. ```bash # Apply semua resources kubectl apply -f app-deployment.yaml kubectl apply -f app-service.yaml kubectl apply -f app-ingress.yaml # Check Ingress status kubectl get ingress ``` ### Multiple Services dengan Ingress Salah satu kelebihan Ingress ialah anda boleh route traffic ke different services berdasarkan path atau hostname. ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: multi-app-ingress annotations: cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - api.example.com - dashboard.example.com secretName: multi-app-tls rules: - host: api.example.com http: paths: - path: / pathType: Prefix backend: service: name: api-service port: number: 80 - host: dashboard.example.com http: paths: - path: / pathType: Prefix backend: service: name: dashboard-service port: number: 80 ``` Dengan setup ini, satu Ingress controller boleh handle traffic untuk multiple applications. Setiap hostname diarahkan ke service yang berbeza. Ini jauh lebih kemas berbanding run multiple reverse proxies. ## ConfigMaps dan Secrets Jangan hardcode configuration dalam Docker image. Gunakan ConfigMaps untuk non-sensitive config dan Secrets untuk sensitive data. ### ConfigMap ```yaml # app-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: my-web-app-config data: APP_ENV: "production" LOG_LEVEL: "info" MAX_CONNECTIONS: "100" CACHE_TTL: "3600" ``` ### Secret ```bash # Buat secret via kubectl kubectl create secret generic my-web-app-secrets \ --from-literal=DATABASE_URL='postgresql://user:pass@db:5432/mydb' \ --from-literal=API_KEY='sk-supersecretkey123' ``` Atau dalam YAML (values mesti base64 encoded): ```yaml # app-secrets.yaml apiVersion: v1 kind: Secret metadata: name: my-web-app-secrets type: Opaque data: DATABASE_URL: cG9zdGdyZXNxbDovL3VzZXI6cGFzc0BkYjo1NDMyL215ZGI= API_KEY: c2stc3VwZXJzZWNyZXRrZXkxMjM= ``` > **Nota Beginner:** Base64 bukan encryption. Sesiapa yang ada access ke cluster boleh decode secrets. Untuk security yang lebih baik, gunakan tools seperti Sealed Secrets atau external secret management seperti HashiCorp Vault. ### Gunakan dalam Deployment ```yaml spec: containers: - name: web image: ghcr.io/username/my-app:v1.0.0 envFrom: - configMapRef: name: my-web-app-config - secretRef: name: my-web-app-secrets # Atau specific keys sahaja: env: - name: DATABASE_HOST valueFrom: configMapKeyRef: name: my-web-app-config key: DATABASE_HOST - name: DATABASE_PASSWORD valueFrom: secretKeyRef: name: my-web-app-secrets key: DATABASE_PASSWORD ``` ## Persistent Storage Pods adalah ephemeral. Kalau pod mati, data di dalamnya hilang. Untuk data yang perlu kekal (database, uploaded files), gunakan Persistent Volumes. ```yaml # pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgres-data spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: local-path ``` ```yaml # postgres-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: postgres spec: replicas: 1 selector: matchLabels: app: postgres template: metadata: labels: app: postgres spec: containers: - name: postgres image: postgres:16-alpine ports: - containerPort: 5432 env: - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: postgres-secrets key: password - name: PGDATA value: /var/lib/postgresql/data/pgdata volumeMounts: - name: postgres-storage mountPath: /var/lib/postgresql/data resources: requests: cpu: 250m memory: 256Mi limits: cpu: '1' memory: 1Gi volumes: - name: postgres-storage persistentVolumeClaim: claimName: postgres-data ``` K3s menyediakan `local-path` storage class secara default. Ia menyimpan data di node tempat pod running. Untuk production yang lebih robust, anda mungkin perlu NFS, Longhorn, atau cloud storage (EBS, GCE PD). ### Longhorn: Distributed Storage untuk K3s Kalau anda run K3s dengan multiple nodes, Longhorn adalah pilihan yang excellent untuk storage. Ia replicate data across nodes, jadi kalau satu node mati, data anda masih selamat. ```bash # Install Longhorn via Helm helm repo add longhorn https://charts.longhorn.io helm repo update helm install longhorn longhorn/longhorn \ --namespace longhorn-system \ --create-namespace \ --set defaultSettings.defaultReplicaCount=2 ``` Selepas install, anda boleh gunakan Longhorn sebagai storage class: ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgres-data spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 10Gi ``` > **Nota Beginner:** Untuk homelab dengan satu node, `local-path` sudah memadai. Anda hanya perlukan Longhorn atau distributed storage bila anda ada multiple nodes dan perlu data redundancy. ## Scaling Salah satu kelebihan utama K8s adalah scaling yang mudah. ### Manual Scaling ```bash # Scale up kubectl scale deployment my-web-app --replicas=5 # Scale down kubectl scale deployment my-web-app --replicas=2 ``` ### Horizontal Pod Autoscaler (HPA) ```yaml # hpa.yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: my-web-app-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: my-web-app 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 ``` Dengan HPA, K8s akan automatically tambah pods kalau CPU usage melebihi 70% atau memory usage melebihi 80%. Dan ia akan kurangkan pods kalau usage rendah. Anda set minimum 2 replicas (untuk high availability) dan maximum 10 replicas (untuk control cost). ```bash # Apply HPA kubectl apply -f hpa.yaml # Monitor HPA kubectl get hpa kubectl describe hpa my-web-app-hpa ``` ## Namespaces Sebelum kita pergi ke Helm, satu concept yang penting ialah namespaces. Namespace adalah cara K8s untuk memisahkan resources dalam satu cluster. ```bash # Lihat semua namespaces kubectl get namespaces # Buat namespace baru kubectl create namespace staging kubectl create namespace production # Deploy ke namespace tertentu kubectl apply -f app-deployment.yaml -n staging kubectl apply -f app-deployment.yaml -n production # Lihat pods dalam namespace tertentu kubectl get pods -n staging kubectl get pods -n production ``` Dengan namespaces, anda boleh run staging dan production dalam satu cluster (walaupun untuk production sebenar, cluster berasingan adalah lebih selamat). Anda juga boleh set resource quotas per namespace supaya satu environment tidak menggunakan semua resources. ```yaml # resource-quota.yaml apiVersion: v1 kind: ResourceQuota metadata: name: staging-quota namespace: staging spec: hard: pods: "20" requests.cpu: "4" requests.memory: 8Gi limits.cpu: "8" limits.memory: 16Gi ``` > **Nota Beginner:** Untuk homelab, anda mungkin cuma guna `default` namespace dan itu sudah okay. Tapi bila anda mula deploy multiple aplikasi atau environments, namespaces akan menjadi sangat berguna untuk organisasi. ## Troubleshooting K8s Sebelum kita pergi ke Helm, ini beberapa teknik troubleshooting yang sangat berguna. Anda pasti akan perlukan ini. ```bash # Pod stuck dalam "Pending" state? Check events kubectl describe pod POD_NAME # Biasanya sebab: insufficient resources, PVC not bound, atau image pull error # Pod dalam "CrashLoopBackOff"? Check logs kubectl logs POD_NAME --previous # "--previous" tunjuk logs dari container yang crash sebelumnya # Pod running tapi app tak respond? Exec ke dalam pod kubectl exec -it POD_NAME -- /bin/sh # Check process, network, files dari dalam pod # Service tak boleh diakses? Check endpoints kubectl get endpoints SERVICE_NAME # Kalau endpoints kosong, selector mungkin tidak match pod labels # Check semua events dalam cluster kubectl get events --sort-by='.lastTimestamp' ``` Debugging Kubernetes boleh jadi frustrating pada awalnya. Tapi selepas anda biasa, pattern yang sama akan muncul berulang kali. Kebanyakan masalah berpunca daripada image pull errors, resource limits yang terlalu ketat, atau selector labels yang tidak match. ## Asas Helm Bila aplikasi anda mempunyai banyak Kubernetes manifests (deployment, service, ingress, configmap, secret, pvc, hpa), managing semua YAML files ini boleh jadi rumit. Helm menyelesaikan masalah ini. Helm adalah package manager untuk Kubernetes. Fikirkan ia macam `apt` untuk Ubuntu atau `brew` untuk macOS, tapi untuk K8s. ### Install Helm ```bash # macOS brew install helm # Linux curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash ``` ### Gunakan Helm Charts yang Sedia Ada ```bash # Tambah repository helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update # Search charts helm search repo postgresql # Install PostgreSQL helm install my-postgres bitnami/postgresql \ --set auth.postgresPassword=mypassword \ --set primary.persistence.size=10Gi # Senarai installations helm list # Uninstall helm uninstall my-postgres ``` ### Buat Helm Chart Sendiri ```bash # Scaffold chart baru helm create my-app # Struktur yang dihasilkan: # my-app/ # Chart.yaml - Metadata # values.yaml - Default values # templates/ - K8s manifest templates # deployment.yaml # service.yaml # ingress.yaml # hpa.yaml ``` Contoh `values.yaml`: ```yaml # values.yaml replicaCount: 3 image: repository: ghcr.io/username/my-app tag: "v1.0.0" pullPolicy: IfNotPresent service: type: ClusterIP port: 80 targetPort: 3000 ingress: enabled: true host: myapp.example.com tls: true resources: limits: cpu: 500m memory: 256Mi requests: cpu: 100m memory: 128Mi autoscaling: enabled: true minReplicas: 2 maxReplicas: 10 targetCPUUtilization: 70 ``` Kemudian dalam templates, anda gunakan values ini: ```yaml # templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ .Release.Name }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app: {{ .Release.Name }} template: spec: containers: - name: app image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" resources: {{- toYaml .Values.resources | nindent 12 }} ``` Deploy menggunakan Helm: ```bash # Install helm install my-release ./my-app # Upgrade dengan values baru helm upgrade my-release ./my-app --set image.tag=v1.1.0 # Upgrade dengan custom values file helm upgrade my-release ./my-app -f production-values.yaml # Rollback kalau ada masalah helm rollback my-release 1 ``` Kelebihan Helm yang paling jelas ialah anda boleh deploy aplikasi yang sama ke multiple environments dengan hanya menukar values file. Staging guna `staging-values.yaml`, production guna `production-values.yaml`. Sama templates, values yang berbeza. ## Bila Guna K8s vs Docker Compose? Ini soalan yang ramai orang tanya. Dan jawapannya bukan "K8s selalu lebih baik." Ada masa untuk Docker Compose dan ada masa untuk Kubernetes. ### Gunakan Docker Compose bila: - Anda deploy ke satu server sahaja - Aplikasi anda ada 2 hingga 5 services - Team anda kecil (1 hingga 3 orang) - Anda tak perlu auto-scaling - Budget terhad (K8s memerlukan lebih resources untuk cluster overhead) - Aplikasi anda bukan mission-critical (sedikit downtime boleh diterima) ### Gunakan Kubernetes bila: - Anda deploy ke multiple servers - Anda perlukan high availability (zero downtime) - Anda perlukan auto-scaling - Anda ada banyak microservices (10+) - Team anda cukup besar untuk manage K8s - Anda sudah ada CI/CD pipeline yang mature > **Nota Beginner:** Jangan gunakan Kubernetes semata-mata kerana ia popular. K8s menambah complexity yang significant. Kalau Docker Compose sudah memenuhi keperluan anda, teruskan gunakannya. Ramai startup berjaya yang run on bare Docker Compose. Gunakan K8s hanya bila anda benar-benar memerlukannya. Satu pendekatan yang bagus ialah mulakan dengan Docker Compose. Bila anda mula rasa limitasinya (perlu multi-server, perlu auto-scaling, perlu self-healing), barulah migrate ke Kubernetes. Pengalaman anda dengan Docker Compose akan memudahkan transition kerana concepts seperti services, volumes, dan networking wujud dalam kedua-duanya. ### Migration Path: Docker Compose ke K8s Kalau anda decide nak migrate, ini rough steps yang boleh anda ikut: 1. **Pastikan semua services anda sudah containerized** dengan proper Dockerfiles dan images di registry. 2. **Setup K3s cluster** di homelab dulu. Test dengan satu node. 3. **Convert Docker Compose services ke K8s manifests** satu per satu. Mulakan dengan stateless services (web apps, APIs) kerana ia paling mudah. 4. **Migrate stateful services** (databases) terakhir. Ini paling tricky kerana perlu handle persistent storage. 5. **Update CI/CD pipeline** untuk deploy ke K8s cluster. 6. **Run kedua-dua environments** secara selari untuk seketika. Route sebahagian traffic ke K8s untuk validate. 7. **Fully cutover** ke K8s bila anda yakin semuanya stable. Proses ini mungkin ambil beberapa minggu atau bulan bergantung pada complexity aplikasi anda. Jangan terburu-buru. Lebih baik migrate dengan yakin daripada cepat tapi penuh masalah. Ada juga tools seperti `kompose` yang boleh convert Docker Compose files ke K8s manifests secara automatik. Tapi hasilnya biasanya perlu banyak tweaking. Saya recommend tulis K8s manifests sendiri supaya anda benar-benar faham apa yang berlaku. ```bash # Kalau nak cuba kompose kompose convert -f docker-compose.yml # Ia akan generate K8s manifests, tapi expect banyak manual adjustment ``` ## Ringkasan Dalam bab ini, kita telah bermula dari soalan "Kenapa Kubernetes?" dan sampai ke tahap boleh deploy, expose, scale, dan manage aplikasi di K8s cluster. Kita telah belajar arsitektur K8s dengan control plane dan worker nodes. Kita telah setup K3s di homelab dan deploy aplikasi pertama lengkap dengan Deployment, Service, Ingress, ConfigMaps, Secrets, persistent storage, dan autoscaling. Kita juga telah sentuh Helm sebagai cara untuk manage Kubernetes manifests dengan lebih terstruktur. Dan yang paling penting, kita telah bincangkan bila sebenarnya anda perlu K8s dan bila Docker Compose sudah memadai. Kubernetes adalah perjalanan yang panjang. Apa yang kita cover di sini adalah asas yang kukuh. Dari sini, anda boleh explore topik yang lebih advanced seperti namespaces, network policies, RBAC, service mesh, dan monitoring. Tapi dengan apa yang anda belajar dalam bab ini, anda sudah boleh mula deploy real applications ke K8s cluster anda sendiri. \newpage