一、MetalLB简介

在使用kubenetes的过程中,主要解决将服务开放到集群外部访问的重要的问题。当使用云平台(阿里云、腾讯云、AWS等)的容器服务时,我们可以通过配置service为 LoadBalancer模式来绑定云平台的负载均衡器,从而实现外网的访问。对于自建的 kubernetes裸机集群我们一般使用MetalLB。,如果没有在受支持的IaaS平台(阿里 云、腾讯云、AWS等)上运行,那么负载均衡器在创建时将无限期地保持pending状态。

祼机集群不支持负载均衡的方式,可用的不外乎NodePort、HostNetwork、 ExternalIPs等方式来实现外部访问。但这些方式并不完美,而MetalLB旨在通过提供与标准网络设备集成的Network LB实施来解决这个痛点,从而使裸机群集上的外部服务 也尽可能“正常运行”,减少运维上的管理成本。

MetalLB由David Anderson开发,直到2019 年 3 月,MetalLB 的版权归谷歌所有,目前已经脱离谷歌,原作者现在已经授权一个维护人员团队协助推进项目。

官方网站:https://metallb.universe.tf/

项目地址:https://github.com/metallb/metallb

二、MetalLB原理

Metallb包含两个组件,Controller(Deployment方式部署)和Speaker(daemonset 方式部署)。

Metallb会在Kubernetes内运行,监控服务对象的变化,一旦察觉有新的 LoadBalancer 服务运行,并且没有可申请的负载均衡器之后,就会完成两部分的工作:

  • Controller:负责监听service变化,当service配置为LoadBalancer模式时,从IP池分配给到相应的IP,并进行IP的生命周期管理。
  • Speaker:则依据Service的变化,按具体的协议发起相应的广播或应答,根据工作模式 (Layer2/BGP)的不同,可采用Leader的方式或负载均衡的方式来响应请求。

基本原理图:

当业务流量通过TCP/UDP协议到达指定的Node时,由Node上面运行的Kube-Proxy组 件对流量进行处理,并分发到对应的Pod上面。

Aspose.Words.8f7a21f5-422d-4170-ba6d-bd8eba7b237e.001

Metallb 支持两种模式:

  • Layer2(推荐):L2 工作模式,使用 ARP/NDP 协议分配地址池;
  • BGP:使用BGP协议分配地址池;

三、MetalLB安装

3.1 前提条件

已准备kuberntes集群:v1.26.9,已准备网络插件:calico等。

[root@master01 ~]# kg node -owide
NAME       STATUS   ROLES           AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
master01   Ready    control-plane   12d   v1.26.9   192.168.1.60   <none>        CentOS Linux 7 (Core)   4.19.12-1.el7.elrepo.x86_64   containerd://1.6.24
master02   Ready    control-plane   12d   v1.26.9   192.168.1.63   <none>        CentOS Linux 7 (Core)   4.19.12-1.el7.elrepo.x86_64   containerd://1.6.24
master03   Ready    control-plane   12d   v1.26.9   192.168.1.64   <none>        CentOS Linux 7 (Core)   4.19.12-1.el7.elrepo.x86_64   containerd://1.6.24
node01     Ready    <none>          12d   v1.26.9   192.168.1.61   <none>        CentOS Linux 7 (Core)   4.19.12-1.el7.elrepo.x86_64   containerd://1.6.24
node02     Ready    <none>          12d   v1.26.9   192.168.1.62   <none>        CentOS Linux 7 (Core)   4.19.12-1.el7.elrepo.x86_64   containerd://1.6.24

如果在 IPVS 模式下使用 kube-proxy,从 Kubernetes v1.14.2 开始,必须启用严格的 ARP模式。

可以通过在当前集群中编辑kube-proxy配置来实现这一点,执行一下命令:

#修改成IPVS模式
[root@master01 ~]# kubectl edit configmap -n kube-system kube-proxy
...
...
    kind: KubeProxyConfiguration
    metricsBindAddress: ""
    mode: "ipvs"
