<p>I would like to dynamically provision 3 persistent volumes for my system, which are all based on a <code>storageClass</code> that I previously created. My v1 code does its job successfully. </p>

<p>v1:</p>

<pre><code>apiVersion: v1
kind: PersistentVolume
metadata:
  name: volume0
  labels:
    type: storage-one
spec:
  storageClassName: storage-one
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 2Gi
  hostPath:
    path: /somepath
    type: "DirectoryOrCreate"

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: volume1
  labels:
    type: storage-one
spec:
  storageClassName: storage-one
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 2Gi
  hostPath:
    path: /somepath
    type: "DirectoryOrCreate"

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: volume2
  labels:
    type: storage-one
spec:
  storageClassName: storage-one
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 2Gi
  hostPath:
    path: /somepath
    type: "DirectoryOrCreate"

</code></pre>

<p>I would like to refactor this code, possibly with a template that k8s can recognize, as the only variable here is the <code>metadata.name</code>. Is it possible?</p>

<p>Natively kubernetes does not recognize any templates. But you can use any templating engine before you pass this yaml to kubectl. </p>

<p>Common practice is to use helm which uses gotpl inside. <a href="https://helm.sh/docs/chart_template_guide/" rel="nofollow noreferrer">https://helm.sh/docs/chart_template_guide/</a></p>

<p>Your example will look like:</p>

<pre><code>{{ range .Values.volume_names }}
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: {{ . }}
  labels:
    type: storage-one
spec:
  storageClassName: storage-one
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 2Gi
  hostPath:
    path: /somepath
    type: "DirectoryOrCreate"
{{ end }}
</code></pre>

<p>And values.yaml:</p>

<pre><code>volume_names: 
- volume_this
- volume_that
</code></pre>

<p>Generally you can do <code>render_with_your_fav_engine_to_stdout | kubectl apply -f</code> using any engine.</p>

<p>UPD: Generate based on given len (this one was weird):</p>

<pre><code>{{ range $k, $v := until (atoi .Values.numVolumes) }}
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: volume-{{ $v }}
  labels:
    type: storage-one
spec:
  storageClassName: storage-one
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 2Gi
  hostPath:
    path: /somepath
    type: "DirectoryOrCreate"
{{ end }}
</code></pre>

<p>And values.yaml:</p>

<pre><code>numVolumes: "3"
</code></pre>
