Multi-Node Cluster
Versi Bahasa Indonesia. Baca dalam Bahasa Inggris
Cluster Kubernetes multi-node adalah cluster yang terdiri dari setidaknya satu atau lebih node ControlPlane dan satu atau lebih node Worker. Node Control Plane bertanggung jawab untuk mengelola siklus hidup cluster dan menjadwalkan workload. Node Worker menjalankan aplikasi sebenarnya (Pod).
Source: https://kubernetes.io/docs/concepts/architecture/
Workloads Scheduling
Secara default, Kubernetes tidak menjadwalkan Pod di node control plane untuk workload biasa. Ini untuk memastikan control plane tetap didedikasikan untuk mengelola cluster dan tidak dibebani dengan menjalankan workload aplikasi. Ini hanya berlaku jika node memiliki taints ini.
Taints: node-role.kubernetes.io/control-plane:NoScheduleMari coba dengan minikube, pertama kita perlu memulai cluster baru dengan 3 node menggunakan perintah di bawah.
β minikube start --nodes 3 -p multinode
π [multinode] minikube v1.34.0 on Darwin 15.3.1 (arm64)
β¨ Automatically selected the docker driver
π Using Docker Desktop driver with root privileges
π Starting "multinode" primary control-plane node in "multinode" cluster
π Pulling base image v0.0.45 ...
π₯ Creating docker container (CPUs=2, Memory=2200MB) ...
π³ Preparing Kubernetes v1.31.0 on Docker 27.2.0 ...
βͺ Generating certificates and keys ...
βͺ Booting up control plane ...
βͺ Configuring RBAC rules ...
π Configuring CNI (Container Networking Interface) ...
π Verifying Kubernetes components...
βͺ Using image gcr.io/k8s-minikube/storage-provisioner:v5
π Enabled addons: storage-provisioner, default-storageclass
π Starting "multinode-m02" worker node in "multinode" cluster
π Pulling base image v0.0.45 ...
π₯ Creating docker container (CPUs=2, Memory=2200MB) ...
π Found network options:
βͺ NO_PROXY=192.168.49.2
π³ Preparing Kubernetes v1.31.0 on Docker 27.2.0 ...
βͺ env NO_PROXY=192.168.49.2
π Verifying Kubernetes components...
π Starting "multinode-m03" worker node in "multinode" cluster
π Pulling base image v0.0.45 ...
π₯ Creating docker container (CPUs=2, Memory=2200MB) ...
π Found network options:
βͺ NO_PROXY=192.168.49.2,192.168.49.3
π³ Preparing Kubernetes v1.31.0 on Docker 27.2.0 ...
βͺ env NO_PROXY=192.168.49.2
βͺ env NO_PROXY=192.168.49.2,192.168.49.3
π Verifying Kubernetes components...
π Done! kubectl is now configured to use "multinode" cluster and "default" namespace by defaultIni akan memulai cluster Kubernetes dengan 3 node, 1 node control plane dan 2 node worker.
β kubectl get nodes
NAME STATUS ROLES AGE VERSION
multinode Ready control-plane 48s v1.31.0
multinode-m02 Ready <none> 35s v1.31.0
multinode-m03 Ready <none> 25s v1.31.0Kemudian mari buat deployment sederhana menggunakan image nginx dengan 3 replika dan apply.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80β kubectl apply -f deployment.yaml
deployment.apps/nginx-deployment createdβ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-54b9c68f67-fq928 1/1 Running 0 4m56s 10.244.1.2 multinode-m02 <none> <none>
nginx-deployment-54b9c68f67-t85zh 1/1 Running 0 4m56s 10.244.2.2 multinode-m03 <none> <none>
nginx-deployment-54b9c68f67-wvzng 1/1 Running 0 4m56s 10.244.0.3 multinode <none> <none>Seperti yang kita lihat di atas, pod tersebar merata di semua node, termasuk node control plane yang seharusnya tidak terjadi. Ini karena minikube tidak menambahkan taint NoSchedule secara default.
β kubectl describe nodes | grep Taint
Taints: <none>
Taints: <none>
Taints: <none>Jika tidak ada taint NoSchedule di node control-plane, node tersebut bisa menerima Pod. Dengan 3 replika dan 3 node, scheduler mendistribusikan Pod secara merata. Untuk mencegah ini, kita bisa menambahkan taint secara manual menggunakan perintah di bawah.
β kubectl taint nodes multinode node-role.kubernetes.io/control-plane:NoSchedule
node/multinode taintedβ kubectl describe nodes multinode | grep Taint
Taints: node-role.kubernetes.io/control-plane:NoScheduleKemudian hapus pod yang dijadwalkan di node control plane.
β kubectl delete pod nginx-deployment-54b9c68f67-wvzng
pod "nginx-deployment-54b9c68f67-wvzng" deletedCek daftar pod lagi dan kamu akan melihat pod baru tidak dijadwalkan di node control plane.
β kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-54b9c68f67-fq928 1/1 Running 0 22m 10.244.1.2 multinode-m02 <none> <none>
nginx-deployment-54b9c68f67-hd6bq 1/1 Running 0 14s 10.244.2.3 multinode-m03 <none> <none>
nginx-deployment-54b9c68f67-t85zh 1/1 Running 0 22m 10.244.2.2 multinode-m03 <none> <none>Node Specific Deployment
Pada akhirnya kita ingin men-deploy atau menempatkan Pod ke node tertentu karena beberapa alasan. Misalnya kita ingin men-deploy service database di region EU untuk kepatuhan GDPR, menempatkan service observability di node yang berbeda untuk meningkatkan keandalan, mengisolasi workload CPU intensif di node yang berbeda, dll.
Kubernetes menyediakan mekanisme seperti nodeSelector, nodeAffinity, serta taints dan tolerations untuk mengontrol penempatan pod.
nodeSelector
nodeSelector adalah cara paling sederhana yang direkomendasikan untuk men-deploy/menempatkan Pod ke node tertentu. Kita bisa menambahkan field nodeSelector ke spesifikasi Pod dan menentukan label node yang ingin kita targetkan. Pastikan kamu memberi label pada node dengan benar. Kubernetes hanya akan menjadwalkan Pod ke node yang memiliki setiap label yang kita tentukan.
Pertama, mari tambahkan label ke node multinode-m02 sehingga kita bisa menggunakannya sebagai node selector.
β kubectl label nodes multinode-m02 node-type=infra
node/multinode-m02 labeledKemudian update file deployment kita untuk menambahkan field nodeSelector di dalam template.spec. Ini akan memberi tahu scheduler Kubernetes untuk menjadwalkan pod ke node yang memiliki label yang sama seperti yang ditentukan di node selector.
nodeSelector:
node-type: infraApply ulang file yaml dan cek daftar pod lagi. Kamu akan melihat bahwa semua pod berjalan di node multinode-m02.
β kubectl apply -f deployment.yaml
deployment.apps/nginx-deployment configuredβ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-5579449f87-8c26w 1/1 Running 0 23s 10.244.1.3 multinode-m02 <none> <none>
nginx-deployment-5579449f87-cjbbf 1/1 Running 0 16s 10.244.1.5 multinode-m02 <none> <none>
nginx-deployment-5579449f87-kdk45 1/1 Running 0 19s 10.244.1.4 multinode-m02 <none> <none>nodeAffinity
Mirip dengan node selector, nodeAffinity juga memberikan batasan pada node mana Pod dapat dijadwalkan. Perbedaannya adalah node affinity bisa memiliki aturan yang lebih kompleks (required dan preferred).
requiredDuringSchedulingIgnoredDuringExecution: Scheduler tidak dapat menjadwalkan Pod kecuali aturannya terpenuhi (Hard Requirements).preferredDuringSchedulingIgnoredDuringExecution: Scheduler mencoba mencari node yang memenuhi aturan. Jika node yang cocok tidak tersedia, scheduler tetap menjadwalkan Pod (Soft Requirements).
Kali ini mari tambahkan label ke node multinode-m03 sehingga kita bisa menggunakannya untuk aturan affinity.
β kubectl label nodes multinode-m03 node-type=product
node/multinode-m03 labeledTambahkan konfigurasi node affinity berikut di field template.spec. Jangan lupa untuk menghapus node selector yang sebelumnya ditambahkan.
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-type
operator: In
values:
- productApply ulang file yaml dan cek daftar pod lagi. Kamu akan melihat bahwa semua pod berjalan di node multinode-m03.
β kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-78b49dbd66-6nkgj 1/1 Running 0 13s 10.244.2.4 multinode-m03 <none> <none>
nginx-deployment-78b49dbd66-brdvt 1/1 Running 0 5s 10.244.2.6 multinode-m03 <none> <none>
nginx-deployment-78b49dbd66-j27td 1/1 Running 0 9s 10.244.2.5 multinode-m03 <none> <none>Ketika nodeSelector dan nodeAffinity dengan aturan required hadir bersamaan, scheduler Kubernetes akan selalu mencoba memenuhi kedua persyaratan. Jika tidak ada node yang memenuhi kedua persyaratan, pod akan stuck di status Pending. Jika kita cek events, akan ada Warning: FailedScheduling dengan pesan seperti di bawah.
32s Warning FailedScheduling Pod/nginx-deployment-785475985d-vdv8q 0/3 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }, 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling.References
- https://kubernetes.io/docs/concepts/architecture/
- https://minikube.sigs.k8s.io/docs/tutorials/multi_node/
- https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
- https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/
Last updated on