Consuming RESTful services orchestrated by Kubernetes - rest

How do you consume a service that is being orchestrated by Kubernetes?
What does the calling statement look like.
When consuming a normal RESTful web service, you might use RestTemplate (for Java) and specify the URL.
How does this differ when Kubernetes creates and destroys occurrences of the service?

Internally, use kubernetes service of ClusterIp type (can also be headless). Externally use service of NodePort or LoadBalancer type to expose your application directly, or Ingress (assuming you have ingress controller deployed/available) to define HTTP(S) based routing from external HTTP(S) level loadbalancer by vhost/path.

Related

How to expose a single REST API to outside cluster in Kubernetes?

I am new to Kubernetes and if I am not wrong, a service can be exposed inside the cluster using ClusterIP, and to the outside world using NodePort or LoadBalancer types. But my requirement is that I have a single container that has few REST APIs. I want that one API (the basic health check API) should be exposed to the outside, and the rest of the APIs should be available only within the cluster (accessible by other nodes). How can I achieve this?
You can keep your service as ClusterIP and use the ingress.
With ingress and ingress controller, you can setup and expose the desired path outside of cluster.
Ingress, you can install the Nginx ingress controller and create the ingress resource.
Read more about the nginx ingress controller setup and ingress reosuce setup.

Why do we need a load balancer to expose kubernetes services using ingress?

For a sample microservice based architecture deployed on Google kubernetes engine, I need help to validate my understanding :
We know services are supposed to load balance traffic for pod replicaset.
When we create an nginx ingress controller and ingress definitions to route to each service, a loadbalancer is also setup automatically.
had read somewhere that creating nginx ingress controller means an nginx controller (deployment) and a loadbalancer type service getting created behind the scene. I am not sure if this is true.
It seems loadbalancing is being done by services. URL based routing is
being done by ingress controller.
Why do we need a loadbalancer? It is not meant to load balance across multiple instances. It will just
forward all the traffic to nginx reverse proxy created and it will
route requests based on URL.
Please correct if I am wrong in my understanding.
A Service type LoadBalancer and the Ingress is the way to reach your application externally, although they work in a different way.
Service:
In Kubernetes, a Service is an abstraction which defines a logical set of Pods and a policy by which to access them (sometimes this pattern is called a micro-service). The set of Pods targeted by a Service is usually determined by a selector (see below for why you might want a Service without a selector).
There are some types of Services, and of them is the LoadBalancer type that permit you to expose your application externally assigning a externa IP for your service. For each LoadBalancer service a new external IP will be assign to it.
The load balancing will be handled by kube-proxy.
Ingress:
An API object that manages external access to the services in a cluster, typically HTTP.
Ingress may provide load balancing, SSL termination and name-based virtual hosting.
When you setup an ingress (i.e.: nginx-ingress), a Service type LoadBalancer is created for the ingress-controller pods and a Load Balancer in you cloud provider is automatically created and a public IP will be assigned for the nginx-ingress service.
This load balancer/public ip will be used for incoming connection for all your services, and nginx-ingress will be the responsible to handle the incoming connections.
For example:
Supose you have 10 services of LoadBalancer type: This will result in 10 new publics ips created and you need to use the correspondent ip for the service you want to reach.
But if you use a ingress, only 1 IP will be created and the ingress will be the responsible to handle the incoming connection for the correct service based on PATH/URL you defined in the ingress configuration. With ingress you can:
Use regex in path to define the service to redirect;
Use SSL/TLS
Inject custom headers;
Redirect requests for a default service if one of the service failed (default-backend);
Create whitelists based on IPs
Etc...
A important note about Ingress Load balancing in ingress:
GCE/AWS load balancers do not provide weights for their target pools. This was not an issue with the old LB kube-proxy rules which would correctly balance across all endpoints.
With the new functionality, the external traffic is not equally load balanced across pods, but rather equally balanced at the node level (because GCE/AWS and other external LB implementations do not have the ability for specifying the weight per node, they balance equally across all target nodes, disregarding the number of pods on each node).
An ingress controller(nginx for example) pods needs to be exposed outside the kubernetes cluster as an entry point of all north-south traffic coming into the kubernetes cluster. One way to do that is via a LoadBalancer. You could use NodePort as well but it's not recommended for production or you could just deploy the ingress controller directly on the host network on a host with a public ip. Having a load balancer also gives ability to load balance the traffic across multiple replicas of ingress controller pods.
When you use ingress controller the traffic comes from the loadBalancer to the ingress controller and then gets to backend POD IPs based on the rules defined in ingress resource. This bypasses the kubernetes service and load balancing(by kube-proxy at layer 4) offered by kubernetes service.Internally the ingress controller discovers all the POD IPs from the kubernetes service's endpoints and directly route traffic to the pods.
It seems loadbalancing is being done by services. URL based routing is being done by ingress controller.
Services do balance the traffic between pods. But they aren't accessible outside the kubernetes in Google Kubernetes Engine by default (ClusterIP type). You can create services with LoadBalancer type, but each service will get its own IP address (Network Load Balancer) so it can get expensive. Also if you have one application that has different services it's much better to use Ingress objects that provides single entry point. When you create an Ingress object, the Ingress controller (e.g. nginx one) creates a Google Cloud HTTP(S) load balancer. An Ingress object, in turn, can be associated with one or more Service objects.
Then you can get the assigned load balancer IP from ingress object:
kubectl get ingress ingress-name --output yaml
As a result your application in pods become accessible outside the kubernetes cluster:
LoadBalancerIP/url1 -> service1 -> pods
LoadBalancerIP/url2 -> service2 -> pods

