Configuring MetalLB and NGINX for Federal Frontier API Services

Understanding the Networking in Kubernetes with MetalLB and NGINX Ingress

Setup Environment

Kubernetes Configuration

To get started, ensure that Kubernetes has been config into your local machine. An example would be:

export KUBECONFIG=~/.kube/bamboo-config.yaml

Application Service Port Setup

Once you have configured Kubernetes in your local machine, you would want to start choosing which application you would like to implement an ingress controller on. For this example, I will be utilizing Federal Frontier API Services. Therefore, within Kubernetes, you would want to make sure the application is able to serve ports. For Federal Frontier at the time of this documentation, it is built to serve on port 8080.

Federal Frontier API Services serving on port 8080

Federal Frontier API Services serving on port 8080

Create Namespaces

You will want to create two namespaces within Kubernetes. One will be for MetalLB and the other will be for Ingress-NGINX.

kubectl create namespace metallb-system
kubectl create namespace ingress-nginx

With these creations, we will install each of the two within their respective namespaces.

Install Metallb

You can install MetalLB through a couple commands. We will be doing this installation through Helm3. If Helm3 is not installed, be sure to visit their installation page from their documentation website.

Step 1: Begin by navigating into the metallb-system Kubernetes namespace. Be sure kubectx into your local machine.

kubens metallb-system

Step 2: Once you’re in the metallb-system namespace, add MetalLB into your Helm repository.

helm repo add metallb https://metallb.github.io/metallb

Step 3: After the download is complete, install MetalLB into Kubernetes.

helm install metallb metallb/metallb

Install Ingress-NGINX

Ingress Conceptual Diagram

Ingress Conceptual Diagram

Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster. Traffic routing is controlled by rules defined on the Ingress resource. The figure above is a simple example where an Ingress sends all its traffic to one service. An Ingress may be configured to give Services externally-reachable URLs, load balance traffic, terminate SSL / TLS, and offer name-based virtual hosting. An Ingress controller is responsible for fulfilling the Ingress, usually with a load balancer, though it may also configure your edge router or additional frontends to help handle the traffic. An Ingress does not expose arbitrary ports or protocols. Exposing services other than HTTP and HTTPS to the internet typically uses a service of type Service.Type=NodePort or Service.Type=LoadBalancer.

For Ingress-NGINX installation, we will be using Helm3 similarily utilized when installing MetalLB.

Step 1: Begin by now navigating into the ingress-nginx Kubernetes namespace.

kubens ingress-nginx

Step 2: Once you’re in the ingress-nginx namespace, add Ingress-NGINX into your Helm repository.

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

Step 3: Update the chart repo.

helm repo update

Step 4: After all downloads and updates are complete, install Ingress-NGINX into Kubernetes.

helm install ingress-controller ingress-nginx/ingress-nginx

NOTE: If you wish to use a different helm release name other than ingress-controller from the command above, you must mirror this change to all other locations where the helm release name resides throughout this tutorial.

Configure MetalLB and Ingress-NGINX for Services

MetalLB and Ingress-NGINX Implementation Diagram

MetalLB and Ingress-NGINX Implementation Diagram

The figure above demonstrates a diagram over the implemenation of MetalLB and Ingress-NGINX for back-end services (for this example: Federal Frontier API Services). Configuration for Ingress-NGINX depends on MetalLB Load Balancer when you are configuring ingress on-premise. All of these components rely on IPAddressPool. In order to advertise the IP coming from an IPAddressPool, an L2Advertisement instance must be associated to the IPAddressPool. In these next steps, we will establish the IPAddressPool for communication between MetalLB and Ingress-NGINX.

Step 1: Navigate to the metallb-system namespace within Kubernetes.

kubens metallb-system

Step 2: Within your local machine, create a ipaddpool-config.yaml and paste this manifest. Note: You can name the .yaml file to your preference.

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: l2-ip
  namespace: metallb-system
spec:
  ipAddressPools:
  - single-ip
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: single-ip
  namespace: metallb-system
spec:
  addresses:
  - 192.168.1.254/32

Step 3: Apply this manifest into Kubernetes within your metallb-system namespace.

kubectl apply -f idaddpool-config.yaml

Step 4: Get ipaddresspool within your metallb-system Kubernetes namespace to confirm the address pool configuration.

kubectl get ipaddresspool -n metallb-system

Step 5: Navigate to your ingress-nginx Kubernetes namespace to begin configuration for Ingress-NGINX with MetalLB Load Balancer.

