Openshift deploy backend and frontend separately - deployment

I have an app on openshift. Currently backend and frontend are mixed up in a single WAR archive.
Though I want to separate frontend and backend into 2 projects and deploy them seperately on the same node.
I haven't found anything in the openshift docs or on google.
Is there any way to accomplish that, or do I need to deploy backend and frontend separately onto 2 nodes?

You can use what is called a "node selector" to ensure a given object, in your case a deployment, is placed onto a specific node.
This behavior is outlined in the documentation.
As per your request, this would allow you to split up your deployment, but have it land on the same node. However, it is not a pattern I would recommend. Relying on a specific node to exist, is not very failure tolerant. As such your frontend and backend should rather communicate via a service for example. This way, it doesn't matter where on your cluster frontend or backend are.

Related

Kubernetes beginner: trigger simple actions between apps

Very simple question, I have a front-end app running in kubernetes. I would like to create a back-end containerized app that would also be in kubernetes obviously.
User actions in the frontend would need to trigger the execution of a command on the backend (echo success! for example). The UI also needs to know what was the command's output.
What is the best way to implement this in k8s?
Either through an internal service, or the two apps can also be in the same pods.
Perhaps there is some kind of messaging involved with applications such as rabbitMQ?
That depends on your application how you are planning.
Some people host frontend on bucket and from there send HTTP request to backend or so.
You can keep frontend and backend in different PODs or in a single POD also.
For example, if you are using the Node JS with express, you can run as simple API service POD also and keep frontend with it also to serve.
You can use the K8s service name for internal communication instead of adding the Message broker(RabbitMQ, Redis also can be used) unless your web app really needs it.
I would also recommend checking out the : https://learnk8s.io/deploying-nodejs-kubernetes
Github repo of application : https://github.com/learnk8s/knote-js/tree/master/01
Official example : https://kubernetes.io/docs/tutorials/stateless-application/guestbook/

Dynamic deployment of stateful applications in GKE

