前言
在 Kubernetes 集群中,要想使用 LoadBalancer 类型的 service 暴露服务,都需要将集群部署在特定 IaaS 平台上。云厂商通常为 Kubernetes 提供云上的 LB 插件,然而,许多企业用户通常都将 Kubernetes 集群部署在裸机上,尤其是用于生产环境时。而且对于本地裸机集群,无法使用 LoadBalancer。
附:LoadBalancer原理
-
LoadBalancer 通过云厂商的 LB 插件实现,LB 插件基于 kubernetes.io/cloud-provider 这个包实现,这个包会自动选择合适的后端暴露给 LB 插件,然后 LB 插件由此创建对应的负载均衡器。
-
网络流量在云服务端就会被分流,就能够避免 NodePort 方式的单点故障和性能瓶颈(NodePort 是将集群中的一个主机作为跳板访问后端服务,所有的流量都会经过跳板机,很容易造成性能瓶颈和单点故障,而且经过了一层snat,pod无法看到真正的IP。)
阿里云企业版3.12,ack 使用的是 cloud-controller-manager ,创建集群时它会自动创建公网slb,把worker的nginx-ingress pod绑定到后端提供对外访问。
OpenELB介绍
官网地址:https://openelb.io/
GitHub地址:https://github.com/openelb/openelb
OpenELB 是由 KubeSphere 开发团队设计、经过 CNCF 认证的一款负载均衡插件。它可以在裸金属服务器、边缘以及虚拟化的 Kubernetes 环境中使用 LoadBalancer 类型的 Service 对外暴露服务。
主要特点
- BGP 模式和二层网络模式下的负载均衡
- ECMP 路由和负载均衡
- IP 池管理
- 基于 CRD 来管理 BGP 配置
- 支持 Helm Chart 方式安装
原理
ECMP
ECMP(Equal-Cost Multi-Pathing,等价路由)即存在多条到达同一个目的地址的相同开销的路径。当设备支持等价路由时,发往该目的 IP 或者目的网段的三层转发流量就可以通过不同的路径分担,实现网络的负载均衡,并在其中某些路径出现故障时,由其它路径代替完成转发处理,实现路由冗余备份功能。
借助于路由器(虚拟路由器),对于某一个IP(对应服务的VIP),ECMP能根据一定的Hash算法从已知的路由中来选择下一跳(Pod),从而实现负载均衡的目的。一般的路由器(虚拟路由器)都具备 ECMP 的能力,OpenELB 要做的就是查询 Kubernetes API Server,将一个服务对应的后端 Pod 信息通过路由的方式发送给路由器。
BGP
在Kubernetes中,Pod可能会漂移,对于路由器来说,一个服务VIP的下一跳是不固定的,等价路由的信息会经常更新。和calico一样,OpenELB 使用了 BGP 实现路由的广播。
上图简单描述了 OpenELB 中 BGP 的实现原理。图中左下是一个两节点的 Kubernetes 集群,集群上方是有两个路由器 leaf1 和 leaf2,leaf 连接了核心交换机层 spine,也同样是两个。最右侧是用户,对应的路由器是 border,border 也连接了 spine,用户和 Kubernetes 服务器三层是可达的。
Kubernetes 集群中创建了 Service,并且使用了 OpenELB,OpenELB 为其分配了一个 1.1.1.1 的 VIP(或者手工指定),OpenELB 通过 BGP 告知 leaf1 和 leaf2,访问 1.1.1.1 的下一跳可以是 node1,也可以是 node2。leaf 一层也会将这个信息告知 spine,spine 的 BGP 经过计算得知访问 1.1.1.1 的下一跳是 leaf1,leaf2。按照同样的逻辑,这个路由也会更新到 border,这样用户访问 1.1.1.1 的完整路径就有了。
同时,由于这个图中每一层都有HA,所以外界访问 1.1.1.1 的路径就有 2*4= 16 条,流量能够在整个网络中被分流,并且任意一层一个路由器宕机都不会影响用户的访问。
架构
OpenELB有两个组件,一个核心控制器和一个部署在所有节点上的 agent。核心控制器主要功能有:
- 监控集群中的 Service 以及对应的 endpoints,获取 Pod漂移信息
- VIP 存储与分配
- 与外界建立 BGP 协议,广播路由
agent 则是一个轻量级组件,用于监控 VIP 资源,增加 Iptables 规则让外部流量能够访问 VIP,默认情况下外部流量访问 VIP 会被内核中的 Forward 表 Drop 掉。
安装
1.在Kubernetes集群中安装
直接使用kubectl安装
kubectl apply -f https://raw.githubusercontent.com/openelb/openelb/master/deploy/openelb.yaml
查看pod
k get po -n openelb-system
openelb-keepalive-vip是agent,openelb-manager是控制中心。
2.使用helm安装
helm repo add test https://charts.kubesphere.io/test
helm repo update
helm install openelb test/openelb
3.在kubeSphere中安装
添加应用仓库
选择企业空间,仓库管理,添加。
创建应用
选择项目,应用负载,应用,创建基于模版的应用。
选择仓库,搜索openelb
点击安装
使用
在 Layer2 使用
1.开启 kube-proxy 的 strictARP
# 修改false为true
kubectl edit configmap kube-proxy -n kube-system
# 重启kube-proxy
kubectl rollout restart daemonset kube-proxy -n kube-system
2.指定 OpenELB 使用的网卡
查看当前master的annotations
k describe node | grep -A5 Annotations
kubectl annotate nodes wghdr layer2.openelb.kubesphere.io/v1alpha1="172.17.88.228"
3.创建eip project
eip project声明了 OpenELB 使用的ip地址池。
cat layer2-eip.yaml
apiVersion: network.kubesphere.io/v1alpha2
kind: Eip
metadata:
name: layer2-eip
spec:
# address必须和集群node在同一个网段下
address: 172.17.88.100-172.17.88.200
interface: eth0
protocol: layer2
kubectl apply -f layer2-eip.yaml
4.创建deployment
使用 luksa/kubia 镜像,外部请求只返回自己的 pod name。
cat layer2-openelb.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: layer2-openelb
spec:
replicas: 1
selector:
matchLabels:
app: layer2-openelb
template:
metadata:
labels:
app: layer2-openelb
spec:
containers:
- image: luksa/kubia
name: kubia
ports:
- containerPort: 8080
kubectl apply -f layer2-openelb.yaml
5.创建服务
cat layer2-svc.yaml
kind: Service
apiVersion: v1
metadata:
name: layer2-svc
annotations:
# 声明service使用OpenELB
lb.kubesphere.io/v1alpha1: openelb
# 声明OpenELB使用layer2模式
protocol.openelb.kubesphere.io/v1alpha1: layer2
# 声明OpenELB使用的eip project
eip.openelb.kubesphere.io/v1alpha2: layer2-eip
spec:
selector:
app: layer2-openelb
# 类型必须是LoadBalancer
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 8080
# 如果是 local,OpenELB在集群中随机选择一个包含Pod的节点来处理服务请求,请求只能到达这个node上。
externalTrafficPolicy: Cluster
kubectl apply -f layer2-svc.yaml
6.确认OpenELB工作在layer 2
kubectl get svc
可以看到layer2-svc类型为LoadBalancer,EXTERNAL-IP为172.17.88.100。
ip neigh
ping 172.17.88.100 -c 4
curl 172.17.88.100
我这里ping不通,curl通,猜测是云厂商底层限制了ARP包。
在bgp模式中使用
没有实测,和layer2不同的是需要创建 BgpConf, BgpPeer,不需要开启 kube-proxy 的 strictARP。
参考链接:https://openelb.io/docs/getting-started/usage/use-openelb-in-bgp-mode/
在VIP模式中使用
这个模式还处于beta阶段,且不支持节点多网卡。与layer2不同的是Eip的协议指定为vip。
参考链接:https://openelb.io/docs/getting-started/use-openelb-in-vip-mode-beta/
注意
如果openelb-manager处于pending状态,可能的原因是443端口冲突了,比如ingress-controller。需要修改openelb-manager的端口。
kubectl edit deployment openelb-manager -n openelb-system
spec:
template:
spec:
container:
- args:
- --webhook-port=443
ports:
- containerPort: 443
hostPort: 443
总结
如果你的kubernets集群是在云上的,可以测试layer2模式,但最好还是使用云服务商提供的 Cloud LoadBalancer plugin。OpenELB是为非云上的集群提供服务的。
当前 OpenELB 版本为0.5.1,支持基于keepalived实现VIP模式下的高可用性(beta),可以和 KubeSphere 集成。
预计今年7月会支持 IPv6,BGP 策略,Prometheus metrics监控,OpenELB Web UI 。