...
...

#设置kubernetes的kube-proxy的ARP模式为true
[root@master01 ~]# kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system

3.2 MetalLB 安装

Metallb 支持 yaml文件、Kustomize、Helm 和 MetalLB Operator多种安装方法,这里 使用yaml方式进行安装。

下载release版本

[root@master01 ~]# cd 6
[root@master01 6]# wget https://github.com/metallb/metallb/archive/refs/tags/v0.13.12.tar.gz
[root@master01 6]# tar -zxvf metallb-0.13.12.tar.gz

执行yaml文件进行安装

##修改metallb-native.yaml文件,将namespace命名空间替换成devops
# 如果没有devops命名空间
[root@master01 ~]# k create ns devops
# 将namespace命名空间替换成devops
[root@master01 ~]# cd /root/6/metallb-0.13.12/config/manifests/
[root@master01 manifests]# vim metallb-native.yaml
:%s/namespace: metallb-system/namespace: devops/g

##修改metallb-native.yaml文件,将国外镜像替换成国内镜像
[root@master01 ~]# cd /root/6/metallb-0.13.12/config/manifests/
[root@master01 manifests]# vim metallb-native.yaml
#替换前的镜像
image: quay.io/metallb/controller:v0.13.12
image: quay.io/metallb/speaker:v0.13.12
#替换后的镜像
registry.cn-hangzhou.aliyuncs.com/abroad_images/controller:v0.13.12
registry.cn-hangzhou.aliyuncs.com/abroad_images/speaker:v0.13.12

##应用
[root@master01 ~]# cd /root/6/metallb-0.13.12/config/manifests/
[root@master01 manifests]# kubectl apply -f  metallb-native.yaml

查看运行的pods,metalLB包含两个部分: a cluster-wide controller, and a per- machine protocol speaker.

[root@master01 manifests]# kgp -n devops
NAME                          READY   STATUS    RESTARTS   AGE
controller-6b44dbf99b-qhhkv   1/1     Running   0          13m
speaker-dzxrv                 1/1     Running   0          13m
speaker-kv52n                 1/1     Running   0          13m
speaker-lmn6t                 1/1     Running   0          13m
speaker-mtkvd                 1/1     Running   0          13m
speaker-nvbvl                 1/1     Running   0          13m

[root@master01 manifests]# kubectl -n devops get deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
controller   1/1     1            1           14m

[root@master01 manifests]# kubectl -n devops get ds
NAME      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
speaker   5         5         5       5            5           kubernetes.io/os=linux   15m

四、配置Layer2模式

复制模板文件进行修改

[root@master01 ~]# cd /root/6/metallb-0.13.12/configsamples
[root@master01 configsamples]# cp deployment_l2.yaml l2.yaml
[root@master01 configsamples]# vim l2.yaml
#修改ns为devops
#修改地址池地址为192.168.1.10-192.168.1.14
#修改nginx镜像地址为registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.21.6

修改后的内容

[root@master01 ~]# cd /root/6/metallb-0.13.12/configsamples
[root@master01 configsamples]# vim l2.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: example
  namespace: devops
spec:
  addresses:
  - 192.168.1.10-192.168.1.20
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: empty
  namespace: devops
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.21.6
        ports:
        - name: http
          containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer

创建测试后端应用和服务

[root@master01 ~]# cd /root/6/metallb-0.13.12/configsamples
[root@master01 configsamples]# kaf l2.yaml

查看service分配的EXTERNAL-IP

[root@master01 configsamples]# kgs
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)        AGE
kubernetes   ClusterIP      10.0.0.1       <none>         443/TCP        13d
nginx        LoadBalancer   10.0.153.205   192.168.1.10   80:31653/TCP   11m

从集群外访问该IP地址192.168.1.10

image-20231129215223350