<p><strong>I am new to helm and kubernetes.</strong></p>
<p>My current requirement is to use setup multiple services using a common helm chart.</p>
<p>Here is the scenario.</p>
<ol>
<li><p>I have a common docker image for all of the services</p>
</li>
<li><p>for each of the services there are different commands to run. <strong>In total there are more than 40 services.</strong></p>
<p>Example</p>
</li>
</ol>
<blockquote>
<pre><code>pipenv run python serviceA.py 
pipenv run python serviceB.py 
pipenv run python serviceC.py  
and so on...
</code></pre>
</blockquote>
<p>Current state of helm chart I have is</p>
<pre><code>demo-helm
|- Chart.yaml
|- templates
   |- deployment.yaml
   |- _helpers.tpl
|- values
   |- values-serviceA.yaml
   |- values-serviceB.yaml
   |- values-serviceC.yaml
    and so on ...
</code></pre>
<p>Now, since I want to use the same helm chart and deploy multiple services. How should I do it?</p>
<p>I used following command <code>helm install demo-helm . -f values/values-serviceA.yaml -f values-serviceB.yaml</code> but it only does a deployment for values file provided at the end.</p>
<p>Here is my <code>deployment.yaml</code> file</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include &quot;helm.fullname&quot; . }}
  labels:
    {{- include &quot;helm.labels&quot; . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include &quot;helm.selectorLabels&quot; . | nindent 6 }}
  template:
    metadata:
    {{- with .Values.podAnnotations }}
      annotations:
        {{- toYaml . | nindent 8 }}
    {{- end }}
      labels:
        {{- include &quot;helm.selectorLabels&quot; . | nindent 8 }}
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      containers:
        - name: {{ .Chart.Name }}
          image: &quot;{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}&quot;
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          command: {{- toYaml .Values.command |nindent 12}} 
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          volumeMounts:
            - name: secrets
              mountPath: &quot;/usr/src/app/config.ini&quot;
              subPath: config.ini
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      volumes:
        - name: secrets
          secret:
            secretName: sample-application
            defaultMode: 0400
</code></pre>
<p><strong>Update.</strong></p>
<p>Since my requirement has been updated to add all the values for services in a single file I am able to do it by following.</p>
<p><code>deployment.yaml</code></p>
<pre><code>{{- range $service, $val := .Values.services }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ $service }}
  labels:
    app: {{ .nameOverride }}
spec:
  replicas: {{ .replicaCount }}
  selector:
    matchLabels:
      app: {{ .nameOverride }}
  template:
    metadata:
      labels:
        app: {{ .nameOverride }}
    spec:
      imagePullSecrets:
        - name: aws-ecr
      containers:
        - name: {{ $service }}
          image: &quot;image-latest-v3&quot;
          imagePullPolicy: IfNotPresent
          command: {{- toYaml .command |nindent 12}}
          resources:
            {{- toYaml .resources | nindent 12 }}
          volumeMounts:
            - name: secrets
              mountPath: &quot;/usr/src/app/config.ini&quot;
              subPath: config.ini
      volumes:
        - name: secrets
          secret:
            secretName: {{ .secrets }}
            defaultMode: 0400
{{- end }}
</code></pre>
<p>and <code>values.yaml</code></p>
<pre><code>services:
  #Services for region1
  serviceA-region1:
    nameOverride: &quot;serviceA-region1&quot;
    fullnameOverride: &quot;serviceA-region1&quot;
    command: [&quot;bash&quot;, &quot;-c&quot;, &quot;python serviceAregion1.py&quot;]
    secrets: vader-search-region2
    resources: {}
    replicaCount: 5

  #Services for region2
  serviceA-region2:
    nameOverride: &quot;serviceA-region2&quot;
    fullnameOverride: &quot;serviceA-region2&quot;
    command: [&quot;bash&quot;, &quot;-c&quot;, &quot;python serviceAregion2.py&quot;]
    secrets: vader-search-region2
    resources: {}
    replicaCount: 5
</code></pre>
<p>Now I want to know will the following configuration work with the changes I am posting below for both <code>values.yaml</code></p>
<pre><code>services:
  region:
  #Services for region1
    serviceA-region1:
      nameOverride: &quot;serviceA-region1&quot;
      fullnameOverride: &quot;serviceA-region1&quot;
      command: [&quot;bash&quot;, &quot;-c&quot;, &quot;python serviceAregion1.py&quot;]
      secrets: vader-search-region2
      resources: {}
      replicaCount: 5
   
  region:2
  #Services for region2
    serviceA-region2:
      nameOverride: &quot;serviceA-region2&quot;
      fullnameOverride: &quot;serviceA-region2&quot;
      command: [&quot;bash&quot;, &quot;-c&quot;, &quot;python serviceAregion2.py&quot;]
      secrets: vader-search-region2
      resources: {}
      replicaCount: 5
</code></pre>
<p>and <code>deployment.yaml</code></p>
<pre><code>{{- range $region, $val := .Values.services.region }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ $region }}-{{ .nameOverride }}
  labels:
    app: {{ .nameOverride }}
spec:
  replicas: {{ .replicaCount }}
  selector:
    matchLabels:
      app: {{ .nameOverride }}
  template:
    metadata:
      labels:
        app: {{ .nameOverride }}
    spec:
      imagePullSecrets:
        - name: aws-ecr
      containers:
        - name: {{ $region }}-{{ .nameOverride }}
          image: &quot;image-latest-v3&quot;
          imagePullPolicy: IfNotPresent
          command: {{- toYaml .command |nindent 12}}
          resources:
            {{- toYaml .resources | nindent 12 }}
          volumeMounts:
            - name: secrets
              mountPath: &quot;/usr/src/app/config.ini&quot;
              subPath: config.ini
      volumes:
        - name: secrets
          secret:
            secretName: {{ .secrets }}
            defaultMode: 0400
{{- end }}
</code></pre>

<p>I can recommend you try a helmfile-based approach. I prefer a 3-file approach.
What you'll need :</p>
<ul>
<li>helmfile-init.yaml: contains YAML instructions that you might need to use for creating and configuring namespaces etc.</li>
<li>helmfile-backend.yaml: contains all the releases you need to deploy (service1, service2 ...)</li>
<li>helmfile.yaml: paths to the above-mentioned (helmfile-init, helmfile-backend YAML files)</li>
<li>a deployment spec file (app_name.json): a specification file that contains all the information regarding the release (release-name, namespace, helm chart version, application-version, etc.)</li>
</ul>
<p>Helmfile has made my life a little bit breezy when deploying multiple applications. I will edit this answer with a couple of examples in a few minutes.</p>
<p>Meanwhile, you can refer to the official docs <a href="https://helmfile.readthedocs.io/en/latest/" rel="nofollow noreferrer">here</a> or the <a href="https://lyz-code.github.io/blue-book/devops/helmfile/" rel="nofollow noreferrer">Blue Books</a> if you have Github access on your machine.</p>
