<p>I have a k8s deployment which consists of a cron job (runs hourly), service (runs the http service) and a storage class (pvc to store data, using gp2).</p>
<p>The issue I am seeing is that gp2 is only readwriteonce.</p>
<p>I notice when the cron job creates a job and it lands on the same node as the service it can mount it fine.</p>
<p>Is there something I can do in the service, deployment or cron job yaml to ensure the cron job and service always land on the same node? It can be any node but as long as cron job goes to the same node as service.</p>
<p>This isn't an issue in my lower environment as we have very little nodes but in our production environments where we have more nodes  it is an issue.</p>
<p>In short I want  to get my cron job, which creates a job then pod to run the pod on the same node as my services pod is on.</p>
<p>I know thing isn't best practice but our webservice reads data from the pvc and serves it. The cron job pulls new data in from other sources and leaves it for the webserver.</p>
<p>Happy for other ideas / ways.</p>
<p>Thanks</p>

<p>Focusing only on the part:</p>
<blockquote>
<p>How can I schedule a workload (<code>Pod</code>, <code>Job</code>, <code>Cronjob</code>) on a specific set of <code>Nodes</code></p>
</blockquote>
<p>You can spawn your <code>Cronjob</code>/<code>Job</code> either with:</p>
<ul>
<li><code>nodeSelector</code></li>
<li><code>nodeAffinity</code></li>
</ul>
<hr />
<h3><code>nodeSelector</code></h3>
<blockquote>
<p><code>nodeSelector</code> is the simplest recommended form of node selection constraint. <code>nodeSelector</code> is a field of PodSpec. It specifies a map of key-value pairs. For the pod to be eligible to run on a node, the node must have each of the indicated key-value pairs as labels (it can have additional labels as well). The most common usage is one key-value pair.</p>
<p>-- <em><a href="https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector" rel="nofollow noreferrer">Kubernetes.io: Docs: Concepts: Scheduling eviction: Assign pod node: Node selector</a></em></p>
</blockquote>
<p>Example of it could be following (assuming that your node have a specific label that is referenced in <code>.spec.jobTemplate.spec.template.spec.nodeSelector</code>):</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: &quot;*/1 * * * *&quot;
  jobTemplate:
    spec:
      template:
        spec:
          nodeSelector: # &lt;-- IMPORTANT
            schedule: &quot;here&quot; # &lt;-- IMPORTANT
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
</code></pre>
<p>Running above manifest will schedule your <code>Pod</code> (<code>Cronjob</code>) on a node that has a <code>schedule=here</code> label:</p>
<ul>
<li><code>$ kubectl get pods -o wide </code></li>
</ul>
<pre class="lang-sh prettyprint-override"><code>NAME                     READY   STATUS      RESTARTS   AGE     IP          NODE                                   NOMINATED NODE   READINESS GATES
hello-1616323740-mqdmq   0/1     Completed   0          2m33s   10.4.2.67   node-ffb5                              &lt;none&gt;           &lt;none&gt;
hello-1616323800-wv98r   0/1     Completed   0          93s     10.4.2.68   node-ffb5                              &lt;none&gt;           &lt;none&gt;
hello-1616323860-66vfj   0/1     Completed   0          32s     10.4.2.69   node-ffb5                              &lt;none&gt;           &lt;none&gt;
</code></pre>
<hr />
<h3><code>nodeAffinity</code></h3>
<blockquote>
<p>Node affinity is conceptually similar to <code>nodeSelector</code> -- it allows you to constrain which nodes your pod is eligible to be scheduled on, based on labels on the node.</p>
<p>There are currently two types of node affinity, called <code>requiredDuringSchedulingIgnoredDuringExecution</code> and <code>preferredDuringSchedulingIgnoredDuringExecution</code>. You can think of them as &quot;hard&quot; and &quot;soft&quot; respectively, in the sense that the former specifies rules that must be met for a pod to be scheduled onto a node (just like nodeSelector but using a more expressive syntax), while the latter specifies preferences that the scheduler will try to enforce but will not guarantee.</p>
<p>-- <em><a href="https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity" rel="nofollow noreferrer">Kubernetes.io: Docs: Concepts: Scheduling eviction: Assign pod node: Node affinity</a></em></p>
</blockquote>
<p>Example of it could be following (assuming that your node have a specific label that is referenced in <code>.spec.jobTemplate.spec.template.spec.nodeSelector</code>):</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: &quot;*/1 * * * *&quot;
  jobTemplate:
    spec:
      template:
        spec:
          # --- nodeAffinity part
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: schedule
                    operator: In
                    values:
                    - here
          # --- nodeAffinity part
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
</code></pre>
<ul>
<li><code>$ kubectl get pods</code></li>
</ul>
<pre class="lang-sh prettyprint-override"><code>NAME                     READY   STATUS      RESTARTS   AGE     IP           NODE                                   NOMINATED NODE   READINESS GATES
hello-1616325840-5zkbk   0/1     Completed   0          2m14s   10.4.2.102   node-ffb5                              &lt;none&gt;           &lt;none&gt;
hello-1616325900-lwndf   0/1     Completed   0          74s     10.4.2.103   node-ffb5                              &lt;none&gt;           &lt;none&gt;
hello-1616325960-j9kz9   0/1     Completed   0          14s     10.4.2.104   node-ffb5                              &lt;none&gt;           &lt;none&gt;
</code></pre>
<hr />
<p>Additional resources:</p>
<ul>
<li><em><a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/" rel="nofollow noreferrer">Kubernetes.io: Docs: Concepts: Overview: Working with objects: Labels</a></em></li>
</ul>
<p>I'd reckon you could also take a look on this StackOverflow answer:</p>
<ul>
<li><em><a href="https://stackoverflow.com/questions/51212904/kubernetes-pvc-with-readwritemany-on-aws">Stackoverflow.com: Questions: Kubernetes PVC with readwritemany on AWS</a></em></li>
</ul>
