Kubernetes Default Loadbalancer for a service run locally? - kubernetes

currently I have 3 virtual machines (1 master kubernetes node and 2 slaves).
I want to create a service which encapsulates 3 replicas of my container.
I am curious if by default, in this local environment, when creating the service, kubernetes offers a load balancer by default, even though it was NOT specified in the service yaml file. Does it offer round robin by default ?

If your not on a supported cloud provider, your pretty much stuck with NodePort or ClusterIP for service types. A project I used when I was experimenting with a local kubernetes environment was Metallb. Metallb allows you to use the LoadBalancer service type and expose your service outside of the cluster network when running kubernetes outside a hosted platform, i.e., local test cluster.
To use Metallb, you must provide a pool of ip addresses the you can use on your pod network.
First create a config map with your pod network ip range --
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.1.240-192.168.1.250
Then add that config map to your cluster.
kubectl apply -f metallb-config.yaml
Finally add the metallb controller to your cluster
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.3/manifests/metallb.yaml
Now you should be able to expose your service.
kubectl expose deployment name-of-deployment --type=LoadBalancer --name=name-of-service

You can not practically use LoadBalancer service in your local.LoadBalancer service creates a LoadBalancer provided by your cloud provider if you are running on public cloud. You can set L7 load balancing capabilities via your cloud provide offering. Load balancing in L4 layer will be controller by kube-proxy which is round robin by default.
If you are using cluster ip or NodePort then also you are getting the L4 load balancing offered by kube proxy.

You won't be able to do that because locally there is no cloud controller available.
When you will be in cloud and you created service with LoadBalancer kubernetes controller will talk to cloud controller and it will create loadbalancer in cluster. But in this case there is no cloud-controller available to create loadbalancer.

Related

Can i use ingress controllers to configure existing Load Balancer provisioned for Kubernetes Bare Metal

We have seen on cloud that installing an ingress controller, automatically provisions a LoadBalancer and ingress rules configure Load Balancer itself.
We have used k8s-hard-way to establish a k8s cluster on bare metal
Here on a bare Metal K8s, we have already provisioned a LoadBalancer as described in this section
Can we use Ingress controllers like Kong / HAProxy/ Nginx to configure this existing Load Balancer via Ingress rules?
If Not, what should be the way?
So generally when Nginx ingress controller or any other controller like Kong got installed to K8s it creates the service type LoadBalancer.
You can create or modify the service that got created by default and map your LoadBalancer IP to the service.
apiVersion: v1
kind: Service
spec:
...
type: LoadBalancer
loadBalancerIP: 192.168.0.01
Now your controller service is pointing to the LB IP and your service is exposed to the internet.
Map LB IP to hostname in DNS and you are good to use it.

Get Externally accessible IP address of Pod in Kubernetes

I need to create two instances using the same Ubuntu Image in Kubernetes. Each instance used two ports i.e. 8080 and 9090. How can I access these two ports externally? Can we use the IP address of the worker in this case?
If you want to access your Ubuntu instances from outside the k8s cluster you should place pods behind the service.
You can access services through public IPs:
create Service of type NodePort- the service will be available on <NodeIp>:<NodePort>
create Service of type LoadBalancer - if you are running your workload in the cloud creating service of type LoadBalancer will automatically deploy LoadBalancer for you.
Alternatively you can deploy Ingress to expose your Service. You would also need Ingress Controller.
Useful links:
GCP example
Ingress Controller
Ingress
Kubernetes Service

Access the Kubernetes cluster/node from outside

I am new to kubernetes. I have created a cluster of db of kubernetes with 2 nodes. I can access those kubernetes pods from thin client like dbeaver to check the data. But I can not access those kubernetes nodes externally. I am currently trying to run a thick client which will load the data into cluster on kubernetes.
kubectl describe svc <svc>
I can see cluster-Ip assigned to the service. Type of my service is loadbalancer. I tried to use that but still not connecting. I read about using nodeport but without any IP address how to access that
So what is the best way to connect any node or cluster from outside.
Thank you in advance
Regards
#KrishnaChaurasia is right but I would like to explain it in more detail with the help of the official docs.
I strongly recommend going through the following sources:
NodePort Type Service: Exposes the Service on each Node's IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created. You'll be able to contact the NodePort Service, from outside the cluster, by requesting <NodeIP>:<NodePort>. Here is an example of the NodePort Service:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: MyApp
ports:
# By default and for convenience, the `targetPort` is set to the same value as the `port` field.
- port: 80
targetPort: 80
# Optional field
# By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
nodePort: 30007
Accessing services running on the cluster: You have several options for connecting to nodes, pods and services from outside the cluster:
Access services through public IPs.
Use a service with type NodePort or LoadBalancer to make the service reachable outside the cluster. See the services and kubectl expose documentation.
Depending on your cluster environment, this may just expose the service to your corporate network, or it may expose it to the internet. Think about whether the service being exposed is secure. Does it do its own authentication?
Place pods behind services. To access one specific pod from a set of replicas, such as for debugging, place a unique label on the pod and create a new service which selects this label.
In most cases, it should not be necessary for application developer to directly access nodes via their nodeIPs.
A supplement example: Use a Service to Access an Application in a Cluster: This page shows how to create a Kubernetes Service object that external clients can use to access an application running in a cluster.
These will help you to better understand the concepts of different Service Types, how to expose and access them from outside the cluster.

Kubernetes LoadBalancer service with hostNetwork binding

