MetalLB is used as LoadBalancer- BGP in Kubernetes cluster

In the previous article Using MetalLB as LoadBalancer in Kubernetes cluster (Part 1) In, we use MetalLB's Layer2 pattern as the implementation of LoadBalancer to expose the services in Kubernetes cluster outside the cluster.

Remember the IP address pool we assigned to MetalLB in Configmap?

apiVersion: v1
kind: ConfigMap
  namespace: metallb-system
  name: config
  config: |
    - name: default
      protocol: layer2

The IP segment allocated here happens to be in the author's home network. When we use, we can successfully access the service.

When I mentioned the disadvantages of Layer2 before, I also missed one point. In addition to the impact on availability and single point network bottleneck during failover, the client needs to be located in the same subnet as the address pool (if the address pool is changed to, the service will not be accessible). However, in the experimental environment or homelab environment like the author, the first two are not problems, and the latter is a little troublesome in network configuration.

Although the disadvantages are obvious, Layer2 mode has stronger universality. Unlike BGP mode, it needs to support BGP routing. However, these can not stop the author's exploration (strong) cable (compulsive) desire (disease), because there is also an OpenWrt soft route running in My Proxmox virtual machine Yes. This OpenWrt provides external routing services in the form of soft routing through, and supports BGP by installing routing software suite.

Before we start, let's take a look at what BPG is and related terms. Students who already know or feel too abstract can skip directly and look back after reading the demo.

What is BGP

BGP is the abbreviation of Border Gateway Protocol.

Border gateway protocol is a core decentralized autonomous routing protocol on the Internet. It realizes the reachability between autonomous systems (AS) by maintaining IP routing table or "prefix" table. It belongs to vector routing protocol. BGP does not use the indicators of traditional internal gateway protocol (IGP), but uses routing based on path, network policy or rule set. Therefore, it is more suitable to be called vector protocol than routing protocol.

The neighbor relationship of BGP (or communication peer / peer entity, peer) is realized through manual configuration. The peer entities establish a session to exchange data through TCP port 179. The BGP router will periodically send 19 bytes of keep alive messages to maintain the connection (the default cycle is 60 seconds). Among various routing protocols, only BGP uses TCP as the transport layer protocol.

BGP running between two or more peer entities in the same AS autonomous system is called iBGP (internal / internal BGP). BGP running between peer entities belonging to different AS is called eBGP (external / external BGP). The router that exchanges information with other AS on the AS boundary is called border/edge router, and the border routers are eBGP opposite ends to each other. In Cisco IOS, the route distance advertised by iBGP is 200, and the priority is lower than that advertised by eBGP and any internal gateway protocol (IGP). In other router implementations, the priority order is that eBGP is higher than IGP, and IGP is higher than iBGP. The main difference between Mar 6, 2022Mar 6, 2022 iBGP and eBGP is the behavior of forwarding routing information. For example, the routing information obtained from eBGP peers will be distributed to all iBGP peers and eBGP peers, but the routing information obtained from iBGP peers will only be distributed to all eBGP peers. All iBGP peers need to be fully interconnected.

Three terms are mentioned here: autonomous system (AS), internal gateway protocol (IGP) and external gateway protocol (EGP).

Autonomous system AS

Let's take a look at the introduction from Wikipedia:

The combination of self-made router and Internet system refers to the combination of self-made router and Internet system. Autonomous system numbers are 16 bit integers, which can be assigned to up to 65536 autonomous systems. The autonomous system number is divided into two ranges. The first range is the public AS N, from 1 to 64511, which can be used on the Internet; The second range is those from 64512 to 65535 called private numbers, which can only be used within an organization's own network.

In short, China Telecom, China Mobile and China Unicom all have their own AS numbers, and there is more than one. If you are interested, you can check the AS numbers in Wikipedia China Internet backbone network Entry.

In addition to the ASN publicly available on the Internet, private numbers can be used internally. For example, I can create several AS using private numbers in my home network.

