kubernetes集群没有L4负载均衡,对外暴漏服务时,只能使用nodePort的方式,比较麻烦,必须要记住不同的端口号。
LoadBalancer:使用云提供商的负载均衡器向外部暴露服务,外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上。
MetalLB 是裸机 Kubernetes 集群的负载均衡器实现,使用标准路由协议。
它提供了两个功能:
不管是Layer2模式还是BGP模式,两者都不使用Linux的网络栈,即无法使用诸如ip
命令准确的查看VIP所在的节点和相应的路由,相对应的是在每个节点上面都能看到一个kube-ipvs0
网卡接口上面的IP。同时,两种模式都只是负责把VIP的请求引到对应的节点上面,之后的请求怎么到达pod,按什么规则轮询等都是由kube-proxy实现的。
对应的的两种工作负载:
LoadBalancer
的服务的EXTERNAL-IP
公布到网络中去,确保客户端能够正常访问到这个IP。apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.4
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 80
selector:
app: nginx
type: LoadBalancer
# 1. ipvs 开启严格 arp模式
$ kubectl edit configmap -n kube-system kube-proxy
...
ipvs:
strictARP: true
# 2. 安装组件
$ mkdir -p $HOME/metallb && cd $_
$ wget https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml
$ kubectl apply -f metallb-native.yaml
$ kubectl get pod -n metallb-system
NAME READY STATUS RESTARTS AGE
controller-6f5c46d94b-b7psv 1/1 Running 1 (29s ago) 80s
speaker-6v8hn 1/1 Running 0 80s
speaker-nzkb6 1/1 Running 0 79s
speaker-wjqxx 1/1 Running 0 79s
组件说明:
metallb-system/controller
:负责IP地址的分配,以及service和endpoint的监听metallb-system/speaker
:负责保证service地址可达,在Layer 2模式下,speaker会负责ARP请求应答并不是真正的负载均衡,因为流量都会先经过一个node后,再通过kube-proxy转给多个endpoints。如果该node故障,MetalLB会迁移 IP到另一个node,并重新发送ARP告知客户端迁移。
请求到达节点后,节点再通过 kube-proxy 将请求负载均衡目标 Pod。所以说,假如Service 是多 Pod 这里有可能会再跳去另一台主机。
配置 layer2 IP池 (layer2.yaml):
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: layer2-pool
namespace: metallb-system
spec:
addresses:
- 192.168.3.170-192.168.3.179
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: layer2-lb
namespace: metallb-system
spec:
ipAddressPools:
- layer2-pool
查看结果:
# 获取
$ kubectl get svc nginx-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc LoadBalancer 10.96.155.95 192.168.3.170 8080:31717/TCP 9m34s
$ kubectl get ep nginx-svc
NAME ENDPOINTS AGE
nginx-svc 10.244.172.62:80,10.244.172.63:80,10.244.46.53:80 9m38s
$ ipvsadm -Ln | grep 192.168.3.170 -A 3
TCP 192.168.3.170:8080 rr
-> 10.244.46.53:80 Masq 1 0 0
-> 10.244.172.62:80 Masq 1 0 0
-> 10.244.172.63:80 Masq 1 0 0
# 每个节点自动增加配置
$ ip addr show kube-ipvs0 | grep 192.168.3.170 -A 1
inet 192.168.3.170/32 scope global kube-ipvs0
valid_lft forever preferred_lft forever
查询实际的工作代理节点:
$ curl -I 192.168.3.170:8080
HTTP/1.1 200 OK
Server: nginx/1.21.4
Date: Thu, 10 Aug 2023 06:44:21 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 02 Nov 2021 14:49:22 GMT
Connection: keep-alive
ETag: "61814ff2-267"
Accept-Ranges: bytes
$ arp 192.168.3.170
Address HWtype HWaddress Flags Mask Iface
192.168.3.170 ether 52::00:63:8f:d3 C br0
$ ip addr | grep 52::00:63:8f:d3 -A 1 -B 1
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52::00:63:8f:d3 brd ff:ff:ff:ff:ff:ff
inet 192.168.3.105/24 brd 192.168.3.255 scope global ens3
kubectl delete -f layer2.yaml
kubectl get pod -n metallb-system | grep Running | awk '{print $1}' | xargs kubectl delete pod -n metallb-system
BGP模式不限于一个二层网络里,各个节点都会与交换机建立BGP Peer,宣告Service External IP的下一跳为自身,这样通过ECMP实现了一层负载。客户端请求通过交换机负载到后端某个节点后,再由Kube-proxy进行转发
通过 openwrt 旁路由实现 BGP。使用命令 vtysh
进行 AS 配置
本地:AS 65000
远端:AS 65001
$ vtysh
OpenWrt# conf t
OpenWrt(config)# router bgp 65000
OpenWrt(config-router)# neighbor 192.168.3.103 remote-as 65001
OpenWrt(config-router)# neighbor 192.168.3.103 description master-01
OpenWrt(config-router)# neighbor 192.168.3.104 remote-as 65001
OpenWrt(config-router)# neighbor 192.168.3.104 description worker-01
OpenWrt(config-router)# neighbor 192.168.3.105 remote-as 65001
OpenWrt(config-router)# neighbor 192.168.3.105 description worker-02
OpenWrt(config-router)# exit
OpenWrt(config)# exit
OpenWrt# show ip bgp summary
BGP router identifier 192.168.3.180, local AS number 65000
RIB entries 0, using 0 bytes of memory
Peers 3, using 27 KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
192.168.3.103 4 65001 0 6 0 0 0 never Active
192.168.3.104 4 65001 0 4 0 0 0 never Active
192.168.3.105 4 65001 0 3 0 0 0 never Active
Total number of neighbors 3
OpenWrt# exit
查看 bgpd 端口监听 179
是否已打开:
$ netstat -lantp | grep -E 'zebra|bgpd'
tcp 0 0 0.0.0.0:179 0.0.0.0:* LISTEN 5355/bgpd
tcp 0 0 0.0.0.0:2601 0.0.0.0:* LISTEN 5350/zebra
tcp 0 0 0.0.0.0:2605 0.0.0.0:* LISTEN 5355/bgpd
tcp 0 0 :::179 :::* LISTEN 5355/bgpd
tcp 0 0 :::2601 :::* LISTEN 5350/zebra
tcp 0 0 :::2605 :::* LISTEN 5355/bgpd
配置BPG IP池 (bgp.yaml):
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
name: sample
namespace: metallb-system
spec:
myASN: 65001
peerASN: 65000
peerAddress: 192.168.3.180
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.0.10-192.168.0.99
---
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: example
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
查看结果:
$ kubectl get svc nginx-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc LoadBalancer 10.96.167.171 192.168.0.10 8080:31323/TCP 25h
$ kubectl get ep nginx-svc
NAME ENDPOINTS AGE
nginx-svc 10.244.172.59:80,10.244.172.60:80,10.244.46.52:80 25h
# 每个节点均添加
$ ip addr show kube-ipvs0 | grep 192.168.0.10 -A 1
inet 192.168.0.10/32 scope global kube-ipvs0
valid_lft forever preferred_lft forever
$ curl -I 192.168.0.10:8080
HTTP/1.1 200 OK
Server: nginx/1.21.4
Date: Thu, 10 Aug 2023 03:39:37 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 02 Nov 2021 14:49:22 GMT
Connection: keep-alive
ETag: "61814ff2-267"
Accept-Ranges: bytes
$ ipvsadm -Ln | grep 192.168.0 -A 3
TCP 192.168.0.10:8080 rr
-> 10.244.46.52:80 Masq 1 0 0
-> 10.244.172.59:80 Masq 1 0 0
-> 10.244.172.60:80 Masq 1 0 0
客户端(windows, 192.168.3.3)添加路由:
route add 192.168.0.0 MASK 255.255.0.0 192.168.3.180
访问:https://192.168.0.10:8080 ok
kubectl delete -f bgp.yaml
kubectl get pod -n metallb-system | grep Running | awk '{print $1}' | xargs kubectl delete pod -n metallb-system
具体的方式是:创建两个Service,并加上metallb.universe.tf/allow-shared-ip
为Key的annotation
,表明Service能容忍使用共享的LoadBalancerIP;然后通过spec.loadBalancerIP
给两个Service指定共享的IP。
1)两个Service的metallb.universe.tf/allow-shared-ip
值是一样的。
2)两个Service的“端口”(带协议)不同,比如tcp/53
和udp/53
是属于不同的“端口”。
3)两个Service对应的后端Pod要一致,如果不一致,那么他们的externalTrafficPolicy需要都是Cluster,不然会无法进行正确的BGP。
在创建LoadBalancer
服务时,会默认创建一个nodeport
服务,可通过配置allocateLoadBalancerNodePorts
来关闭。
不同的loadbalancer实现原理不同,有的需要依赖nodeport来进行流量转发,有些则直接转发请求到pod中。
对于MetalLB而言,是通过kube-proxy将请求的流量直接转发到pod,因此可以关闭nodeport。
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
allocateLoadBalancerNodePorts: false
externalTrafficPolicy: Cluster
internalTrafficPolicy: Cluster
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 80
selector:
app: nginx
type: LoadBalancer
loadBalancerIP: 192.168.0.20
验证:
$ kubectl delete svc nginx-svc
$ kubectl apply -f nginx-svc-disable-nodeport.yaml
$ kubectl get svc nginx-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-svc LoadBalancer 10.96..226 192.168.0.20 8080/TCP 3s
优点:
缺点:
优点:
缺点:
BGP,Border Gateway Protocol,边界网关协议
BGP是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或“前缀”表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。
BGP的邻居关系(或称通信对端/对等实体,peer)是通过人工配置实现的,对等实体之间通过TCP端口179建立会话交换数据。BGP路由器会周期地发送19字节的保持存活(keep-alive)消息来维护连接(默认周期为60秒)。在各种路由协议中,只有BGP使用TCP作为传输层协议。
同一个AS自治系统中的两个或多个对等实体之间运行的BGP被称为iBGP(Internal/Interior BGP)。归属不同的AS的对等实体之间运行的BGP称为eBGP(External/Exterior BGP)。在AS边界上与其他AS交换信息的路由器被称作边界路由器(border/edge router),边界路由器之间互为eBGP对端。在Cisco IOS中,iBGP通告的路由距离为200,优先级比eBGP和任何内部网关协议(IGP)通告的路由都低。其他的路由器实现中,优先级顺序也是eBGP高于IGP,而IGP又高于iBGP。
iBGP和eBGP的区别主要在于转发路由信息的行为。例如,从eBGP peer获得的路由信息会分发给所有iBGP peer和eBGP peer,但从iBGP peer获得的路由信息仅会分发给所有eBGP peer。所有的iBGP peer之间需要全互联。
三个核心名词:
自制系统(Autonomous system,缩写 AS),是指在互联网中,一个或多个实体管辖下的所有IP 网络和路由器的组合,它们对互联网执行共同的路由策略。自治系统编号都是16位长的整数,这最多能被分配给65536个自治系统。自治系统编号被分成两个范围。第一个范围是公开的ASN,从1到511,它们可在互联网上使用;第二个范围是被称为私有编号的从512到65535的那些,它们仅能在一个组织自己的网络内使用。
简单理解,电信、移动、联通都有自己的 AS 编号,且不只一个。除了互联网公开的 ASN 以外,私有的编号可以在内部使用。比如我可以我的家庭网络中使用私有编号创建几个 AS。
内部路由协议(Interior Gateway Protocol,IGP)是指在一个自治系统(AS)内部所使用的一种路由协议。
外部网关协议(Exterior Gateway Protocol,EGP)是一个已经过时互联网路由协议。已由 BPG 取代。
BPG 是为了替换 EGP 而创建的,而除了应用于 AS 外部,也可以应用在 AS 内部。因此又分为 EBGP 和 IBGP。
wget https://mirrors.aliyun.com/openwrt/releases/19.07.4/targets/x86//openwrt-19.07.4-x86--combined-ext4.img.gz
gunzip openwrt-19.07.4-x86--combined-ext4.img.gz
cp openwrt-19.07.4-x86--combined-ext4.img openwrt.img
# 双网口(wan+lan)
virt-install --name=openwrt --vcpus=1 --ram=512 --os-type=generic --disk path=/root/eli/openwrt.img,bus=ide --autostart --network bridge=br0,model=e1000 --network bridge=br0,model=e1000 --import --noautoconsole --graphics vnc,listen=0.0.0.0,password=123456
# 单网口(lan)
virt-install --name=openwrt --vcpus=1 --ram=512 --os-type=generic --disk path=/root/eli/openwrt.img,bus=ide --autostart --network bridge=br0,model=e1000 --import --noautoconsole --graphics vnc
修改网络配置:
# 改成与宿主机在同一网络下
$ vi /etc/config/network
...
config interface 'lan'
option type 'bridge'
option ifname 'eth0'
option proto 'static'
option ipaddr '192.168.3.180'
option netmask '255.255.255.0'
option ip6assign '60'
option gateway '192.168.3.1'
option dns '114.114.114.114'
$ service network restart
登录配置页面:http://192.168.3.180
为了让 OpenWrt 支持 BGP,需要安装路由软件套件 Quagga。它提供了 OSPFv2、OSPFv3、RIP v1 v2、RIPng 和 BGP-4 的实现。
Quagga 架构由核心守护进程和 zebra 组成,后者作为底层 Unix 内核的抽象层,并通过 Unix 或者 TCP 向 Quagga 客户端提供 Zserv API。正是这些 Zserv 客户端实现了路由协议,并将路由的更新发送给 zebra 守护进程。当前 Zserv 的实现:
Quagga 的守护进程可以通过网络可访问的 CLI(简称 vty)进行配置。 CLI 遵循与其他路由软件类似的风格。还额外提供了一个工具 vtysh,充当了所有守护进程的聚合前端,允许在一个地方管理所有 Quagga 守护进程的所有功能。
$ opkg update && opkg install quagga quagga-zebra quagga-bgpd quagga-vtysh
$ netstat -lantp | grep -E 'zebra|bgpd'
tcp 0 0 0.0.0.0:2601 0.0.0.0:* LISTEN 5350/zebra
tcp 0 0 0.0.0.0:2605 0.0.0.0:* LISTEN 5355/bgpd
tcp 0 0 :::2601 :::* LISTEN 5350/zebra
tcp 0 0 :::2605 :::* LISTEN 5355/bgpd
参考资料:
https://metallb.universe.tf/configuration/
https://tinychen.com/20220519-k8s-06-loadbalancer-metallb/
https://atbug.com/load-balancer-service-with-metallb-bgp-mode/
https://ieevee.com/tech/2019/06/30/metallb.html
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- yrrf.cn 版权所有 赣ICP备2024042794号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务