Unsolved
30 Posts
0
756
EKS Anywhere, and MetalLB Load Balancer services
This article is part of the EKS Anywhere series EKS Anywhere., extending the Hybrid cloud momentum
This article has been updated for v0.13.0+ due to depreciation of ConfigInLine method of creating IP address pools for MetalLB.
Kubernetes core and/or EKS Anywhere equally does not provide for any Load Balancers. Here in the choices are left to the end adopter of deploying a relevant load-balancer that can help access the spread of of deployed applications via the pods
Generally speaking., in public clouds, the default integrations with the load-balancer service extensions are an out-of-box solution. However, in an on-premises scenario, you would need a hardware, or a software defined load-balancer that can be integrated with your Kubernetes cluster.
This could be a limiting factor both in terms of cost as well as availability and integration of such solutions from leading vendors.
In that context, the MetalLB open-source project is one of the preferred choices for alternative Load balancer services that does not depend on any external load-balancers. While the project aimed at bare-metal clusters (hence the name)., however it can be used with any kind of cluster (bare-metal or virtualized).
MetalLB is one of the most popular on-premises replacements for the LoadBalancer cloud integrations. The whole solution runs inside a particular Kubernetes cluster where these services are needed. MetalLB is a native Kubernetes load balancing solution for bare-metal Kubernetes clusters. Detailed information about MetalLB can be found here
The main component is an in-cluster Kubernetes controller which watches LB service resources, and based on the configuration supplied in a ConfigMap, allocates and writes back IP addresses from a dedicated pool for new services. It maintains a leader node for each service, and depending on the working mode, advertises it via BGP or ARP (sending out unsolicited ARP packets in case of failovers).
The main difference from the user’s point of view between the two is that the ARP solution requires each node to be in a single L2 network (subnet), while BGP requires dynamic routing configuration on the upstream router.
Let’s apply this solution in the context of EKS Anywhere and practically view it’s benefit and usage.
Note: We will use the Layer 2 mode of MetalLB implementation for this scenario
Pre-requisite:
A working EKS Anywhere cluster either standalone or with a dedicated management cluster. It does not matter which model you use to deploy the cluster., at the end of the day we need a working EKS Anywhere cluster.
Note: As per the cluster creation process you should have ear-marked a set of static IP addresses (for control plane and for load balancer services). We will need those static IP addresses in this configuration
In my case the range of IP addresses used as static are 172.24.165.21 to 172.24.165.25 (yours could/will be different)
Step-1 Install MetalLB via the helm chart
Assuming our cluster name is testworkload01
source eks-anywhere/cluster-ops/switch-cluster.sh
clusterName: testworkload01
Once the above is done, the kubeconfig and context is set for the admin user targeting testworkload01 EKS Anywhere cluster
helm upgrade --install --wait --timeout 15m --namespace metallb-system --create-namespace --repo https://metallb.github.io/metallb metallb metallb
Release "metallb" does not exist. Installing it now.
W0711 06:55:51.507363 23991 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
W0711 06:55:51.510195 23991 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
W0711 06:55:51.606228 23991 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
W0711 06:55:51.607914 23991 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
NAME: metallb
LAST DEPLOYED: Mon Jul 11 06:55:48 2022
NAMESPACE: metallb-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
MetalLB is now running in the cluster.
Now you can configure it via its CRs. Please refer to the metallb official docs
on how to use the CRs.
Next we will use the Custom Resources to create the IP address pools and advertise them
cat <
Step-2 Deploy sample application and quick observations
Sample files for the load-balancer testing using a hello-world deployment are already placed inside of $HOME/eks-anywhere/hello-world sub-directory of the EKS-A administrative machine
kubectl apply -f hello-world-deployment.yaml
Once the pods are in running state
kubectl apply -f hello-world-service.yaml
The below logs indicate a sample execution and observation for the above commands in my scenario
cd /home/ubuntu/eks-anywhere/hello-world
kubectl apply -f hello-world-deployment.yaml
deployment.apps/hello-world created
kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-world-6df5659cb7-7hwxl 1/1 Running 0 88s
hello-world-6df5659cb7-gdzr7 1/1 Running 0 88s
kubectl create -f hello-world-service.yaml
service/hello-world created
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-world LoadBalancer 10.104.206.5 172.24.165.21 80:31965/TCP 5s
kubernetes ClusterIP 10.96.0.1 443/TCP 120m
kubectl describe svc hello-world
Name: hello-world
Namespace: default
Labels:
Annotations:
Selector: app=hello-world
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.104.206.5
IPs: 10.104.206.5
LoadBalancer Ingress: 172.24.165.21
Port: 80/TCP
TargetPort: 80/TCP
NodePort: 31965/TCP
Endpoints:
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal IPAllocated 2m22s metallb-controller Assigned IP ["172.24.165.21"]
kubectl logs metallb-controller-69bbb4669c-zwlb8 -n metallb-system
{"branch":"HEAD","caller":"level.go:63","commit":"v0.12.1","goversion":"gc / go1.16.14 / amd64","level":"info","msg":"MetalLB controller starting version 0.12.1 (commit v0.12.1, branch HEAD)","ts":"2022-05-09T05:25:40.010545729Z","version":"0.12.1"}
{"caller":"level.go:63","level":"info","msg":"secret succesfully created","op":"CreateMlSecret","ts":"2022-05-09T05:25:40.035930967Z"}
{"caller":"level.go:63","configmap":"metallb-system/metallb","event":"configLoaded","level":"info","msg":"config (re)loaded","ts":"2022-05-09T05:25:40.136808958Z"}
{"caller":"level.go:63","event":"stateSynced","level":"info","msg":"controller synced, can allocate IPs now","ts":"2022-05-09T05:25:40.137910533Z"}
{"caller":"level.go:63","event":"ipAllocated","ip":["172.24.165.21"],"level":"info","msg":"IP address assigned by controller","service":"default/hello-world","ts":"2022-05-09T06:50:06.082923965Z"}
{"caller":"level.go:63","event":"serviceUpdated","level":"info","msg":"updated service object","service":"default/hello-world","ts":"2022-05-09T06:50:06.094906055Z"}
>>>> As you can see from the output, the metalLB controller interacts with the kubernetes service component to allocate the IP to the exposed load-balancer service for hello-world" <<<<
As one can see from the above output, the service name hello-world gets an IP address of 172.24.165.21. This is due to the fact that my static IP ranges 172.21.165.21 to 172.24.165.25
In addition, one can also see from the service description how the MetalLB controller interacts with the Kubernetes control plane to assign the IP address and update the hello-world service.
Step-4 Observe MetalLB constructs
We can use the below gist to issue commands and observe the namespace, pods created after installing MetalLB. You can notice that the above installation creates one controller as a Deployment type pod and another 4 pods via a DaemonSet.
All these pods run in a dedicated namespace called metallb-system
kubectl get namespace
NAME STATUS AGE
capi-kubeadm-bootstrap-system Active 49m
capi-kubeadm-control-plane-system Active 49m
capi-system Active 49m
capv-system Active 49m
cert-manager Active 50m
default Active 52m
eksa-system Active 48m
etcdadm-bootstrap-provider-system Active 49m
etcdadm-controller-system Active 49m
kube-node-lease Active 52m
kube-public Active 52m
kube-system Active 52m
metallb-system Active 17m <<<<<<<<<<<<<<<<<<<
kubectl get deployments -n metallb-system
NAME READY UP-TO-DATE AVAILABLE AGE
metallb-controller 1/1 1 1 26m
kubectl get daemonset -n metallb-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
metallb-speaker 4 4 4 4 4 kubernetes.io/os=linux 27m
As you can see a new namespace called metallb-system has been created. Let's observe the pods in this namespace that form the operational context for metalLB.
As you can see below, one pod reflecting the controller component via a deployment and another 4 pods that form a part of the DaemonSet as seen above
kubectl get pods -n metallb-system
NAME READY STATUS RESTARTS AGE
metallb-controller-69bbb4669c-zwlb8 1/1 Running 0 17m
metallb-speaker-pfhdb 1/1 Running 0 17m
metallb-speaker-qxbp7 1/1 Running 0 17m
metallb-speaker-wsbls 1/1 Running 0 17m
metallb-speaker-zxc6q 1/1 Running 0 17m
An example log of the controller pod
kubectl logs metallb-controller-69bbb4669c-zwlb8 -n metallb-system
{"branch":"HEAD","caller":"level.go:63","commit":"v0.12.1","goversion":"gc / go1.16.14 / amd64","level":"info","msg":"MetalLB controller starting version 0.12.1 (commit v0.12.1, branch HEAD)","ts":"2022-05-09T05:25:40.010545729Z","version":"0.12.1"}
{"caller":"level.go:63","level":"info","msg":"secret succesfully created","op":"CreateMlSecret","ts":"2022-05-09T05:25:40.035930967Z"}
{"caller":"level.go:63","configmap":"metallb-system/metallb","event":"configLoaded","level":"info","msg":"config (re)loaded","ts":"2022-05-09T05:25:40.136808958Z"}
{"caller":"level.go:63","event":"stateSynced","level":"info","msg":"controller synced, can allocate IPs now","ts":"2022-05-09T05:25:40.137910533Z"}
The configuration map created as a part of the installation
kubectl get configmap -n metallb-system
NAME DATA AGE
kube-root-ca.crt 1 34m
metallb 1 34m
RBAC created as a part of the MetalLB installation
kubectl get serviceaccount -n metallb-system
NAME SECRETS AGE
default 1 35m
metallb-controller 1 35m
metallb-speaker 1 35m
kubectl get role -n metallb-system
NAME CREATED AT
metallb-config-watcher 2022-05-09T05:25:23Z
metallb-controller 2022-05-09T05:25:23Z
metallb-pod-lister 2022-05-09T05:25:23Z
kubectl get rolebinding -n metallb-system
NAME ROLE AGE
metallb-config-watcher Role/metallb-config-watcher 36m
metallb-controller Role/metallb-controller 36m
metallb-pod-lister Role/metallb-pod-lister 36m
We can easily observe the simplicity with which we can induce a software defined load balancer in a Kubernetes setup. That’s it for now. Hope you found the article insightful and easy to get started with deploying MetalLB on EKS Anywhere clusters
cheers
Ambar Hassani
#iwork4dell