kind(本地docker模拟k8s集群) 部署MetalLB

kind Ingress 采用 Kubernetes Ingress控制器Nginx 实现服务对外输出后,如果要像云计算厂商一样提供完整可控的服务,还需要部署 Kubernetes MetalLB 负载均衡 来为 裸金属(bare-metal) NGINX Ingress 提供类似云厂商的 LoadBalancer 。Kind通过安装标准的 Kubernetes MetalLB 负载均衡 就能具备完整的服务输出能力。

安装

安装MetalLB 有多种方法,比较简单的是采用 kubectl apply 通过Manifest方式安装:

  • 通过编辑当前集群的 kube-proxy 配置实现:

通过编辑 kube-proxy 配置激活 strict ARP
kubectl edit configmap -n kube-system kube-proxy

设置:

设置 ipvs 模式中 strictARP: true
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true
  • 执行以下 manifest 完成MetalLB安装:

使用Manifest方式安装MetalLB
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml
  • 执行以下命令等待 MetalLB pods (controller 和 speakers)就绪:

等待 MetalLB pods (controller 和 speakers)就绪
kubectl wait --namespace metallb-system \
                --for=condition=ready pod \
                --selector=app=metallb \
                --timeout=90s

一切正常的话会看到以下输出:

等待 MetalLB pods (controller 和 speakers)就绪的输出信息
pod/controller-84d6d4db45-xtgmj condition met
pod/speaker-2cpfg condition met
pod/speaker-2ffjg condition met
pod/speaker-8t8tj condition met
pod/speaker-9c727 condition met
pod/speaker-l942f condition met
pod/speaker-tmxt8 condition met
pod/speaker-wjxhh condition met
pod/speaker-x4fv4 condition met

配置

  • 首先检查 kind (bridge)网络 docker 分配的IP地址段:

检查 kind (bridge)网络的IP地址段
docker network inspect -f '{{.IPAM.Config}}' kind

可能类似以下输出信息(我的kind网络):

检查 kind (bridge)网络的IP地址段输出信息
[{172.22.0.0/16  172.22.0.1 map[]}]

可以看到我部署的 kind 集群分配的节点网络IP地址(可路由访问外网的IP地址,也就是每个node节点分配的IP地址) 是 172.22.0.0/16

  • 需要 一部分地址保留给 MetalLB 来分配作为负载均衡对外VIP的地址,所以配置 metallb-config.yaml 如下:

分配一段IP地址保留给MetalLB用于对外VIP实例
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: dev-ip-pool
  namespace: metallb-system
spec:
  addresses:
  - 172.22.255.200-172.22.255.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: dev-ip-pool
  namespace: metallb-system
spec:
  ipAddressPools:
  - dev-ip-pool

备注

这里同时定义了 dev-ip-pool 地址池( kind: IPAddressPool ),并且声明了ARP公告( kind: L2Advertisement ) 这样外部才能访问到

奇怪,我这里在 ARP公告( kind: L2Advertisement ) 没有像 在Cilium网络部署MetalLB 那样设置spec,似乎也能访问

  • 应用地址:

应用MetalLB的配置
kubectl apply -f metallb-config.yaml

提示信息:

应用MetalLB的配置
ipaddresspool.metallb.io/dev-pool created
l2advertisement.metallb.io/dev created

应用LoadBalancer

部署 fedora-dev-tini (未设置LoadBalancer服务类型)检查 kubectl get services
% kubectl get services
NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                 AGE
fedora-dev-service   ClusterIP   10.96.175.32    <none>        22/TCP,80/TCP,443/TCP   47h
修订 kind部署 fedora-dev-tini (tini替代systmed) 使用的 fedora-dev-tini-deployment.yaml 服务类型改成 LoadBalancer
---
apiVersion: v1
kind: Service
metadata:
  name: fedora-dev-service
  labels:
    app: fedora-dev-tini
spec:
  type: LoadBalancer
  ports:
    - name: ssh
      protocol: TCP
      port: 22
      targetPort: 22
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
    - name: https
      protocol: TCP
      port: 443
      targetPort: 443
  selector:
    app: fedora-dev-tini
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: fedora-dev-tini
spec:
  replicas: 1
  selector:
    matchLabels:
      app: fedora-dev-tini
  template:
    metadata:
      labels:
        app: fedora-dev-tini
    spec:
      containers:
      - name: fedora-dev-tini
        image: localhost:5001/fedora-dev-tini:latest
        ports:
          - containerPort: 22
            name: ssh
            protocol: TCP
  • 执行修订:

将修订后 fedora-dev-tini 更新部署到kind集群
kubectl apply -f fedora-dev-tini-deployment.yaml

检查服务,可以看到 fedora-dev-service 类型已经从 ClusterIP 改为 LoadBalancer ,并且分配了一个外部可访问IP 172.22.255.201 ,这个地址就是Kubernetes集群外面的用户可以访问的服务IP地址(而不是之前只能在Kubernetes集群内部访问的IP地址 10.96.175.32 )

配置 fedora-dev-tini 设置LoadBalancer服务类型后 kubectl get services 显示服务具备了 EXTERNAL-IP
% kubectl get svc
NAME                 TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                                   AGE
fedora-dev-service   LoadBalancer   10.96.175.32    172.22.255.201   22:32440/TCP,80:31218/TCP,443:32049/TCP   4d1h

备注

这里 Ports 显示是 22:32440/TCP,80:31218/TCP,443:32049/TCP 表示什么意思?

不过,我确实从 kind集群本地Registry 部署的 registry 容器(这个容器比较特殊,配置了 kind 网络,也配置了docker默认 bridge 网络,是一个跨网络pod,所以可以作为桥接测试)能够直接 ssh 172.22.255.201 登陆到容器 fedora-dev-tini 了,证明负载均衡转发是成功的

接下来是如何结合 Kubernetes Ingress控制器Nginx 来构建完成的网络流量链路了(HTTP/HTTPS)

此外,还需要解决 Docker Desktop for mac 端口转发(port forwarding) 以便能够从外部访问Docker VM内部构建的 kind(本地docker模拟k8s集群) 集群输出的 LoadBalancer ( MetalLB ) 的IP对应服务(折腾^_^)

参考