<p>The <a href="https://cloud.google.com/blog/products/containers-kubernetes/best-practices-for-building-kubernetes-operators-and-stateful-apps" rel="nofollow noreferrer">Best Practices</a> for building Kubernetes Operators say I should write a whole bunch of Operators to manage my application. How does inter-operator communication happen?</p>
<p>In other words, how should I build my Operator so that it can talk to other Operators?</p>

I'll Eat My Hat
<p>They don't. Not directly, anyways. Communication on Kubernetes occurs purely through YAML files.</p>
<p>For example, if your application requires access to a database, you <em>should</em> install an operator for Postgresql, create a PostgreSQLCluster CR Object, and pull credentials from it once it's setup.</p>
<p>However, this isn't a practical solution in the long term, because Operators <a href="https://docs.openshift.com/container-platform/4.6/operators/admin/olm-upgrading-operators.html#olm-approving-pending-upgrade_olm-upgrading-operators" rel="nofollow noreferrer">should be able to update automatically and without interaction</a>. You are also not allowed to install older versions. To name names, the Crunchy Postgres Operator actually goes through <a href="https://github.com/CrunchyData/postgres-operator/releases/tag/v4.6.0" rel="nofollow noreferrer">many breaking changes</a> with every update.
If you were relying on them maintaining their CRD format, you made your architecture a brittle one.</p>
<p>A few exceptions do exist. Operators for products like Tekton Pipelines and Argo Pipelines are very stable and unlikely to change by design, and it's perfectly OK to depend on these.</p>
<p>Speaking purely towards the best practices, <em><a href="https://web.archive.org/web/20201221021842/https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/" rel="nofollow noreferrer">you are supposed to be able to migrate from older to newer versions of your CRD API using webhooks</a></em>, though it isn't clear that any Operator implementations actually do this.
Still, as of writing this post, there are no Operators on <a href="http://operatorhub.io/" rel="nofollow noreferrer">OperatorHub.io</a> which rely on other Operators (Feb 16, 2021). Reader, you will be the first.</p>
<p>If you wanted to do so anyway, chances are the Operator you want to depend on is available on the <a href="https://pkg.go.dev/github.com/crunchydata/postgres-operator@v4.5.1+incompatible/pkg/apis/crunchydata.com/v1#Pgcluster" rel="nofollow noreferrer">Go package repository</a>. You can just <code>go get</code> them and use their CRD API types natively in your code, which should make it very easy to keep up to date with the API.</p>
<h3>Bonus Non-Answer</h3>
<p>Technically, the Operator you want to depend on could implement a REST API in their manager, and expose it as a service. I seriously doubt anybody will ever do this. It doesn't seem smart to poke holes into the Kubernetes design philosophy and open up attack vectors.</p>
