Node Affinity and Taints on EKS#
Everything in my taints, affinity and quotas notes works on EKS verbatim. kubectl taint, tolerations, nodeAffinity, topologySpreadConstraints - the API doesn’t know or care that AWS is underneath. What is different is how nodes appear, how they get their labels and taints, and what happens to all of it when the autoscaler is involved.
Kısa hatırlatma: taint node’un kapıdaki tabelası (“her pod giremez”), toleration pod’un geçiş izni, nodeAffinity ise “şu node’a git” talebi. İkisini karıştırmayın - toleration sizi oraya göndermez, sadece engeli kaldırır.
How nodes get labels and taints on EKS#
On kubeadm you kubectl taint nodes ... after joining. On EKS, worker nodes are cattle owned by a managed node group, and the right place to declare labels and taints is when the group is created - in the eksctl config:
managedNodeGroups:
- name: patientping-workers
instanceType: t3.small
desiredCapacity: 2
privateNetworking: true
- name: gpu-workers
instanceType: g4dn.xlarge
desiredCapacity: 1
privateNetworking: true
labels:
workload: ai
taints:
- key: workload
value: ai
effect: NoScheduleWhy not just kubectl taint after the fact? You can - it works - but the next node group scale-up or instance refresh creates brand new nodes from the group’s template. A taint applied by hand to an old node vanishes with that node; a taint in the group config comes back on every replacement.
Not: node group’taki
labels/taintsnode’lara join anında basılır. Ellekubectl labelile eklenenler node ölünce gider. “Cattle, not pets” - EKS bunu node’larda da zorunlu kılıyor.
EKS’s automatic labels#
You don’t label zone or instance type yourself; the node admission controller (via the AWS cloud provider and the AMI) stamps them on join:
eks.amazonaws.com/nodegroup- node group adıtopology.kubernetes.io/zone,topology.kubernetes.io/regionnode.kubernetes.io/instance-type- AMI ailesine göre
eks.amazonaws.com/compute-type(ec2veyafargate)
That means the nodeAffinity rules from your kubeadm notes work unchanged:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values: ["us-east-1a"]Fargate is a different animal#
With Fargate there are no nodes at all, so taints and node affinity have nothing to bite on. Instead, a Fargate profile selects pods by namespace + labels and decides “these run serverless”. Same idea (isolate workloads), different mechanism.
The autoscaler interaction#
If a pod can’t schedule because of a taint, the Cluster Autoscaler may respond by scaling up another node group - or doing nothing, if no group can satisfy the pod. Taints and affinity are therefore not just scheduling rules; they’re capacity rules. A misconfigured toleration can silently double your node count (and your bill).
Assignment#
Prove that a taint from the node group config keeps a normal pod off the tainted nodes - and that a toleration lets a special pod in.
Cost check: An extra t3.small node group of 1 node adds a few dollars per month. Delete the gpu-workers-style group when you’re done (eksctl delete nodegroup).
- Add the
gpu-workers-style node group from the config above topatientping-eks.yamland apply it:
eksctl create nodegroup --cluster patientping-eks -f patientping-eks.yaml- Deploy a plain pod with no toleration, and one with a toleration:
apiVersion: v1
kind: Pod
metadata:
name: normal-pod
spec:
containers: [{ name: web, image: nginx }]
---
apiVersion: v1
kind: Pod
metadata:
name: ai-pod
spec:
tolerations:
- key: workload
operator: Equal
value: ai
effect: NoSchedule
nodeSelector:
workload: ai
containers: [{ name: train, image: nginx }]kubectl apply -f taint-test.yaml- Check where they landed:
kubectl get pods -o wide
kubectl describe pod normal-pod | grep -A3 EventsExpected: ai-pod runs on the tainted node (it has both the toleration and the nodeAffinity via nodeSelector), normal-pod sits Pending with 0/3 nodes are available: 1 node(s) had untolerated taint... in its events.
Hatırlatma:
Pending+ “untolerated taint” mesajı taint’in çalıştığını gösterir - hata değil, doğrulamadır. Pod’u temizlemek içinkubectl delete pod normal-pod.