王海庆的云笔记

本地集群使用Metallb实现Load Balancer


        k8s的LoadBalancer类型的Service依赖于外部的云提供的Load Balancer。

当我们把k8s部署在裸机上面时,或者是测试环境时,需要简单的LoadBalancer来验证工作,开源的metallb就是一个不错的选择。

 

Metallb支持两种工作模式: Layer2模式、BGP模式(上层路由器支持BGP)


Layer2模式:这是我在实验环境下面常用的模式,只需要一段跟K8s管理网相同网段的地址即可。

Metallb在这种模式下,会从k8s节点中选一个Leader节点,在这个节点上面响应LB地址段的ARP请求,从而使上层路由把发往LB的流量都发到Leader节点。

缺点也很明显,所有对LB的请求都会发往Leader节点。如果当前Service下面的Pod分布在不同节点,那么这个流量还会从Leader发往相应的节点。

不过用在实验环境里这个模式真是太好用了,不需要路由器支持BGP。


BGP模式: 需要路由器支持接收Metallb的BGP广播,从而把请求分布到正确的节点上。

跟L2模式的区别就是能够通过BGP协议正确分布流量了,不再需要一个Leader节点。

缺点就是需要上层路由器支持BGP。而且因为BGP单session的限制,如果Calico也是使用的BGP模式,就会有冲突从而导致metallb无法正常工作。


下面以Layer2模式为例,进行部署测试


 首先需要保证所有 Kubernetes 集群节点必须在同一个二层网络(在同一个路由器下)。

[root@zkxy ~]# kubectl get nodes
NAME   STATUS   ROLES                  AGE     VERSION
zkxy   Ready    control-plane,master   4m42s   v1.22.6
[root@zkxy ~]#


首先需要为 kube-proxy 启用 strictARP,以便 Kubernetes 集群中的所有网卡停止响应其他网卡的 ARP 请求,而由 OpenELB 处理 ARP 请求。 

kubectl edit configmap kube-proxy -n kube-system
......
ipvs:
  strictARP: true
......


If you are trying to automate this change, these shell snippets may help you

kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl diff -f - -n kube-system


然后执行下面的命令重启 kube-proxy 组件即可 

kubectl rollout restart daemonset kube-proxy -n kube-system


安装镜像

# 已经修改为阿里云的镜像
kubectl apply -f namespace.yaml
kubectl apply -f metallb.yaml

# 官方镜像
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml


镜像下载

docker pull quay.io/metallb/speaker:v0.12.1
docker pull quay.io/metallb/controller:v0.12.1

docker tag quay.io/metallb/speaker:v0.12.1 registry.cn-hangzhou.aliyuncs.com/wanghaiqing/speaker:v0.12.1
docker tag quay.io/metallb/controller:v0.12.1 registry.cn-hangzhou.aliyuncs.com/wanghaiqing/controller:v0.12.1

docker push registry.cn-hangzhou.aliyuncs.com/wanghaiqing/speaker:v0.12.1
docker push registry.cn-hangzhou.aliyuncs.com/wanghaiqing/controller:v0.12.1


安装完成后查看 Pod 的状态是否正常

[root@zkxy ~]# kubectl get pod -A
NAMESPACE        NAME                           READY   STATUS    RESTARTS   AGE
kube-system      coredns-7f6cbbb7b8-9vwqp       1/1     Running   0          7m30s
kube-system      coredns-7f6cbbb7b8-rppq6       1/1     Running   0          7m30s
kube-system      etcd-zkxy                      1/1     Running   0          8m38s
kube-system      kube-apiserver-zkxy            1/1     Running   0          7m58s
kube-system      kube-controller-manager-zkxy   1/1     Running   0          7m52s
kube-system      kube-flannel-ds-jjm2h          1/1     Running   0          7m31s
kube-system      kube-proxy-4p2bv               1/1     Running   0          3m9s
kube-system      kube-scheduler-zkxy            1/1     Running   0          7m51s
metallb-system   controller-6bf4d657bc-vtwfm    1/1     Running   0          33s
metallb-system   speaker-brrmp                  1/1     Running   0          33s
[root@zkxy ~]#

 

创建一个  ConfigMap  的 IP 地址池 

cat > eip.yaml << EOF
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 172.18.0.206-172.18.0.209
EOF

kubectl apply -f eip.yaml

 

创建nginx服务

cat > nginx.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:  
    matchLabels:
      app: nginx
  template:  
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
EOF

kubectl apply -f nginx.yaml
kubectl get pods


创建 LoadBalancer 类型的 Service 来暴露我们的 nginx 服务

cat > loadbalancer.yaml << EOF
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  type: LoadBalancer
  loadBalancerIP: 172.18.0.206
  ports:
    - name: http
      port: 80
      targetPort: 80
EOF

kubectl apply -f loadbalancer.yaml
kubectl get svc

如果字段loadBalancerIP没有指定,该负载均衡器会被指定一个短暂性的IP。 loadBalancerIP还必须要在之前设置的网段内才可以。


查询service的LB情况

[root@zkxy ~]# kubectl get svc -A
NAMESPACE     NAME         TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)                  AGE
default       kubernetes   ClusterIP      10.2.0.1       <none>         443/TCP                  8h
default       nginx        LoadBalancer   10.2.239.232   172.18.0.206   80:31824/TCP             2m51s
kube-system   kube-dns     ClusterIP      10.2.0.10      <none>         53/UDP,53/TCP,9153/TCP   8h
[root@zkxy ~]#


访问

http://172.18.0.206/


namespace.yaml

metallb.yaml


 参考

https://zhuanlan.zhihu.com/p/103717169
https://mp.weixin.qq.com/s/BY6hrLjaWfPYJzYmpbl1fQ
https://metallb.universe.tf/installation/

文章最后更新时间: 2022-05-27 10:19:53