Kubernetes MetalLB 作为 Load Balancer 上

简介: Kubernetes MetalLB 作为 Load Balancer 上

图片.png

TL;DR

网络方面的知识又多又杂,很多又是系统内核的部分。原本自己不是做网络方面的,系统内核知识也薄弱。但恰恰是这些陌生的内容满满的诱惑,加上现在的工作跟网络关联更多了,逮住机会就学习下。

这篇以 Kubernetes LoadBalancer 为起点,使用 MetalLB 去实现集群的负载均衡器,在探究其工作原理的同时了解一些网络的知识。

由于 MetalLB 的内容有点多,一步步来,今天这篇仅介绍其中简单又容易理解的部分,不出意外还会有下篇(太复杂,等我搞明白先 :D)。
LoadBalancer 类型 Service

由于 Kubernets 中 Pod 的 IP 地址不固定,重启后 IP 会发生变化,无法作为通信的地址。Kubernets 提供了 Service 来解决这个问题,对外暴露。

Kubernetes 为一组 Pod 提供相同的 DNS 名和虚拟 IP,同时还提供了负载均衡的能力。这里 Pod 的分组通过给 Pod 打标签(Label )来完成,定义 Service 时会声明标签选择器(selector)将 Service 与 这组 Pod 关联起来。

根据使用场景的不同,Service 又分为 4 种类型:ClusterIP、NodePort、LoadBalancer 和 ExternalName,默认是 ClusterIP。这里不一一详细介绍,有兴趣的查看 Service 官方文档[1]。

除了今天的主角 LoadBalancer 外,其他 3 种都是比较常用的类型。LoadBalancer 官方的解释是:

使用云提供商的负载均衡器向外部暴露服务。外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上。

图片.png

lb-service

看到“云提供商提供”几个字时往往望而却步,有时又需要 LoadBalancer 对外暴露服务做些验证工作(虽然除了 7 层的 Ingress 以外,还可以使用 NodePort 类型的 Service),而 Kubernetes 官方并没有提供实现。比如下面要介绍的 MetalLB[2] 就是个不错的选择。
MetalLB 介绍

MetalLB 是裸机 Kubernetes 集群的负载均衡器实现,使用标准路由协议。

注意: MetalLB 目前还是 beta 阶段。

前文提到 Kubernetes 官方并没有提供 LoadBalancer 的实现。各家云厂商有提供实现,但假如不是运行在这些云环境上,创建的 LoadBalancer Service 会一直处于 Pending 状态(见下文 Demo 部分)。

MetalLB 提供了两个功能:

地址分配:当创建 LoadBalancer Service 时,MetalLB 会为其分配 IP 地址。这个 IP 地址是从预先配置的 IP 地址库获取的。同样,当 Service 删除后,已分配的 IP 地址会重新回到地址库。

对外广播:分配了 IP 地址之后,需要让集群外的网络知道这个地址的存在。MetalLB 使用了标准路由协议实现:ARP、NDP 或者 BGP。

广播的方式有两种,第一种是 Layer 2 模式,使用 ARP(ipv4)/NDP(ipv6) 协议;第二种是 BPG。

今天主要介绍简单的 Layer 2 模式,顾名思义是 OSI 二层的实现。

具体实现原理,看完 Demo 再做分析,等不及的同学请直接跳到最后。
运行时

MetalLB 运行时有两种工作负载:

Controler:Deployment,用于监听 Service 的变更,分配/回收 IP 地址。

Speaker:DaemonSet,对外广播 Service 的 IP 地址。

Demo

安装之前介绍下网络环境,Kubernetes 使用 K8s 安装在 Proxmox 的虚拟机[3]上。

图片.png

安装 K3s

安装 K3s,这里需要通过 --disable servicelb 禁用 k3s 默认的 servicelb。

参考 K3s 文档[4],默认情况下 K3s 使用 Traefik[5] ingress 控制器 和 Klipper[6] Service 负载均衡器来对外暴露服务。

