×

As an OKD system administrator, you can gain insights into the operational status of your MetalLB deployments by examining the status of its custom resources (CRs). These status fields provide information about IP address allocations, BGP peer announcements, and session states, which are important for effective monitoring and troubleshooting.

For more information about how to install the MetalLB Operator, see About MetalLB and the MetalLB Operator.

Understanding MetalLB status custom resources

MetalLB provides a scalable framework for monitoring the health of network traffic and IP addresses. Use status fields in MetalLB custom resources to track session status and troubleshoot configuration.

MetalLB exposes status information for several key components, providing a comprehensive view of its configuration and operation.

Table 1. MetalLB status resources
Resource Description Troubleshooting command

IPAddressPool (status field)

Shows the cluster-wide allocation and availability of IP addresses within a defined pool, including the number of assigned and available addresses for both IPv4 and IPv6.

oc get ipaddresspool <IPAddressPool-name> -n metallb-system -o yaml

ServiceBGPStatus

Shows which service IP addresses the system announces to specific BGP peers across the network infrastructure.

oc get servicebgpstatus -n metallb-system

BGPSessionStatus

Shows the real-time operational state of the border gateway protocol (BGP) and bidirectional forwarding detection (BFD) sessions between a specific cluster node and a BGP peer, indicating if the channel is Established or Up based on routing stack feedback.

oc get bgpsessionstatus -o wide

The MetalLB controller, typically deployed as metallb-system/controller, is responsible for managing IP address assignments and updating the IPAddressPool status. When a service requests a LoadBalancer IP, the controller allocates an IP from an appropriate IPAddressPool and updates the status fields to reflect the current number of assigned and available IP addresses.

Viewing the IPAddressPool status

Check IP address allocation from your MetalLB pools by viewing the IPAddressPool status. This status shows the number of addresses assigned to services and the number remaining available for assignment.

As a cluster administrator, you can add address pools to your cluster to control the IP addresses that MetalLB can assign to load-balancer services. This example shows how to create an IPAddressPool custom resource (CR) and view its status. The configuration sets the advertisement mode to Layer 2 (L2).

Prerequisites
  • You have an OKD cluster with the MetalLB Operator installed.

  • You have deployed a MetalLB instance.

Procedure
  1. Create an IP address pool.

    1. Create a file, named for example ipaddresspool.yaml, with content such as the following:

      apiVersion: metallb.io/v1beta1
      kind: IPAddressPool
      metadata:
        name: doc-example-l2
        namespace: metallb-system
      spec:
        addresses:
        - 192.168.122.200-192.168.122.220
        autoAssign: true
        avoidBuggyIPs: false
    2. Apply the configuration for the IP address pool:

      $ oc apply -f ipaddresspool.yaml
  2. View the status of the IP address pool by running the following command:

    $ oc get ipaddresspool doc-example-l2 -n metallb-system -o yaml

    The output is similar to the following:

    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"metallb.io/v1beta1","kind":"IPAddressPool","metadata":{"annotations":{},"name":"doc-example-l2","namespace":"metallb-system"},"spec":{"addresses":["192.168.122.200-192.168.122.220"],"autoAssign":true,"avoidBuggyIPs":false}}
      creationTimestamp: "2025-07-17T10:13:37Z"
      generation: 1
      name: doc-example-l2
      namespace: metallb-system
      resourceVersion: "29080"
      uid: 8df1c303-03ac-4d31-8970-6dacdb173dc2
    spec:
      addresses:
      - 192.168.122.200-192.168.122.220
      autoAssign: true
      avoidBuggyIPs: false
    status:
      assignedIPv4: 0
      assignedIPv6: 0
      availableIPv4: 21
      availableIPv6: 0
    • assignedIPv4 represents the total number of IPv4 addresses that MetalLB has successfully assigned from this pool to LoadBalancer services.

    • assignedIPv6 represents the total number of IPv6 addresses that MetalLB has successfully assigned from this pool to LoadBalancer services.

    • availableIPv4 indicates the total number of IPv4 addresses remaining and available for assignment within this pool. MetalLB calculates this value by subtracting assignedIPv4 from the total theoretical IPv4 addresses in the spec.addresses ranges, potentially accounting for avoidBuggyIPs if enabled.

    • availableIPv6 indicates the total number of IPv6 addresses remaining and available for assignment within this pool. The system calculates this value similarly to availableIPv4, using the total theoretical IPv6 addresses in the spec.addresses ranges.

  3. Create an L2Advertisement CR for Layer 2 mode with the following sample YAML:

    apiVersion: metallb.io/v1beta1
    kind: L2Advertisement
    metadata:
      name: l2advertisement
      namespace: metallb-system
    spec:
      ipAddressPools:
      - doc-example-l2
    1. Apply the configuration for the L2 advertisement by running the following command:

      $ oc apply -f l2advertisement.yaml
  4. Deploy an application and expose it with a LoadBalancer service.

    1. Create a file, like nginx.yaml, with the following content to deploy an Nginx application:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: nginx-deployment
        labels:
          app: nginx
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - name: nginx
              image: quay.io/openshifttest/hello-openshift:multiarch
              ports:
              - containerPort: 8080
    2. Apply the configuration by running the following command:

      $ oc apply -f nginx.yaml
    3. Expose the deployment as a LoadBalancer service by creating a file, such as nginx-service.yaml, with content like the following:

      apiVersion: v1
      kind: Service
      metadata:
        name: nginx-service
        namespace: default
        annotations:
          metallb.universe.tf/address-pool: doc-example-l2
      spec:
        selector:
          app: nginx
        ports:
          - protocol: TCP
            port: 80
            targetPort: 8080
        type: LoadBalancer

      The service must be in the same namespace as your application deployment. The metallb.universe.tf/address-pool annotation tells MetalLB which IPAddressPool to use for IP allocation.

    4. Apply the service configuration by running the following command:

      $ oc apply -f nginx-service.yaml
  5. View the updated IPAddressPool status to see the assigned and available IP addresses by running the following command:

    $ oc get ipaddresspool doc-example-l2 -n metallb-system -o yaml

    The output is similar to the following:

    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"metallb.io/v1beta1","kind":"IPAddressPool","metadata":{"annotations":{},"name":"doc-example-l2","namespace":"metallb-system"},"spec":{"addresses":["192.168.122.200-192.168.122.220"],"autoAssign":true,"avoidBuggyIPs":false}}
      creationTimestamp: "2025-07-17T10:13:37Z"
      generation: 1
      name: doc-example-l2
      namespace: metallb-system
      resourceVersion: "30250"
      uid: 8df1c303-03ac-4d31-8970-6dacdb173dc2
    spec:
      addresses:
      - 192.168.122.200-192.168.122.220
      autoAssign: true
      avoidBuggyIPs: false
    status:
      assignedIPv4: 1
      assignedIPv6: 0
      availableIPv4: 20
      availableIPv6: 0

    The assignedIPv4 value of 1 indicates that one IPv4 address from this pool has been successfully assigned by MetalLB to your nginx-service LoadBalancer.

