文章目录
- [0 背景与架构](#0 背景与架构)
-
- [0.1 为什么需要MetalLB](#0.1 为什么需要MetalLB)
- [0.2 环境架构](#0.2 环境架构)
- [0.3 镜像拉取方案](#0.3 镜像拉取方案)
- [1 安装前准备](#1 安装前准备)
-
- [1.1 检查kube-proxy模式](#1.1 检查kube-proxy模式)
- [1.2 确认集群状态](#1.2 确认集群状态)
- [2 安装MetalLB](#2 安装MetalLB)
-
- [2.1 应用官方Manifest](#2.1 应用官方Manifest)
- [2.2 处理镜像拉取问题](#2.2 处理镜像拉取问题)
- [2.3 验证安装](#2.3 验证安装)
- [3 配置IP地址池](#3 配置IP地址池)
-
- [3.1 创建IPAddressPool](#3.1 创建IPAddressPool)
- [3.2 创建L2Advertisement](#3.2 创建L2Advertisement)
- [3.3 验证配置](#3.3 验证配置)
- [4 Mac宿主机用 Safari 浏览器就行](#4 Mac宿主机用 Safari 浏览器就行)
- [5 测试LoadBalancer Service](#5 测试LoadBalancer Service)
-
- [5.1 创建svc](#5.1 创建svc)
- [5.2 验证EXTERNAL-IP](#5.2 验证EXTERNAL-IP)
- [5.3 从宿主机访问](#5.3 从宿主机访问)
- [6 常见问题与解决](#6 常见问题与解决)
-
- [6.1 镜像拉取失败](#6.1 镜像拉取失败)
- [7 总结](#7 总结)
- 感谢阅读
0 背景与架构
0.1 为什么需要MetalLB
在 《02_在多个RockyLinux10虚拟机上安装k8s集群》 搭建的三节点集群中,如果我们创建一个 type: LoadBalancer 的 Service,它的 EXTERNAL-IP 会一直显示 <pending>:
bash
[root@rockylinux10-1 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kiada-loadbalancer-svc LoadBalancer 10.1.147.173 <pending> 80:30080/TCP,443:30443/TCP 30s
原因是 Kubernetes 本身并不提供裸金属环境的负载均衡器实现,它自带的 Network LB 都是调用云平台(GCP、AWS、Azure)的接口。如果不在受支持的 IaaS 平台上,LoadBalancer 类型的 Service 就会永远处于 pending 状态。
MetalLB 正是为了解决这个问题而生的------它为裸金属 Kubernetes 集群提供了 LoadBalancer 的实现,使用标准路由协议来对外暴露服务。
0.2 环境架构
| IP | 虚拟机名称 | 角色 | 说明 |
|---|---|---|---|
| 192.168.56.101 | rockylinux10-1 | control-plane | k8s master 节点 |
| 192.168.56.102 | rockylinux10-2 | worker | k8s worker 节点 |
| 192.168.56.103 | rockylinux10-3 | worker | k8s worker 节点 |
0.3 镜像拉取方案
由于国内网络限制,我们采用以下镜像源:
| 原始仓库 | 替换地址 | 用途 |
|---|---|---|
| docker.io | docker.m.daocloud.io | DaoCloud 镜像加速 |
| quay.io | quay.m.daocloud.io | DaoCloud 的 quay 镜像代理 |
1 安装前准备
1.1 检查kube-proxy模式
MetalLB 的 L2 模式需要确认 kube-proxy 的运行模式。只有在 IPVS 模式 下才需要启用 strictARP,而 iptables 模式(默认)则不需要。
执行以下命令查看当前模式:
bash
kubectl get cm kube-proxy -n kube-system -o yaml | grep mode
如果输出为 mode: "",表示使用默认的 iptables 模式,无需任何额外配置,直接继续安装即可。
说明 :只有在输出为
mode: "ipvs"时,才需要执行sed -e "s/strictARP: false/strictARP: true/"并重启 kube-proxy。iptables 模式下 strictARP 参数不生效,也不需要修改。
如果输出为 mode: "ipvs",执行以下命令启用 strict ARP:
bash
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system
之后重启 kube-proxy Pod:
bash
kubectl rollout restart daemonset kube-proxy -n kube-system
1.2 确认集群状态
bash
kubectl get nodes
kubectl get pods -n kube-system
确保所有节点为 Ready,控制平面 Pod 正常运行。
2 安装MetalLB
2.1 应用官方Manifest
MetalLB 提供了多种 Manifest,对于 L2 模式,使用 metallb-native 版本即可:
bash
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.16.1/config/manifests/metallb-native.yaml
如果该地址因网络问题无法访问,可以先将文件下载到本地再应用:
bash
# 在可以访问外网的机器上下载
curl -L -o metallb-native.yaml https://raw.githubusercontent.com/metallb/metallb/v0.16.1/config/manifests/metallb-native.yaml
# 传输到 master 节点
scp metallb-native.yaml root@192.168.56.101:/root/
# 在 master 上应用
kubectl apply -f /root/metallb-native.yaml
2.2 处理镜像拉取问题
安装后查看 Pod 状态:
bash
kubectl get pods -n metallb-system
如果出现 ImagePullBackOff,执行以下命令查看使用的镜像:
bash
kubectl describe pod -n metallb-system <pod-name> | grep -E "Image:|Failed"
MetalLB 的镜像通常来自 quay.io/metallb/,可以将 quay.io 替换为 quay.m.daocloud.io。修改方式是在 Manifest 中全局替换镜像地址,或者手动拉取并打标签。
2.3 验证安装
bash
kubectl get pods -n metallb-system
期望输出:
NAME READY STATUS RESTARTS AGE
controller-7d8f9c6b8b-xxxxx 1/1 Running 0 2m
speaker-xxxxx 1/1 Running 0 2m
speaker-yyyyy 1/1 Running 0 2m
speaker-zzzzz 1/1 Running 0 2m
controller 是集群范围的控制器,负责 IP 地址分配;speaker 是 DaemonSet,负责通过协议(L2 或 BGP)让服务可达。
3 配置IP地址池
3.1 创建IPAddressPool
MetalLB 需要知道可以为 Service 分配哪些 IP。地址范围必须与你的 VirtualBox Host-Only 网络在同一网段,且不能与节点 IP、DHCP 地址池重叠。
创建文件 ip-pool.yaml:
yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.56.240-192.168.56.250
应用:
bash
kubectl apply -f ip-pool.yaml
3.2 创建L2Advertisement
L2 模式是最简单的配置方式,只需将 IPAddressPool 与 L2Advertisement 关联即可:
创建文件 l2-advertisement.yaml:
yaml
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: first-l2
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
应用:
bash
kubectl apply -f l2-advertisement.yaml
3.3 验证配置
bash
kubectl get ipaddresspool -n metallb-system
kubectl get l2advertisement -n metallb-system
4 Mac宿主机用 Safari 浏览器就行
如果宿主机是 mac 电脑,那么直接用 safari 浏览器访问 k8s 的 service 的 ip 吧。Chrome 浏览器可能无法访问 k8s 的 svc
5 测试LoadBalancer Service
参照 k8s in action 这本书的第11章的 11.2.2 Exposing a service through an external load balancer 小节所说
5.1 创建svc
创建文件 svc.kiada.loadbalancer.yaml:
yaml
apiVersion: v1
kind: Service
metadata:
name: kiada-loadbalancer-svc
spec:
type: LoadBalancer
selector:
app: kiada
ports:
- name: http
port: 80
targetPort: 8080
nodePort: 30080
protocol: TCP
- name: https
port: 443
targetPort: 8443
nodePort: 30443
protocol: TCP
应用:
bash
kubectl apply -f svc.kiada.loadbalancer.yaml
5.2 验证EXTERNAL-IP
bash
kubectl get svc
期望输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kiada-loadbalancer-svc LoadBalancer 10.1.147.173 192.168.56.240 80:30080/TCP,443:30443/TCP 9h
EXTERNAL-IP 从 <pending> 变为 192.168.56.240,说明 MetalLB 已成功分配 IP。
5.3 从宿主机访问
如果宿主机是 Mac ,那么就在 Safari 浏览器访问 http://192.168.56.240,应该能看到 Kiada 的页面。Chrome 浏览器是不行的,访问不了。
6 常见问题与解决
6.1 镜像拉取失败
现象 :MetalLB Pod 处于 ImagePullBackOff。
解决 :将 quay.io 替换为 quay.m.daocloud.io,或手动拉取镜像并打标签:
bash
sudo ctr -n k8s.io images pull quay.m.daocloud.io/metallb/controller:v0.16.1
sudo ctr -n k8s.io images tag quay.m.daocloud.io/metallb/controller:v0.16.1 quay.io/metallb/controller:v0.16.1
7 总结
通过本文,我们完成了以下工作:
- 理解了 MetalLB 的用途:为裸金属 Kubernetes 集群提供 LoadBalancer 类型的 Service 实现
- 确认了 kube-proxy 模式:iptables 模式下无需配置 strictARP
- 安装了 MetalLB:通过官方 Manifest 部署了 controller 和 speaker
- 配置了 IP 地址池和 L2Advertisement:为负载均衡 Service 提供可分配的 IP 范围
- 测试了 LoadBalancer Service :验证了
EXTERNAL-IP从 pending 变为实际 IP