Kubernetes 1.28.2 负载均衡解决方案 MetalLB实践

MetalLB 是一个用于在 Kubernetes 集群中提供外部 IP 地址的负载均衡器实现。
安装须知:
  • Kubernetesv1.13.0 或者更新的版本
  • 规划 IPv4 地址给 MetalLB 用于分配。
  • 当使用 BGP 操作模式时,你将需要一个或多个能够支持 BGP 协议的路由器。
  • L2 模式下需要各个节点间 7946 端口(TCP & UDP)需要互通。
  • 集群中的 CNI 要能兼容 MetalLB,最新的兼容性参考 https://metallb.universe.tf/installation/network-addons/

    常见的 Flannel、Cilium 等都是兼容的,Calico 的话大部分情况都兼容,BGP 模式下需要额外处理。因为 BGP 单 session 的限制,如果 CNI 插件为 Calico ,同时 Calico 也是使用的 BGP 模式,就会有冲突从而导致 MetalLB 无法正常工作。

确保Kubernetes 集群已经部署并且运行正常。

[root@k8s-master-01 ~]# kubectl get nodes -o wide
NAME            STATUS   ROLES           AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE                           KERNEL-VERSION              CONTAINER-RUNTIME
k8s-master-01   Ready    control-plane   38d   v1.28.2   192.168.61.147   <none>        Rocky Linux 8.7 (Green Obsidian)   4.18.0-425.3.1.el8.x86_64   docker://26.1.3
k8s-worker-01   Ready    <none>          38d   v1.28.2   192.168.61.148   <none>        Rocky Linux 8.7 (Green Obsidian)   4.18.0-425.3.1.el8.x86_64   docker://26.1.3
k8s-worker-02   Ready    <none>          38d   v1.28.2   192.168.61.149   <none>        Rocky Linux 8.7 (Green Obsidian)   4.18.0-425.3.1.el8.x86_64   docker://26.1.3

##### 网络组件
[root@k8s-master-01 ~]# kubectl get pods -n kube-system -o wide
NAME                                       READY   STATUS    RESTARTS      AGE   IP               NODE            NOMINATED NODE   READINESS GATES
calico-kube-controllers-658d97c59c-5rkzg   1/1     Running   1 (12d ago)   38d   10.244.151.133   k8s-master-01   <none>           <none>
calico-node-5ch6s                          1/1     Running   1 (12d ago)   38d   192.168.61.148   k8s-worker-01   <none>           <none>
calico-node-kqwjf                          1/1     Running   1 (12d ago)   38d   192.168.61.149   k8s-worker-02   <none>           <none>
calico-node-q8ztz                          1/1     Running   1 (12d ago)   38d   192.168.61.147   k8s-master-01   <none>           <none>
coredns-66f779496c-8hsjx                   1/1     Running   1 (12d ago)   38d   10.244.151.132   k8s-master-01   <none>           <none>
coredns-66f779496c-bdt8k                   1/1     Running   1 (12d ago)   38d   10.244.151.134   k8s-master-01   <none>           <none>
etcd-k8s-master-01                         1/1     Running   1 (12d ago)   38d   192.168.61.147   k8s-master-01   <none>           <none>
kube-apiserver-k8s-master-01               1/1     Running   1 (12d ago)   38d   192.168.61.147   k8s-master-01   <none>           <none>
kube-controller-manager-k8s-master-01      1/1     Running   2 (12d ago)   38d   192.168.61.147   k8s-master-01   <none>           <none>
kube-proxy-rph9c                           1/1     Running   0             51m   192.168.61.149   k8s-worker-02   <none>           <none>
kube-proxy-s4kd9                           1/1     Running   0             51m   192.168.61.148   k8s-worker-01   <none>           <none>
kube-proxy-zdx6t                           1/1     Running   0             51m   192.168.61.147   k8s-master-01   <none>           <none>
kube-scheduler-k8s-master-01               1/1     Running   2 (12d ago)   38d   192.168.61.147   k8s-master-01   <none>           <none>


部署 MetalLB

官方提供了好几种安装方式,yaml、helm、operator 等,这里使用 yaml 方式安装。
如果kube-proxy使用的是IPVS模式,在v1.14.2版本之后,需要启用strict ARP mode。

