<p>As a k8s cluster administrator, I want to specify on which nodes (using labels) pods will be scheduled, but without modifying any PodSpec section.</p>

<p>So, nodeSelector, affinity and taints can't be options.
Is there any other solution ?</p>

<p>PS: the reason I can't modify the PodSpec is that deployed applications are available as Helm charts and I don't have hand on those files. Moreover, if I change the PodSpec, it will be lost on next release upgrade.</p>

<p>You can use the <a href="https://kubernetes.io/docs/admin/admission-controllers/#podnodeselector" rel="nofollow noreferrer">PodNodeSelector</a> admission controller for this:</p>
<blockquote>
<p>This admission controller has the following behavior:</p>
<ol>
<li>If the Namespace has an annotation with a key <code>scheduler.kubernetes.io/nodeSelector</code>, use its value as the node selector.</li>
<li>If the namespace lacks such an annotation, use the <code>clusterDefaultNodeSelector</code> defined in the PodNodeSelector plugin configuration file as the node selector.</li>
<li>Evaluate the pod’s node selector against the namespace node selector for conflicts. Conflicts result in rejection.</li>
<li>Evaluate the pod’s node selector against the namespace-specific whitelist defined the plugin configuration file. Conflicts result in rejection.</li>
</ol>
</blockquote>
<p>First of all you will need to <a href="https://kubernetes.io/docs/admin/admission-controllers/#how-do-i-turn-on-an-admission-controller" rel="nofollow noreferrer">enable this admission controller</a>. The way to enable it depends on your environment, but it's done via the parameter <code>kube-apiserver --enable-admission-plugins=PodNodeSelector</code>.</p>
<p>Then create a namespace and annotate it with whatever node label you want all Pods in that namespace to have:</p>
<pre><code>kubectl create ns node-selector-test
kubectl annotate ns node-selector-test \
    scheduler.alpha.kubernetes.io/node-selector=mynodelabel=mynodelabelvalue
</code></pre>
<p>To test it you could do something like this:</p>
<pre><code>kubectl run busybox \
    -n node-selector-test -it --restart=Never --attach=false --image=busybox

kubectl get pod busybox -n node-selector-test -o yaml
</code></pre>
<p>It should output something like this:</p>
<pre><code>apiVersion: v1
kind: Pod 
metadata:
  name: busybox
  ....
spec:
  ...
  nodeSelector:
    mynodelabel: mynodelabelvalue
</code></pre>
<p>Now, unless that label exists on some nodes, this Pod will never be scheduled, so put this label on a node to see it scheduled:</p>
<pre><code>kubectl label node myfavoritenode mynodelabel=mynodelabelvalue
</code></pre>
