I have a web applicaton (e.g. "india"
) that depends on postgres and redis (e.g. a typical Rails application).
I have a docker-compose.yml
file that composes the containers to start this application.
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
# ....
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:
I can build india
, postgres-india
, and redis-india
as separate deployments (and therefore separate Services) in k8s
I can build india
, postgres-india
, and redis-india
as a single deployment (and therfore a single pod
/ service
)
#2 makes more sense to me personally - all 3 items here comprise the entire "application service" that should be exposed as a single service URL (i.e. the frontend for the web application).
However, if I use an automated tool like kompose
to translate my docker-compose.yml
file into k8s resources, it follows approach #1 and creates three individual k8s Services.
Is there a "right way" or standard I should follow?
Thanks!
Your three components should run as separate deployments on Kubernetes. You want these three components to be:
Your app should be designed to be stateless, and can be deployed as a Deployment. But the Redis and PostgreSQL are stateful components and should be deployed as StatefulSet.
In a production environment, you typically want to:
With a stateless app deployed as a Deployment, 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 Topology Spread Constraints.
With a stateful component as e.g. Redis or PostgreSQL, this is more difficult. You typically need to run it as a cluster. See e.g. Redis Cluster. But it is more difficult for PostgreSQL, you could consider a PostgreSQL-compatible db that has a distributed design, e.g. CockroachDB that is designed to be run on Kubernetes or perhaps consider CrunchyData PostgreSQL Operator.
When you deploy a Pod with multiple containers, one container is the "main" application and the other containers are supposed to be "helper" / "utility" containers to fix a problem for the "main container" - 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 Twelve-Factor App. You typically only use "multiple containers" 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.