I'm trying to figure out which tools from GKE stack I should apply to my use case which is a dynamic deployment of stateful application with dynamic HTTP endpoints.
Stateful in my case means that I don't want any replicas and load-balancing (because the app doesn't scale horizontally at all). I understand though that in k8s/gke nomenclature I'm still going to be using a 'load-balancer' even though it'll act as a reverse proxy and not actually balance any load.
The use case is as follows. I have some web app where I can request for a 'new instance' and in return I get a dynamically generated url (e.g. http://random-uuid-1.acme.io). This domain should point to a newly spawned, single instance of a container (Pod) hosting some web application. Again, if I request another 'new instance', I'll get a http://random-uuid-2.acme.io which will point to another (separate), newly spawned instance of the same app.
So far I figured out following setup. Every time I request a 'new instance' I do the following:
create a new Pod with dynamic name app-${uuid} that exposes HTTP port
create a new Service with NodePort that "exposes" the Pod's HTTP port to the Cluster
create or update (if exists) Ingress by adding a new http rule where I specify that domain X should point at NodePort X
The Ingress mentioned above uses a LoadBalancer as its controller, which is automated process in GKE.
A few issues that I've already encountered which you might be able to help me out with:
While Pod and NodePort are separate resources per each app, Ingress is shared. I am thus not able to just create/delete a resource but I'm also forced to keep track of what has been added to the Ingress to be then able to append/delete from the yaml which is definitely not the way to do that (i.e. editing yamls). Instead I'd probably want to have something like an Ingress to monitor a specific namespace and create rules automatically based on Pod labels. Say I have 3 pods with labels, app-1, app-2 and app-3 and I want Ingress to automatically monitor all Pods in my namespace and create rules based on the labels of these pods (i.e. app-1.acme.io -> reverse proxy to Pod app-1).
Updating Ingress with a new HTTP rule takes around a minute to allow traffic into the Pod, until then I keep getting 404 even though both Ingress and LoadBalancer look as 'ready'. I can't figure out what I should watch/wait for to get a clear message that the Ingress Controller is ready for accepting traffic for newly spawned app.
What would be the good practice of managing such cluster where you can't strictly define Pods/Services manifests because you are creating them dynamically (with different names, endpoints or rules). You surely don't want to create bunch of yaml-s for every application you spawn to maintain. I would imagine something similar to consul templates in case of Consul but for k8s?
I participated in a similar project and our decision was to use Kubernetes Client Library to spawn instances. The instances were managed by a simple web application, which took some customisation parameters, saved them into its database, then created an instance. Because of the database, there was no problem with keeping track of what have been created so far. By querying the database we were able to tell if such deployment was already created or update/delete any associated resources.
Each instance consisted of:
a deployment (single or multi-replica, depending on the instance);
a ClusterIp service (no reason to reserve machine port with NodePort);
an ingress object for shared ingress controller;
and some shared configMaps.
And we also used external DNS and cert manager, one to manage DNS records and another to issue SSL certificates for the ingress. With this setup it took about 10 minutes to deploy a new instance. The pod and ingress controller were ready in seconds but we had to wait for the certificate and it's readiness depended on whether issuer's DNS got our new record. This problem might be avoided by using a wildcard domain but we had to use many different domains so it wasn't an option in our case.
Other than that you might consider writing a Helm chart and make use of helm list command to find existing instances and manage them. Though, this is a rather 'manual' solution. If you want this functionality to be a part of your application - better use a client library for Kubernetes.

Notify containers of updated pods in Kubernetes

I have some servers I want to deploy in Kubernetes. The clients of those servers will also be in Kubernetes. Clients and servers can independently be deployed or scaled.
The clients must know the list of the servers (IPs). I have an HTTP endpoint on the clients to update the list of the servers while the clients are running (hot config reload).
All this is currently running outside of Kubernetes. I want to migrate to GCP.
What's the industry standard regarding pods updates and notifications? I want to get notified when servers are updated to call the endpoints on the clients to update the list of the servers.
Can't use a LoadBalancer since the clients really need to call a specific server (business logic are in the clients).
Thanks
The standard for calling a group of pods that offer a functionality is services. If you don't want automated load-balancing or a single IP address, which regular services do, you should look into headless services. Calling headless services returns a list of DNS A records that point to the pods behind the service. This list is automatically updated as pods become available/unavailable.
While I think modifying an existing script to just pull a list from a headless is much simpler, it might be worth mentioning CRDs (Custom Resource Definitions) as well.
You could build a custom controller that listens to service events and then posts the data from that event to an HTTP endpoint of another Service or Ingress. The custom resource would define which service to watch and where to post the results.
Though, this is probably much heavier weight solution that just having a sidecar / separate container in a pod polling the service for changes (which sounds closer to you existing model).
I upvoted Alassane answer as I think it is the correct first path to something like this before building a CRD.

Kubernetes - Load balancing Web App access per connections

Long time I did not come here and I hope you're fine :)
So for now, i have the pleasure of working with kubernetes ! So let's start ! :)
[THE EXISTING]
I have an operationnal kubernetes cluster with which I work every day.it consists of several applications, one of which is of particular interest to us, which is the web management interface.
I currently own one master and four nodes in my cluster.
For my web application, pod contain 3 containers : web / mongo /filebeat, and for technical reasons, we decided to assign 5 users max for each web pod.
[WHAT I WANT]
I want to deploy a web pod on each nodes (web0,web1,web2,web3), what I can already do, and that each session (1 session = 1 user) is distributed as follows:
For now, all HTTP requests are processed by web0.
[QUESTIONS]
Am I forced to go through an external loadbalancer (haproxy)?
Can I use an internal loadbalancer, configuring a service?
Does anyone have experience on the implementation described above?
I thank in advance those who can help me in this process :)
This generally depends how and where you've deployed your Kubernetes infrastructure, but you can do this natively with a few options.
Firstly, you'll need to scale your web deployment. This is very simple to do:
kubectl scale --current-replicas=2 --replicas=3 deployment/web
If you're deployed into a cloud provider (such as AWS using kops, or GKE) you can use a service. Just specify the type as LoadBalancer. Services will spread the sessions for your users.
Another option is to use an Ingress. In order to do this, you'll need to use an Ingress Controller, such as the nginx-ingress-controller which is the most featureful and widely deployed.
Both of these options will automatically loadbalance your incoming application sessions, but they may not necessarily do it in the order you've described in your image, it'll be random across the available web deployments

how to use load balancer route traffic to REST based stateless services which not spread on all nodes of a given node type

say, I have a service fabric cluster with one node type which has 5 nodes, and deployed two stateless services on those 5 nodes, but I would deploy service_1 on 3 nodes and service_2 on 2 other nodes.
I understand that a node type is actually a VMSS and azure will create a load balancer on top of that VMSS. It works perfectly on REST stateless service which spread to all of nodes of certain node type.
But in my case, the service deployed on part of nodes, can I still leverage the load balancer to route to instances of two separate services?
You have multiple options:
Use the built in HTTP gateway service from Service Fabric. Unfortunately, I haven't found any documentation about this yet, so I don't know about the advantages and disadvantages of this solution. See this comment in the service-fabric-issues project for some details.
Implement your own stateless gateway service which has an InstanceCount of -1 (which means it gets placed on every node). This service will act like an internal load balancer and route every request to the correct service. See weidazhao's (a Microsoft employee - this project might become part of the SDK) or our project for existing gateway projects.
Keep using one load balancer which points to the whole scale set and use probe methods to let the load balancer disable nodes on which the service is not running. However, in case of placement changes, this results in failing requests until the load balancer figures it out.
Create separate node types (VM Scale Sets) for every service and create a separate load balancer for each node type. However, this results in management overhead and might not be ideal in terms of resource usage.
There is an open feature suggestion for this topic on the Azure UserVoice site - your votes would be welcome.