公众号关注 「奇妙的 Linux 世界」
设为「星标」,每天带你提升技术视野!
私有云裸金属架构(这是相对云上环境来说,不是说无操作系统)上部署的 Kubernetes 集群,通常是无法使用 LoadBalancer 类型的 Service 的。因为 Kubernetes 本身没有为裸机群集提供网络负载均衡器的实现。
如果你的 Kubernetes 集群没有在公有云的 IaaS 平台(GCP,AWS,Azure …)上运行,则 LoadBalancers 将在创建时无限期地保持 “挂起” 状态,也就是说只有公有云厂商自家的 Kubernetes 支持 LoadBalancer 。
为了从外部访问裸机 Kubernetes 群集,目前只能使用 NodePort
或 Ingress
的方法进行服务暴露。前者的缺点是每个暴露的服务需要占用所有节点的某个端口,后者的缺点是仅仅能支持 HTTP
协议。
MetalLB
是一个负载均衡器,专门解决裸金属 Kubernetes 集群中无法使用 LoadBalancer
类型服务的痛点。MetalLB
使用标准化的路由协议,以便裸金属 Kubernetes 集群上的外部服务也尽可能地工作。即 MetalLB 能够帮助你在裸金属 Kubernetes 集群中创建 LoadBalancer 类型的 Kubernetes 服务,该项目发布于 2017 年底,当前处于 Beta
阶段。
项目地址:https://github.com/danderson/metallb
MetalLB 会在 Kubernetes 内运行,监控服务对象的变化,一旦监测到有新的 LoadBalancer 服务运行,并且没有可申请的负载均衡器之后,就会完成地址分配和外部声明两部分的工作。
在云环境中,当你请求一个负载均衡器时,云平台会自动分配一个负载均衡器的 IP 地址给你,应用程序通过此 IP 来访问经过负载均衡处理的服务。
使用 MetalLB 时,MetalLB 会自己为用户的 LoadBalancer 类型 Service 分配 IP 地址,当然该 IP 地址不是凭空产生的,需要用户在配置中提供一个 IP 地址池,Metallb 将会在其中选取地址分配给服务。
MetalLB 将 IP 分配给某个服务后,它需要对外宣告此 IP 地址,并让外部主机可以路由到此 IP。
MetalLB 支持两种声明模式:Layer 2( ARP / NDP )模式或者 BGP 模式。
Layer 2 模式
在任何以太网环境均可使用该模式。当在第二层工作时,将有一台机器获得 IP 地址(即服务的所有权)。MetalLB 使用标准的地址发现协议(对于 IPv4 是 ARP,对于 IPv6 是 NDP)宣告 IP 地址,使其在本地网路中可达。从 LAN 的角度来看,仅仅是某台机器多配置了一个 IP 地址。
Layer 2 模式下,每个 Service 会有集群中的一个 Node 来负责。服务的入口流量全部经由单个节点,然后该节点的 Kube-Proxy 会把流量再转发给服务的 Pods。也就是说,该模式下 MetalLB 并没有真正提供负载均衡器。尽管如此,MetalLB 提供了故障转移功能,如果持有 IP 的节点出现故障,则默认 10 秒后即发生故障转移,IP 会被分配给其它健康的节点。
Layer 2 模式的优缺点:
Layer 2 模式更为通用,不需要用户有额外的设备;
Layer 2 模式下存在单点问题,服务的所有入口流量经由单点,其网络带宽可能成为瓶颈;
由于 Layer 2 模式需要 ARP/NDP 客户端配合,当故障转移发生时,MetalLB 会发送 ARP 包来宣告 MAC 地址和 IP 映射关系的变化,地址分配略为繁琐。
BGP 模式
当在第三层工作时,集群中所有机器都和你控制的最接近的路由器建立 BGP 会话,此会话让路由器能学习到如何转发针对 K8S 服务 IP 的数据包。
通过使用 BGP,可以实现真正的跨多节点负载均衡(需要路由器支持 multipath),还可以基于 BGP 的策略机制实现细粒度的流量控制。
具体的负载均衡行为和路由器有关,可保证的共同行为是:每个连接(TCP 或 UDP 会话)的数据包总是路由到同一个节点上。
BGP 模式的优缺点:
不能优雅处理故障转移,当持有服务的节点宕掉后,所有活动连接的客户端将收到 Connection reset by peer ;
BGP 路由器对数据包的源 IP、目的 IP、协议类型进行简单的哈希,并依据哈希值决定发给哪个 K8S 节点。问题是 K8S 节点集是不稳定的,一旦(参与 BGP)的节点宕掉,很大部分的活动连接都会因为 rehash 而坏掉。
BGP 模式问题的缓和措施:
将服务绑定到一部分固定的节点上,降低 rehash 的概率。
在流量低的时段改变服务的部署。
客户端添加透明重试逻辑,当发现连接 TCP 层错误时自动重试。
根据部署模式不同,MetalLB 可能需要以下环境:
一个 Kubernetes 集群,运行 Kubernetes 1.13.0 或更高版本。
Kubernetes 集群的网络配置可以与 MetalLB 共存。
有一些提供给 MetalLB 分发的 IPv4 地址。
根据部署模式,可能需要一个或多个 BGP 的路由器 。
MetalLB 目前支持网络插件范围
网络插件 | 兼容性 |
---|---|
Calico | 部分支持(有附加文档) |
Flannel | 支持 |
Kube-router | 不支持 |
Romana | 支持(有附加文档) |
Weave Net | 支持 |
从 Kubernetes 1.9 开始, Kube-Proxy 除了支持默认的 Iptables 模式之外,还支持更高效的 IPVS 模式。
MetalLB 可以在Kubenetes 1.13 或更高版本的 Kube-Proxy 中使用 IPVS 模式。但是,它尚未明确测试,因此风险自负。具体内容可参考:https://github.com/google/metallb/issues/153
安装 MetalLB 一共有两种方法:使用 Kubernetes YAML 文件或使用 Helm 包管理器。
# 目前 MetalLB 最新版本为 0.8.1
$ kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.1/manifests/metallb.yaml
部署完成后,将在 metallb-system
命名空间下将 MetalLB 部署到集群。YAML 文件中主要包含以下一些组件:
metallb-system/controller
,这是处理 IP
地址分配的控制器。
metallb-system/speakerdaemonset
这是支持你选择协议以使服务可达的组件。
Controller
和 Speaker
的 Service Accounts
,以及组件需要运行的 RBAC
权限。
通过 YAML 安装文件部署并不包含 MetalLB 配置文件,但 MetalLB 的组件仍能启动,但在你定义和部署
configmap
之前将保持空闲状态 。
$ helm install --name metallb stable/metallb
如果你还不知道什么是 Helm,可以先参考 「Helm 入门指南」 一文。
MetalLB 安装完成后,我们还需要根据具体的地址和通告方式配置名为 metallb-system/config
的 ConfigMap。Controller 会读取该 ConfigMap,并重新加载配置。
通过 Helm 安装时,MetalLB 读取的 ConfigMap 名为 metallb-config 。
第二层模式是最简单的配置方式:在许多情况下,您不需要任何特定于协议的配置,只需要 IP 地址。
第二层模式不要求将 IP 绑定到工作节点的网络接口。它的工作原理是直接响应本地网络上的 ARP 请求,将机器的 MAC 地址提供给客户端。
下面我们来看一个实际例子,我们将配置一个由 MetalLB 二层模式控制的外部 IP 段为 192.168.1.240 - 192.168.1.250。
$ cat MetalLB-Layer2-Config.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: config
namespace: metallb-system
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.0.10-192.168.0.100
注意:这里的 IP 地址范围需要跟集群实际情况相对应。
首先,我们使用 kubectl apply -f MetalLB-Layer2-Config.yaml
命令使配置生效。如果你想看到详细配置更新过程,可以使用以下类似命令查看。
$ kubectl logs -f [metallb-controller-pod]
或者
$ kubectl logs -l component=speaker -n metallb-system
接下来,我们来创建一个服务类型为 LoadBalancer 的 Nginx 服务来验证下。
$ cat nginx-test.yaml
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 apply -f nginx-test.yaml
命令后,我们可以看到对应服务信息。
$ kubectl get pods nginx-68995d8957-bczhf -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx-68995d8957-bczhf 2/2 Running 0 19d 10.244.0.78 ubuntu-1
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer 10.97.187.100 192.168.0.10 80:32353/TCP 179m
从输出结果,我们可以看到 LoadBalancer 类型的服务,并且分配的外部 IP 地址是地址池中的第一个 IP 192.168.0.10
。
最后,我们通过 curl http://192.168.0.10
命令来验证下,发现可以正常显示 Nginx 的欢迎信息。
Welcome to nginx!
................
Thank you for using nginx.
至此,MetalLB Layer 2
模式的配置就结束了。
对于配置为具有一个 BGP
路由器和一个 IP 地址范围的 BGP 模式,你需要先准备好以下 4 条配置信息:
MetalLB 应连接的路由器 IP 地址。
路由器的 AS 号。
MetalLB 应该使用的 AS 编号。
IP 地址范围,表示为 CIDR 前缀。
由于这种配置方式需要具备 BGP 功能的硬件路由器支持,目前我们环境中不具备此等条件。这里就简单说下 MetalLB 对应的配置方式,具体内容就不展开讲解了。
由于前面已经安装了 MetalLB 的 Controller
和 Speaker
,只是使用的是 Layer 2 模式。这里只需要改为 BGP 模式,我们修改 Configmap 中 Config 配置就可以了。
# 假如要为 MetalLB 提供范围 192.168.9.0/24 和 AS 号 65009,并将其连接到 192.168.0.1 的 AS 号为 65000 的路由器。
$ cat MetalLB-BGP-Config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
peers:
- peer-address: 192.168.0.1
peer-asn: 65000
my-asn: 65009
address-pools:
- name: default
protocol: bgp
addresses:
#- 192.168.0.10-192.168.0.100
- 192.168.9.0/24
本文简单介绍了 MetalLB 的用途以及 MetalLB 的两种部署模式:Layer 2 模式和 BGP 模式。在实际应用中,如果条件满足,推荐使用 BGP 模式。
http://www.google.com
https://blog.fleeto.us/post/intro-metallb/
https://ieevee.com/tech/2019/06/30/metallb.html
https://blog.csdn.net/kunyus/article/details/88616653
https://vqiu.cn/metallb-si-you-ji-qun-loadbalancer/amp/
https://sre.ink/metallb-kubernetes-loadbalancer-no-ipvs/
https://blog.csdn.net/networken/article/details/85928369
https://blog.gmem.cc/external-lb-for-on-premise-k8s-cluster
https://leeif.me/2019/02/k8s-deploy-metallb-LoadBalancer.html
https://mshk.top/2019/04/kubernetes-metallb-loadbalancer-nginx-ingress-controller/
你可能还喜欢
点击下方图片即可阅读
再见 Docker,是时候拥抱下一代容器工具了
点击上方图片,打开小程序,加入「玩转 Linux」圈子
更多有趣的互联网新鲜事,关注「奇妙的互联网」视频号全了解!