MetalLB在kubernetes集群中起到了引流的作用。在其中提供Layer2模式和BGP模式。本文将从不同的场景角度出发展示MetalLB使用过程。
实验环境安装
实验环境
在做实验过程中,采用四台虚拟机作为测试主机。主机列表于虚拟机服务如下所示:
IP | 用途 |
---|---|
192.168.56.15 | Master节点 |
192.168.56.16 | Node节点 |
192.168.56.17 | 虚拟交互机主机,在该主机上安装zebra。 模拟路由支持BGP协议 |
192.168.56.18 | Node节点 |
同时部署两个Nginx,具体如下所示:
名称 | 说明 |
---|---|
nginxv1 | Nnginx服务,3个副本 |
nginxv2 | Nginx服务,1个副本 |
如上列表所示,在nginxv1zhogn ,访问服务的根地址返回内容为v1_1、v1_2、v1_3,nginx2请求返回v2。这样方便于我们进行验证转发后的结果。
MetalLB安装
在安装MetalLB前,从kubernetes.1.4之后的版本,需要将kube-proxy的strictARP打开,首先先在master下执行一下命令:
kubectl edit configmap -n kube-system kube-proxy
然后在ipvs模式下增加以下值:
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
strictARP: true
如以上代码片段所示,strictARP:true
如果没有该值可添加,如果已经有确保该值为true。在集群已经提前安装,如果发现实践过程中出现网络不通的情况,可使用kubectl delete po
方式将kube-proxy的pod删除,令配置重新生效。
准备完成后开始安装MetalLB服务。可通过github的官方网站进行安装,当前实验使用版本为0.9.5,具体安装命令如下所示:
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.5/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.5/manifests/metallb.yaml
执行完成以上命令后,可查看到MetalLB的namespace的情况。具体如下所示:
虚拟路由器安装
在BGP的验证过程中,需要一台支持BGP路由协议的路由器。在一般的家用路由器不支持该协议,因此采用quagga
作为模拟路由器来实现BGP写的支持。本文的安装过程中采用yum方式进行安装。quagga
和zebra
的安装于配置,具体步骤如下所示:
- 安装quagga
yum install quagga
- 设置SElinux
setsebool -P zebra_write_config 1
- 设置开机启动及配置日志
cp /usr/share/doc/quagga-0.99.22.4/zebra.conf.sample /etc/quagga/zebra.conf
systemctl start zebra
systemctl enable zebra
BGP的安装步骤:
-
启动BGP服务
cp /usr/share/doc/quagga-0.99.22.4/bgpd.conf.sample /etc/quagga/bgpd.conf systemctl start bgpd systemctl enable bgpd systemctl status bgpd
-
配置节点服务
vtysh configure terminal no router bgp 7675 router bgp 200 no auto-summary no synchronization network 10.1.245.0/24 neighbor 192.168.56.15 remote-as 100 neighbor 192.168.56.15 description "provider 15" neighbor 192.168.56.16 remote-as 100 neighbor 192.168.56.16 description "provider 16"
以上与语句达成几点目标,1. 将默认的AS ID由默认的7675修改为200,同时将192.168.56.15和192.168.56.16声明为远端AS,ASID分别是100和300。
##Layer2模式
Layer2模式的配置较为简单,工作原理也较为简单。Layer2模式不需要特定的协议配置,只需要配置IP地址池便可。其工作原理是采用对ARP请求的应答来暴露服务。因此Layer2模式一般会受限于局域网内,跨交换机暴露服务会出现不可达。
如果采用Layer2模式,ConfigMap配置信息如下所示:
apiVersion: v1
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.56.20-192.168.56.30
kind: ConfigMap
metadata:
name: config
namespace: metallb-system
创建后,创建一下Servcie:
apiVersion: v1
kind: Service
metadata:
name: appv1-lb
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginxv1
type: LoadBalancer
#type: ClusterIP
创建完成后,实用贴kubect get svc
可看到的Service如下所示:
从上图中,针对LoadBalance的Service,kubernetes分别分配了ClusterIP和External-IP。而External-IP则有MetalLB监听Service响应分配,同时也暴露一个Nodeport。下面我们再看一下ipvs规则如下所示:
从以上两张图可以看出,kube-proxy同时为clusterip和Exteernal-IP提供转发规则。从这个规则上可以看出kube-proxy没有走nodeport方式转发给pod,而是直接转发。发起如下命令:
for ((i=1;i<=10;i++)); do curl "http://192.168.56.20/"; done
显示结果如下所示:
分别在192.168.56.17
上执行ip neigh
查看arp结果和在192.168.56.18
上执行ip addr show dev enp0s8
可看到如下图所示:
从上图可知,192.168.56.20
已经被解析到192.168.56.18
。
BGP模式
简单配置
关于BGP模式的配置,需要拥有一个支持BGP路由协议的路由器和一个与现网不冲突的IP段。配置前需要具备一下四点信息:
- MetalLB应该连接的路由器IP地址;
- 路由器的AS号;
- MetalLB应该使用的AS号;
- 以CIDR前缀表示的IP地址范围。
在实验环境安装
中已经介绍过软路由模拟的安装,这里不再进行介绍。按照配置执行后,执行以下命令可看到当前活跃的AS信息:
show ip bgp summary
下面我们修改配置信息为BGP模式配置,具体配置信息如下所示:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
peers:
- peer-address: 192.168.56.17
peer-asn: 200
my-asn: 100
address-pools:
- name: default
protocol: bgp
avoid-buggy-ips: true
addresses:
- 10.1.245.0/24
如以上配置信息所示,peer-address
表示远端对等体的地址、peer-asn
表示ASID、my-asn
表示与当前对等体协商好的ASID。另外avoid-buggy-ips: true
表示IP分配使用0和254。创建配置信息后,在创建Service,使用如下命令可看到如下信息:
kubect get svc
可看到如下信息。
可看到External-IP已经切换到BGP定义的虚拟IP。此时可在192.168.56.17
主机上执行以下命令查看BGP的同步消息:
show ip bgp summary
再在192.168.56.17
主机上执行以下命令查看转发结果:
for ((i=1;i<=10;i++)); do curl "http://10.1.245.1/"; done
如上所示,通过虚拟IP已经可以访问到服务。再查看ipvs的情况,执行如下命令:
ipvsadm -Ln
如上图可知,kube-proxy直接对External-IP进行转发到具体的pod上。MetalLB将流量引流到主机上,具体的接受通过ipvs实现转发。
节点选择
在使用BGP时可出于安全的考虑、数据包由于服务中断缩短影响范围的因素考虑、更加均衡流量到同的接单上,可采用通过固定节点或者主机标签来解决。MetalLB采用两种方式提供支持,分别是match-labels
和match-expressions
。具体配置信息如下所示:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
peers:
- peer-address: 192.168.56.17
peer-asn: 200
my-asn: 100
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]
address-pools:
- name: default
protocol: bgp
avoid-buggy-ips: true
addresses:
- 10.1.245.0/24
如上所示,node-selectors
字段表示节点选择方式,提供两种分别是match-labels
和match-expressions
。下面以match-expressions
为例子展示例子。下面以节点选择为例子。ConfigMap具体内容如下所示:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
peers:
- peer-address: 192.168.56.17
peer-asn: 200
my-asn: 100
node-selectors:
- match-expressions:
- key: kubernetes.io/hostname
operator: In
values: [192.168.56.16]
address-pools:
- name: default
protocol: bgp
avoid-buggy-ips: true
addresses:
- 10.1.245.0/24
如上所示,使用192.168.56.16节点作为对外暴露节点。重新创建Service查看一下结果。泗洪show ip bgp summary
查看路由器的同步情况
如上图所示,可以看到两个节点是活跃的,但是只有192.168.56.16发起同步路由规则。
多IP池设置
在很多场景中,可采用多个IP池子进行设置。然后在Service中可通过注解方式来选择具体使用Ip池情况。从而实现Layer2模式和BGP模式共存。下面采用BGP模式作为默认模式,再由Service来决定使用那种情况。
先来看一下配置文件,配置文件如下所示:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
peers:
- peer-address: 192.168.56.17
peer-asn: 200
my-asn: 100
node-selectors:
- match-expressions:
- key: kubernetes.io/hostname
operator: In
values: [192.168.56.16]
address-pools:
- name: default
protocol: bgp
avoid-buggy-ips: true
addresses:
- 10.1.245.0/24
- name: layer20-30
protocol: layer2
addresses:
- 192.168.56.20-192.168.56.30
从以上可以看到,有两个地址池,分别是default和layer20-30,其中bgp使用虚拟IP10.1.245.0/24
段,layer22-30使用layer2模式,IP段为192.168.56.20-192.168.56.30
段。下面我们开始创建两个Service,分别如下所示:
Service1:
apiVersion: v1
kind: Service
metadata:
name: appv1-lb
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginxv1
type: LoadBalancer
Service2:
apiVersion: v1
kind: Service
metadata:
name: appv1-1-lb
annotations:
metallb.universe.tf/address-pool: layer20-30
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginxv1
type: LoadBalancer
如以上所示,创建两个Service,分别是appv1-lb
和appv1-1-lb
。其中appv1-lb
使用为声明使用哪个地址池,而appv1-1-lb
使用layer20-30的地址池。使用如下命令查看service情况:
kubectl get svc
显示如下所示:
如上图可看到appv1-1-lb
的IP分配192.168.56.20
,该IP属于layer2-20-30池中的IP。然后appv1-lb
则分配默认地址池的IP。
总结
从整个实验过程中来看,MetalLB实现Layer2和bgp的引流方式。能够实现将流量引流到主机上,服务的具体的负载均衡过程则是通过ipvs来实现负载均衡。
在实验的过程中发现,Controller和Speaker会出现配置信息无法装载生效。但是从代码来看确实发生变化,这个问题有待追究。