背景
在K8S/OpenShift中,如果要向集群外部暴露应用的服务,目前使用的方法有:NodePort、HostPort、Route、LoadBalancer、HostNetwork。
- Route:为最常用的方法,但是一般只支持7层负载(默认),使用一个外部LB来负载多个Route实例,对外的访问的IP为该LB的IP。
- NodePort:在私有集群中也常用来暴露服务,但是它必须使用30000以上的端口,数量有限,不便于管理,而且对于一些特殊的服务,如DNS,必须使用小端口号,那么使用NodePort则无法满足。
- HostNetwork:对于集群中的一些特殊服务使用该方式,它将容器与宿主机的网络绑定,如OpenShift中的Router服务就是使用HostNetwork与Router节点绑定。它的缺点是pod必须与主机绑定,同时每个Node上只能运行一个Pod实例,因为端口无法被复用。
- HostPort:与HostNetwork类似,将Pod指定的端口与Node对应的端口绑定。
- LoadBalancer:一般只在公有云平台使用,可以使Service获得与主机同一平面的IP,方便对服务进行控制与对外输出。缺点是依赖于公有云平台。
从上可看出对于HTTP服务使用Route可以很方便地对外提供服务,而对于TCP/UDP服务比较好的方式是使用LoadBalancer(当然HTTP服务也方便使用该方式),但是它依赖于云平台,有没有一种方式能够帮助集群在非IaaS平台上使用LoadBalancer方式呢?答案是有的,那就是Google的项目MetalLB。
什么是MetalLB
MetalLB的官方地址:https://metallb.universe.tf/
MetalLB是使用标准路由协议的裸机Kubernetes/OpenShift集群的软负载均衡器,可以在物理机环境下实现对Service服务分配IP。
MetalLB支持两种申明模式:
- Layer 2模式:ARP/NDP
Layer 2模式下,每个service会有集群中的一个node来负责。当服务客户端发起ARP解析的时候,对应的node会响应该ARP请求,之后,该service的流量都会指向该node(看上去该node上有多个地址)。
Layer 2模式并不是真正的负载均衡,因为流量都会先经过1个node后,再通过kube-proxy转给多个end points。如果该node故障,MetalLB会迁移 IP到另一个node,并重新发送免费ARP告知客户端迁移。现代操作系统基本都能正确处理免费ARP,因此failover不会产生太大问题。
Layer 2模式更为通用,不需要用户有额外的设备;但由于Layer 2模式使用ARP/ND,地址池分配需要跟客户端在同一子网,地址分配略为繁琐。同时Layer 2模式所有流量会进入到一个Node,该Node的带宽可能会成为一个网络瓶颈。
- BGP模式。
BGP模式下,集群中所有node都会跟上联路由器建立BGP连接,并且会告知路由器应该如何转发service的流量。
BGP模式是真正的LoadBalancer。
MetalLB由两个组件组成:
- controller,负责IP地址的分配,以及service和endpoint的监听。
- speaker,负责保证service地址可达,例如Layer 2模式下,speaker会负责ARP请求应答。
部署MetalLB
Kubernetes
- 安装metalLB相关的应用
# kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.1/manifests/metallb.yaml
- 创建configmap配置
# cat << EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.1.240-192.168.1.250
EOF
OpenShift
- 关闭OpenShift自带的LoadBalancer功能,这一步很重要,否则会跟
删除
/etc/origin/master/master-config.yaml中的externalIPNetworkCIDRs
设置
networkConfig:
externalIPNetworkCIDRs:
- 0.0.0.0/0
- 下载MetalLB安装文件
# wget https://raw.githubusercontent.com/google/metallb/v0.8.1/manifests/metallb.yaml
- 删除将文件中DaemonSet资源中的配置
spec.template.spec.securityContext.runAsUser
- 添加权限
# oc adm policy add-scc-to-user privileged -n metallb-system -z speaker
- 运行安装
# oc apply -f metallb.yaml
- 创建configmap配置
# cat << EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.1.240-192.168.1.250
EOF
测试
- 对已有的一个应用创建新LoadBalancer类型的svc
[root@master1 ~]# oc expose dc/flask-app --name=metallb-app --type=LoadBalancer --port=5000
- 查看当前svc的状态
[root@master1 ~]# oc get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
flask-app ClusterIP 172.30.193.89 <none> 5000/TCP 35d
metallb-app LoadBalancer 172.30.7.121 192.168.1.240,172.29.114.1 5000:32276/TCP 6m
其中service flask-app为之前创建的ClusterIP类型;service metallb-app为新建的LoadBalancer类型的服务,它带有一个由MetalLB控制器分配的一个IP 192.168.1.240
(另外还有一个OpenShift分配的一个额外IP 172.29.114.1,该IP可忽略)。
- 使用openshift集群外部的机器访问该应用
[root@i-avler8qs ~]# curl http://192.168.1.240:5000
Hello world v2
总结
在没有使用了LoadBalancer(如MetalLB)前,OpenShift上的Service像是待在这里的宠物,外部访问它非常受限;使用了LoadBalancer后,Service主动向外面世界敞开了怀抱,每个Service都绑定有一个独立的IP,方便外部应用访问,同时也方便使用传统的防火墙方式进行控制访问。
LoadBalancer扩大了对OpenShift/Kubernetes集群使用的想象空间,而MetalLB无疑是性价比最高的方式。
参考文章
MetalLB - 贫苦 K8S 用户的负载均衡支持
为裸金属K8S集群提供外部负载均衡器
OpenShift上安装MetalLB
网友评论