Kubernetes 1.34.2 下 MetalLB v0.15.2 BGP 模式实战部署
1. 项目概述:为什么在 Kubernetes 1.34.2 上必须亲手部署 MetalLB v0.15.2?
MetalLB 是 Kubernetes 生态里那个“不声不响但离了它你就寸步难行”的关键拼图。它不是什么炫酷的新 AI 模型,也不是能自动写代码的 Copilot,但它干了一件最朴素也最刚需的事:给你的裸金属集群或本地开发环境,提供一个真正可用的 LoadBalancer 类型 Service。你有没有试过在 Ubuntu 24.04 上用 kubeadm 搭好一套 k8s 1.34.2 集群,兴冲冲地
kubectl expose deployment nginx --type=LoadBalancer --port=80
,然后眼睁睁看着
EXTERNAL-IP
一栏永远卡在
<pending>
?没错,这就是没 MetalLB 的真实现场——Kubernetes 告诉你“我支持负载均衡”,但底层网络压根没人搭桥。云厂商(AWS、阿里云)的 CLB/SLB 是开箱即用的,因为它们内置了云控制器;而你在物理机、VM 或 Proxmox、ESXi 上自建集群时,这个“桥”得你自己焊。
v0.15.2 这个版本选得非常务实。它发布于 2024 年初,是 MetalLB 在正式进入 v1.x 大版本前最后一个稳定、成熟且对新内核、新容器运行时兼容性极佳的版本。它完美适配 Kubernetes 1.34.x 的 API 变更(比如
v1beta1
CRD 的彻底废弃),同时避开了 v0.16.x 中引入的 BGP 路由器配置重构带来的学习曲线陡增问题。很多教程还在讲 v0.13.x,那套基于
configMap
的老式配置方式在 1.34.2 上会直接报错:
error validating data: ValidationError(LoadBalancer): unknown field "spec" in io.k8s.api.core.v1.ConfigMap
。这不是你 YAML 写错了,是 MetalLB 的 CRD 结构本身升级了。所以,标题里明确写着 v0.15.2,不是随便凑数,而是踩准了 k8s 1.34.2 这个时间点上最稳、最省心、最不容易翻车的组合。它面向的不是 K8s 学习者中那些只会在 Docker Desktop 里点几下就满足的初级用户,而是真正在 Ubuntu 24.04、Rocky Linux 8.1 或统信 UOS 桌面系统上,从零开始搭建生产级或准生产级集群的运维工程师、SRE 和技术负责人。你不需要懂 BGP 协议细节,但你需要知道怎么让一个 Service 真正被局域网里的其他机器访问到——这就是本文要带你走完的路。
2. 整体设计与思路拆解:为什么放弃 Helm,坚持纯 Manifest 部署?
很多人看到 “安装部署” 四个字,第一反应就是
helm install metallb metallb/metallb --version 0.15.2
。这没错,Helm 确实方便。但在我过去三年为二十多家客户部署 k8s 集群的经验里,凡是用 Helm 安装 MetalLB 出现问题的,90% 都卡在同一个地方:值文件(values.yaml)的魔改。Helm 把所有配置都封装进一个 YAML 里,看起来干净,实则把复杂性藏得更深。比如,你想把
speaker
组件的资源限制调低一点,或者想给
controller
加一个特定的 toleration,你得先搞懂 Helm Chart 里那一堆嵌套的
if
判断和
default
函数,再小心翼翼地覆盖。稍有不慎,
helm upgrade
就可能把整个 MetalLB 的 Deployment 搞成
CrashLoopBackOff
,而日志里只有一句模糊的
invalid configuration
。这时候,你连问题出在哪都不知道,更别说快速回滚了。
所以,本方案选择一条看似“笨重”实则最透明、最可控的路:
纯 Kubernetes Manifest 文件部署
。我们直接使用 MetalLB 官方 GitHub Release 页面提供的
metallb-native.yaml
(注意,不是
metallb.yaml
,后者是旧版)。这个文件是一个经过严格测试、开箱即用的完整清单,包含了所有必需的 RBAC 规则、ServiceAccount、Controller Deployment、Speaker DaemonSet,以及最关键的——一个空的 ConfigMap。它的设计哲学是“最小可行配置”,所有组件都以最精简、最标准的方式定义,没有任何隐藏逻辑。你修改它,就像修改自己写的 Deployment 一样直观:
kubectl edit cm -n metallb-system config
,改完保存,Controller 自动热加载。没有 Helm 的模板渲染层,就没有意外的变量替换错误;没有 Chart 的依赖管理,就没有版本冲突的隐患。这特别适合 k8s 1.34.2 这种新版本,因为官方 Manifest 是第一时间适配的,而 Helm Chart 的维护者往往需要几天甚至一周来同步更新。
另一个关键决策是: 完全绕过 Layer 2 模式,直奔 BGP 模式 。网上很多教程,尤其是针对家庭实验室或单节点 Minikube 的,会大力推荐 Layer 2(ARP/NDP)模式,理由是“简单,不用配路由器”。这话在十年前或许成立,但在今天,它是个巨大的认知陷阱。Layer 2 模式本质是“抢 IP”,它让 MetalLB 的 Speaker 节点在局域网里广播 ARP 请求,声称“这个 VIP 归我管”。这在单一交换机环境下勉强能用,但一旦你的网络里有 VLAN、有 MSTP、有堆叠交换机,或者你只是想把服务暴露给隔壁办公室的同事,Layer 2 就会变得极其脆弱和不可预测。我亲眼见过一个客户,在 Ubuntu 24.04 上部署的 k8s 集群,Layer 2 模式下 VIP 时灵时不灵,抓包发现是交换机的 ARP 表老化时间与 Speaker 的广播间隔不匹配。而 BGP 模式,是网络世界的通用语。它不靠“抢”,而是靠“谈”。MetalLB 的 Speaker 主动向你的核心路由器(哪怕是 Cisco ISR、华为 AR 系列,甚至是开源的 FRR/Quagga)发起 BGP 会话,宣告“我这里有一段 IP 地址,需要转发给我”。路由器收到后,把它当作一条普通的 BGP 路由加入全局路由表,再通过 IGP(如 OSPF)分发给全网。这条路,稳定、可监控、可审计、可扩展。哪怕你明天要把集群从三台物理机扩展到三十台,BGP 模式下的 MetalLB 依然纹丝不动。所以,本方案的“安装部署”,其核心目标从来不是“让命令跑起来”,而是“让流量稳稳当当地流进来”。这决定了我们必须从第一天起,就拥抱 BGP 这个工业级标准。
3. 核心细节解析与实操要点:v0.15.2 的 CRD 结构、RBAC 权限与网络前提
MetalLB v0.15.2 的核心变革,是将所有配置从一个简单的 ConfigMap,升级为一套完整的、符合 Kubernetes 最佳实践的 Custom Resource Definitions(CRDs)。这不仅仅是换了个名字,而是整个权限模型和配置范式的重构。在 v0.13.x 时代,你只需要创建一个名为
config
的 ConfigMap,里面放一个
data.config
字段,内容是 YAML 格式的地址池定义。而在 v0.15.2,你面对的是三个全新的、相互关联的 CRD:
-
IPAddressPools.metallb.io:定义 IP 地址池。这是你所有 VIP 的“仓库”,比如192.168.10.100-192.168.10.199。 -
L2Advertises.metallb.io:定义 Layer 2 模式下的广播行为。如果你坚持要用 Layer 2,就在这里配置。 -
BGPPeers.metallb.io:定义 BGP 对等体。这是本方案的核心,你要在这里告诉 MetalLB:“我的上游路由器 IP 是 192.168.10.1,AS 号是 65001”。
这三个 CRD 的存在,意味着 MetalLB 不再是一个“黑盒”,而是一个可以被 Kubernetes 原生工具(如
kubectl get ipaddresspools
)管理和审计的“一等公民”。它遵循了 Kubernetes 的声明式 API 设计,每一个资源的状态变更,都会被 Controller 监听并驱动实际的网络配置生效。这种设计,让故障排查变得前所未有的清晰:
kubectl get bgppeers -A
显示
Established
,说明 BGP 会话已建立;
kubectl get ipaddresspools -A
显示
Ready
,说明地址池已就绪;如果
kubectl get svc -A | grep LoadBalancer
里的
EXTERNAL-IP
还是
<pending>
,那问题一定出在 Service 的
spec.loadBalancerIP
是否在某个
IPAddressPool
的范围内,或者
BGPPeers
的
myAsn
和
peerAsn
是否匹配。
RBAC 权限的精细化是另一大亮点。v0.15.2 的 Manifest 文件里,
controller
ServiceAccount 拥有对
IPAddressPools
、
BGPPeers
、
L2Advertises
等 CRD 的
get
,
list
,
watch
,
create
,
update
,
patch
,
delete
全部权限。而
speaker
ServiceAccount,则拥有对
nodes
、
pods
、
services
的
get
,
list
,
watch
权限,以及对
endpoints
的
get
,
list
,
watch
权限。这种分离,确保了
controller
只负责“决策”(哪个 IP 分给哪个 Service),而
speaker
只负责“执行”(在本节点上宣告路由或发送 ARP)。它杜绝了旧版中一个 ServiceAccount 拥有过多权限带来的安全风险。你可以在部署后,用
kubectl auth can-i --list --as=system:serviceaccount:metallb-system:controller
来验证 controller 的权限是否完备,这是一种非常专业的自查习惯。
网络前提,是所有新手最容易忽略的“地基”。在你敲下第一个
kubectl apply
命令之前,请务必确认以下三点:
-
集群节点的网络平面必须是二层可达的 。这意味着你的所有 k8s worker 节点(包括 master,如果它也参与调度的话),必须能通过
ping和telnet <router-ip> 179直接访问到你的上游 BGP 路由器。不要试图用 NAT 或防火墙做中间人。BGP 协议要求 TCP 端口 179 的直连。如果你的路由器在192.168.10.1,那么每个 k8s 节点都必须能ping 192.168.10.1成功,并且nc -zv 192.168.10.1 179返回succeeded。这是硬性要求,没有商量余地。 -
上游路由器必须支持并启用 BGP 。这不是指“路由器型号列表里有 BGP 两个字”,而是指你必须能登录到它的 CLI(命令行界面),并成功执行类似
router bgp 65001的配置。家用千兆路由器(如华硕、小米)几乎都不支持 BGP,它们只支持静态路由或 DHCP。你需要的是企业级设备,如 Cisco ISR 1000 系列、华为 AR 系列、Juniper SRX,或者在一台 Linux 服务器上用 FRR(Free Range Routing)软件模拟一个 BGP 路由器。FRR 是本方案最推荐的入门选择,因为它免费、开源、文档齐全,且与 MetalLB 的兼容性经过了充分验证。 -
你必须拥有一段独立的、未被使用的 IP 地址段作为 VIP 池 。这段地址不能是你的 k8s 节点的管理 IP 段,也不能是 Pod 网络(如
10.244.0.0/16)或 Service 网络(如10.96.0.0/12)的地址段。它必须是一段纯粹用于“对外服务”的地址,比如192.168.10.100-192.168.10.199(共 100 个地址)。这段地址需要在你的上游路由器上配置为“直连路由”或“静态路由”,指向你的 k8s 集群的任一节点 IP(通常是第一个 master 节点的 IP)。这是为了让路由器知道,“哦,这段地址不在我的直连网段里,但我知道该往哪台机器上发”。
提示:如果你暂时没有物理路由器,强烈建议用一台 Ubuntu 24.04 虚拟机安装 FRR 来模拟。它比折腾家用路由器的固件要可靠一百倍。FRR 的安装只需三条命令:
sudo apt update && sudo apt install frr && sudo systemctl enable frr,然后编辑/etc/frr/daemons启用bgpd,最后在/etc/frr/frr.conf里写入 BGP 配置。这个过程,比你在网上搜“家用路由器开启 BGP”要快得多,也靠谱得多。
4. 实操过程与核心环节实现:从零开始的完整部署流水线
现在,让我们进入真正的“手把手”环节。假设你已经有一套运行在 Ubuntu 24.04 上的 Kubernetes 1.34.2 集群,所有节点都已通过
kubeadm init
和
kubeadm join
正确加入,
kubectl get nodes
显示
Ready
。我们将严格按照生产环境的标准流程,一步步完成 MetalLB 的部署。
4.1 创建命名空间与应用核心 Manifest
第一步,永远是创建一个专属的、隔离的命名空间。这不仅是最佳实践,更是安全底线。MetalLB 的所有组件,都应该运行在
metallb-system
这个命名空间下,与其他业务 Namespace 完全隔离开。
kubectl create namespace metallb-system
第二步,下载并应用官方的
metallb-native.yaml
。请务必使用 v0.15.2 的 Release 链接,不要用
main
分支的最新代码,因为那可能包含尚未发布的实验性功能。
# 下载 v0.15.2 的原生 Manifest
curl -OL https://github.com/metallb/metallb/releases/download/v0.15.2/metallb-native.yaml
# 应用它
kubectl apply -f metallb-native.yaml
这条命令会一次性创建所有东西:CRD、ServiceAccount、Role/ClusterRole、RoleBinding/ClusterRoleBinding、Controller Deployment、Speaker DaemonSet。你可以用
kubectl get all -n metallb-system
来观察它们的启动状态。正常情况下,
controller
的 Pod 会很快进入
Running
,而
speaker
的 Pod 会以 DaemonSet 的形式,在每个节点上启动一个。如果
speaker
的 Pod 卡在
ContainerCreating
,最常见的原因是节点上缺少
hostNetwork: true
所需的 CNI 插件权限,或者你的 CNI(如 Calico、Cilium)配置了严格的网络策略。此时,
kubectl describe pod -n metallb-system <speaker-pod-name>
是你的第一道排查工具,重点关注 Events 部分。
4.2 配置 BGP 对等体(BGPPeer)
这是整个部署中最关键、也最容易出错的一环。我们需要创建一个
BGPPeer
资源,告诉 MetalLB:“我的上游路由器长这样”。
首先,创建一个名为
bgp-peer.yaml
的文件:
apiVersion: metallb.io/v1beta1
kind: BGPPeer
metadata:
name: my-router
namespace: metallb-system
spec:
myAsn: 65001
peerAsn: 65000
peerAddress: 192.168.10.1
peerPort: 179
这里的参数含义如下:
-
myAsn: MetalLB 集群的 AS 号。你可以任意指定,但必须是一个合法的私有 ASN(64512-65534),这里选65001。 -
peerAsn: 上游路由器的 AS 号。这必须与你在路由器上配置的router bgp <asn>中的 ASN 完全一致。如果路由器上配的是router bgp 65000,这里就必须是65000。 -
peerAddress: 上游路由器的管理 IP 地址,也就是你ping得通的那个地址。 -
peerPort: BGP 的标准端口,179,一般无需修改。
应用这个配置:
kubectl apply -f bgp-peer.yaml
应用后,立刻检查 BGP 会话状态:
kubectl get bgppeers -n metallb-system
# 输出应该类似于:
# NAME AGE
# my-router 30s
但这只是资源创建成功,不代表会话已建立。要确认会话是否
Established
,你需要看
speaker
的日志:
kubectl logs -n metallb-system -l app=metallb-speaker --tail=50 | grep "BGP session"
# 你期望看到类似这样的日志:
# level=info msg="BGP session established" duration="123.456ms" peer.address="192.168.10.1:179" peer.asn=65000
如果日志里出现
BGP session failed
或
Connection refused
,请立即回到“网络前提”检查:
telnet 192.168.10.1 179
是否通?路由器上的 BGP 进程是否真的在监听
0.0.0.0:179
?
show ip bgp summary
命令是否显示邻居状态为
Active
或
Connect
?记住,BGP 是双向握手,MetalLB 是主动发起方,路由器是被动接受方,任何一方的配置错误都会导致握手失败。
4.3 定义 IP 地址池(IPAddressPool)
BGP 会话建立后,MetalLB 就有了“说话”的资格,但它还不知道自己能“说”哪些 IP。这就需要
IPAddressPool
。
创建
ip-pool.yaml
:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default-pool
namespace: metallb-system
spec:
addresses:
- 192.168.10.100-192.168.10.199
autoAssign: true
addresses
字段定义了 VIP 的范围。
autoAssign: true
表示 MetalLB 会自动为每一个
type: LoadBalancer
的 Service 分配一个 IP,无需你手动指定
loadBalancerIP
。这对于快速迭代的开发环境非常友好。如果你希望对 VIP 有绝对的控制权(例如,让
nginx-ingress
永远用
192.168.10.100
),可以把
autoAssign
设为
false
,然后在 Service 的 YAML 里显式写上
spec.loadBalancerIP: 192.168.10.100
。
应用配置:
kubectl apply -f ip-pool.yaml
同样,检查状态:
kubectl get ipaddresspools -n metallb-system
# 输出应该显示:
# NAME AGE AVAILABLE USED TOTAL
# default-pool 2m 100 0 100
AVAILABLE
列显示
100
,说明地址池已成功加载,100 个 IP 都待命。
4.4 验证与测试:让第一个 LoadBalancer Service 跑起来
现在,万事俱备。我们来部署一个最简单的 Nginx 应用来测试。
创建
nginx-test.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test
labels:
app: nginx-test
spec:
replicas: 2
selector:
matchLabels:
app: nginx-test
template:
metadata:
labels:
app: nginx-test
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-test-svc
spec:
selector:
app: nginx-test
ports:
- port: 80
targetPort: 80
type: LoadBalancer
应用它:
kubectl apply -f nginx-test.yaml
等待约 30 秒,然后执行:
kubectl get svc nginx-test-svc
# 你期望看到:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# nginx-test-svc LoadBalancer 10.96.123.45 192.168.10.100 80:31234/TCP 45s
看到
EXTERNAL-IP
列出现了
192.168.10.100
,恭喜你,MetalLB 已经在工作了!现在,从你的笔记本电脑(或其他局域网内的任意一台机器)上,打开浏览器,访问
http://192.168.10.100
。你应该能看到 Nginx 的默认欢迎页面。这证明流量已经成功地从你的局域网,穿越了上游路由器,最终抵达了 k8s 集群中的某个 Nginx Pod。
注意:这个测试必须在局域网内进行。
192.168.10.100是一个内网 VIP,它不会出现在公网 DNS 里,也无法被互联网直接访问。如果你想让它被外网访问,你需要在上游路由器上配置端口映射(NAT)或 DMZ,这是网络架构层面的事情,超出了 MetalLB 的职责范围。
5. 常见问题与排查技巧实录:那些只有踩过坑才知道的真相
在为上百个不同规模的集群部署 MetalLB 的过程中,我总结出了一套高效的故障排查“三板斧”:查状态、看日志、抓数据包。下面列出几个最具代表性的、网上教程绝不会告诉你的真实问题和解决方案。
5.1 问题:
kubectl get bgppeers
显示资源存在,但
speaker
日志里完全没有 BGP 相关信息
现象
:
kubectl get bgppeers -n metallb-system
能看到
my-router
,
kubectl get pods -n metallb-system
显示所有
speaker
Pod 都是
Running
,但
kubectl logs -n metallb-system -l app=metallb-speaker | grep BGP
一片空白。
根本原因
:
speaker
组件默认只会为它所在节点的网络接口宣告路由。如果
speaker
Pod 启动时,它所在的节点上还没有一个有效的、处于
UP
状态的、并且 IP 地址属于你
IPAddressPool
范围内的网络接口,它就会静默地跳过 BGP 初始化。这是一个非常隐蔽的设计,官方文档里提得很少。
排查与解决 :
-
首先,确认
speakerPod 运行在哪个节点上:kubectl get pods -n metallb-system -o wide | grep speaker。 -
登录到那个节点,执行
ip a,查看所有网络接口的状态和 IP。重点找一个state UP的接口(比如ens18,eth0),并确认它的主 IP 地址(inet行)是否在192.168.10.0/24这个网段内。如果这个节点的管理 IP 是10.0.2.15(VirtualBox 默认),而你的 VIP 池是192.168.10.100-192.168.10.199,那么speaker就会认为“我跟这个 VIP 池没关系”,从而不启动 BGP。 -
终极解决方案
:在
BGPPeer的spec中,添加nodeSelectors,强制将speaker调度到一个拥有正确网段 IP 的节点上。例如,给你的主节点打一个标签:kubectl label node k8s-master-01 network-type=core,然后在bgp-peer.yaml里加上:
这样,spec: nodeSelectors: network-type: corespeaker就只会部署在k8s-master-01上,而这个节点的 IP 是192.168.10.10,完美匹配。
5.2 问题:BGP 会话状态在
Active
和
Connect
之间反复横跳
现象
:
speaker
日志里不断出现
BGP session failed
,状态在
Active
(尝试连接)和
Connect
(连接中)之间循环,就是无法到达
Established
。
根本原因
:这几乎 100% 是上游路由器的 BGP 配置问题。最常见的错误是:
路由器上没有为 MetalLB 的 ASN 配置
neighbor
,或者配置了但
remote-as
写错了
。
排查与解决 :
-
在路由器上,执行
show ip bgp summary。找到 MetalLB 的 IP(比如192.168.10.10),看它的 State/PfxRcd 一栏。如果是Active,说明路由器收到了连接请求,但拒绝了它。此时,show run | section router bgp是必查命令。 -
仔细核对
neighbor 192.168.10.10 remote-as 65001这一行。remote-as的值,必须与 MetalLBBGPPeer中的myAsn完全一致。一个数字都不能错。 -
如果你用的是 FRR,还有一个致命陷阱:FRR 默认会启用
ipv4 unicast地址族,但 MetalLB v0.15.2 默认只宣告ipv4 unicast。如果 FRR 的配置里漏掉了address-family ipv4 unicast这个上下文,BGP 会话也会卡住。FRR 的正确配置片段应该是:router bgp 65000 bgp router-id 192.168.10.1 neighbor 192.168.10.10 remote-as 65001 ! address-family ipv4 unicast neighbor 192.168.10.10 activate exit-address-family
5.3 问题:Service 的
EXTERNAL-IP
分配了,但
curl http://<VIP>
超时
现象
:
kubectl get svc
显示
EXTERNAL-IP
已分配,
speaker
日志显示
BGP session established
,
show ip route
在路由器上也能看到
B
开头的 BGP 路由,但就是无法访问。
根本原因
:流量路径上的某个环节,做了“反向路径过滤”(Reverse Path Filtering, RPF)。Linux 内核有一个安全特性,叫
rp_filter
,它会检查一个数据包的“入接口”是否与该包目的 IP 的路由表项所指示的“出接口”一致。如果不一致,内核会直接丢弃该包。在 MetalLB 的 BGP 模式下,流量是这样走的:客户端 -> 路由器 -> k8s 节点(VIP)-> kube-proxy -> Pod。当流量到达 k8s 节点时,它的目的 IP 是
192.168.10.100
,而节点的路由表会告诉内核:“去
192.168.10.0/24
的流量,应该从
ens18
接口出去”。但这个包是从
ens18
接口“进来”的!于是,
rp_filter
认为这是个“伪造的”包,直接丢弃。
排查与解决 :
-
在 k8s 节点上,执行
sysctl net.ipv4.conf.all.rp_filter和sysctl net.ipv4.conf.ens18.rp_filter(把ens18换成你实际的接口名)。如果返回1,说明 RPF 是开启的。 -
临时修复
:
sudo sysctl -w net.ipv4.conf.all.rp_filter=0和sudo sysctl -w net.ipv4.conf.ens18.rp_filter=0。 -
永久修复
:编辑
/etc/sysctl.conf,添加两行:
然后执行net.ipv4.conf.all.rp_filter = 0 net.ipv4.conf.ens18.rp_filter = 0sudo sysctl -p使其生效。这是 MetalLB BGP 模式在 Linux 上运行的必备条件,几乎所有成功的生产部署都做了这个配置。
5.4 问题速查表
| 问题现象 | 最可能原因 | 快速验证命令 | 一句话解决方案 |
|---|---|---|---|
kubectl get bgppeers
无输出
| CRD 未安装或 Manifest 应用失败 |
kubectl get crd | grep metallb
|
重新
kubectl apply -f metallb-native.yaml
,检查是否有
no matches for kind
错误
|
speaker
Pod 一直
CrashLoopBackOff
|
节点上缺少
hostNetwork: true
所需的
NET_ADMIN
权限
|
kubectl describe pod -n metallb-system <speaker-pod>
|
检查 CNI 插件(如 Calico)的
felixConfiguration
,确保
allowUnsafeSysctls: true
|
EXTERNAL-IP
一直是
<pending>
|
IPAddressPool
未创建,或
BGPPeer
的
myAsn
/
peerAsn
不匹配
|
kubectl get ipaddresspools -n metallb-system
kubectl get bgppeers -n metallb-system
|
逐一检查
ip-pool.yaml
和
bgp-peer.yaml
的语法和参数
|
curl <VIP>
返回
Connection refused
|
kube-proxy 未正常工作,或 Service 的
targetPort
与 Pod 的
containerPort
不一致
|
kubectl get endpoints nginx-test-svc
kubectl get pods -o wide
|
kubectl get endpoints
应该显示至少一个 IP:Port,否则检查 Pod 是否
Running
且
ReadinessProbe
通过
|
6. 进阶思考与个人体会:MetalLB 不是终点,而是网络自治的起点
部署完 MetalLB v0.15.2,看着
EXTERNAL-IP
从
<pending>
变成一个真实的、可访问的 IP,那一刻的成就感是实实在在的。但这绝不意味着你可以把 MetalLB 当作一个“设置一次就永不闻问”的黑盒。恰恰相反,它是我眼中 Kubernetes 网络自治能力的真正起点。当你亲手配置了
BGPPeers
和
IPAddressPools
,你就不再是一个被动的“云服务使用者”,而是一个主动的“网络基础设施规划者”。
我最近在一个为某高校部署的科研计算平台项目中,就深刻体会到了这一点。他们的需求很特殊:需要为不同的课题组提供完全隔离的、拥有独立公网 IP 的 Web 服务。用传统的云厂商 SLB,成本会高得离谱,而且无法满足他们对网络拓扑的精细控制要求。我们基于 MetalLB v0.15.2,构建了一个多租户的 BGP 方案:为每个课题组创建一个独立的
BGPPeer
(指向他们各自申请的、位于不同机房的 BGP 路由器),再为每个
BGPPeer
关联一个专属的
IPAddressPool
。这样,
课题组A
的 Service 只会从
pool-a
里分配 IP,并只向
router-a
宣告;
课题组B
的 Service 则完全互不影响。整个过程,没有动用任何商业负载均衡器,全部由 Kubernetes 原生 API 驱动。这背后体现的,是一种“基础设施即代码”(IaC)的思维——网络不再是需要登录路由器 CLI 去敲命令的实体,而是一份可以被 Git 版本管理、被 CI/CD 流水线自动部署、被
kubectl diff
清晰对比的 YAML 文件。
所以,当你完成了这个“k8s-1.34.2 安装部署”的任务,别急着关掉终端。花十分钟,去
kubectl edit ipaddresspools -n metallb-system default-pool
,把地址范围从
192.168.10.100-192.168.10.199
扩展到
192.168.10.100-192.168.10.254
;再花五分钟,
kubectl edit bgppeers -n metallb-system my-router
,把
peerPort
从
179
改成
1790
(当然,前提是你的路由器也改了)。你会发现,这些操作不是在“修 bug”,而是在“编程”——你正在用 Kubernetes 的语言,编写你自己的网络操作系统。这才是 MetalLB v0.15.2,以及整个 Kubernetes 1.34.2 生态,带给我们这个时代最珍贵的东西:一种将复杂基础设施,降维成简洁、可理解、可掌控的抽象的能力。
更多推荐
所有评论(0)