<h2>Hi!</h2>
<p>My problem is relevant with the deployment of node.js apps via k8s, architecture patterns, and connected them with DBs.</p>
<pre><code> alpha | beta | gamma1 | gamma2
</code></pre>
<p>I have the following node.js app services, some of them are scalable with app instances (like gamma), others are separate ones, all of them are built in a single docker image with <code>.Dockefile</code> and running from it.</p>
<p>And I also have a-non-cloud DBs, like elastic &amp; mongo running from their containers with <code>.env</code>: <code>mongo | elastic</code></p>
<p>As for now, my <code>docker-compose.yml</code> is like a typical node.js example app, but with common volume and bridge-network (except I have more then one node.js app):</p>
<pre class="lang-yaml prettyprint-override"><code>version: '3'
services:
  node:
    restart: always
    build: .
    ports:
      - 80:3000
    volumes:
      - ./:/code
  mongo:
    image: mongo
    ports:
      - 27017:27017
    volumes:
      - mongodb:/data/db
volumes:
 mongodb:

networks:
  test-network:
    driver: bridge
</code></pre>
<h2>Current deployment:</h2>
<p>All these things are running on a single heavy VPS (X CPU cores, Y RAM, Z SSD, everything loaded by 70%) from single <code>docker-compose.yml</code> file.</p>
<h2>What I want to ask and achieve:</h2>
<p>Since one VPS is already not enough, I'd like to start using <code>k8s</code> with rancher. So the question is about correct deployment:</p>
<p>For example, I have <code>N</code> VPSs connected within one private network, each VPS is a worker connected in one cluster, (with Rancher, of course, one of them is a master node) which gives me X cores, Y RAM, and other shared resources.</p>
<ol>
<li><p>Do I need another, separate cluster (or a VPS machine in a private network, but not part of a cluster) with DB running on it? Or I could deploy DB in the same cluster? And what if each VPS (worker) in the cluster has only 40GB volume, and DB will grow more than this volume? Do shared resources from workers include the shared volume space?</p>
</li>
<li><p>Is it right to have one image from which I can start all my apps, or in the case of k8s, I should I have a separate docker image for each service? So if I have 5 node.js apps within one mono-repo, I should have 5 separate docker-image, not one common?</p>
</li>
</ol>
<blockquote>
<p><em>I'll understand that my question can have a complex answer, so I will be glad to see, not just answer but links or anything that is connected with a problem. It's much more easy to find or google for something, if you know and how to ask.</em></p>
</blockquote>

AlexZeDim
<p><strong>A purist answer:</strong></p>
<p>Each of your five services should have their own image, and their own database.  It's okay for the databases to be in the same cluster so long as you have a way to back them up, run migrations, and do other database-y things.  If your cloud provider offers managed versions of these databases then storing the data outside the cluster is fine too, and can help get around some of the disk-space issues you cite.</p>
<p>I tend to use <a href="https://helm.sh" rel="nofollow noreferrer">Helm</a> for actual deployment mechanics as a way to inject things like host names and other settings at deploy time.  Each service would have its own Dockerfile, its own Helm chart, its own <code>package.json</code>, and so on.  Your CI system would build and deploy each service separately.</p>
<p><strong>A practical answer:</strong></p>
<p>There's nothing technically wrong with running multiple containers off the same image doing different work.  If you have a single repository and a single build system now, and you don't mind a change in one service causing all of them to redeploy, this approach will work fine.</p>
<p>Whatever build system your repository has now, if you go with this approach, I'd put a single Dockerfile in the repository root and probably have a single Helm chart to deploy it.  In the Helm chart Deployment spec you can override the command to run with something like</p>
<pre class="lang-yaml prettyprint-override"><code># This fragment appears under containers: in a Deployment's Pod spec
# (this is Helm chart, Go text/template templated, YAML syntax)
image: {{ .Values.repository }}/{{ .Values.image }}:{{ .Values.tag }}
command: node service3/index.js
</code></pre>
<p>Kubernetes's terminology here is slightly off from Docker's, particularly if you use an entrypoint wrapper script.  Kubernetes <code>command:</code> overrides a Dockerfile <code>ENTRYPOINT</code>, and Kubernetes <code>args:</code> overrides <code>CMD</code>.</p>
<p><strong>In either case:</strong></p>
<p>Many things in Kubernetes allocate infrastructure dynamically.  For example, you can set up a <em>horizontal pod autoscaler</em> to set the replica count of a Deployment based on load, or a <em>cluster autoscaler</em> to set up more (cloud) instances to run Pods if needed.  If you have a <em>persistent volume provisioner</em> then a Kubernetes PersistentVolumeClaim object can be backed by dynamically allocated storage (on AWS, for example, it creates an EBS volume), and you won't be limited to the storage space of a single node.  You can often find prebuilt Helm charts for the databases; if not, use a StatefulSet to have Kubernetes create the PVCs for you.</p>
<p>Make sure your CI system produces images with a unique tag, maybe based on a timestamp or source control commit ID.  Don't use <code>...:latest</code> or another fixed string: Kubernetes won't redeploy on update unless the text of the <code>image:</code> string changes.</p>
<p>Multiple clusters is tricky in a lot of ways.  In my day job we have separate clusters per environment (development, pre-production, production) but the application itself runs in a single cluster and there is no communication between clusters.  If you can manage the storage then running the databases in the same cluster is fine.</p>
<p>Several Compose options don't translate well to Kubernetes.  I'd especially recommend removing the <code>volumes:</code> that bind-mount your code into the container and validating your image runs correctly, before you do anything Kubernetes-specific.  If you're replacing the entire source tree in the image then you're not really actually running the image, and it'll be much easier to debug locally.  In Kubernetes you also have almost no control over <code>networks:</code> but they're not really needed in Compose either.</p>
