<p>Assuming deployment, replicaSet and pod are all 1:1:1 mapping.</p>
<pre><code>deployment ==&gt; replicaSet ==&gt; Pod
</code></pre>
<p>When we do deployment, replicaSet adds <code>pod-template-hash</code> label to pods. So, this looks enough for a replicaSet to check if enough pods are running. Then what is the significance of replicaSet <code>matchLabels</code> selector? Why is it mandatory?</p>
<p>To explain for better understanding</p>
<p>For ex: I deploy an app with these labels. 2 pods are running</p>
<pre><code>spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-app
</code></pre>
<p>Now change label value of pod-template-hash to something else for one of the pods (changing to <code>testing</code> here). Now we immediately see another pod started. So replicaSet does not seem to care about <code>selector.matchLabels</code></p>
<pre><code>NAME                            READY   STATUS    RESTARTS   AGE   LABELS
pod/nginx-app-b8b875889-cpnnr   1/1     Running   0          53s   app=nginx-app,pod-template-hash=testing
pod/nginx-app-b8b875889-jlk6m   1/1     Running   0          53s   app=nginx-app,pod-template-hash=b8b875889
pod/nginx-app-b8b875889-xblqr   1/1     Running   0          11s   app=nginx-app,pod-template-hash=b8b875889

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE    LABELS
service/kubernetes   ClusterIP   10.96.0.1    &lt;none&gt;        443/TCP   151d   component=apiserver,provider=kubernetes

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
deployment.apps/nginx-app   2/2     2            2           53s   app=nginx-app

NAME                                  DESIRED   CURRENT   READY   AGE   LABELS
replicaset.apps/nginx-app-b8b875889   2         2         2       53s   app=nginx-app,pod-template-hash=b8b875889
</code></pre>

<p>Let me summarize it. The whole discussion is about: Why deployment forces me to set matchLabels selector even though it could easly live without it, since its adding pod-template-hash and it would be totally fine with using only that.</p>
<p>After reading all the comments and all the discussion I decided to look in kubernetes documentation.</p>
<p>I will allow myself to quote k8s documentation about replicasets: <a href="https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/#how-a-replicaset-works" rel="noreferrer">How a ReplicaSet works</a></p>
<blockquote>
<h3>How a ReplicaSet works:</h3>
<p>[...]</p>
<p><strong>A ReplicaSet is linked to its Pods via the Pods'</strong>
<strong>metadata.ownerReferences field</strong>, which specifies what resource the
current object is owned by. All Pods acquired by a ReplicaSet have
their owning ReplicaSet's identifying information within their
ownerReferences field. It's through this link that the ReplicaSet
knows of the state of the Pods it is maintaining and plans
accordingly.</p>
</blockquote>
<p>So does is mean that it's not using labels at all? Well, not exactly. Let's keep reading:</p>
<blockquote>
<p>A ReplicaSet identifies new Pods to acquire by using its selector. If
there is a Pod that has no OwnerReference or the OwnerReference is not
a Controller and it matches a ReplicaSet's selector, it will be
immediately acquired by said ReplicaSet</p>
</blockquote>
<p>Ouh, so it looks like it is using the selector only as an alternative to the first method.</p>
<p>Let's keep reading. Here is a quote from <a href="https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/#pod-selector" rel="noreferrer">Pod Selector</a> section:</p>
<blockquote>
<h3>Pod Selector</h3>
<p>The .spec.selector field is a label selector. As
discussed earlier <strong>these are the labels used to identify potential Pods</strong>
<strong>to acquire</strong></p>
</blockquote>
<p>It looks like these labels are not used as a primary method to keep track of pod owned by the ReplicaSet, they are use to <em>&quot;identify potential Pods to acquire&quot;</em>. But what does it mean?</p>
<p>Why would ReplicaSet acquire pods it does not own? There is a section in documentation that tries to answer this very question: <a href="https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/#non-template-pod-acquisitions" rel="noreferrer">Non-Template Pod acquisition</a></p>
<blockquote>
<h3>Non-Template Pod acquisitions</h3>
<p>While you can create bare Pods with no problems, it is strongly
recommended to make sure that the bare Pods do not have labels which
match the selector of one of your ReplicaSets. The reason for this is
because a ReplicaSet is not limited to owning Pods specified by its
template-- it can acquire other Pods in the manner specified in the
previous sections.</p>
<p>[...]</p>
<p>As those Pods do not have a Controller (or any object) as their owner
reference and match the selector of the [...] ReplicaSet, they will
immediately be acquired by it.</p>
</blockquote>
<p>Great, but this still does not answer the question: Why do I need to provide the selector? Couldn't it just use that hash?</p>
<p>Back in the past when there was a bug in k8s:
<a href="https://github.com/kubernetes/kubernetes/issues/23170" rel="noreferrer">https://github.com/kubernetes/kubernetes/issues/23170</a>
so someone suggested the validation is needed: <a href="https://github.com/kubernetes/kubernetes/issues/23218" rel="noreferrer">https://github.com/kubernetes/kubernetes/issues/23218</a>
And so validation appeared:
<a href="https://github.com/kubernetes/kubernetes/pull/23530" rel="noreferrer">https://github.com/kubernetes/kubernetes/pull/23530</a></p>
<p>And it stayed with us to this day, even if today we probably could live without it.</p>
<p>Although I think its better that it's there because it minimizes the chances of overlaping labels in case of pod-template-hash collision for different RSs.</p>