[root@k8s-master-01 ~]#  kubectl edit configmap -n kube-system kube-proxy
...
    ipvs:
      excludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: ""
      strictARP: true   # 启用strictARP
      syncPeriod: 0s
      tcpFinTimeout: 0s
      tcpTimeout: 0s
      udpTimeout: 0s
    kind: KubeProxyConfiguration
    logging:
      flushFrequency: 0
      options:
        json:
          infoBufferSize: "0"
      verbosity: 0
    metricsBindAddress: ""
    mode: "ipvs"      # kube-proxy模式,默认为iptables
    nodePortAddresses: null
    oomScoreAdj: null
...

# 重启kube-proxy生效
[root@k8s-master-01 ~]#  kubectl rollout restart daemonset/kube-proxy -n kube-system

kube-proxy默认使用的是iptables转发模式,在大规模集群中,建议改为ipvs。如果当前转发模式是ipvs,启用严格的 ARP。
  1. 创建 MetalLB 命名空间
[root@k8s-master-01 ~]#  kubectl create namespace metallb-system
  1. 使用Manifest安装MetalLB
    MetalLB 提供了一组清单文件来部署所需的组,使用如下命令部署:
[root@k8s-master-01 ~]#  curl https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml -O
kubectl apply -f metallb-native.yaml
查询官网文档获取最新的安装命令。https://metallb.io/installation/
  1. 验证安装
[root@k8s-master-01 ~]# kubectl get pods -n metallb-system
NAME                          READY   STATUS    RESTARTS   AGE
controller-56bb48dcd4-6qvx4   1/1     Running   0          65m
speaker-6k7m2                 1/1     Running   0          65m
speaker-jsckg                 1/1     Running   0          65m
speaker-kwzrm                 1/1     Running   0          65m

  1. 配置 MetalLB
    MetalLB 支持两种操作模式:Layer 2 模式和 BGP 模式。因为 BGP 对路由器有要求,POC测试时建议使用 Layer2 模式。
    Layer2模式配置:
    Layer 2 模式是最简单的配置方式:在许多情况下,你不需要任何特定协议的配置,只需要 IP 地址。
    Layer 2 模式不需要将 IP 绑定到你的工作节点的网络接口上。它通过直接响应本地网络上的 ARP 请求,向客户端提供机器的 MAC 地址来工作。
    Layer2模式配置,首先创建一个IPAddressPool资源对象:
[root@k8s-master-01 ~]#  cat ip-pool.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: ip-pool
  namespace: metallb-system
spec:
  addresses:
    - 192.168.61.156-192.168.61.160 #分配给LB的IP池

[root@k8s-master-01 ~]#  kubectl apply -f ip-pool.yaml
备注
  • IP地址池与集群IP位于同一个网段。
  • 多个实例IP地址池可以共存,并且可以分配IPV4和IPV6地址。

创建一个广播声明,关联上面的 IP 池对象:

cat advertise.yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: l2adver
  namespace: metallb-system
spec:
  ipAddressPools:
    - ip-pool

说明:

  • 如果不设置关联到 IPAdressPool,L2Advertisement 默认会关联所有可用的 IPAdressPool。
    Layer2模式demo应用示例
    为了验证 MetalLB 的配置是否正确,你可以创建一个简单的 Nginx 服务。
    创建一个 nginx-deployment.yaml 文件,内容如下
[root@k8s-master-01 ~]# cat nginx-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
[root@k8s-master-01 ~]# cat nginx-service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: LoadBalancer
[root@k8s-master-01 ~]# kubectl apply -f nginx-deployment.yaml
[root@k8s-master-01 ~]# kubectl apply -f nginx-service.yaml
[root@k8s-master-01 ~]# kubectl get svc
NAME            TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
kubernetes      ClusterIP      10.96.0.1      <none>           443/TCP        38d
nginx-service   LoadBalancer   10.96.64.154   192.168.61.156   80:32145/TCP   25m

posted @ 2024-08-23 16:04  一毛丶丶  阅读(294)  评论(0编辑  收藏  举报