Di episode ini kita akan coba bahas Kubernetes Taints dan Tolerations untuk node affinity control. Kita akan mempelajari bagaimana taint repel Pod, bagaimana toleration allow Pod scheduled di tainted node, dan best practice untuk workload placement.

Catatan
Untuk kalian yang ingin membaca episode sebelumnya, bisa click thumbnail episode 33 di bawah ini
Di episode sebelumnya kita sudah belajar tentang RBAC dan RoleBinding untuk authorization. Selanjutnya di episode 34 kali ini, kita akan coba bahas Taints dan Tolerations, yang control Pod mana yang bisa scheduled di node mana.
Catatan: Disini saya akan menggunakan Kubernetes Cluster yang di install melalui K3s.
Sementara node affinity attract Pod ke node, taint dan toleration work opposite way - taint repel Pod dari node kecuali mereka punya matching toleration. Ini enable powerful workload placement strategy seperti dedicated node, GPU node, atau node dengan special hardware.
Taints adalah property applied ke node yang repel Pod kecuali mereka punya matching toleration.
Tolerations adalah property applied ke Pod yang allow mereka scheduled di node dengan matching taint.
Bayangkan taint seperti "no entry" sign di node - by default, Pod tidak bisa enter. Toleration seperti special pass yang allow specific Pod untuk enter despite "no entry" sign.
Karakteristik kunci:
Pod tanpa matching toleration tidak bisa scheduled di node.
kubectl taint nodes node-1 gpu=true:NoScheduleBehavior:
Kubernetes prefer tidak schedule Pod tanpa matching toleration, tapi akan jika necessary.
kubectl taint nodes node-1 gpu=true:PreferNoScheduleBehavior:
Pod tanpa matching toleration di evict dari node.
kubectl taint nodes node-1 gpu=true:NoExecuteBehavior:
kubectl taint nodes node-1 gpu=true:NoSchedulekubectl taint nodes node-1 gpu=true:NoSchedule
kubectl taint nodes node-1 storage=ssd:NoScheduleAtau dalam satu command:
kubectl taint nodes node-1 gpu=true:NoSchedule storage=ssd:NoSchedulekubectl describe node node-1 | grep TaintsOutput:
Taints: gpu=true:NoSchedule,storage=ssd:NoSchedule# Remove specific taint
kubectl taint nodes node-1 gpu=true:NoSchedule-
# Remove semua taint
kubectl taint nodes node-1 gpu- storage-apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoSchedule
containers:
- name: app
image: nvidia/cuda:11.0Equal - Value harus match exactly:
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoScheduleExists - Key harus exist, value ignored:
tolerations:
- key: gpu
operator: Exists
effect: NoScheduleapiVersion: v1
kind: Pod
metadata:
name: special-pod
spec:
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoSchedule
- key: storage
operator: Equal
value: ssd
effect: NoSchedule
containers:
- name: app
image: myapp:latestUntuk NoExecute effect, specify berapa lama Pod bisa stay:
apiVersion: v1
kind: Pod
metadata:
name: temporary-pod
spec:
tolerations:
- key: maintenance
operator: Equal
value: "true"
effect: NoExecute
tolerationSeconds: 3600 # 1 jam
containers:
- name: app
image: myapp:latestDedicate node untuk GPU workload:
# Taint GPU node
kubectl taint nodes gpu-node gpu=true:NoSchedulePod requesting GPU:
apiVersion: v1
kind: Pod
metadata:
name: gpu-workload
spec:
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoSchedule
containers:
- name: gpu-app
image: nvidia/cuda:11.0
resources:
limits:
nvidia.com/gpu: 1Reserve node dengan fast storage:
# Taint SSD node
kubectl taint nodes ssd-node storage=ssd:NoSchedulePod requiring SSD:
apiVersion: apps/v1
kind: Deployment
metadata:
name: database
spec:
replicas: 1
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
spec:
tolerations:
- key: storage
operator: Equal
value: ssd
effect: NoSchedule
containers:
- name: postgres
image: postgres:15Temporarily evict Pod untuk maintenance:
# Taint node untuk maintenance
kubectl taint nodes node-1 maintenance=true:NoExecutePod tolerating maintenance:
apiVersion: v1
kind: Pod
metadata:
name: maintenance-pod
spec:
tolerations:
- key: maintenance
operator: Equal
value: "true"
effect: NoExecute
tolerationSeconds: 300 # 5 menit
containers:
- name: app
image: myapp:latestReserve node untuk specific team:
# Taint node untuk team-a
kubectl taint nodes node-1 team=a:NoSchedule
kubectl taint nodes node-2 team=a:NoScheduleTeam A workload:
apiVersion: apps/v1
kind: Deployment
metadata:
name: team-a-app
spec:
replicas: 3
selector:
matchLabels:
app: team-a-app
template:
metadata:
labels:
app: team-a-app
spec:
tolerations:
- key: team
operator: Equal
value: a
effect: NoSchedule
containers:
- name: app
image: team-a-app:latestTolerate any taint dengan specific key:
apiVersion: v1
kind: Pod
metadata:
name: flexible-pod
spec:
tolerations:
- key: workload-type
operator: Exists # Accept any value
effect: NoSchedule
containers:
- name: app
image: myapp:latestapiVersion: apps/v1
kind: Deployment
metadata:
name: special-workload
spec:
replicas: 3
selector:
matchLabels:
app: special
template:
metadata:
labels:
app: special
spec:
tolerations:
- key: workload-type
operator: Equal
value: special
effect: NoSchedule
containers:
- name: app
image: special-app:latest
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"Gunakan taint/toleration dengan node affinity untuk powerful placement:
apiVersion: v1
kind: Pod
metadata:
name: placed-pod
spec:
# Tolerate taint
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoSchedule
# Prefer GPU node
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: gpu
operator: In
values:
- "true"
containers:
- name: app
image: gpu-app:latestKubernetes automatically taint node dalam certain condition:
Node tidak ready:
Taints: node.kubernetes.io/not-ready:NoExecuteNode unreachable:
Taints: node.kubernetes.io/unreachable:NoExecuteNode punya memory pressure:
Taints: node.kubernetes.io/memory-pressure:NoScheduleNode punya disk pressure:
Taints: node.kubernetes.io/disk-pressure:NoScheduleNode punya PID pressure:
Taints: node.kubernetes.io/pid-pressure:NoScheduleNode network unavailable:
Taints: node.kubernetes.io/network-unavailable:NoSchedulekubectl describe node node-1 | grep Taintskubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taintskubectl get pod gpu-pod -o yaml | grep -A 10 tolerationsProblem: Pod tidak bisa scheduled di tainted node.
# Node tainted
kubectl taint nodes node-1 gpu=true:NoSchedule
# Pod tanpa toleration - tidak scheduled
kubectl run gpu-pod --image=nvidia/cuda:11.0Solusi: Add toleration ke Pod:
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoScheduleProblem: Toleration tidak match taint.
# Bad: Wrong operator
tolerations:
- key: gpu
operator: In # Wrong! Should be Equal
values: ["true"]
effect: NoScheduleSolusi: Gunakan correct operator:
# Good: Correct operator
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoScheduleProblem: Toleration effect tidak match taint effect.
# Taint dengan NoExecute
kubectl taint nodes node-1 gpu=true:NoExecute# Bad: Wrong effect
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoSchedule # Wrong! Should be NoExecuteSolusi: Match effect:
# Good: Matching effect
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoExecuteProblem: Tainting semua node tanpa toleration.
# Bad: Taint semua node
for node in $(kubectl get nodes -o name); do
kubectl taint $node special=true:NoSchedule
doneSolusi: Taint hanya specific node:
# Good: Taint hanya GPU node
kubectl taint nodes gpu-node gpu=true:NoScheduleProblem: Temporary taint left di node.
Solusi: Remove taint ketika done:
kubectl taint nodes node-1 gpu=true:NoSchedule-# Good: Clear purpose
kubectl taint nodes gpu-node gpu=true:NoSchedule
kubectl taint nodes ssd-node storage=ssd:NoSchedule
# Avoid: Vague name
kubectl taint nodes node-1 special=true:NoSchedule# Add label untuk document
kubectl label nodes gpu-node node-type=gpu
kubectl label nodes ssd-node node-type=ssdUntuk non-critical workload:
kubectl taint nodes node-1 workload=batch:PreferNoScheduleUntuk precise placement:
spec:
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoSchedule
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: gpu
operator: In
values:
- "true"Prevent indefinite Pod eviction:
tolerations:
- key: maintenance
operator: Equal
value: "true"
effect: NoExecute
tolerationSeconds: 3600 # 1 jamReview taint regularly:
# List semua taint
kubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
# Check untuk orphaned taintkubectl describe pod gpu-pod
# Event show: node(s) had taint yang pod tidak tolerateSolusi: Add matching toleration:
# Check node taint
kubectl describe node node-1 | grep Taints
# Add toleration ke Podkubectl describe pod pod-name
# Status: Evicted
# Reason: Tainted nodeSolusi: Add NoExecute toleration dengan timeout:
tolerations:
- key: maintenance
operator: Equal
value: "true"
effect: NoExecute
tolerationSeconds: 3600# Verify taint applied
kubectl describe node node-1 | grep Taints
# Check jika Pod punya toleration
kubectl get pod -o yaml | grep -A 5 tolerationskubectl get nodes -o json | jq '.items[].spec.taints'kubectl get pods -o json | jq '.items[].spec.tolerations'kubectl describe node node-1
# Show Taint sectionkubectl taint nodes node-1 gpu=true:NoSchedule-kubectl taint nodes node-1 gpu- storage- workload-Pada episode 34 ini, kita telah membahas Taints dan Tolerations di Kubernetes secara mendalam. Kita sudah belajar cara gunakan taint untuk repel Pod dari node dan toleration untuk allow specific Pod di tainted node.
Key takeaway:
Taints dan Tolerations adalah powerful tool untuk workload placement di Kubernetes. Dengan memahami cara gunakan mereka effectively, kalian bisa optimize resource utilization, dedicate node untuk specific workload, dan manage maintenance window gracefully.
Catatan
Untuk kalian yang ingin melanjutkan ke episode selanjutnya, bisa click thumbnail episode 35 di bawah ini