Viewing the ServiceBGPStatus custom resource

You can verify border gateway protocol (BGP) advertisement status for your services by viewing the ServiceBGPStatus custom resource, which shows which BGP peers receive advertisements from each node. This is essential for debugging connectivity in telco environments.

The ServiceBGPStatus CR reports the BGP peering status for a service, detailing which neighbors are receiving updates from a specific node.

ServiceBGPStatus resources are created in the metallb-system namespace, not in the namespace where your LoadBalancer service is deployed. Always query these resources with -n metallb-system.

Prerequisites
  • You have an OKD cluster with the MetalLB Operator installed.

  • You have deployed a MetalLB instance.

This example shows how to configure MetalLB for BGP mode, deploy a service, and view the ServiceBGPStatus to verify BGP advertisements.

Procedure
  1. Create an IPAddressPool CR for BGP, like the following example, and save it as ipaddresspool.yaml:

    apiVersion: metallb.io/v1beta1
    kind: IPAddressPool
    metadata:
      name: bgp-pool
      namespace: metallb-system
    spec:
      addresses:
      - 192.168.122.210-192.168.122.220
      autoAssign: true
  2. Run the following command to create the IPAddressPool configuration:

    $ oc apply -f ipaddresspool.yaml
  3. To configure a BGP peer, create a file named bgppeer.yaml with the following content:

    apiVersion: metallb.io/v1beta2
    kind: BGPPeer
    metadata:
      name: bgp-peer
      namespace: metallb-system
    spec:
      myASN: 64501
      peerASN: 64500
      peerAddress: 192.168.1.1
    • Set the spec:peerAddress field to the IP address of your BGP router.

  4. Apply the BGPPeer configuration by running the following command:

    $ oc apply -f bgppeer.yaml
  5. To create a BGP advertisement to advertise the pool, create a file named bgpadvertisement.yaml with the following content:

    apiVersion: metallb.io/v1beta1
    kind: BGPAdvertisement
    metadata:
      name: bgp-advertisement
      namespace: metallb-system
    spec:
      ipAddressPools:
      - bgp-pool
  6. Apply the BGPAdvertisement configuration by running the following command:

    $ oc apply -f bgpadvertisement.yaml
  7. Deploy an application and expose it with a LoadBalancer service. For this example, create a simple test application named for example test-app by creating a file named deployment.yaml with the following content:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: test-app
      namespace: default
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: test-app
      template:
        metadata:
          labels:
            app: test-app
        spec:
          containers:
          - name: test-app
            image: quay.io/openshifttest/hello-openshift:multiarch
            ports:
            - containerPort: 8080
  8. Apply the deployment:

    $ oc apply -f deployment.yaml
  9. Create a LoadBalancer service for the application:

    apiVersion: v1
    kind: Service
    metadata:
      name: test-service
      namespace: default
    spec:
      selector:
        app: test-app
      ports:
        - protocol: TCP
          port: 80
          targetPort: 8080
      type: LoadBalancer

    The system creates ServiceBGPStatus resources automatically only when the service has at least one ready endpoint (running pod). Ensure your application pods are running before checking for ServiceBGPStatus resources.

  10. Apply the service configuration by running the following command:

    $ oc apply -f service.yaml
  11. Verify the service received an external IP by running the following command:

    $ oc get svc test-service -n default

    The output is similar to the following:

    NAME           TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)        AGE
    test-service   LoadBalancer   172.30.116.108   192.168.122.210   80:32431/TCP   2m
  12. View the ServiceBGPStatus resources by running the following command:

    $ oc get servicebgpstatus -n metallb-system

    The output is similar to the following:

    NAME                  NODE       SERVICE NAME   SERVICE NAMESPACE
    bgp-xxxxx             worker0    test-service   default

    ServiceBGPStatus resources are created with generated names. Use labels to find the status for your service:

    $ oc get servicebgpstatus -n metallb-system -l metallb.io/service-name=test-service
  13. View the details of the ServiceBGPStatus CR for your service:

    $ oc get servicebgpstatus bgp-xxxxx -n metallb-system -o yaml

    The output is similar to the following:

    apiVersion: metallb.io/v1beta1
    kind: ServiceBGPStatus
    metadata:
      name: bgp-xxxxx
      namespace: metallb-system
      labels:
        metallb.io/node: worker0
        metallb.io/service-name: test-service
        metallb.io/service-namespace: default
    status:
      node: worker0
      peers:
      - bgp-peer
      serviceName: test-service
      serviceNamespace: default
    • metadata.labels.metallb.io/node indicates the node that is advertising the service via BGP.

    • metadata.labels.metallb.io/service-name identifies the service being advertised.

    • metadata.labels.metallb.io/service-namespace identifies the namespace of the service being advertised.

    • status.node confirms the name of the node advertising the service.

    • status.peers lists the names of the BGPPeer resources to which the service is being advertised. This is useful for confirming that the advertisement is reaching the intended peers.

    • status.serviceName indicates the name of the service being advertised.

    • status.serviceNamespace indicates the namespace of the service being advertised.

