<p>I need to automate the provisioning of a complex application in Kubernetes. It's a complex, multi-step process that involves provisioning of some cluster-wide resources and some app-specific resources. The cluster-wide resources are:</p>
<ul>
<li>Istio</li>
<li>A few Operators (Cert Manager, Prometheus Operator, Postgres Operator, among others)</li>
</ul>
<p>Then I want to create an application (let's call it <code>Foo</code>) which leverages Istio and the aforementioned operators. It will create statefulsets, services, Certificates, a Postgres database, Istio gateways, Prometheus PodMonitors, etc.</p>
<p>There will be multiple <code>Foo</code>'s created, each configured differently (since the Kubernetes cluster will be used to provide <code>Foo</code> applications as a multi-tenant service).</p>
<p>What's the idiomatic way to do this? I think I should write a <code>Foo</code> controller which assumes that Istio and the other operators (prometheus, cert-manager, postgres, etc) already exist.</p>
<p>Is it possible to write a meta <code>ClusterOfFoos</code> operator that installs Istio, installs the required operators, and then installs the <code>Foo</code> controller?</p>
<p>If so, how does one go about provisioning operators (normally installed through Helm) from within a controller?</p>
<p>So far I have looked into using helm to do this, but there are too many dependencies and Helm just tends to create all resources at once, which makes some things fail (eg. when a deployment refers to a Secret that hasn't yet been created by cert-manager).</p>

<p>The <a href="https://olm.operatorframework.io/docs/getting-started/" rel="nofollow noreferrer">Operator Lifecycle Manager</a> is really well suited for the task.</p>
<p>When you create operator <code>Foo</code>, you can package it in the OLM way by creating a bundle which contains the <a href="https://olm.operatorframework.io/docs/tasks/creating-operator-manifests/#writing-your-operator-manifests" rel="nofollow noreferrer">ClusterServiceVersion</a> needed to inform OLM of dependencies that need to be resolved before install and during upgrades. These can just be a list of APIs you need - and OLM will find and install the set of latest versions of the operators that own each API.</p>
<p>All your dependencies are operators available in the <a href="https://operatorhub.io/" rel="nofollow noreferrer">Operatorhub.io Catalog</a> so they are available for install and dependency resolution as soon as you install OLM.</p>
<p>You can also configure certain dependencies by including these objects in the bundle itself. According to <a href="https://olm.operatorframework.io/docs/tasks/creating-operator-manifests/#packaging-additional-objects-alongside-an-operator" rel="nofollow noreferrer">the docs</a>, the following objects are supported as of the time of this post:</p>
<pre><code>Secret
ClusterRole
ClusterRoleBinding
ConfigMap
ServiceAccount
Service
Role
RoleBinding
PrometheusRule
ServiceMonitor
PodDisruptionBudget
PriorityClasse
VerticalPodAutoscaler
ConsoleYAMLSample
ConsoleQuickStart
ConsoleCLIDownload
ConsoleLink
</code></pre>
<p>The <a href="https://sdk.operatorframework.io/docs/olm-integration/" rel="nofollow noreferrer">Operator SDK</a> can help you with bootstrapping the bundle.</p>
