<p>I have a web applicaton (e.g. <code>&quot;india&quot;</code>) that depends on postgres and redis (e.g. a typical Rails application).</p>
<p>I have a <code>docker-compose.yml</code> file that composes the containers to start this application.</p>
<pre><code>version: '3'
services:

  redis-india:
    image: redis:5.0.6-alpine
    # .....

  postgres-india:
    image: postgres:11.5-alpine
    # ....

  india:
    depends_on:
      - postgres-india
      - redis-india
    image: india/india:local
    # ....

</code></pre>
<p>I'd like to run this application deployment with Kubernetes. I'm trying to figure out how to build the k8s resource objects correctly, and I'm weighing two options:</p>
<ol>
<li><p>I can build <code>india</code>, <code>postgres-india</code>, and <code>redis-india</code> as separate deployments (and therefore separate Services) in k8s</p>
</li>
<li><p>I can build <code>india</code>, <code>postgres-india</code>, and <code>redis-india</code> as a single deployment (and therfore a single <code>pod</code> / <code>service</code>)</p>
</li>
</ol>
<p>#2 makes more sense to me personally - all 3 items here comprise the entire &quot;application service&quot; that should be exposed as a single service URL (i.e. the frontend for the web application).</p>
<p>However, if I use an <a href="https://kubernetes.io/docs/tasks/configure-pod-container/translate-compose-kubernetes/" rel="nofollow noreferrer">automated tool like <code>kompose</code></a> to translate my <code>docker-compose.yml</code> file into k8s resources, it follows approach #1 and creates three individual k8s Services.</p>
<p>Is there a &quot;right way&quot; or standard I should follow?</p>
<p>Thanks!</p>

<h1>Independent components</h1>
<p>Your three components should run as separate deployments on Kubernetes. You want these three components to be:</p>
<ul>
<li>Independently upgradable and deployable (e.g. you deploy a new version of Redis but not your app or database)</li>
<li>Independently scalable - e.g. you might get many users and want to scale up to multiple instances (e.g. 5 replicas) of your app.</li>
</ul>
<h3>State</h3>
<p>Your app should be designed to be <a href="https://12factor.net/processes" rel="nofollow noreferrer">stateless</a>, and can be deployed as a <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="nofollow noreferrer">Deployment</a>. But the Redis and PostgreSQL are <em>stateful</em> components and should be deployed as <a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/" rel="nofollow noreferrer">StatefulSet</a>.</p>
<h3>Availability</h3>
<p>In a production environment, you typically want to:</p>
<ul>
<li>Avoid downtime when upgrading any application or database</li>
<li>Avoid downtime if you or the cloud provider upgrade the node</li>
<li>Avoid downtime if the node crash, e.g. due to hardware failure or kernel crash.</li>
</ul>
<p>With a <em>stateless</em> app deployed as a <a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="nofollow noreferrer">Deployment</a>, this is trivial to solve - run at least two instances (replicas) of it - and make sure they are deployed on different nodes in the cluster. You can do this using <a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/" rel="nofollow noreferrer">Topology Spread Constraints</a>.</p>
<p>With a <em>stateful</em> component as e.g. Redis or PostgreSQL, this is more difficult. You typically need to run it as a cluster. See e.g. <a href="https://redis.io/topics/cluster-tutorial" rel="nofollow noreferrer">Redis Cluster</a>. But it is more difficult for PostgreSQL, you could consider a PostgreSQL-compatible db that has a distributed design, e.g. <a href="https://www.cockroachlabs.com/product/sql/" rel="nofollow noreferrer">CockroachDB</a> that is designed to be <a href="https://www.cockroachlabs.com/docs/stable/deploy-cockroachdb-with-kubernetes.html" rel="nofollow noreferrer">run on Kubernetes</a> or perhaps consider <a href="https://access.crunchydata.com/documentation/postgres-operator/v5/" rel="nofollow noreferrer">CrunchyData PostgreSQL Operator</a>.</p>
<h1>Pod with multiple containers</h1>
<p>When you deploy a Pod with <a href="https://kubernetes.io/docs/concepts/workloads/pods/#how-pods-manage-multiple-containers" rel="nofollow noreferrer">multiple containers</a>, one container is the &quot;main&quot; application and the other containers are supposed to be &quot;helper&quot; / &quot;utility&quot; containers to fix a problem for the &quot;main container&quot; - e.g. if your app logs to two different files - you could have helper containers to tail those files and output it to stdout, as is the recommended log output in <a href="https://12factor.net/logs" rel="nofollow noreferrer">Twelve-Factor App</a>. You typically only use &quot;multiple containers&quot; for apps that are not designed to be run on Kubernetes, or if you want to extend with some functionality like e.g. a Service Mesh.</p>
