<p>I have the following setup in a kubernetes cluster:</p>
<pre><code>Node Name          Node Label
worker-zone-a-1    topology.kubernetes.io/zone=a
worker-zone-a-2    topology.kubernetes.io/zone=a
worker-zone-a-3    topology.kubernetes.io/zone=a
worker-zone-a-4    topology.kubernetes.io/zone=a
worker-zone-b-1    topology.kubernetes.io/zone=b
worker-zone-b-2    topology.kubernetes.io/zone=b
worker-zone-b-3    topology.kubernetes.io/zone=b
</code></pre>
<p>And I have the following deployment:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: topology.kubernetes.io/zone
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: nginx
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
</code></pre>
<p>The purpose of using <code>topologySpreadConstraints</code> is to distribute the Deployment in a way that zone-a will run 3 Pods and zone-b will run 2 Pods.</p>
<p>When applying the Deployment several times, sometimes the pods are distributed 3 for zone-a and 2 for zone-b and sometimes the pods are distributed 2 for zone-a and 3 for zone-b.</p>
<p>Is there a way to set the Pods distribution of the Deployment so it will always run 3 Pods in zone-a and 2 pods in zone-b?</p>
<p>Thanks :-)</p>

Boris
<p>There is a solution.</p>
<p>First I want to thank @yair-elmaliah for providing the solution in a different channel.
<a href="https://stackoverflow.com/users/16521581/yair-elmaliah">https://stackoverflow.com/users/16521581/yair-elmaliah</a></p>
<p>So, my adjusted setup is as follows.</p>
<p>The nodes in the Kubernetes cluster have the following labels:</p>
<pre><code>Node Name        Node Labels 
worker-zone-a-1  topology.kubernetes.io/zone=a,topology.kubernetes.io/zone-a=true,node-role.kubernetes.io/data=data
worker-zone-a-2  topology.kubernetes.io/zone=a,topology.kubernetes.io/zone-a=true,node-role.kubernetes.io/data=data
worker-zone-a-3  topology.kubernetes.io/zone=a,topology.kubernetes.io/zone-a=true,node-role.kubernetes.io/data=data
worker-zone-a-4  topology.kubernetes.io/zone=a,topology.kubernetes.io/zone-a=true,node-role.kubernetes.io/data=data
worker-zone-b-1  topology.kubernetes.io/zone=b,topology.kubernetes.io/zone-b=true,node-role.kubernetes.io/data=data
worker-zone-b-2  topology.kubernetes.io/zone=b,topology.kubernetes.io/zone-b=true,node-role.kubernetes.io/data=data
worker-zone-b-3  topology.kubernetes.io/zone=b,topology.kubernetes.io/zone-b=true,node-role.kubernetes.io/data=data
</code></pre>
<p>And this is the adjusted deployment:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeSelector:
        node-role.kubernetes.io/data: data
      topologySpreadConstraints:
      - topologyKey: topology.kubernetes.io/zone
        maxSkew: 1
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: nginx
      - topologyKey: topology.kubernetes.io/zone-a
        maxSkew: 1
        whenUnsatisfiable: ScheduleAnyway
        labelSelector:
          matchLabels:
            app: nginx
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
</code></pre>
<p>The first constraint (<code>topologyKey: topology.kubernetes.io/zone</code>) will distribute the 5 pods between zone <code>a</code> and zone <code>b</code> using a 3/2 or 2/3 ratio. This is good, but we cannot control where the 3 pods will be allocated.</p>
<p>The second constraint (<code>topologyKey: topology.kubernetes.io/zone-a</code>) will try to schedule one of the pods on a node that has the <code>zone-a</code> label.</p>
<p>Since all constraints are evaluated and combined together, this setup will tell the scheduler to deploy 4 pods based on zone name and the fifth pod based on zone-type.</p>