kubens ingress-nginx

Step 6: Within your local machine, create a nginx-service.yaml and paste this manifest. Note: You can name the .yaml file to your preference.

apiVersion: v1
kind: Service
metadata:
  annotations:
    meta.helm.sh/release-name: ingress-controller
    meta.helm.sh/release-namespace: ingress-nginx
    metallb.universe.tf/address-pool: single-ip 
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-controller
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.3.0
    helm.sh/chart: ingress-nginx-4.2.1
  name: ingress-controller-ingress-nginx-controller
  namespace: ingress-nginx
spec:
  externalTrafficPolicy: Local
  ports:
  - name: http
    port: 8080
    protocol: TCP
    targetPort: http
  - name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-controller
    app.kubernetes.io/name: ingress-nginx
  sessionAffinity: None
  type: LoadBalancer

Step 7: Apply this manifest into Kubernetes within your ingress-nginx namespace.

kubectl apply -f nginx-service.yaml

Step 8: Confirm changes by getting your service in your ingress-controller in a yaml format to find metallb.universe.tf/address-pool: single-ip within metadata annotations. You can run the following command below to view the yaml of the service.

kubectl get svc ingress-controller-ingress-nginx-controller -o yaml

Step 9: By this step, when you get the services within your ingress-nginx Kubernetes namespace, you should receive an output such as this response below.

NAME                                                    TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                        AGE
ingress-controller-ingress-nginx-controller             LoadBalancer   10.107.123.3    <pending>       8080:32402/TCP,443:32702/TCP   2d

Notice EXTERNAL-IP is still in a pending state. To allow the service to find and connect to an external IP, you will need to configure ingress to your application within Kubernetes. Start by navigating to your application’s namespace. For this example, we will navigate to Federal Frontier API Services’ Kubernetes namespace.

kubens frontier

Step 10: Within your local machine, create a ingress-app-config.yaml and paste these contents inside of your manifest. Note: You can name the .yaml file to your preference.

NOTE: Keep in mind, you will need to have a host domain available in order to apply this manifest to utilize Ingress-NGINX.

apiVersion: v1
items:
- apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    annotations:
      kubectl.kubernetes.io/last-applied-configuration: |
        {"apiVersion":"networking.k8s.io/v1","kind":"Ingress","metadata":{"annotations":{"kubernetes.io/ingress.class":"nginx"},"creationTimestamp":"2022-08-05T21:08:12Z","generation":1,"name":"federal-frontier-api-service","namespace":"frontier","resourceVersion":"35503249","uid":"2a599a8c-f831-4298-9267-914d8cf42814"},"spec":{"rules":[{"host":"fas.eupraxialabs.com","http":{"paths":[{"backend":{"service":{"name":"frontier-api","port":{"number":8080}}},"path":"/","pathType":"ImplementationSpecific"}]}}]}}
      kubernetes.io/ingress.class: nginx
    creationTimestamp: "2022-08-05T21:08:12Z"
    generation: 8
    name: federal-frontier-api-service
    namespace: frontier
    resourceVersion: "36083984"
    uid: 2a599a8c-f831-4298-9267-914d8cf42814
  spec:
    rules:
    - host: fas.eupraxialabs.com
      http:
        paths:
        - backend:
            service:
              name: frontier-api
              port:
                number: 8080
          path: /
          pathType: ImplementationSpecific
  status:
    loadBalancer:
      ingress:
      - ip: 192.168.1.254
kind: List
metadata:
  resourceVersion: ""

Step 11: Apply this manifest into Kubernetes within your application’s namespace.

kubectl apply -f ingress-app-config.yaml

Step 12: Confirm these changes by inputting this command within your application’s Kubernetes namespace.

kubectl get ingress

Step 13: With all the configurations you made within Kubernetes throughout these steps, you should now possess and external IP for your ingress controller service within your ingress-nginx Kubernetes namespace. Confirm by inputting the command below. You should be able to see a similar response such as that provided in this example.

kubectl get svc ingress-controller-ingress-nginx-controller 

NAME                                          TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                        AGE
ingress-controller-ingress-nginx-controller   LoadBalancer   10.107.123.3   192.168.1.254   8080:32402/TCP,443:32702/TCP   2d

If you no longer see your external IP in a pending state and your service has been configured to your desired address, then congratulations! You are now finished with configuring MetalLB and Ingress-NGINX to your application in Kubernetes!