欢迎加入本站的kubernetes技术交流群,微信添加:加Blue_L。
metallb用来实现在私有化搭建的裸机环境中实现负载均衡器的功能,在没有云环境的情况下通过metallb将service暴露到网络环境中,供其他系统访问。
部署metallb
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/metallb.yaml
创建配置
metallb监视名为config或metallb-config(helm部署)的configmap资源,我们创建这个资源之后它就开始工作了。
下面是layer 2模式下的配置示例,其中的addresses配置为预留的ip地址段,可配置多个。
[root@master3 ~]# cat metallb-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
# 可配置为下列形式或者192.168.1.0/24形式,根据预留的网段具体决定
# 可配置多个
- 10.77.1.220-10.77.1.240
kubectl apply -f metallb-configmap.yaml
测试
[root@master3 ~]# kubectl run nginx --image=nginx --port=80
[root@master3 ~]# kubectl expose pod nginx --port=80 --target-port=80 --type=LoadBalancer
[root@master3 ~]# kubectl get svc nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer 172.17.12.39 10.77.1.220 80:31339/TCP 3h7m
# 登录到集群外的节点上,执行进行curl访问测试
[root@vm10-77-1-63 ~]# curl 10.77.1.220
在网络环境支持的情况下,还可以使用bgp方式。
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
peers:
- peer-address: 10.0.0.1
peer-asn: 64501
my-asn: 64500
address-pools:
- name: default
protocol: bgp
addresses:
- 192.168.10.0/24
上面配置配置了一个192.168.10.0/24网段的地址池,指定协议为bgp。并且配置了一个bpg peer,地址为10.0.0.1,对方的as号为64501,本地的as号为64500。则集群内的节点都会连接10.0.0.1,通过bpg发布路由信息。每个节点都会像peer建议每个service的ip/32地址,本节点的优先级为0。
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
peers:
- peer-address: 10.0.0.1
peer-asn: 64501
my-asn: 64500
address-pools:
- name: default
protocol: bgp
addresses:
- 198.51.100.0/24
bgp-advertisements:
- aggregation-length: 32
localpref: 100
communities:
- no-advertise
- aggregation-length: 24
bgp-communities:
no-advertise: 65535:65282
有些路由器可能不能接收台详细的前缀,比如一个路由器只接受前缀为24和24一下的前缀。那么上面的/32前缀他就不处理,因此可以通过aggregation-length指定对前缀进行聚合,每个服务路由前缀都是/32,如果对方路由器只接受/28以下的前缀,则这块我们需要配置值为28,这样每个节点就会传播一条这个前缀的路由。
bgp路由advertise的时候可以由不同的属性,其中有一个广为人知的属性为no-advertise,值为0xffffff02,该属性的意思是不告诉任何人这条路由信息,我就告诉你了,别告诉别人。
上面例子配置了两个bgp传播配置,第一条定义了/32前缀的路由,并且设置本地优先级为100,第二条为/24前缀,没有配置优先级,那么这个peer会将我们这个/24的前缀的路由传播给其他路由器,而/32的只有这个peer使用。
Bgp-communities.no-advertise 这块就是上面cummunities.no-advertise的用名字表示的值。
除了配置全局的peer,还可以限定特定的节点连接特定的peer。比如针对下面网络
可以采用下面这个配置
peers:
- peer-address: 10.0.0.1
peer-asn: 64501
my-asn: 64500
# 基于label做选择
node-selectors:
- match-labels:
rack: frontend
match-expressions:
- key: network-speed
operator: NotIn
values: [slow]
- match-expressions:
- key: kubernetes.io/hostname
operator: In
values: [hostA, hostB]
还可以指定源ip地址,使会使用这个ip地址和其他服务通信,和peer建链接时也会使用这个ip地址。默认情况下metallb自动选择的ip地址可能不满足,则可以通过这个配置明确指定节点的源ip。
peers:
- peer-address: 10.0.0.1
peer-asn: 64501
my-asn: 64500
source-address: 10.0.0.2
node-selectors:
- match-labels:
kubernetes.io/hostname: node-1
才外还可以通过auto-assign: false来禁用这个池子的自动ip地址分配。
# Rest of config omitted for brevity
address-pools:
- name: cheap
protocol: bgp
addresses:
- 192.168.144.0/20
- name: expensive
protocol: bgp
addresses:
- 42.176.25.64/30
auto-assign: false
bpg模式配置参考:https://metallb.universe.tf/configuration/。
https://www.iana.org/assignments/bgp-well-known-communities/bgp-well-known-communities.xhtml
工作模型
bgp模式
优势
能够在节点之间做到负载均衡。
限制
后端rs节点发生变化可能导致大部分链接损坏。如果路由器支持ECMP协议可很大限度解决,也可将speeker部署在固定几个节点减缓rs节点变化。
环境需求
- 底层网络路由器必须支持bgp协议,同时最好支持ecmp协议实现多个后端rs的负载均衡。
- 客户允许cloud-controller使用bgp协议修改路由器的路由配置。
- 客户需要在路由上预留一些固定的网段给kubernetes的服务使用。
bpg原来可以参考前面网络原理章节。
layer 2模式
在Layer 2模式下,需要为服务预留ip段,用来做为LoadBalancer类型服务的外部访问地址。在layer 2模式下,可支持下列几种网络结构:
优点
支持任意以太网络环境,不需要特殊硬件设备支持。
缺点
每个服务的流量都由单独一台节点转发,可能会有性能瓶颈。
要求
- 网络环境中支持配置虚拟IP
- 该子网可预留部分ip地址给kubernetes的service使用,保留ip地址可以是连续的也可以不连续,但是一定要保证不能再分给其他主机
大概原理:
metallb会使用这些预留的ip地址关联到不同的kubernetes服务实例,并通过arp协议发布ip地址。 metallb的speeker进程会部署到集群的所有节点,speeker会在预留的网段内选取一个ip作为service的外部访问入口,并通过arp协议将ip地址广播到该子网中的所有节点上(包括网关),类似如下过程:
arp请求:谁有10.0.1.223这个ip地址告诉你的mac地址,我的ip地址是10.0.1.3,我的mac是aabbccddeeff。
arp响应:发给10.0.1.3,我有10.0.1.223这个地址,我的mac地址qqwweerrttyy。
客户端的数据包达到网关后,由网关根据ip地址和mac地址的缓存新查到要发送到那个mac地址,并通过交换机发送到对应的节点上。该节点收到数据包之后,会通过iptables规则或ipvs将请求转发到对用的Pod上。
预留网段和集群节点在同一个子网中(推荐使用)
预留网段和集群节点不在同一个子网中,在预留网段部署额外节点作为负载均衡器入口
在这种情况下,如果使用calico的vxlan,跨了子网,节点3上访问pod会通过vxlan封包。
预留网段和集群节点不在同一个子网中,通过自定义静态路由或arp代理
其他功能
metallb支持多个service共享同一个ip地址,满足下列三个条件的话,metallb会自动复用现有的ip。
- 具有相同的共享key配置
- 不同服务使用时不同的端口
- 所有服务的spec.externalTrafficPolicy都设置为Cluster(默认),或者共享的服务具有完全pod集合
若要多个service共享一个ip地址可通过加下面这个annotation,值为共享的key,比如租户的名称。
metallb.universe.tf/allow-shared-ip=tenant1
metallb实现了外部流量策略为Local的情况,那么在二层模式下则具有那个pod的节点才会成为具有lb的ip地址的节点,在3层情况下只会有到具有pod节点的路由。
参考:https://metallb.universe.tf/usage/
链接:https://en.wikipedia.org/wiki/Proxy_ARP,https://www.ietf.org/rfc/rfc1027.txt