Internal routing protocol IGP

Quoting from encyclopedia is not the focus of this article, so I won't introduce it too much.

Internal gateway protocol (IGP) refers to a routing protocol used within an autonomous system (AS).

External gateway protocol EGP

External gateway protocol (EGP) is an outdated Internet routing protocol. Replaced by BPG.

Origin of BPG

BPG is created to replace EGP, and can be applied not only outside the AS, but also inside the AS. Therefore, it is divided into EBGP and IBGP.

Having said so much, it may be a little abstract. Go directly to the demo.


The environment is the same AS before. According to the pre assumption, we want to create two AS: 65000 and 65001< u> The former is the AS where the router and client are located, while the latter is the AS where our cluster service LoadBalancer IP is located < / u >.

We need to make OpenWrt support BGP first.

OpenWrt supports BGP

In order to make OpenWrt support BGP, the routing software suite is used here Quagga . Quagga provides the implementation of OSPFv2, OSPFv3, RIP v1 v2, RIPng and BGP-4.

Quagga architecture consists of core daemon and zebra, which serves as the abstraction layer of the underlying Unix kernel and provides Zserv API to quagga clients through Unix or TCP. It is these Zserv clients that implement the routing protocol and send the routing updates to the zebra daemon. The current implementation of Zserv is:

Quagga's daemon can be configured through a network accessible cli (vty). The CLI follows a similar style to other routing software. An additional tool vtysh is provided, which acts as the aggregation front end of all daemons, allowing all functions of all quagga daemons to be managed in one place.

Execute the following command to complete the installation:

$ opkg update && opkg install quagga quagga-zebra quagga-bgpd quagga-vtysh

After successful installation, it will automatically start and listen to the port:

$ netstat -lantp | grep -e 'zebra\|bgpd'
tcp        0      0  *               LISTEN      2984/zebra
tcp        0      0  *               LISTEN      3000/bgpd
tcp        0      0 :::2601                 :::*                    LISTEN      2984/zebra
tcp        0      0 :::2605                 :::*                    LISTEN      3000/bgpd

The 179 port that bpgd listens to for receiving routing information is not seen here, because the route has not been assigned AS yet. Don't worry, let's use the command vtysh to enter vty for configuration:

$ vtysh
OpenWrt# conf t
OpenWrt(config)# router bgp 65000
OpenWrt(config-router)# neighbor remote-as 65001
OpenWrt(config-router)# neighbor description ubuntu-dev1
OpenWrt(config-router)# neighbor remote-as 65001
OpenWrt(config-router)# neighbor description ubuntu-dev2
OpenWrt(config-router)# exit
OpenWrt(config)# exit

Use the show ip bgp summary command in vty to view:

OpenWrt# show ip bgp summary
BGP router identifier, local AS number 65000
RIB entries 0, using 0 bytes of memory
Peers 2, using 18 KiB of memory

Neighbor        V         AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd     4 65001       0       0        0    0    0 never    Active     4 65001       0       0        0    0    0 never    Active

Total number of neighbors 2

Total num. Established sessions 0
Total num. of routes received     0

At this point, we can see that bgpd is already monitoring port 179 by checking port monitoring:

$ netstat -lantp | grep -e 'zebra\|bgpd'
tcp        0      0   *               LISTEN      3000/bgpd
tcp        0      0  *               LISTEN      2984/zebra
tcp        0      0  *               LISTEN      3000/bgpd
tcp        0      0 :::179                  :::*                    LISTEN      3000/bgpd
tcp        0      0 :::2601                 :::*                    LISTEN      2984/zebra
tcp        0      0 :::2605                 :::*                    LISTEN      3000/bgpd

After the BGP route is set, it is part of MetalLB.

MetalLB BGP mode

Let's update the configmap:

apiVersion: v1
kind: ConfigMap
  namespace: metallb-system
  name: config
  config: |
    - peer-address:
      peer-asn: 65000
      my-asn: 65001
    - name: default
      protocol: bgp

