Use MetalLB with Oracle Cloud Native Environment
Introduction
Network load balancers provide a method of externally exposing Kubernetes applications. A Kubernetes LoadBalancer service creates a network load balancer that provides and exposes an external IP address for connecting to an application from outside the cluster.
MetalLB is a network load balancer for Kubernetes applications deployed with Oracle Cloud Native Environment that runs on bare metal hosts. MetalLB allows you to use Kubernetes LoadBalancer services, which traditionally use a cloud provider's network load balancer, in bare metal environments.
Objectives
At the end of this tutorial, you should be able to set up and use the MetalLB module for Kubernetes applications using MetalLB and Oracle Cloud Native Environment.
Prerequisites
The free lab environment uses the following host systems:
6 Oracle Linux instances for Oracle Cloud Native Environment:
- Operator node (ocne-operator)
- 3 Kubernetes control plane nodes (ocne-control-01, ocne-control-02, ocne-control-03 )
- 2 Kubernetes worker nodes (ocne-worker-01, ocne-worker-02)
Note: We recommend that production environments have a cluster with at least five control plane nodes and three worker nodes.
A virtual IP address for the primary control plane node. Do not use this IP address on any of the nodes. The load balancer dynamically sets the IP address to the control plane node assigned as the primary controller.
Note: If you are deploying to Oracle Cloud Infrastructure, your tenancy requires enabling a new feature introduced in OCI: Layer 2 Networking for VLANs within your virtual cloud networks (VCNs). The OCI Layer 2 Networking feature is not generally available, although the free lab environment's tenancy enables this feature.
If you have a use case, please work with your technical team to get your tenancy listed to use this feature.Configure each system with the following:
- The latest Oracle Linux with the Unbreakable Enterprise Kernel Release 7 (UEK R7)
- An
oracle
user account withsudo
access - Key-based SSH, also known as passwordless SSH, between the instances
- Install Oracle Cloud Native Environment ready for creating the environment and installing modules
- Create a VLAN and assign IPv4 addresses
Set Up the Lab Environment
Note: When using the free lab environment, see Oracle Linux Lab Basics for connection and other usage instructions.
Important: The free lab environment deploys a fully installed Oracle Cloud Native Environment across the provided nodes. This deployment takes approximately 25-30 minutes to finish after launch. Therefore, you might want to step away while this runs and then return to complete the lab.
Open a terminal and connect via ssh to the ocne-operator node.
ssh oracle@<ip_address_of_operator_node>
Verify you can run the Kubernetes command line tool.
ssh ocne-control-01 kubectl get nodes
The
ssh
is required before thekubectl
command because thekubectl
utility installs on the control plane nodes as part of the free lab deployment. The output displays a list of the nodes, along with their status, role, and version.
Install the MetalLB Module
Open the firewall for MetalLB on each of the worker nodes.
for host in ocne-worker-01 ocne-worker-02 ocne-worker-03 do ssh $host "sudo firewall-cmd --zone=public --add-port=7946/tcp --permanent; sudo firewall-cmd --zone=public --add-port=7946/udp --permanent; sudo firewall-cmd --reload" done
Avoid using the
--api-server
flag in future olcnectl commands.Get a list of the module instances and add the
--update-config
flag.olcnectl module instances \ --config-file myenvironment.yaml \ --update-config
Create the MetalLB configuration file.
cat << 'EOF' | tee metallb-config.yaml apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: default namespace: metallb spec: addresses: - 10.0.12.240-10.0.12.250 --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: l2sample namespace: metallb spec: ipAddressPools: - default EOF
Deploy the MetalLB module.
olcnectl module create --environment-name myenvironment --module metallb --name mymetallb --metallb-kubernetes-module mycluster --metallb-config metallb-config.yaml olcnectl module install --environment-name myenvironment --name mymetallb
Show the installed modules.
olcnectl module instances --environment-name myenvironment
Example Output:
[oracle@ocne-operator ~]$ olcnectl module instances --environment-name myenvironment INSTANCE MODULE STATE mycluster kubernetes installed mymetallb metallb installed ...
Create a Kubernetes Application
In this section, you create a Kubernetes application that uses a LoadBalancer service.
Switch to the control-plane-01 node terminal session.
Create a Kubernetes application.
tee echo-oci-lb.yml > /dev/null << 'EOF' --- apiVersion: apps/v1 kind: Deployment metadata: name: echo-deployment labels: app: echo1 spec: replicas: 2 selector: matchLabels: app: echo1 template: metadata: labels: app: echo1 spec: containers: - name: echoserver image: k8s.gcr.io/echoserver:1.4 ports: - containerPort: 80 --- kind: Service apiVersion: v1 metadata: name: echo-lb-service spec: selector: app: echo1 type: LoadBalancer ports: - name: http port: 80 targetPort: 8080 EOF
Create the service.
kubectl apply -f echo-oci-lb.yml
Example Output:
[oracle@ocne-control-01 ~]$ kubectl apply -f echo-oci-lb.yml deployment.apps/echo-deployment created service/echo-lb-service created
Confirm the Kubernetes deployment is running.
kubectl get deployments
Example Output:
[oracle@ocne-control-01 ~]$ kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE echo-deployment 2/2 2 2 3m15s
Show the Kubernetes service is running.
kubectl get svc
Example Output:
[oracle@ocne-control-01 ~]$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo-lb-service LoadBalancer 10.111.72.49 10.0.12.240 80:31727/TCP 4m47s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 58m
Notice the
EXTERNAL-IP
for theecho-lb-service
LoadBalancer has an IP address of 10.0.12.240. MetalLB provides this IP address and is the external IP address that you can use to connect to the application.
Testing the Deployment
The next step is to test the newly deployed application. As the EXTERNAL-IP
value is dynamically provisioned by MetalLB (in this scenario between the range 10.0.12.240-10.0.12.250
), the first two steps store this dynamic value as operating system variables.
Capture the assigned
EXTERNAL-IP
address.LB=$(kubectl get svc -o jsonpath="{.status.loadBalancer.ingress[0].ip}" echo-lb-service)
Capture the port number assigned.
LBPORT=$(kubectl get svc -o jsonpath="{.spec.ports[0].port}" echo-lb-service)
Confirm the environment variables exist.
echo $LB echo $LBPORT
Example Output:
[oracle@ocne-control-01 ~]$ echo $LB 10.0.12.240 [oracle@ocne-control-01 ~]$ echo $LBPORT 80
Use
curl
to connect to the deployed application.curl -i -w "\n" $LB:$LBPORT
Example Output:
[oracle@ocne-control-01 ~]$ curl -i -w "\n" $LB:$LBPORT HTTP/1.1 200 OK Server: nginx/1.10.0 Date: Wed, 10 Aug 2022 10:52:10 GMT Content-Type: text/plain Transfer-Encoding: chunked Connection: keep-alive CLIENT VALUES: client_address=10.244.2.0 command=GET real path=/ query=nil request_version=1.1 request_uri=http://10.0.12.240:8080/ SERVER VALUES: server_version=nginx: 1.10.0 - lua: 10001 HEADERS RECEIVED: accept=*/* host=10.0.12.240 user-agent=curl/7.61.1 BODY: -no body in request-
Test From a Non-Kubernetes Host
Switch to the ocne-operator node terminal session.
This last test confirms that MetalLB is responding to external requests.
curl -v http://10.0.12.240:80
Example Output:
[oracle@ocne-operator ~]$ curl -v http://10.0.12.240:80 * Rebuilt URL to: http://10.0.12.240:80/ * Trying 10.0.12.240... * TCP_NODELAY set * Connected to 10.0.12.240 (10.0.12.240) port 80 (#0) > GET / HTTP/1.1 > Host: 10.0.12.240 > User-Agent: curl/7.61.1 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.10.0 < Date: Wed, 10 Aug 2022 11:38:08 GMT < Content-Type: text/plain < Transfer-Encoding: chunked < Connection: keep-alive < CLIENT VALUES: client_address=10.244.0.0 command=GET real path=/ query=nil request_version=1.1 request_uri=http://10.0.12.240:8080/ SERVER VALUES: server_version=nginx: 1.10.0 - lua: 10001 HEADERS RECEIVED: accept=*/* host=10.0.12.240 user-agent=curl/7.61.1 BODY: * Connection #0 to host 10.0.12.240 left intact
Summary
These results confirm the successful configuration of MetalLB and the ability to accept application requests.