I have a query regarding the usage of a LoadBalancer service with hostNetwork
If we set hostNetwork: true, then the pods bind on the host network - to which the external services connect to. If we need only one instance of the pod running - then I believe we do not need a LoadBalancer service for the external services to connect to the pod. I do not see any use-case for a a LoadBalancer service here, or are there any I am missing ?
hostNetwork=true is not the recommended approach for exposing pods outside of the cluster. It has a few limitations:
Only 1 instance of a pod can run on a specific node on the same port
You have to use the nodeIP to access the pod, however, the node IP can change.
If the pod fails, the k8s scheduler may spawn it on a different node.
The recommended way for exposing pods outside of the cluster is via Kubernetes Service Controllers.
All service controllers act as load balancers (they will balance the traffic across all "ready" pods) no matter the Service.spec.type property.
Service.spec.type property can be one of the below:
ClusterIP, NodePort, LoadBalancer, ExternalName
The LoadBalancer type means that k8s will use a cloud provider LoadBalancer to expose the service outside of the cluster (for example AWS Elastic Load balancer if the k8s cluster is running on AWS).
LoadBalancer: Exposes the Service externally using a cloud provider’s
load balancer. NodePort and ClusterIP Services, to which the external
load balancer routes, are automatically created.
More on k8s service types

Is there a way to not use GKE's standard load balancer?

I'm trying to use Kubernetes to make configurations and deployments explicitly defined and I also like Kubernetes' pod scheduling mechanisms. There are (for now) just 2 apps running on 2 replicas on 3 nodes. But Google's Kubernetes Engine's load balancer is extremely expensive for a small app like ours (at least for the moment) at the same time I'm not willing to change to a single instance hosting solution on a container or deploying the app on Docker swarm etc.
Using node's IP seemed like a hack and I thought that it might expose some security issues inside the cluster. Therefore I configured a Træfik ingress and an ingress controller to overcome Google's expensive flat rate for load balancing but turns out an outward facing ingress spins up a standart load balancer or I'm missing something.
I hope I'm missing something since at this rates ($16 a month) I cannot rationalize using kubernetes from start up for this app.
Is there a way to use GKE without using Google's load balancer?
An Ingress is just a set of rules that tell the cluster how to route to your services, and a Service is another set of rules to reach and load-balance across a set of pods, based on the selector. A service can use 3 different routing types:
ClusterIP - this gives the service an IP that's only available inside the cluster which routes to the pods.
NodePort - this creates a ClusterIP, and then creates an externally reachable port on every single node in the cluster. Traffic to those ports routes to the internal service IP and then to the pods.
LoadBalancer - this creates a ClusterIP, then a NodePort, and then provisions a load balancer from a provider (if available like on GKE). Traffic hits the load balancer, then a port on one of the nodes, then the internal IP, then finally a pod.
These different types of services are not mutually exclusive but actually build on each other, and it explains why anything public must be using a NodePort. Think about it - how else would traffic reach your cluster? A cloud load balancer just directs requests to your nodes and points to one of the NodePort ports. If you don't want a GKE load balancer then you can already skip it and access those ports directly.
The downside is that the ports are limited between 30000-32767. If you need standard HTTP port 80/443 then you can't accomplish this with a Service and instead must specify the port directly in your Deployment. Use the hostPort setting to bind the containers directly to port 80 on the node:
containers:
- name: yourapp
image: yourimage
ports:
- name: http
containerPort: 80
hostPort: 80 ### this will bind to port 80 on the actual node
This might work for you and routes traffic directly to the container without any load-balancing, but if a node has problems or the app stops running on a node then it will be unavailable.
If you still want load-balancing then you can run a DaemonSet (so that it's available on every node) with Nginx (or any other proxy) exposed via hostPort and then that will route to your internal services. An easy way to run this is with the standard nginx-ingress package, but skip creating the LoadBalancer service for it and use the hostPort setting. The Helm chart can be configured for this:
https://github.com/helm/charts/tree/master/stable/nginx-ingress
One option is to completely disable this feature on your GKE cluster. When creating the cluster (on console.cloud.google.com) under Add-ons disable HTTP load balancing. If you are using gcloud you can use gcloud beta container clusters create ... --disable-addons=HttpLoadBalancing.
Alternatively, you can also inhibit the GCP Load Balancer by adding an annotation to your Ingress resources, kubernetes.io/ingress.class=somerandomstring.
For newly created ingresses, you can put this in the yaml document:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: somerandomstring
...
If you want to do that for all of your Ingresses you can use this example snippet (be careful!):
kubectl get ingress --all-namespaces \
-o jsonpath='{range .items[*]}{"kubectl annotate ingress -n "}{.metadata.namespace}{" "}{.metadata.name}{" kubernetes.io/ingress.class=somerandomstring\n"}{end}' \
| sh -x
Now using Ingresses is pretty useful with Kubernetes, so I suggest you check out the nginx ingress controller and after deployment, annotate your Ingresses accordingly.
If you specify the Ingress class as an annotation on the Ingress object
kubernetes.io/ingress.class: traefik
Traefik will pick it up while the Google Load Balancer will ignore it. There is also a bit of Traefik documentation on this part.
You could deploy the nginx ingress controller using NodePort mode (e.g. if using the helm chart set controller.service.type to NodePort) and then load-balance amongst your instances using DNS. Just make sure you have static IPs for the nodes or you could even create a DaemonSet that somehow updates your DNS with each node's IP.
Traefik seems to support a similar configuration (e.g. through serviceType in its helm chart).