<p>I have an <code>EKS cluster</code> with two <code>nodegroups</code> each in different <code>AZ</code>. One <code>deployment</code> <code>Deployment1</code> is running on 2 <code>namespaces</code> for redundancy, one copy per <code>namespace</code> and each of them run in separate <code>AZs</code>/<code>nodegroup</code>. Also there is another <code>deployment</code> <code>Deployment2</code> that does not have any <code>node affinity</code> set and K8s manages where pods get scheduled.
Both <code>deployments</code> are huge with lots of pods. I have a subnet of 250 IPs available to me for each node group.</p>
<p>The problem is that while <code>Deployment1</code> is fine on it's own, and gets split almost equally per <code>AZ/Nodegroup</code>, the <code>Deployment2</code> tends to schedule most pods in one of the <code>nodegroups</code> and that ends when there are no more IPs available. This is a problem for <code>Deployment1</code> since one <code>namespace</code> of it is tied to that <code>nodegroup</code> and no new pods can be scheduled there if load changes.</p>
<p>Can I somehow balance <code>Deployment2</code> so it has 'soft affinity' that would split it 50/50 per each nodegroup, but if needed, can schedule pods in the other nodegroup?</p>

<p>If you're using Kubernetes 1.19 or later you can use <code>topologySpreadConstraints</code>, adding this to the pod template:</p>
<pre><code>topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: ScheduleAnyway
    labelSelector:
      matchLabels:
        foo: bar
</code></pre>
<p>where <code>maxSkew</code> define how uneven pods can be scheduled, <code>topologyKey</code> is the key of node labels and the <code>labelSelector</code> matches a label of your deployment. See <a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/" rel="nofollow noreferrer">docs</a></p>
<p>If your on an older Kubernetes version, you can look at pod anti affinity.</p>
