<p>Given a following scheme of services and their dependencies I would like to engineer a set of Helm charts.</p>

<ul>
<li><code>API Gateway</code> calls <code>Service A</code> and <code>Service C</code></li>
<li><code>Service A</code> calls <code>Service B</code></li>
<li><code>Service B</code> calls <code>Database</code></li>
<li><code>Service C</code> calls <code>Service B</code> and <code>Service D</code></li>
</ul>

<p>At the moment I see two alternatives:</p>

<ol>
<li><p>Each of the 6 components in a diagram below is a single chart and each arrow in a diagram is a single dependency. <br /> <img src="https://i.stack.imgur.com/LeCHw.png" width="400" /></p></li>
<li><p>There's an <code>Umbrella</code> chart that has a dependency on all other charts. The <code>Database</code> chart is a dependency of <code>Service B</code> chart.<br /> <img src="https://i.stack.imgur.com/cgxHn.png" width="320" /></p></li>
</ol>

<p><a href="https://helm.sh/docs/howto/charts_tips_and_tricks/#complex-charts-with-many-dependencies" rel="noreferrer">Helm documentation</a> suggest going with option 2. I am however more keen towards option 1 due to an ease of local development and CI/CD pipeline.</p>

<p>Example scenario: developer is refactoring <code>Service C</code> and he wants to run the code he changed and test it.</p>

<ul>
<li>Option 1. Developer installs a <code>Service C</code> chart only.</li>
<li>Option 2: Developer would have to either:

<ul>
<li>install an <code>Umbrella</code> chart which leads to waste of a CPU and memory resources because of running unneeded services like <code>Service A</code> or <code>API Gateway</code>, which doesn't scale well with the complexity of the system;</li>
<li>install <code>Service C</code>, then <code>Service B</code> and then <code>Service D</code>, which also doesn't scale well with the complexity of the system because it requires to perform many manual actions and also require from developer to be faimiliar with the architecture of the system in order to know what charts needs to be installed.</li>
</ul></li>
</ul>

<p>I would like to make an educated decision on which alternative to take. I am more keen towards option 1, but Helm docs and also few examples I was able to find on the Internet (<a href="https://github.com/microservices-demo/microservices-demo/tree/master/deploy/kubernetes/helm-chart" rel="noreferrer">link</a>) are also going with option 2, so I think I might be missing something.</p>

<p>I would recommend one chart per service, with the additional simplification of making the "service B" chart depend on its database.  I would make these charts independent: none of the services depend on any other.</p>

<p>The place where Helm dependencies work well is where you have a service that embeds/hides specific single other parts.  The database behind B is an implementation detail, for example, and nothing outside B needs to know about it.  So B can depend on <code>stable/postgres</code> or some such, and this works well in Helm.</p>

<p>There's one specific mechanical problem that causes problems for the umbrella-chart approach.  Say service D also depended on a database, and it was the same "kind" of database (both use PostgreSQL, say).  Operationally you want these two databases to be separate.  Helm will see the two paths <code>umbrella &gt; B &gt; database</code> and <code>umbrella &gt; D &gt; database</code>, and only install one copy of the database chart, so you'll wind up with the two services sharing a database.  You probably don't want that.</p>

<p>The other mechanical issue you'll encounter using Helm dependencies here is that most resources are named some variant of <code>{{ .Release.Name }}-{{ .Chart.Name }}</code>.  In your option 1, say you do just install service C; you'd wind up with Deployments like <code>service-C-C</code>, <code>service-C-B</code>, <code>service-C-database</code>.  If you then wanted to deploy service A alongside it, that would introduce its own <code>service-A-B</code> and <code>service-A-database</code>, which again isn't what you want.</p>

<p>I'm not aware of a great high-level open-source solution to this problem.  A Make-based solution is hacky, but can work:</p>

<pre class="lang-make prettyprint-override"><code># -*- gnu-make -*-
all: api-proxy.deployed

%.deployed:
        helm upgrade --install --name $* -f values.yaml ./charts/$*
        touch $@

api-proxy.deployed: a.deployed c.deployed
a.deployed: b.deployed
c.deployed: b.deployed d.deployed
</code></pre>
