> ## Documentation Index
> Fetch the complete documentation index at: https://www.latitude.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Load balancing with MetalLB and Cloudflare

> Set up a load balancer to distribute incoming traffic to the apps running on your Kubernetes cluster

The instructions here should work for any Kubernetes distro running on bare metal. If you don't have a cluster yet, start by [deploying one](/guides/kubernetes-on-bare-metal).

***

Running a Kubernetes cluster on bare metal is great, but you need a way to distribute incoming traffic to your applications. This is where a load balancer comes in. A load balancer is a service that distributes incoming network traffic across multiple servers. It ensures that no single server becomes overwhelmed with traffic, and it can help improve the performance and reliability of your applications.

In this guide, we'll show you how to set up a load balancer for your Kubernetes cluster on bare metal. We'll use Cloudflare for DNS and load balancing, but you can use any load balancer you want, like Nginx or HAProxy.

## Requirements

* [Cloudflare account](https://dash.cloudflare.com) for DNS and load balancing
* [Kubernetes cluster](/guides/kubernetes-on-bare-metal) deployed on Latitude.sh

## Getting started

To distribute traffic to the applications on your Kubernetes cluster, you first need to expose a service that acts as a load balancer — note that this is different from the load balancer we'll set up for DNS.

For bare metal, [MetalLB](https://metallb.universe.tf/) is a great option. MetalLB is a stable and reliable service for Kubernetes load balancing. Let's get started.

## Install MetalLB

<Steps>
  <Step title="Install with Helm">
    Use Helm to install MetalLB. Refer to MetalLB's [installation guide](https://metallb.universe.tf/installation/#installation-with-helm) for up to date instructions.
  </Step>

  <Step title="Create an IPAddressPool">
    An `IPAddressPool` is a range of IP addresses that MetalLB will use to assign IP addresses to the load balancer services. You can use your own server's IP addresses or [get additional IPs](/networking/ips#additional-ips) if you prefer.

    The IPAddressPool requires an IP range, but we can also add the IPs of our worker nodes, which isn't the best for a production environment but not a different process from doing with additional IPs.

    So let's say our Kubernetes worker nodes IPs are `160.202.129.150`, `160.202.145.233`, and `197.187.133.133`. Make note of these IPs and create a file named `ipaddresspool.yaml` on your local machine.

    Each Latitude.sh server has its own /31 VLAN, so we need to create an IPAddressPool for each server. Make sure to replace the IP addresses with the IPs of your worker nodes.

    ```yaml theme={null}
    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: first-pool
      namespace: metallb-system
    spec:
      addresses:
        - 160.202.129.150-160.202.129.150
    ---
    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: second-pool
      namespace: metallb-system
    spec:
      addresses:
        - 160.202.145.233-160.202.145.233
    ---
    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: third-pool
      namespace: metallb-system
    spec:
      addresses:
        - 197.187.133.133-197.187.133.133
    ```

    Then apply to your cluster.

    ```sh theme={null}
    kubectl apply -f ipaddresspool.yaml
    ```
  </Step>

  <Step title="Create L2Advertisements">
    After creating the IPAddressPool, we need to create an L2Advertisement to announce the IP addresses to the network. Create a file named `l2advertisement.yaml` with the following content.

    ```yaml theme={null}
    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: first-pool-advertisement
      namespace: metallb-system
    spec:
      ipAddressPools:
      - first-pool
      nodeSelectors:
      - matchLabels:
          kubernetes.io/hostname: node1

    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: second-pool-advertisement
      namespace: metallb-system
    spec:
      ipAddressPools:
      - second-pool
      nodeSelectors:
      - matchLabels:
          kubernetes.io/hostname: node2

    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: third-pool-advertisement
      namespace: metallb-system
    spec:
      ipAddressPools:
      - third-pool
      nodeSelectors:
      - matchLabels:
          kubernetes.io/hostname: node3
    ```

    And apply it

    ```sh theme={null}
    kubectl apply -f l2advertisement.yaml
    ```
  </Step>

  <Step title="Make sure everything is working">
    To make sure everything is working, you can create a service and a deployment and see if the load balancer is distributing traffic to the pods. Here's an example of a service and a deployment for nginx.

    ```yaml theme={null}
    apiVersion: v1
    kind: Service
    metadata:
      name: my-service
    spec:
      type: LoadBalancer
      selector:
        app: MyApp
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
    ```

    If everything is working, you should be able to access the service from outside the cluster by visiting the IP address of the load balancer.
  </Step>
</Steps>

## Setup Cloudflare DNS

Now that we have a load balancer, we need to set up Cloudflare DNS to point to the load balancer. We have two options:

1. Create a DNS record that points to all the IPs of the load balancer.
2. Create a DNS record through Cloudflare's load balancer service.

For the purpose of this guide, we'll go with the second option.

<Steps>
  <Step title="Create load balancer service">
    From your Cloudflare dashboard, go to the **Traffic > Load Balancing** section and click on "Create Load Balancer".
  </Step>

  <Step title="Set the load balancer settings">
    * Hostname: choose a hostname for your service. E.g., `k8s-guide.my-domain.com`.
    * Endpoints: create and add a pool with the IPs of your Kubernetes worker nodes. You don't need a fallback pool.

    Everything else is optional and can be changed later to your liking.
  </Step>
</Steps>

## That's it!

You should now be able to access services from outside the cluster with MetalLB as the load balancer for application traffic and Cloudflare for DNS.