How to expose nginx ingress controller [on-premise infrastructure]

This is more a design question than an issue. We have deployed in our company our own Kubernetes infrastructure and we are trying to use ingresses and NGINX ingress controller to externally expose our services, but since it is not a cloud environment such as GCP or AWS, we can't use service type "LoadBalancer". Should we just expose our ingress controller through a service type "NodePort"? Is that the normal way to go for production environments (non-cloud)?
From what I've read in another post, one suitable recommendation is to use NodePort, and manually point yet another external load balancer to the port on your Kubernetes nodes.
It just seems that exposing the ingress controller through this mechanism is somehow not very practical or robust (e.g. you don’t know what port your service is going to be allocated, and the port might get re-allocated at some point, etc.)
Is there any other mechanism maybe to expose the ingress controller to the external world?
The Loadbalancer service approach is one way to do it but behind it it's nothing more than a nodeport on the cluster.
Even if you use a service that create a LB on cloud provider, the LB needs to have a target port to communicate with the cluster.
When using a nginx-ingress that will mostly handle web requests, it's common usage to put an ingress in front of a nodeport service.
So with this I think using NodePort services is a good idea to do what you want ;)
This is my opinion, I'm interested if anyone else has another way to do it.
You can specify the port via nodePort in the service. Then it would not be random.

Kubernetes - Have an ingress on a service - is it ok for its type to be ClusterIP

I have a Kubernetes services that I would like to be accessible from outside the cluster.
I've setup Traefik and have created an Ingress file for that service and am able to go to 'somemadeupdomain.com' and access the service fine. (Having locally added a line in my hosts file).
However my question is with the service type, I've currently set as ClusterIP. I can access the service fine, so is it fine to continue to use that or should I use NodePort.
Of course if I use NodePort I'm aware that when doing minikube service list I'll get a specific URL created by Kubernetes to access that service, but I feel I don't need to do that as I have that ingress file?
Any explanation would be appreciated.
Thanks
As you are using ingress already it does not make much sense to use NodePort. As you already have a way to access your application. Its totally fine to have a service type you need at service level that you need for the internal access(within Kubernets) purpose.
Ingress will redirect your external traffic to your service within the cluster, so ClusterIP is a good choice. No need to use NodePort.
From Documentation
Ingress, added in Kubernetes v1.1, exposes HTTP and HTTPS routes from
outside the cluster to services within the cluster

Clarify Ingress load balancer

I'm not sure how load balancing works with Ingress.
If I understand correctly, what happens is actually something like this:
I fail to see how the load balancing is performed.
What is wrong in the above scheme that I have drawn?
Can you help me rectify it?
Notes:
- The following answer tells me that the Ingress controller itself is of type 'loadbalancer': Ingress service type
- I use kind ClusterIP because I don't want to expose the loadbalancer to the outside world. The following article does not support this claim, where the load balancer would be provided by the service:
https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0
The ClusterIP services themselves perform load balancing. The naming can be confusing as LoadBalancer services are not the only services that involve load balancing - LoadBalancer actually means something more like 'cloud provider please create an external load balancer and point it at this service'. The kubernetes ClusterIP services also load-balance across Pods in different Nodes using the kube-proxy. If you don't want kubernetes to do load balancing then you have to specifically disable it by creating a headless service.
It seems like the first scheme you drew is correct. But I think you get confused in terminology. Particularly in the difference between ingress and ingress-controller.
Ingress is a type of resources in k8s (like Service, Deployment, ReplicaSet etc). We use ingress if we want to expose some services to an external world with binding to some path and host (i.e. myapp.com/api -> my-api-service).
The job of ingress-controller is to handle creation/update/deletion of ingress resources and implement all the functionality needed for ingress. Under the hood ingress-controller is a simple deployment exposed as LoadBalancer or NodePort service depending on where k8s is deployed. And image-controller forwards received request further to one of pods of service which matches host and path in some of the deployed ingress resources.
I got curious and thought: why would I need an Ingress for load balancing on layer 7 if the only thing it does is forward the traffic to a Service that implements the load balancing on layer 4?
Most Ingress controller implementations I looked up, talk to the Kubernetes API server to keep track of all Pods associated with a Service. Instead of forwarding traffic to the Service, they skip the intermediary and directly forward to the Pods. Since an ingress controller operates on layer 7, it enables a more application-oriented load balancing.