MetalLB实践

1,125 阅读8分钟

MetalLB在kubernetes集群中起到了引流的作用。在其中提供Layer2模式和BGP模式。本文将从不同的场景角度出发展示MetalLB使用过程。

实验环境安装

实验环境

在做实验过程中,采用四台虚拟机作为测试主机。主机列表于虚拟机服务如下所示:

IP用途
192.168.56.15Master节点
192.168.56.16Node节点
192.168.56.17虚拟交互机主机,在该主机上安装zebra。
模拟路由支持BGP协议
192.168.56.18Node节点

同时部署两个Nginx,具体如下所示:

名称说明
nginxv1Nnginx服务,3个副本
nginxv2Nginx服务,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方式进行安装。quaggazebra的安装于配置,具体步骤如下所示:

  1. 安装quagga
 yum install quagga 
  1. 设置SElinux
setsebool -P zebra_write_config 1
  1. 设置开机启动及配置日志
cp /usr/share/doc/quagga-0.99.22.4/zebra.conf.sample /etc/quagga/zebra.conf
systemctl start zebra
systemctl enable zebra

BGP的安装步骤:

  1. 启动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
    
  2. 配置节点服务

    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-labelsmatch-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-labelsmatch-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-lbappv1-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会出现配置信息无法装载生效。但是从代码来看确实发生变化,这个问题有待追究。