<p>I want to describe my services in kubernetes template files. Is it possible to parameterise values like number or <code>replicas</code>, so that I can set this at deploy time.</p>

<p>The goal here is to be able to run my services locally in minikube (where I'll only need one replica) and have them be as close to those running in staging/live as possible.</p>

<p>I'd like to be able to change the number of replicas, use locally mounted volumes and make other minor changes, without having to write a seperate template files that would inevitably diverge from each other.</p>

<h1>Helm</h1>
<p>Helm is becoming the standard for templatizing kubernetes deployments. A helm chart is a directory consisting of yaml files with golang variable placeholders</p>
<pre><code>---
kind: Deployment
metadata:
  name: foo
spec:
  replicas: {{ .Values.replicaCount }}
</code></pre>
<p>You define the default value of a 'value' in the 'values.yaml' file</p>
<pre><code>replicaCount: 1
</code></pre>
<p>You can optionally overwrite the value using the <code>--set</code> command line</p>
<pre><code>helm install foo --set replicaCount=42
</code></pre>
<p>Helm can also point to an external answer file</p>
<pre><code>helm install foo -f ./dev.yaml
helm install foo -f ./prod.yaml
</code></pre>
<p>dev.yaml</p>
<pre><code>---
replicaCount: 1
</code></pre>
<p>prod.yaml</p>
<pre><code>---
replicaCount: 42
</code></pre>
<p>Another advantage of <code>Helm</code> over simpler solutions like <code>envbsubst</code> is that <code>Helm</code> supports plugins. One powerful plugin is the <code>helm-secrets</code> plugin that lets you encrypt sensitive data using pgp keys. <a href="https://github.com/futuresimple/helm-secrets" rel="noreferrer">https://github.com/futuresimple/helm-secrets</a></p>
<p>If using <code>helm</code> + <code>helm-secrets</code> your setup may look like the following where your code is in one repo and your data is in another.</p>
<p>git repo with helm charts</p>
<pre><code>stable
  |__mysql
     |__Values.yaml
     |__Charts
  |__apache
     |__Values.yaml
     |__Charts
incubator
  |__mysql
     |__Values.yaml
     |__Charts
  |__apache
     |__Values.yaml
     |__Charts

</code></pre>
<p>Then in another git repo that contains the environment specific data</p>
<pre><code>values
|__ mysql
    |__dev
       |__values.yaml
       |__secrets.yaml
    |__prod
       |__values.yaml
       |__secrets.yaml

</code></pre>
<p>You then have a wrapper script that references the values and the secrets files</p>
<pre><code>helm secrets upgrade foo --install -f ./values/foo/$environment/values.yaml -f ./values/foo/$environment/secrets.yaml
</code></pre>
<hr />
<h1>envsubst</h1>
<p>As mentioned in other answers, <code>envsubst</code> is a very powerful yet simple way to make your own templates. An example from <a href="https://github.com/kubernetes/kubernetes/issues/52787#issuecomment-355694085" rel="noreferrer">kiminehart</a></p>
<pre><code>apiVersion: extensions/v1beta1
kind: Deployment
# ...
    architecture: ${GOOS}
</code></pre>
<pre><code>GOOS=amd64 envsubst &lt; mytemplate.tmpl &gt; mydeployment.yaml
</code></pre>
<pre><code>apiVersion: extensions/v1beta1
kind: Deployment
# ...
    architecture: amd64
</code></pre>
<hr />
<h1>Kubectl</h1>
<p>There is a <a href="https://github.com/kubernetes/kubernetes/issues/52787" rel="noreferrer">feature request</a> to allow <code>kubectl</code> to do some of the same features of helm and allow for variable substitution. There is a <a href="https://docs.google.com/document/d/1cLPGweVEYrVqQvBLJg6sxV-TrE5Rm2MNOBA_cxZP2WU" rel="noreferrer">background document</a> that strongly suggest that the feature will never be added, and instead is up to external tools like <code>Helm</code> and <code>envsubst</code> to manage templating.</p>
<hr />
<p>(edit)</p>
<h1>Kustomize</h1>
<p><a href="https://kubernetes.io/blog/2018/05/29/introducing-kustomize-template-free-configuration-customization-for-kubernetes/" rel="noreferrer">Kustomize</a> is a new project developed by google that is very similar to helm. Basically you have 2 folders <code>base</code> and <code>overlays</code>. You then run <code>kustomize build someapp/overlays/production</code> and it will generate the yaml for that environment.</p>
<pre><code>   someapp/
   ├── base/
   │   ├── kustomization.yaml
   │   ├── deployment.yaml
   │   ├── configMap.yaml
   │   └── service.yaml
   └── overlays/
      ├── production/
      │   └── kustomization.yaml
      │   ├── replica_count.yaml
      └── staging/
          ├── kustomization.yaml
          └── cpu_count.yaml
</code></pre>
<p>It is simpler and has less overhead than helm, but does not have plugins for managing secrets. You could combine <code>kustomize</code> with <a href="https://github.com/mozilla/sops" rel="noreferrer">sops</a> or  <code>envsubst</code> to manage secrets.</p>
<p><a href="https://kubernetes.io/blog/2018/05/29/introducing-kustomize-template-free-configuration-customization-for-kubernetes/" rel="noreferrer">https://kubernetes.io/blog/2018/05/29/introducing-kustomize-template-free-configuration-customization-for-kubernetes/</a></p>
