How does Kubernetes create replicas of containerized apps with a common database? - kubernetes

This is more of a question to understand the architecture. If I have a containerized e-commerce web application, how would K8s make sure that different replicas of the application have the same information in sync?
For example, what if I use K8s to deploy the application and scale it and use a load balancer so I can optimally route traffic. Now, if I have two (or more) replicas of the application running, and the load balancer is actively dividing the traffic between the applications, how would I ensure data is in sync between the different replicas?
Like if I am routed to one replica and place an order there, and tomorrow I'm routed to another replica, how would I ensure that the second replica also shows I've placed an order and has all the data in sync with the other one?

Related

Deploying stateful application as master slave (replicas) in kubernetes

I want to deploy my application (stateful) in kubernetes as 3 replicas just for high availability. Therefore only one instance of my application should get all the request. Other replicas are just for HA (in case master is down).
I know things like Redis or MySQL can be deployed but they themselves provide the master-slave architecture. https://kubernetes.io/docs/tasks/run-application/run-replicated-stateful-application/
How can this be achieved in kubernetes for any other simple application?
You need to put the failover logic somewhere. Either on the server-side or client-side. Either client can talk to instance 1 by default and if it is not up, then failover to instance 2 and so on. Or you can have an agent/proxy on the server-side which does this routing for you. In this case, the proxy has the logic of checking if instance 1 is up or down, etc.
Usually, for stateful applications, failover is not just as simple as connecting to the other instance when the primary is down. It might involve reconciling the state, making sure the other replica has an up-to-date state or has a quorum, etc depending on the application. So there is no "one size fits all" type solution for all stateful applications. You need to build and chose the model appropriate for your application.

How to connect a web server to a Kubernetes statefulset and headless service

I have been learning Kubernetes for a few weeks and now I am trying to figure out the right way to connect a web server to a statefulset correctly.
Let's say I deployed a master-slave Postgres statefulset and now I will connect my web server to it. By using a cluster IP service, the requests will be load balanced across the master and the slaves for both reading (SELECT) and writing (UPDATE, INSERT, DELETE) records, right? But I can't do that because writing requests should be handled by the master. However, when I point my web server to the master using the headless service that will give us a DNS entry for each pod, I won't get any load balancing to the other slave replications and all of the requests will be handled by one instance and that is the master. So how am I supposed to connect them the right way? By obtaining both load balancing to all replications along with the slave in reading records and forwarding writing records requests to the master?
Should I use two endpoints in the web server and configure them in writing and reading records?
Or maybe I am using headless services and statefulsets the wrong way since I am new to Kubernetes?
Well, your thinking is correct - the master should be read-write and replicas should be read only. How to configure it properly? There are different possible approaches.
First approach is what you thinking about, to setup two headless services - one for accessing primary instances, the second one to access to the replica instances - good example is Kubegres:
In this example, Kubegres created 2 Kubernetes Headless services (of default type ClusterIP) using the name defined in YAML (e.g. "mypostgres"):
a Kubernetes service "mypostgres" allowing to access to the Primary PostgreSql instances
a Kubernetes service "mypostgres-replica" allowing to access to the Replica PostgreSql instances
Then you will have two endpoints:
Consequently, a client app running inside a Kubernetes cluster, would use the hostname "mypostgres" to connect to the Primary PostgreSql for read and write requests, and optionally it can also use the hostname "mypostgres-replica" to connect to any of the available Replica PostgreSql for read requests.
Check this starting guide for more details.
It's worth noting that there are many database solutions which are using this approach - another example is MySQL. Here is a good article in Kubernetes documentation about setting MySQL using Stateful set.
Another approach is to use some middleware component which will act as a gatekeeper to the cluster, for example Pg-Pool:
Pg pool is a middleware component that sits in front of the Postgres servers and acts as a gatekeeper to the cluster.
It mainly serves two purposes: Load balancing & Limiting the requests.
Load Balancing: Pg pool takes connection requests and queries. It analyzes the query to decide where the query should be sent.
Read-only queries can be handled by read-replicas. Write operations can only be handled by the primary server. In this way, it loads balances the cluster.
Limits the requests: Like any other system, Postgres has a limit on no. of concurrent connections it can handle gracefully.
Pg-pool limits the no. of connections it takes up and queues up the remaining. Thus, gracefully handling the overload.
Then you will have one endpoint for all operations - the Pg-Pool service. Check this article for more details, including the whole setup process.

K8s: how to deploy multiple Django services inside the same node

