K8S 用户的负载均衡支持
简介
在私有网络上运行 Kubernetes,和御三家相比,对 LoadBalancer
类型的服务的支持应该是众多表面差异中最醒目的一个了。类型为 LoadBalancer
的服务在 Kubernetes 中并没有直接支持,NodePort 和 ExternalIP 方案让很多私有云用户成为了 K8S 世界中的二等公民。接下来介绍的 Metallb
,就给私有 Kubernetes 用户带来了一个方便、可用(而且不太成熟)的软件解决方案。
该项目发布于 2017 年底,当前处于 Beta 阶段。
Metallb 会在 Kubernetes 内运行,监控服务对象的变化,一旦察觉有新的 LoadBalancer
服务运行,并且没有可申请的负载均衡器之后,就会完成两部分的工作:
地址分配
用户需要在配置中提供一个地址池,Metallb 将会在其中选取地址分配给服务。
地址广播
根据不同配置,Metallb 会以二层(ARP/NDP)或者 BGP 的方式进行地址的广播。
支持范围
不支持 IPVS
网络插件 | 兼容性 |
---|---|
Calico | 部分支持(有附加文档) |
Flannel | 支持 |
Kube-router | 不支持(正在跟进) |
Romana | 支持(有附加文档) |
Weave Net | 支持 |
一个小测试
安装
Metallb 支持 Helm 和 YAML 两种安装方法,这里我们使用第二种:
kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.1/manifests/metallb.yaml
很简单,Metallb 就会开始安装,会生成自己的命名空间以及 RBAC 配置。
$ kubectl get pods -n metallb-system NAME READY STATUS RESTARTS AGE controller-b7896bf94-g449l 1/1 Running 0 51m speaker-mt6kd 1/1 Running 0 51m speaker-sqbn4 1/1 Running 0 51m
配置
接下来我们要生成一个 Configmap 文件,为 Metallb 设置网址范围以及协议相关的选择和配置,这里以一个简单的二层配置为例:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: my-ip-space
protocol: layer2
addresses:
- 10.211.55.240/28
注意:这里的 IP 地址范围需要跟集群实际情况相对应。
使用 kubectl apply
命令应用之后,使用 kubectl logs -f [metallb-controller-pod]
会看到配置更新过程。
测试
创建一个 Nginx 的服务,服务类型为 LoadBalancer
:
apiVersion: apps/v1beta2
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
服务创建运行之后,可以列出服务信息:
kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.96.0.10 53/UDP,53/TCP 7d nginx LoadBalancer 10.96.245.212 10.211.55.240 80:32207/TCP 54m
这里就发现,LoadBalancer 类型的服务,分配到了我们地址池中的第一个 IP。
用 curl http://10.211.55.240
验证,就会发现返回了 Nginx 的欢迎信息。
补充
除了这里提到的一点点简单配置之外,Metallb 的配置能力还是比较强大的,这点可以参考官网,其中谈及了不少较为务实的案例,另外还提到了部分 Issue 供用户参考。
前言
我们知道,Service 机制,以及 Kubernetes 里的 DNS 插件,都是在帮助我们解决同样一个问题,即:如何找到某一个容器;而 Service 是由 kube-proxy 组件,加上 iptables 来共同实现的;所谓 Service 的访问入口,其实就是每台宿主机上由 kube-proxy 生成的 iptables 规则,以及 kube-dns 生成的 DNS 记录。而一旦离开了这个集群,这些信息对用户来说,也就自然没有作用了
在使用 Kubernetes 的 Service 时,一个必须要面对和解决的问题就是:如何从外部(Kubernetes 集群之外),访问到 Kubernetes 里创建的 Service?
从外界连通 Service
三种方式
- NodePort
- ExternalIP
- LoadBalance
这里 NodePort
和 externalIPs
是 K8S 集群本身就支持的特性,这两个方案让很多私有云用户成为了 K8S 世界中的二等公民,而 NodePort
也是我们最常用的;
而 kubernetes 没有为裸机群集提供网络负载均衡器(类型为 LoadBalancer
的服务)的实现,如果你的 K8S 集群没有在公有云的 IaaS 平台(GCP,AWS,Azure …)上运行,则 LoadBalancers 将在创建时无限期地保持 “挂起” 状态,也就是说只有公有云厂商自家的 kubernetes 支持 LoadBalancer,对 LoadBalancer 类型的服务的支持应该是众多表面差异中最醒目的一个了
纯软件解决方案: MetalLB
该项目发布于 2017 年底,当前处于 Beta 阶段,旨在解决上述中的不平衡,通过提供与标准网络设备集成的网络 LB 实现来纠正这种不平衡,以便裸机集群上的外部服务也 “尽可能” 地工作;即 MetalLB 能够帮助你在 kubernetes 中创建 LoadBalancer 类型的 kubernetes 服务
Metallb
会在 Kubernetes 内运行,监控服务对象的变化,一旦察觉有新的 LoadBalancer 服务运行,并且没有可申请的负载均衡器之后,就会完成两部分的工作:
- 地址分配用户需要在配置中提供一个地址池,Metallb 将会在其中选取地址分配给服务。
- 地址广播根据不同配置,Metallb 会以二层(ARP/NDP)或者 BGP 的方式进行地址的广播
安装部署演示
部署 Metallb 负载均衡器
Metallb 支持 Helm 和 YAML 两种安装方法(这里推荐第二种)
- Helm
$ helm install --name metallb stable/metallb
- YAML
$ kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml
很简单,
Metallb
就会开始安装,会生成自己的命名空间以及 RBAC 配置[root@lee ~]# kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml namespace/metallb-system created serviceaccount/controller created serviceaccount/speaker created clusterrole.rbac.authorization.k8s.io/metallb-system:controller created clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created role.rbac.authorization.k8s.io/config-watcher created clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created rolebinding.rbac.authorization.k8s.io/config-watcher created daemonset.apps/speaker created deployment.apps/controller created [root@lee ~]# kubectl get pods -n metallb-system -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE controller-765899887-bdwdk 1/1 Running 0 82s 10.0.0.22 lee speaker-qldl6 1/1 Running 0 82s 192.168.50.124 lee
目前还没有宣布任何内容,因为我们没有提供 ConfigMap,也没有提供负载均衡地址的服务;
接下来我们要生成一个 ConfigMap文件,为 Metallb 设置网址范围以及协议相关的选择和配置提供 IP pool
通过之前提到的原理图可知,需要创建一个
ConfigMap
文件,以提供IP 池
;$ wget https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/example-layer2-config.yaml
修改 ip 地址池和集群节点网段相同,且必须为一个 IP 区间
apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: my-ip-space protocol: layer2 addresses: # 与集群节点网段相同 -192.168.50.211-192.168.50.220
IP 地址为
无占用
[root@lee ~]# ping 192.168.50.211 PING 192.168.50.211 (192.168.50.211) 56(84) bytes of data. From 192.168.50.124 icmp_seq=1 Destination Host Unreachable From 192.168.50.124 icmp_seq=2 Destination Host Unreachable From 192.168.50.124 icmp_seq=3 Destination Host Unreachable From 192.168.50.124 icmp_seq=4 Destination Host Unreachable ^C --- 192.168.50.211 ping statistics --- 5 packets transmitted, 0 received, 4 errors, 100% packet loss, time 4001ms
部署?
example-layer2-config.yaml
?文件$ kubectl apply -f example-layer2-config.yaml
部署应用服务测试
$ wget https://raw.githubusercontent.com/google/metallb/master/manifests/tutorial-2.yaml $ kubectl apply -f tutorial-2.yaml
查看 yaml 文件配置,包含了一个 deployment 和一个 LoadBalancer 类型的 service,默认即可;
查看 service 分配的 EXTERNAL-IP
[root@lee ~]# kubectl get svc -owide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR nginx LoadBalancer 10.0.228.36 192.168.50.211 80:31796/TCP 65s app=nginx
ping 该
EXTERNAL-IP
地址,发现该地址可以访问了[root@lee ~]# ping 192.168.50.211 PING 192.168.50.211 (192.168.50.211) 56(84) bytes of data. 64 bytes from 192.168.50.211: icmp_seq=1 ttl=64 time=0.050 ms 64 bytes from 192.168.50.211: icmp_seq=2 ttl=64 time=0.082 ms 64 bytes from 192.168.50.211: icmp_seq=3 ttl=64 time=0.068 ms
集群内访问该?
EXTERNAL-IP
?地址[root@lee ~]# curl 192.168.50.211 ...............
Thank you for using nginx.
从集群外访问该 IP 地址
Administrator at 16:47:09 / $ curl 192.168.50.211 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 612 100 612 0 0 597k 0 --:--:-- --:--:-- --:--:-- 597k ................
Thank you for using nginx.
另外使用
Node IP NodePort
也可以访问Administrator at 16:47:09 / $ curl 192.168.50.124:31796 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 612 100 612 0 0 597k 0 --:--:-- --:--:-- --:--:-- 597k ................
Thank you for using nginx.
文章目录