kubernetes网络 – metallb讲解

欢迎加入本站的kubernetes技术交流群,微信添加:加Blue_L。


metallb用来实现在私有化搭建的裸机环境中实现负载均衡器的功能,在没有云环境的情况下通过metallb将service暴露到网络环境中,供其他系统访问。

https://metallb.universe.tf/

部署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节点变化。

环境需求

  1. 底层网络路由器必须支持bgp协议,同时最好支持ecmp协议实现多个后端rs的负载均衡。
  2. 客户允许cloud-controller使用bgp协议修改路由器的路由配置。
  3. 客户需要在路由上预留一些固定的网段给kubernetes的服务使用。

bpg原来可以参考前面网络原理章节。

layer 2模式

在Layer 2模式下,需要为服务预留ip段,用来做为LoadBalancer类型服务的外部访问地址。在layer 2模式下,可支持下列几种网络结构:

优点

支持任意以太网络环境,不需要特殊硬件设备支持。

缺点

每个服务的流量都由单独一台节点转发,可能会有性能瓶颈。

要求

  1. 网络环境中支持配置虚拟IP
  2. 该子网可预留部分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_ARPhttps://www.ietf.org/rfc/rfc1027.txt

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注