<p>No matter how hard I tune this, I am not able to make the Pods spread evenly across the four nodes in AWS EKS Cluster. Here's the Pod yaml.</p>
<pre><code>  nodeSelector:
    node_env: my-node-name
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
            - key: node_env
              operator: In
              values:
                - my-node-name
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - my-app-name
          topologyKey: topology.kubernetes.io/hostname
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - my-app-name
          topologyKey: node_env
  topologySpreadConstraints:
    - maxSkew: 1
      nodeAffinityPolicy: Honor
      topologyKey: kubernetes.io/hostname
      whenUnsatisfiable: DoNotSchedule
      labelSelector:
        matchExpressions:
        - key: app
          operator: In
          values:
          - my-app-name
</code></pre>
<p>There are seven nodes under the EKS Cluster - four for apps pods, two for envoy pods and one for miscellaneous pods.</p>
<p>I am looking to place four replicas of a pod and evenly distribute it in those apps pods node.</p>

Arun V
<p>While it's possible to utilize <code>topologySpreadConstraints</code> alongside <code>podAntiAffinity/podAffinity</code>, I wouldn't recommend doing so. I suggest you review the following answers for a comparison:</p>
<p><a href="https://stackoverflow.com/a/73159361/19206466">https://stackoverflow.com/a/73159361/19206466</a></p>
<p>If your objective is to achieve an even distribution across nodes, you can accomplish this by combining <code>nodeAffinity</code> with <code>topologySpreadConstraints</code>. Use <code>nodeAffinity</code> to select the appropriate nodes, ensuring that your EKS nodes have the <code>node_env: my-node-name</code> label attached. To list a node's labels, you can use <code>kubectl describe node &lt;eks_node&gt;</code>.</p>
<p>Then, employ <code>topologySpreadConstraints</code> to evenly distribute the pods across these nodes; setting <code>maxSkew: 1</code> should suffice for evenly distributing the pods across the selected nodes.
In addition, make sure that the <code>app: my-app-name</code> label exists in your app pods' template.</p>
<p><strong>Important Note:</strong>
In case you are utilizing an auto-scaler for your EKS cluster (e.g. Karpenter) you may also need to define the <code>minDomains</code> <code>topologySpreadConstraints</code> attribute supported since Kubernetes 1.25.
In your case, it would define the minimum amount of required EKS nodes.</p>
<p>For more information, refer to: <a href="https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/#spread-constraint-definition" rel="nofollow noreferrer">https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/#spread-constraint-definition</a></p>
<pre><code>affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
          - key: node_env
            operator: In
            values:
              - my-node-name
topologySpreadConstraints:
  - maxSkew: 1
    nodeAffinityPolicy: Honor
    topologyKey: kubernetes.io/hostname
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        app: my-app-name
</code></pre>
<p><strong>References</strong></p>
<ul>
<li>Karpenter: <a href="https://github.com/aws/karpenter/issues/2572" rel="nofollow noreferrer">https://github.com/aws/karpenter/issues/2572</a></li>
</ul>