curl -sfL https://get.k3s.io | sh -s - --disable traefik --disable servicelb --write-kubeconfig-mode 644 --write-kubeconfig ~/.kube/config

创建工作负载

使用 nginx 镜像,创建两个工作负载:

kubectl create deploy nginx --image nginx:latest --port 80 -n default
kubectl create deploy nginx2 --image nginx:latest --port 80 -n default

同时为两个 Deployment 创建 Service,这里类型选择 LoadBalancer:

kubectl expose deployment nginx --name nginx-lb --port 8080 --target-port 80 --type LoadBalancer -n default
kubectl expose deployment nginx2 --name nginx2-lb --port 8080 --target-port 80 --type LoadBalancer -n default

检查 Service 发现状态都是 Pending 的,这是因为安装 K3s 的时候我们禁用了 LoadBalancer 的实现:

kubectl get svc -n default
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 443/TCP 14m
nginx-lb LoadBalancer 10.43.108.233 8080:31655/TCP 35s
nginx2-lb LoadBalancer 10.43.26.30 8080:31274/TCP 16s

这时就需要 MetalLB 登场了。
安装 MetalLB

使用官方提供 manifest 来安装,目前最新的版本是 0.12.1。此外,还可以其他安装方式供选择,比如 Helm[7]、Kustomize[8] 或者 MetalLB Operator[9]。

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml

kubectl get po -n metallb-system
NAME READY STATUS RESTARTS AGE
speaker-98t5t 1/1 Running 0 22s
controller-66445f859d-gt9tn 1/1 Running 0 22s

此时再检查 LoadBalancer Service 的状态仍然是 Pending 的,嗯?因为,MetalLB 要为 Service 分配 IP 地址,但 IP 地址不是凭空来的,而是需要预先提供一个地址库。

这里我们使用 Layer 2 模式,通过 Configmap 为其提供一个 IP 段:

apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |

address-pools:
- name: default
  protocol: layer2
  addresses:
  - 192.168.1.30-192.168.1.49

此时再查看 Service 的状态,可以看到 MetalLB 为两个 Service 分配了 IP 地址 192.168.1.30、192.168.1.31:

kubectl get svc -n default
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 443/TCP 28m
nginx-lb LoadBalancer 10.43.201.249 192.168.1.30 8080:30089/TCP 14m
nginx2-lb LoadBalancer 10.43.152.236 192.168.1.31 8080:31878/TCP 14m

可以请求测试下:

curl -I 192.168.1.30:8080
HTTP/1.1 200 OK
Server: nginx/1.21.6
Date: Wed, 02 Mar 2022 15:31:15 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 25 Jan 2022 15:03:52 GMT
Connection: keep-alive
ETag: "61f01158-267"
Accept-Ranges: bytes

curl -I 192.168.1.31:8080
HTTP/1.1 200 OK
Server: nginx/1.21.6
Date: Wed, 02 Mar 2022 15:31:18 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 25 Jan 2022 15:03:52 GMT
Connection: keep-alive
ETag: "61f01158-267"
Accept-Ranges: bytes

macOS 本地使用 arp -a 查看 ARP 表可以找到这两个 IP 及 mac 地址,可以看出两个 IP 都绑定在同一个网卡上,此外还有虚拟机的 IP 地址。也就是说 3 个 IP 绑定在该虚拟机的 en0 上:

图片.png

而去虚拟机(节点)查看网卡(这里只能看到系统绑定的 IP):

图片.png
Layer 2 工作原理

Layer 2 中的 Speaker 工作负载是 DeamonSet 类型,在每台节点上都调度一个 Pod。首先,几个 Pod 会先进行选举,选举出 Leader。Leader 获取所有 LoadBalancer 类型的 Service,将已分配的 IP 地址绑定到当前主机到网卡上。也就是说,所有 LoadBalancer 类型的 Service 的 IP 同一时间都是绑定在同一台节点的网卡上。

