MetalLB是一个开源的负载均衡器,为私有云环境中的k8s集群设计。使用标准网络协议来实现外部流量的负载均衡,使k8s可以跟像公有云环境一样使用loadbalancer类型的service。MetalLB也是CNCF的沙盒项目
Installation :: MetalLB, bare metal load-balancer for Kubernetes
这种方法的下位替代就是做haproxy+NodePort,也可以起到负载均衡的作用
工作模式
- 分配一个地址池,从地址池中拿IP分配给LB service
- 分配地址后使用Layer2/BGP模式
L2模式直接使用ARP和NDP进行通告
BGP模式需要与网络设备建立会话,通告负载均衡地址
使用metallb,其实是在地址池里分了个ip当做某个服务的VIP,不需要像nodeport一样关心访问的节点和端口是哪个,直接访问这个VIP就完事了,而且可以提供标准的端口,更加清爽与安全
MetalLB组件
- Controller:deployment,负责监听k8s service的变更,分配和回收地址
- Speaker:daemonset,负责对外广播service的IP地址
除了资源文件部署还可以通过helm部署,但是略过了,因为这个东西不需要手动配置什么,那helm肯定更加简单
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| 如果使用的是calico,且使用的是ipvs模式 需要修改kube-proxy配置 kubectl get configmap kube-proxy -n kube-system -o yaml | \ sed -e "s/strictARP: false/strictARP: true/" | \ kubectl apply -f - -n kube-system
kubectl -n kube-system rollout restart daemonset kube-proxy
直接使用配置安装 kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.15.2/config/manifests/metallb-native.yaml
我的MetalLB版本是v0.15.2 需求镜像: quay.io/metallb/controller:v0.15.2 quay.io/metallb/speaker:v0.15.2
kubectl get pods -n metallb-system NAME READY STATUS RESTARTS AGE controller-679d565488-xmhgj 1/1 Running 0 21m speaker-52q4b 1/1 Running 0 21m speaker-8pqqc 1/1 Running 0 21m speaker-d2t9s 1/1 Running 0 21m speaker-hq86m 1/1 Running 0 21m speaker-tvfl4 1/1 Running 0 21m speaker-w9tbh 1/1 Running 0 21m
创建地址池资源 cat > metaippool.yaml <<EOF apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: ip-pool namespace: metallb-system spec: addresses: - 10.163.2.200-10.163.2.220 --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: example namespace: metallb-system spec: ipAddressPools: - ip-pool EOF kubectl apply -f metaippool.yaml
kubectl get IPAddressPool -A NAMESPACE NAME AUTO ASSIGN AVOID BUGGY IPS ADDRESSES metallb-system ip-pool true false ["10.163.2.200-10.163.2.220"]
|
创建测试service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| cat > empty-svc.yaml << EOF apiVersion: v1 kind: Service metadata: name: empty-service spec: type: LoadBalancer ports: - port: 80 targetPort: 80 EOF
kubectl apply -f empty-svc.yaml kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE csi-metrics-rbdplugin ClusterIP 10.233.6.103 <none> 8080/TCP 22h csi-rbdplugin-provisioner ClusterIP 10.233.38.11 <none> 8080/TCP 22h empty-service LoadBalancer 10.233.32.246 10.163.2.200 80:31546/TCP 1s kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 4d14h
|
可以看到这个空service已经获得了一个VIP
后记
如果只用metallb还会存在一个问题,每个service都需要占用一个VIP,那服务一多不就炸了吗,所以可以与ingress结合,这样使用就可以只使用同一个IP/域名
再结合ingress路由或者双层代理的方式将流量路由到后端pod