NGINX loadbalancing on Kubernetes - nginx

I have some services running in Kubernetes. I need an NGINX in front of them, to redirect traffic according to the URLs, handle SSL encryption and load balancing.
There is a working nginx.conf for that scenario. What I´m missing is the right way to set up the architecture on gcloud.
Is it correct to launch a StatefulSet with nginx and have a Loadbalancing Service expose NGINX? Do I understand it right, that gcloud LB would pass the configured Ports ( f.e. 80 + 443) to my NGINX service, where I can handle the rest and forward the traffic to the backend services?

You don't really need a StatefulSet, a Deployment will do since nginx is already being fronted by a gcloud TCP load balancer, if for any reason one of your nginx pods is down the gcloud load balancer will not forward traffic to it. Since you already have a gcloud load balancer you will have to use a NodePort Service type and you will have to point your gcloud load balancer to all the nodes on your K8s cluster on that specific port.
Note that your nginx.conf will have to know how to route to all the services internally in your K8s cluster. I recommend you set up an nginx ingress controller, which will basically manage the nginx.conf for you through an Ingress resource and you can also expose it as a LoadBalancer Service type.

Related

How does the nginx resolver behave when pointed at a Kubernetes Service?

I'm exploring the nginx container as a load balancer. I'm using a Kubernetes Service in the upstream module.
Here is a snippet of my nginx.conf...
upstream backend {
hash $remote_addr consistent;
server mgmt-1; # <-- these entries are Kubernetes Services
server mgmt-2;
server mgmt-3;
}
Right now each service maps to only ONE pod. Which of course, is not ideal.
So, the resolver directive for nginx+ is said to consistently update the endpoint IP, in the event that the Service is changed/moved/deleted/ephemeralized, etc.
Question: If I wanted to scale up my pods, resulting in multiple endpoints maintained by one Service, would the nginx resolver extract and load the entire set of endpoints? Or will it not know what to do? Thanks
You can test this for yourself. It's quite fun. You spin up a pod running Ubuntu for example and then kubectl exec -it podname /bin/sh into the pod and from there you can run nslookup mgmt-1 (if they're in the same namespace).
What you will find is that the service resolves to a single IP. This IP is unique to the service. When you actually send the service IP traffic on a port it is listening on it will make it to the endpoints.
To answer your question. I do not believe Nginx will be able to tell mgmt-1 has three endpoints (for example) while mgmt-2 has 1 endpoint (for example). Nginx will only see the service IP.
To see the service IP for yourself you can run kubectl get svc/servicename -n namespacename

What is the role of an external Load Balancer if we are using nginx ingress controller?

I have deployed my application in a cluster of 3 nodes. Now to make this application externally accessible, I have followed this documentation and integrated nginx ingress controller.
Now when I checked my Google's Load Balancer console, I can see a new load balancer created and everything works fine. But the strange thing is I found two of my nodes are unhealthy and only one node is accepting connection. Then I found this discussion and understood that the only node running nginx ingress controller pod will be healthy for load balancer.
Now I feel hard to understand this data flow and the use of external load balancer here. We use external load balancer to balance the load to multiple machines. But with this configuration external load balancer will always forward traffic to the node with nginx ingress controller pod. If that is correct, what is the role of external load balance here?
You can have more than one replica of the Nginx ingress controller pods deployed across more than one kubernetes nodes for high availability purpose to reduce the possibility of downtime in case one kubernetes node is unavailable. The LoadBalancer will send the request to one of those nginx ingress Controller pods. From nginx ingress controller pods it will forwarded to any of the backend pods. The role of the external load balancer is to expose nginx ingress controller pods outside the cluster. Because NodePort is not recommended for usage in production and ClusterIP can not be used expose pods outside the cluster, hence LoadBalancer is the viable option.

Handling CONNECT request with Nginx Ingress on GCP GKE

I have a cluster of proxy servers on GKE, and I'm trying to figure out how to load balance CONNECT requests to these.
Without GKE, I'm using the nginx stream module (http://nginx.org/en/docs/stream/ngx_stream_core_module.html) which works perfectly.
GCP load balancers do not accept CONNECT requests, so I'm trying to take my existing nginx configuration file and apply it to an nginx ingress resource for GKE. Is this possible?

Should I run nginx in every Kubernetes pod?

I have a kubernetes cluster with 20 worker nodes. My main application is a Flask API that serves thousands of android/ios requests per minute. The way my Kubernetes deployment is configured is that each pod has 2 containers - flask/python server and nginx. The flask app runs on-top of gunicorn with meinheld workers (20 workers per pod).
My question is: do I need to be running nginx in each of the pods alongside the flask app or can I just use a main nginx ingress controller as a proxy buffering layer?
NOTE:
I am using ELB to route external traffic to my internal k8s cluster.
Is not too strange to have a proxy on every pod, in fact, istio injects one envoy container per pod as a proxy to control de ingress and egress traffic and also to having more accurate metrics.
Check de documentation https://istio.io/
But if you don't want to manage a service mesh by the moment you can avoid the nginx and use directly the port mapping on the services an ingress definition.
I don't see any reason to have a nginx container for every other flask container. You can have one nginx container as API gateway to your entire set of apis

Nginx to load balance deployment inside a service kubernetes

I want to use Nginx to load balance a kubernetes deployment.
The deployment is part of a service. It contains pod which can be scaled. I want NGINX to be part of the service without being scaled.
I know that I can use NGINX as an external load balancer by configuring it with external dns resolver. With that it can get the IP of the pods scaled and apply its own load balanced rules.
Is it possible to make NGINX part of the service? Then how to do the DNS resolution to the pods? In that case, which pods the service name is refered to?
I would like to avoid the declaration of two services to keep a single definition of the setup which represent a microservice.
More generally, how can I declare in a same service:
a unit which is scaled
a backend, not scaled
a database, not scaled
Thanks all
You can't have NGINX as part of the service. Service doesn't contain any pods, deployment does. It sounds like you want an ingress service, that would be a load balancer any and all services on the cluster
EDIT:
An ingress controller in essence is a deployment of NGINX exposed publicly as a service acting as a load balancer/fan out. The deployment scans your cluster for ingress resources and reconfigures NGINX to forward requests to appropriate services.
Typically people deploy a single controller that acts as the load balancer for all of your microservices. You can fan out based on DNS, URI, other headers and so on. You can also do TLS termination, add basic auth to specific services, it's even possible to splice in NGINX config snippets directly into the ingress resources.

Resources