MetalLB简介
MetalLB 是为裸机Kubernetes集群实现的负载均衡器,使用标准路由协议ARP或BGP。Kubernetes官方没有为裸机集群提供网络负载均衡器(LoadBalancer类型的服务)的实现。各家云厂商(GCP、AWS、Azure…)有相应实现,但必须运行在自身的云环境上才能使用,如果没有在受支持的IaaS平台(GCP、AWS、Azure…)上运行,那么负载均衡器在创建时将无限期地保持pending状态。
裸机集群环境剩下两个较小的工具来将用户流量引入他们的集群,“NodePort”和“externalIPs”服务。这两种选择在生产使用方面都有很大的缺点,这使得裸机集群成为 Kubernetes 生态系统中的二等公民。
MetalLB 旨在通过提供与标准网络设备集成的网络负载均衡器实现来纠正这种不平衡,以便裸机集群上的外部服务也尽可能“正常工作”。
MetalLB 由David Anderson开发,直到 2019 年 3 月,MetalLB 的版权归谷歌所有,目前已经脱离谷歌,原作者现在已经授权一个维护人员团队协助推进项目。
官方网站:https://metallb.universe.tf 项目地址:https://github.com/metallb/metallb
Metallb原理
Metallb 会在 Kubernetes 内运行,监控服务对象的变化,一旦察觉有新的LoadBalancer 服务运行,并且没有可申请的负载均衡器之后,就会完成两部分的工作:
1.地址分配 用户需要在配置中提供一个地址池,Metallb 将会在其中选取地址分配给服务。
2.地址广播 根据不同配置,Metallb 会以二层(ARP/NDP)或者 BGP 的方式进行地址的广播。
基本原理图:
Metallb 支持两种模式:
- Layer2
- BGP
MetalLB安装
1、前提条件
已准备kuberntes集群:v1.23.6,已准备网络插件:calico等。
root@master:~# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master Ready control-plane,master 8d v1.23.6 192.168.72.30 <none> Ubuntu 22.04 LTS 5.15.0-27-generic cri-o://1.23.2
worker1 Ready <none> 8d v1.23.6 192.168.72.31 <none> Ubuntu 22.04 LTS 5.15.0-27-generic cri-o://1.23.2
worker2 Ready <none> 8d v1.23.6 192.168.72.32 <none> Ubuntu 22.04 LTS 5.15.0-27-generic cri-o://1.23.2
如果在 IPVS 模式下使用 kube-proxy,从 Kubernetes v1.14.2 开始,必须启用严格的 ARP模式。请注意,如果使用 kube-router 作为服务代理,则不需要这个,因为它默认启用严格的 ARP。
可以通过在当前集群中编辑 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
2、Metallb 安装 Metallb 支持 yaml文件、Kustomize、Helm 和 MetalLB Operator多种安装方法,这里使用yaml方式进行安装。
下载release版本
wget https://github.com/metallb/metallb/archive/refs/tags/v0.12.1.tar.gz
tar -zxvf metallb-0.12.1.tar.gz
cd metallb-0.12.1/manifests
执行yaml文件进行安装
kubectl apply -f namespace.yaml
kubectl apply -f metallb.yaml
查看运行的pods,metalLB包含两个部分: a cluster-wide controller, and a per-machine protocol speaker.
root@ubuntu:/data/k8s/metallb-0.12.1/manifests# kubectl -n metallb-system get pods
NAME READY STATUS RESTARTS AGE
controller-57fd9c5bb-txv25 1/1 Running 0 63m
speaker-8sfx2 1/1 Running 0 63m
speaker-hpblt 1/1 Running 0 63m
speaker-hpwm7 1/1 Running 0 63m
查看其它信息,包含了 “controller” deployment,和 the “speaker” DaemonSet.
root@ubuntu:/data/k8s/metallb-0.12.1/manifests# kubectl -n metallb-system get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
controller 1/1 1 1 64m
root@ubuntu:/data/k8s/metallb-0.12.1/manifests# kubectl -n metallb-system get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
speaker 3 3 3 3 3 kubernetes.io/os=linux 64m
目前还没有宣布任何内容,因为我们没有提供ConfigMap,也没有提供负载均衡地址的服务。接下来要生成一个 Configmap 文件,为 Metallb 设置网址范围以及协议相关的选择和配置,这里以一个简单的二层配置为例。
配置Layer2模式
创建config.yaml提供IP地址池,查看提供的默认示例configmap
root@ubuntu:/data/k8s/metallb-0.12.1/manifests# cat example-layer2-config.yaml
修改ip地址池,从集群IP地址段中为MetalLB分配部分IP地址:
root@ubuntu:/data/k8s/metallb-0.12.1/manifests# vim example-layer2-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.72.200-192.168.72.250
执行yaml文件
kubectl apply -f example-layer2-config.yaml
创建后端应用和服务测试
root@ubuntu:/data/k8s/metallb-0.12.1/manifests# kubectl apply -f tutorial-2.yaml
查看yaml文件配置,包含了一个deployment和一个LoadBalancer类型的service,默认即可。
root@ubuntu:/data/k8s/metallb-0.12.1/manifests# cat tutorial-2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1
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
查看service分配的EXTERNAL-IP
[centos@k8s-master ~]$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d15h
nginx LoadBalancer 10.101.112.1 192.168.72.200 80:31274/TCP 123m
从集群外访问该IP地址
配置BGP模式
1、frr安装,准备一个Ubuntu 22.04节点192.168.72.16作为frr路由器。
创建/etc/frr/daemons配置文件
podman run --name frr docker.io/frrouting/frr:v8.2.2
mkdir /etc/frr
podman cp frr:/etc/frr/daemons /etc/frr/daemons
启用bgp模式
sed -i 's#bgpd=no#bgpd=yes#g' /etc/frr/daemons
创建bgp配置文件
cat >/etc/frr/bgpd.conf<<EOF
! -*- bgp -*-
hostname ukw-p-rtr-01
frr defaults datacenter
log file stdout
service integrated-vtysh-config
!
!
router bgp 65000
bgp router-id 192.168.72.16
neighbor 192.168.72.30 remote-as 65001
neighbor 192.168.72.31 remote-as 65001
neighbor 192.168.72.32 remote-as 65001
!
address-family ipv4 unicast
redistribute connected
redistribute kernel
neighbor V4 soft-reconfiguration inbound
neighbor V4 route-map ALLOW-ALL in
neighbor V4 route-map ALLOW-ALL out
exit-address-family
!
route-map ALLOW-ALL permit 10
!
line vty
!
EOF
启动frr容器
podman run -d --name frr-upstream \
-v /etc/frr:/etc/frr:Z \
--net=host \
--privileged \
docker.io/frrouting/frr:v8.2.2
查看bgp配置
podman exec -it frr-upstream vtysh
ubuntu# show ip bgp neighbor
ubuntu# show ip bgp summary
IPv4 Unicast Summary (VRF default):
BGP router identifier 192.168.72.16, local AS number 65000 vrf-id 0
BGP table version 3
RIB entries 3, using 552 bytes of memory
Peers 3, using 2149 KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
192.168.72.30 4 65001 86 380 0 0 0 00:04:09 1 3 N/A
192.168.72.31 4 65001 86 381 0 0 0 00:04:09 1 3 N/A
192.168.72.32 4 65001 86 393 0 0 0 00:04:09 1 3 N/A
Total number of neighbors 3
删除原有configmap配置,重新配置
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
peers:
- peer-address: 192.168.72.16
peer-asn: 65000
my-asn: 65001
address-pools:
- name: default
protocol: bgp
addresses:
- 192.168.72.150-192.168.72.199
删除控制器 pod 进行重启,此时可以看到 Service 分配到了新的 IP:
kubectl -n metallb-system delete pods -l app=metallb,component=controller
检查 speaker POD 的日志,可以看到与 peer 192.168.72.16 之间的通信已经开始,并对外发布了 IP 地址的公告:
root@master:~# kubectl -n metallb-system logs -f speaker-8sfx2 |grep 192.168.72.16
{"caller":"level.go:63","configmap":"metallb-system/config","event":"peerAdded","level":"info","msg":"peer configured, starting BGP session","peer":"192.168.72.16","ts":"2022-04-29T09:47:27.801204546Z"}
{"caller":"level.go:63","event":"sessionUp","level":"info","localASN":65001,"msg":"BGP session established","peer":"192.168.72.16:179","peerASN":65000,"ts":"2022-04-29T09:47:27.804513819Z"}
然后可以在 frr 路由器节点查看路由表,从表中可以找到 192.168.72.150/32
和 192.168.72.151/32
两条 BGP 的路由。
root@ubuntu:~# ip route
default via 192.168.72.8 dev ens160 proto static
10.88.0.0/16 dev cni-podman0 proto kernel scope link src 10.88.0.1 linkdown
192.168.72.0/24 dev ens160 proto kernel scope link src 192.168.72.16
192.168.72.150 nhid 29 proto bgp metric 20
nexthop via 192.168.72.30 dev ens160 weight 1
nexthop via 192.168.72.31 dev ens160 weight 1
nexthop via 192.168.72.32 dev ens160 weight 1
192.168.72.151 nhid 29 proto bgp metric 20
nexthop via 192.168.72.30 dev ens160 weight 1
nexthop via 192.168.72.31 dev ens160 weight 1
nexthop via 192.168.72.32 dev ens160 weight 1
说在最后:
公众号内容:将主要以 “DevOps K8S” 主题为主,小伙伴们想要了解云原生、DevOps和Kubernetes技术的同学不要错过。 提供价值:订阅 “运维狗工作日记” 微信公众号,将收到相关技术资讯、独家的开源技术实践案例和技术策略建议。 当然这里还可以了解最新的云计算和容器技术、DevOps最佳实践和自动化工具等相关领域的最新动态和趋势。 后续我准备将近7年的DEVOPS搞成合集,例如:“监控”,“CICD”,“运维管理”,“可观测性”等,展示给大家,咱们共同学习探讨。 现在还没有群,后续大家有疑问了我再创建吧。