当外部主机有请求要发往集群内的某个 Service,需要先确定目标主机网卡的 mac 地址(至于为什么,参考维基百科[10])。这是通过发送 ARP 请求,Leader 节点的会以其 mac 地址作为响应。外部主机会在本地 ARP 表中缓存下来,下次会直接从 ARP 表中获取。

请求到达节点后,节点再通过 kube-proxy 将请求负载均衡目标 Pod。所以说,假如 Service 是多 Pod 这里有可能会再跳去另一台主机。

图片.png

sequence
优缺点

优点很明显,实现起来简单(相对于另一种 BGP 模式下路由器要支持 BPG)。就像笔者的环境一样,只要保证 IP 地址库与集群是同一个网段即可。

当然缺点更加明显了,Leader 节点的带宽会成为瓶颈;与此同时,可用性欠佳,故障转移需要 10 秒钟的时间(每个 speaker 进程有个 10s 的循环[11])

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
Kubernetes 容器
K8S的Service的LoadBanlance之Metallb解决方案
本文介绍了如何在Kubernetes中使用MetalLB来实现Service的LoadBalancer功能,包括MetalLB的部署、配置、以及通过创建地址池和部署服务来测试MetalLB的过程。
1082 2
K8S的Service的LoadBanlance之Metallb解决方案
|
Kubernetes 应用服务中间件 nginx
Kubernetes上安装Metallb和Ingress并部署应用程序
Kubernetes上安装Metallb和Ingress并部署nginx应用程序,使用LoadBalancer类型的KubernetesService
1392 121
|
Kubernetes Linux 容器
1.xshell传不了文件输出0000如何解决.....2.k8s中metalLB文件内容
1.xshell传不了文件输出0000如何解决.....2.k8s中metalLB文件内容
188 1
|
Kubernetes 网络协议 前端开发
Kubernetes MetalLB 作为 Load Balancer 下
Kubernetes MetalLB 作为 Load Balancer 下
699 1
Kubernetes MetalLB 作为 Load Balancer 下
|
Kubernetes 网络协议 容器
Kubernetes开源LoadBalancer—Metallb(BGP)
Kubernetes开源LoadBalancer—Metallb(BGP)
Kubernetes开源LoadBalancer—Metallb(BGP)
|
存储 Kubernetes 负载均衡
Kubernetes 【负载均衡器】 MetalLB 实践
Kubernetes 【负载均衡器】 MetalLB 实践
|
9月前
|
人工智能 算法 调度
阿里云ACK托管集群Pro版共享GPU调度操作指南
本文介绍在阿里云ACK托管集群Pro版中,如何通过共享GPU调度实现显存与算力的精细化分配,涵盖前提条件、使用限制、节点池配置及任务部署全流程,提升GPU资源利用率,适用于AI训练与推理场景。
721 1
|
9月前
|
弹性计算 监控 调度
ACK One 注册集群云端节点池升级:IDC 集群一键接入云端 GPU 算力,接入效率提升 80%
ACK One注册集群节点池实现“一键接入”,免去手动编写脚本与GPU驱动安装,支持自动扩缩容与多场景调度,大幅提升K8s集群管理效率。
518 89
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
本文介绍如何利用阿里云的分布式云容器平台ACK One的多集群应用分发功能,结合云效CD能力,快速将单集群CD系统升级为多集群CD系统。通过增加分发策略(PropagationPolicy)和差异化策略(OverridePolicy),并修改单集群kubeconfig为舰队kubeconfig,可实现无损改造。该方案具备多地域多集群智能资源调度、重调度及故障迁移等能力,帮助用户提升业务效率与可靠性。
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
ACK One 的多集群应用分发,可以最小成本地结合您已有的单集群 CD 系统,无需对原先应用资源 YAML 进行修改,即可快速构建成多集群的 CD 系统,并同时获得强大的多集群资源调度和分发的能力。
1082 9