Verifying BGP session state

Once you configure MetalLB for border gateway protocol (BGP) mode, you can verify that the system has established BGP sessions and is advertising routes. You can examine the BGPSessionStatus custom resource (CR) and the FRRNodeState CR to troubleshoot BGP connectivity and confirm proper route advertisement.

The BGPSessionStatus CR is updated at a regular poll interval of 2 minutes. It can take up to 2 minutes for the CR to reflect the actual BGP state.

Prerequisites
  • You have an OKD cluster with the MetalLB Operator installed.

  • You have configured MetalLB for BGP mode with:

    • An IPAddressPool

    • A BGPPeer configuration

    • A BGPAdvertisement

  • You have deployed at least one LoadBalancer service.

Procedure
  1. Check BGP session status by running the following command:

    $ oc get bgpsessionstatus -o wide

    This example output shows the BGP session status between each node and its configured BGP peers. Look for the State column to confirm that the session is Established.

    NAMESPACE        NAME               NODE       PEER         VRF   BGP           BFD
    frr-k8s-system   worker-2gjfq   	worker     10.89.0.64         Active        N/A
    frr-k8s-system   worker-9gtnb    	worker     10.89.0.63         Established   N/A
    frr-k8s-system   worker2-rknga  	worker2    10.89.0.66         Established   Up
    frr-k8s-system   worker2-t7bfc  	worker2    172.30.0.2         Established   Down
  2. Check FRRNodeState to see the BGP configuration on each node by running the following command:

    $ oc get frrnodestate -n metallb-system

    The example output lists the FRRNodeState resources for each node where the MetalLB speaker is running.

    NAME                 AGE
    worker0.example.com  5m
  3. View the detailed BGP configuration and running state by running the following command for a specific node:

    $ oc get frrnodestate worker0.example.com -n metallb-system -o yaml

    The status.runningConfig field shows the FRR BGP configuration including configured BGP neighbors, route advertisements, and prefix lists.

  4. Verify that the system is advertising routes by checking the FRRNodeState resource for the relevant node with this command:

    $ oc get frrnodestate _<node-name>_ -n metallb-system -o jsonpath='{.status.runningConfig}' | grep "network"

    The output displays the network prefixes that BGP advertises. For example:

     address-family ipv4 unicast
      network 192.168.122.210/32

    This confirms that BGP is advertising the service IP.