Accessing the cluster🔗︎
Cloud providers that support Kubernetes clusters typically provide load balancer provisioning on demand. By setting a Service type to LoadBalancer
, an external load balancer is automatically provisioned with its own unique IP address. This load balancer redirects all incoming connections to the Service, as illustrated in the figure below.
In on-premise environments, there is no load balancer that can be provisioned on demand. Therefore, some alternative solutions are explained in this document.
Node ports🔗︎
Setting Service type to NodePort
makes Kubernetes reserve a port on all its nodes. As a result, the Service becomes available on <NodeIP>:<NodePort>
, as shown in the figure below.
When using NodePort
, it does not matter to which node a client sends the request, since it is routed internally to the appropriate Pod. However, if all traffic is directed to a single node, its failure will make the Service unavailable.
Self-provisioned edge🔗︎
With Kubitect, it is possible to configure the port forwarding of the load balancer to distribute incoming requests to multiple nodes in the cluster, as shown in the figure below.
To set up load balancer port forwarding, at least one load balancer must be configured. The following example shows how to set up load balancer port forwarding for ports 80 (HTTP) and 443 (HTTPS).
cluster:
nodes:
loadBalancer:
forwardPorts:
- name: http
port: 80
- name: https
port: 443
instances:
- id: 1
Load balancer port forwarding is particularly handy when combined with a NodePort
Service or a Service whose ports are exposed on the host. For example, for HTTP and HTTPS traffic an Ingress is most often used. To use Ingress resources in the Kubernetes cluster, an ingress controller is required. With Kubitect, a load balancer can be configured to accept connections on ports 80 and 443, and redirect them to all cluster nodes on ports 50080 and 50443 where an ingress controller is listening for incoming requests. The following code snippet shows the configuration for such a scenario.
cluster:
nodes:
loadBalancer:
forwardPorts:
- name: http
port: 80
targetPort: 50080
target: workers # (1)!
- name: https
port: 443
targetPort: 50443
instances:
- id: 1
addons:
kubespray:
ingress_nginx_enabled: true
ingress_nginx_namespace: "ingress-nginx"
ingress_nginx_insecure_port: 50080 # (2)!
ingress_nginx_secure_port: 50443
-
By default, each configured port instructs the load balancer to distribute traffic across all worker nodes. The default behavior can be changed using the
target
property.Possible target values are:
workers
- Distributes traffic across worker nodes. (default)masters
- Distributes traffic across master nodes.all
- Distributes traffic across master and worker nodes.
-
When the ingress-nginx controller is set up with Kubespray, a DaemonSet is created that exposes ports on the host (
hostPort
).
MetalLB🔗︎
MetalLB is a network load balancer implementation for bare metal Kubernetes clusters. In short, it allows you to create Services of type LoadBalancer
where actual on-demand load balancers are not an option.
For MetalLB to work, a pool of unused IP addresses needs to be provided. In the following example, MetalLB is configured to use an IP address pool with the IP range 10.10.13.225/27
.
addons:
kubespray:
metallb_enabled: true
metallb_speaker_enabled: true
metallb_ip_range:
- "10.10.13.225/27"
metallb_pool_name: "default"
metallb_auto_assign: true
metallb_version: v0.12.1
metallb_protocol: "layer2"
When a Service of type LoadBalancer
is created, it is assigned an IP address from the pool. For example, we could deploy an ingress-nginx controller and change its Service type to LoadBalancer
.
# Deploy ingress-nginx controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/1.23/deploy.yaml
# Patch ingress controller Service type to LoadBalancer
kubectl patch svc ingress-nginx-controller -n ingress-nginx -p '{"spec": {"type":"LoadBalancer"}}'
As a result, MetalLB assigns the service ingress-nginx-controller
an external IP address from the address pool.
kubectl get svc -n ingress-nginx ingress-nginx-controller
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# ingress-nginx-controller LoadBalancer 10.233.55.194 10.10.13.225 80:31497/TCP,443:30967/TCP 63s
By sending a request to the assigned IP address, it can be seen that Nginx responds to the request.
curl -k https://10.10.13.225
# <html>
# <head><title>404 Not Found</title></head>
# <body>
# <center><h1>404 Not Found</h1></center>
# <hr><center>nginx</center>
# </body>
# </html>
This example has demonstrated the functionality of MetalLB in layer2
mode. For more MetalLB configuration options, see the official MetalLB documentation.