Affinity and Anti-affinity have the same functionality as nodeSeclector.
Affinity and Anti-afffinity allow for more complex scheduling than nodeSelector and work with pods as well.
You can create rules that are not hard requirements but a preferred rule. Meaning that, the scheduler will still be able to schedule a pod even if the rules aren't met. In nodeSelector if there is no matching label then the node will not schedule.
Kubernetes can do node affinity and Pod affinity/anti-affinity
Node affinity is similar to nodeSelector
Pod affinity/anti-affinity allows you to create rules and how pods should be scheduled
Affinity and anti-affinity is only relevant during scheduling. Once a pod is running, it'll need to be recreated and apply the changes again.
There are currently two types that you can use for node affinity
1) requiredDuringSchedulingIgnoredDuringExecution
2) preferredDuringSchedulingIgnoreDuringExecution
The first one sets a hard requirement(like nodeSelector). The rule must be met before the pod can be scheduled.
The second type will try to enforce the rule but no guarantee it. Even if the rule is not met, the pod can still be scheduled. It's soft requirement, a preference.
When scheduling, Kubernetes will score every node by summarizing the weightings per node
For example: If you have two different rules with weights 1 and 5. If both the rules match, the node will have a score of 6. If only the rule with weight 1 match then, the score will be only 1
The pod will be scheduled on in which the score is highest.
In addition to the labels you can add yourself, there are pre-populated labels:
2) failure-domain.beta.kubernetes.io/zone
3) failure-domain.beta.kubernetes.io/region