LoadBalancer for Bare Metal Kubernetes Cluster-MetalLB

本文最后更新于 2025年1月27日 下午

在 Kubernetes 中,对于 LoadBalancer 类型的 Service,k8s 并没有为裸机集群实现负载均衡器,因此我们只有在以下 IaaS 平台(GCP, AWS, Azure)上才能使用 LoadBalancer 类型的 service。

因此裸机集群只能使用 NodePort 或者 externalIPs service 来对面暴露服务,然而这两种方式和 LoadBalancer service 相比都有很大的缺点,而 MetalLB 的出现就是为了解决这个问题。 也就是说在裸机的 K8s 集群无法使用 LoadBancer 类型的 Service。否则,您会发现 LoadBancer 的 Service 一直处于 Pending 状态,而 MetalLB 的出现就是为了解决这个问题。

MetalLB

MetalLB 是一款开源软件,它采用标准的路由协议(ARP 或 BGP)实现了裸机 K8s 集群的负载均衡功能。

https://metallb.io/installation/

工作模式:

L2 模式 (ARP)(https://docs.daocloud.io/network/modules/metallb/#l2-arp)

L2 模式下,MetalLB 会通过 memberlist 选举出一个 Leader 节点,此节点负责向本地网络宣告 LoadBalancerIP。 从网络的角度来看,这台机器似乎有多个 IP 地址,它会响应来自 LoadBancerIP 的 ARP 请求。 L2 模式最大的优势是它不需要依赖譬如路由器等硬件的依赖便可工作。

  • 优势:通用型,不需要额外的硬件支持
  • 缺点:单节点的带宽限制、稍缓慢的故障转移(10s 左右)

L3 模式 (BGP)(https://docs.daocloud.io/network/modules/metallb/#l3-bgp)

在 BGP 模式下,集群中的每个节点都会与路由器建立 BGP Peer,并使用该会话向集群外部通告集群服务的 LoadBalanceIP。 BGP Router 基于每个不同的连接选择一个下一跳(即集群某个节点,这不同于 L2 模式下所有流量先到达某个 Leader 节点)。

  • 优势:负载均衡性更好
  • 缺点:
    • 当某个节点故障,所有 BGP 会话将会中断
    • Calico BGP 模式无法和 MetaLB L3 模式并存,会存在冲突,详情请参考 ISSUES WITH CALICO

安装 MetalLB

我的网络插件使用的是kube-router, 默认启用了ARP,所以直接安装:

1
2
3
4
5
root@master-01 ~]# kubectl get pod -A | grep route
kube-system kube-router-2hpsc 1/1 Running 6 (ago) 2d
kube-system kube-router-gjpvf 1/1 Running 6 (ago) 2d
kube-system kube-router-sqqmj 1/1 Running 7 (ago) 2d
[root@master-01 ~]#

image-20241013144444215

L2 模式

1
2
3
4
5
6
[root@master-01 metallb]# kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml
[root@master-01 metallb]# kubectl get pod -A | grep metallb
metallb-system controller-6dd967fdc7-9lq2p 1/1 Running 0 11h
metallb-system speaker-kjm8c 1/1 Running 0 11h
metallb-system speaker-knv64 1/1 Running 0 11h
metallb-system speaker-rcxhc 1/1 Running 0 11h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@master-01 metallb]# cat IPAddressPool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.240-192.168.1.250 # 可分配的 IP 地址,可以指定多个,包括 ipv4、ipv6,我的路由器网段就是下面的网段
[root@master-01 metallb]# cat L2Advertisement.yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- pool #上一步创建的 ip 地址池,通过名字进行关联
[root@master-01 metallb]# kubectl create -f IPAddressPool.yaml
[root@master-01 metallb]# kubectl create -f L2Advertisement.yaml
Nginx 部署测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
[root@master-01 metallb]# cat nginx-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: docker.io/nginx:latest
ports:
- containerPort: 80
[root@master-01 metallb]# cat nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
selector:
app: nginx
ports:
- name: nginx-port
protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
[root@master-01 metallb]# kubectl create -f nginx-deployment.yml
[root@master-01 metallb]# kubectl create -f nginx-svc.yaml
[root@master-01 metallb]# kubectl get deployments.apps nginx-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 10h
[root@master-01 metallb]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.68.0.1 <none> 443/TCP 11h
nginx LoadBalancer 10.68.74.145 192.168.1.240 80:31054/TCP 10h
[root@master-01 metallb]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-755fbfbc49-gljgb 1/1 Running 0 10h
nginx-deployment-755fbfbc49-l2928 1/1 Running 0 10h
nginx-deployment-755fbfbc49-lvbsp 1/1 Running 0 10h
[root@master-01 metallb]# ip addr show ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:80:af:bc brd ff:ff:ff:ff:ff:ff
altname enp2s1
inet 192.168.1.56/24 brd 192.168.1.255 scope global dynamic noprefixroute ens33
valid_lft 45382sec preferred_lft 45382sec
inet6 fe80::20c:29ff:fe80:afbc/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@master-01 metallb]# curl -I 192.168.1.240
HTTP/1.1 200 OK
Server: nginx/1.27.2
Date: Sun, 13 Oct 2024 20:34:22 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Wed, 02 Oct 2024 15:13:19 GMT
Connection: keep-alive
ETag: "66fd630f-267"
Accept-Ranges: bytes

image-20241014003558937


LoadBalancer for Bare Metal Kubernetes Cluster-MetalLB
https://msfts.org/2024/10/13/LoadBalancer-for-bare-metal-Kubernetes-cluster-MetalLB/
作者
Jas0n0ss
发布于
2024年10月13日
许可协议