After the update, you will find that the EXTERNAL-IP of the Service has not been reassigned, and the controller of MetalLB has not been automatically configured. We delete the controller pod to restart:

$ kubectl delete po -n metallb-system -l app=metallb,component=controller
pod "controller-66445f859d-vss2t" deleted

You can see that the Service is assigned a new IP address:

$ kubectl get svc -n default
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)          AGE
kubernetes   ClusterIP       <none>         443/TCP          25m
nginx-lb     LoadBalancer   8080:30381/TCP   21m
nginx2-lb    LoadBalancer   8080:32319/TCP   21m

Check the log of speaker POD. You can see that the communication with peer has started and the announcement of IP address has been released:

{"caller":"level.go:63","configmap":"metallb-system/config","event":"peerAdded","level":"info","msg":"peer configured, starting BGP session","peer":"","ts":"2022-03-06T22:56:17.336335657Z"}
{"caller":"level.go:63","configmap":"metallb-system/config","event":"configLoaded","level":"info","msg":"config (re)loaded","ts":"2022-03-06T22:56:17.336366122Z"}
struct { Version uint8; ASN16 uint16; HoldTime uint16; RouterID uint32; OptsLen uint8 }{Version:0x4, ASN16:0xfde8, HoldTime:0xb4, RouterID:0xc0a80102, OptsLen:0x1e}
{"caller":"level.go:63","event":"sessionUp","level":"info","localASN":65001,"msg":"BGP session established","peer":"","peerASN":65000,"ts":"2022-03-06T22:56:17.337341549Z"}
{"caller":"level.go:63","event":"updatedAdvertisements","ips":[""],"level":"info","msg":"making advertisements using BGP","numAds":1,"pool":"default","protocol":"bgp","service":"default/nginx-lb","ts":"2022-03-06T22:56:17.341939983Z"}
{"caller":"level.go:63","event":"serviceAnnounced","ips":[""],"level":"info","msg":"service has IP, announcing","pool":"default","protocol":"bgp","service":"default/nginx-lb","ts":"2022-03-06T22:56:17.341987657Z"}
{"caller":"level.go:63","event":"updatedAdvertisements","ips":[""],"level":"info","msg":"making advertisements using BGP","numAds":1,"pool":"default","protocol":"bgp","service":"default/nginx2-lb","ts":"2022-03-06T22:56:17.342041554Z"}
{"caller":"level.go:63","event":"serviceAnnounced","ips":[""],"level":"info","msg":"service has IP, announcing","pool":"default","protocol":"bgp","service":"default/nginx2-lb","ts":"2022-03-06T22:56:17.342056076Z"}

Then you can view the routing table in vty:

OpenWrt# show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, P - PIM, A - Babel, N - NHRP,
       > - selected route, * - FIB route

K>* via, br-lan
C>* is directly connected, lo
B>* [20/0] via, br-lan, 00:00:06
B>* [20/0] via, br-lan, 00:00:06
C>* is directly connected, br-lan

From the table, we can find the routes of and bgps.


Our new IP access:

$ curl -I
HTTP/1.1 200 OK
Server: nginx/1.21.6
Date: Sun, 06 Mar 2022 23:10:33 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 25 Jan 2022 15:03:52 GMT
Connection: keep-alive
ETag: "61f01158-267"
Accept-Ranges: bytes


So far, we have tried two modes of MetalLB: Layer2 has strong universality and does not need any other dependencies, but its disadvantages are also obvious; In addition to relying on the route supporting BGP, BGP mode has no restrictions in other aspects, and there is no availability problem.

BGP should be the ultimate mode of LoadBalancer, but Layer2 is not useless. We still need to make rational choices based on the scenarios used. For example, I will choose Layer2 mode for homelab.

The article is unified in the official account of the cloud.

Keywords: Go Nginx openwrt layer

Added by Distant_storm on Mon, 07 Mar 2022 05:51:24 +0200