I'm new to DevOps work and am having a though time figuring out how the whole final architecture should look like. My project currently runs on a single Kubernetes Cluster and a single node with a single pod, in the very common Nginx reverse proxy + UWSGI Django app. I have to implement a scaling architecture. My understanding is that I should use an Ingress Controller behind a LoadBalancer (I'm hosted at OVH, they do provide a built-in LoadBalancer). The Ingress Controller will then distribute the traffic to my pods.
Question 1: if my Django app listens on port 8000, setting ReplicaSet to 2 does not work because the port is already taken. This makes me believe I'm only supposed to have one pod per node but some information says otherwise. How can I run multiple replicas on the same node?
Question2: let's say I deploy 9 more nodes. Should all my 10 nodes be behind 1 Ingress Controller (and 1 Load Balancer) or should each node have its own Ingress Controller ?
Question3: if I have only one Ingress Controller, the Load Balancer does not really "balance" any load, its sole purpose is to expose my service to the Internet, is that normal?
Question4: what happens when the Ingress Controller is overloaded? Do I duplicate everything and then the Load Balancer distributes the requests on the 2 Controllers?
This and this is a good starting point, but still does not answer my questions directly.
Every pod has its own networking setup so two replicas (i.e. two pods) can both listen on the same port. Unless you've enabled host networking mode which should not be used here.
Not directly, the ingress controller can be a lot of things. If you're using a self-hosted one (I see the ingress-nginx tag so assuming you are using that) then each controller replica is an independent copy of the proxy setup. You would want 2 at least for redundancy but unless you need to break up your traffic because those two can't keep up with it (would have to be truly huge request volume) that's probably all you need.
Yes, that's fine on the K8s side, though as mentioned if you have multiple nodes available you probably want at least two ingress controller replicas in case one node dies unexpectedly.
The edge LoadBalancer is round-robin-ing requests between all the nginx proxy instances so if you need more capacity you would spawn more replicas (assuming you have spare CPU on the cluster, if not then more nodes first then more replicas).

How to achieve high availability and load balancing in Kubernetes cluster

I am creating a two node Kubernetes cluster (1 master and 2 slave nodes) which will host Netflix eureka. Microservices would be created for applications which would register themselves on the Eureka server and would find other microservices to communicate from the service registry of Eureka.I want a scenario such that if any node fails, then how can we achieve high availability in this ? Also , there should be load balancing so that requests get simultaneously directed to other nodes in the cluster.
Can anybody let me know a solution for this ?
I want a scenario such that if any node fails, then how can we achieve high availability in this
Creating a Pod directly is not a recommended approach. Lets say that the node on which the Pod is running crashes, then the Pod is not rescheduled and the service is not accessible.
For HA (High Availability), higher level abstractions like Deployments should be used. A Deployment will create a ReplicaSet which will have multiple Pods associated with it. So, if a node on which the Pod is running crashes then the ReplicaSet will automatically reschedule the Pod on a healthy node and you will get HA.
Also , there should be load balancing so that requests get simultaneously directed to other nodes in the cluster.
Create a Service of type LoadBalancer for the Deployment and the incoming requests will be automatically redirected to the Pods on the different nodes. In this case a Load Balancer will be automatically created. And there is charge associated with the Load Balancer.
If you don't want to use a Load Balancer then another approach though which is a bit more complicated and powerful is to use Ingress. This will also load balance the requests across multiple nodes.
Here is a nice article explaining the difference between a Load Balancer and Ingress.
All the above queries are addressed directly or indirectly in the K8S documentation here.

How to deploy multi - tier application with Kubernetes

If I have a multi - tier application (say web / logic / database), where each tier having it's own container, and I need to deploy all of these en - bloc, do they all have to go into the same pod?
And if they are in the same pod, does this have any implications in terms of the maximum size of application that can be run?
Or is there some higher level abstraction that I can use to start all three layers, but have them running on different minions?
Why do you need to deploy all of the components together? In a micro services architecture, you would want to reduce the dependencies between each layer to a clean interface and then allow each layer to be deployed and scaled separately from the others.
If you need to deploy them together (e.g. they share local disk or localhost networking) then you need to deploy them as a single pod. A single pod is an atomic scheduling unit, so it will be deployed onto a single host machine. Since it lands on a single host, this limits the scalability of your application to the size of a single host (not allowing you to scale out as your traffic increases).
If your three layers are not tightly coupled, then you can run them in different pods, which allows them to be scheduled across multiple hosts (or on the same host if, for example, you are doing local development). To connect the pods together, you can define services.
You should take a look at the guestbook example which illustrates how to define pods and services for a simple multi-tier web application running on Kubernetes.