<p>We run a Kubernetes-compatible (OKD 3.11) on-prem / private cloud cluster with backend apps communicating with low-latency Redis databases used as caches and K/V stores. The new architecture design is about to divide worker nodes equally between two geographically distributed data centers (&quot;regions&quot;). We can assume static pairing between node names and regions, an now we have added labeling of nodes with region names as well.</p>
<p>What would be the recommended approach to protect low-latency communication with the in-memory databases, making client apps stick to the same region as the database they are allowed to use? Spinning up additional replicas of the databases is feasible, but does not prevent round-robin routing between the two regions...</p>
<p>Related: <a href="https://stackoverflow.com/questions/55743299/kubernetes-node-different-region-in-single-cluster">Kubernetes node different region in single cluster</a></p>

<p>So effective region-pinning solution is more complex than just using <code>nodeAffinity</code> in  the &quot;preferred&quot; version. This alone will cause you a lot of unpredictable surprises due to the opinionated character of Kubernetes that has zone spreading hard-coded, as seen in this <a href="https://github.com/kubernetes/kubernetes/issues/99630#issuecomment-790705286" rel="nofollow noreferrer">Github issue</a>, where they clearly try to put at least some eggs in another basket and see zone selection as an antipattern.</p>
<p>In practice the usefulness of <code>nodeAffinity</code> alone is restricted to a scenario with a very limited number of pod replicas, because when the pods number exceeds the number of nodes in a region (i.e. typically for the 3rd replica in a 2-nodes / 2-regions setup), scheduler will start &quot;correcting&quot; or &quot;fighting&quot; with user preference weights (even as unbalanced of 100:1) very much in favor of spreading, placing at least one &quot;representative&quot; pod on every node in every region (including the non-preferred ones with minimum possible weights of 1).</p>
<p>But this default zone spreading issue can be overcome if you create a single-replica container that will act as a &quot;master&quot; or &quot;anchor&quot; (a natural example being a database). For this single-pod &quot;master&quot; <code>nodeAffinity</code> will still work correctly - of course in the HA variant, i.e. &quot;preferred&quot; not &quot;required&quot; version. As for the remaining multi-pod apps, you use something else - <code>podAffinity</code> (this time in the &quot;required&quot; version), which will make the &quot;slave&quot; pods follow their &quot;master&quot; between zones, because setting any pod-based spreading disables the default zone spreading. You can have as many replicas of the &quot;slave&quot; pods as you want and never run into a single misplaced pod (at least at schedule time), because of the &quot;required&quot; affinity used for &quot;slaves&quot;. Note that the known limitation of <code>nodeAffinity</code> applies here as well: the number of &quot;master&quot; pod replicas must not exceed the number of nodes in a region, or else &quot;zone spreading&quot; will kick in.</p>
<p>And here's an example of how to label the &quot;master&quot; pod correctly for the benefit of <code>podAffinity</code> and using a deployment config YAML file: <a href="https://stackoverflow.com/a/70041308/9962007">https://stackoverflow.com/a/70041308/9962007</a></p>
