1.1 环境准备
如果您在 IPVS 模式下使用 kube-proxy,那么从 Kubernetes v1.14.2 开始,您必须启用严格的 ARP 模式。
注意:如果您使用 kube-router 作为服务代理,则不需要此操作,因为它默认已启用严格的 ARP。
环境准备有两种方式,您可以按需选择。
方式一:响应式更改
直接编辑 kube-proxy 的 ConfigMap:
[root@k8s-master01 ~]# kubectl -n kube-system edit cm kube-proxy
#...
mode: "ipvs"
ipvs:
strictARP: true # 将此处从 false 改为 true
#...
:wq
configmap/kube-proxy edited
方式二:声明式修改
您可以参考 MetalLB 官方安装文档 进行声明式修改,下面的命令可以预览并应用更改。
# 预览将要发生的更改,如果配置不同则返回非零状态码
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl diff -f - -n kube-system
# 实际应用更改,仅在出错时返回非零状态码
kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system
参考 MetalLB 官方安装指南,直接使用清单文件部署应用。
# 通过清单部署应用
[root@k8s-master01 ~]# kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.15.3/config/manifests/metallb-native.yaml
namespace/metallb-system created
customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgppeers.metallb.io created
customresourcedefinition.apiextensions.k8s.io/communities.metallb.io created
customresourcedefinition.apiextensions.k8s.io/configurationstates.metallb.io created
customresourcedefinition.apiextensions.k8s.io/ipaddresspools.metallb.io created
customresourcedefinition.apiextensions.k8s.io/l2advertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/servicebgpstatuses.metallb.io created
customresourcedefinition.apiextensions.k8s.io/servicel2statuses.metallb.io created
serviceaccount/controller created
serviceaccount/speaker created
role.rbac.authorization.k8s.io/controller created
role.rbac.authorization.k8s.io/pod-lister created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/controller created
rolebinding.rbac.authorization.k8s.io/pod-lister created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
configmap/metallb-excludel2 created
secret/metallb-webhook-cert created
service/metallb-webhook-service created
deployment.apps/controller created
daemonset.apps/speaker created
validatingwebhookconfiguration.admissionregistration.k8s.io/metallb-webhook-configuration created
部署完成后,验证 metallb-system 命名空间下的 Pod 状态,确保所有组件都正常运行。这是进行后续负载均衡配置的基础。
[root@k8s-master01 /data/manifests/add-one/01-metallb]# kubectl -n metallb-system get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
controller-66bdd896c6-z6nv6 1/1 Running 0 11m 10.244.2.102 k8s-node02.dinginx.org <none> <none>
speaker-46xk9 1/1 Running 0 11m 11.0.1.12 k8s-node02.dinginx.org <none> <none>
speaker-fd5sw 1/1 Running 0 11m 11.0.1.10 k8s-master01.dinginx.org <none> <none>
speaker-wl2lk 1/1 Running 0 11m 11.0.1.11 k8s-node01.dinginx.org <none> <none>
MetalLB 部署成功只是第一步,接下来需要配置地址池并创建服务来验证其功能。官方使用文档地址:https://metallb.universe.tf/usage/ 。
2.1 创建分配地址池
我们需要为 MetalLB 指定一个 IP 地址池,用于分配给类型为 LoadBalancer 的服务。官方提供了完整的配置示例:https://metallb.universe.tf/usage/example/ 。
以下是一个 IPAddressPool 和 L2Advertisement 的 YAML 配置示例,采用 L2 模式。
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: dinginx-pool
namespace: metallb-system
spec:
# MetalLB分配的地址池,请确保此IP段在您的网络环境中可用且未被占用
addresses:
- 11.0.1.110-11.0.1.200
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: dinginx-l2
namespace: metallb-system
spec:
ipAddressPools:
- dinginx-pool
将上述配置保存为 01-metallb-IPAddressPool.yaml 并应用。
2.2 创建deploy及svc资源
为了测试,我们创建一个简单的 Nginx 部署(Deployment)和一个类型为 LoadBalancer 的服务(Service)。
apiVersion: apps/v1
kind: Deployment
metadata:
name: dinginx-metallb-deploy
namespace: metallb-system
spec:
replicas: 3
selector:
matchLabels:
apps: web
# 定义Pod的模板
template:
metadata:
labels:
apps: web
spec:
containers:
- image: harbor.dinginx.org/dinginx/app-dinginx:v1
name: dinginx-web001
---
# 创建svc资源,注意type为LoadBalancer
apiVersion: v1
kind: Service
metadata:
labels:
app: metallb-svc
name: metallb-svc
namespace: metallb-system
spec:
ports:
- targetPort: 80
port: 80
selector:
apps: web
type: LoadBalancer # 关键:指定服务类型为LoadBalancer
将上述配置保存为 02-metallb-deploy.yaml 并应用。这个步骤的运维操作会创建测试应用和对外服务。
2.3 验证资源信息
应用所有配置后,查看资源状态,确认 MetalLB 已为我们的服务分配了外部 IP(EXTERNAL-IP)。
[root@k8s-master01 /data/manifests/add-one/01-metallb]# kubectl get -f . -owide
NAME AUTO ASSIGN AVOID BUGGY IPS ADDRESSES
ipaddresspool.metallb.io/dinginx-pool true false ["11.0.1.110-11.0.1.200"]
NAME IPADDRESSPOOLS IPADDRESSPOOL SELECTORS PEERS NODE SELECTORS
bgpadvertisement.metallb.io/external ["dinginx-pool"]
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/dinginx-metallb-deploy 3/3 3 3 7m49s dinginx-web001 harbor.dinginx.org/dinginx/app-dinginx:v1 apps=web
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/metallb-svc LoadBalancer 10.96.143.217 11.0.1.111 80:31346/TCP 117s apps=web
[root@k8s-master01 /data/manifests/add-one/01-metallb]# kubectl -n metallb-system get pods,svc
NAME READY STATUS RESTARTS AGE
pod/controller-66bdd896c6-z6nv6 1/1 Running 0 59m
pod/dinginx-metallb-deploy-669cc94d8f-dh9kf 1/1 Running 0 9m7s
pod/dinginx-metallb-deploy-669cc94d8f-fnmbk 1/1 Running 0 9m7s
pod/dinginx-metallb-deploy-669cc94d8f-gnbjc 1/1 Running 0 9m7s
pod/speaker-46xk9 1/1 Running 0 59m
pod/speaker-fd5sw 1/1 Running 0 59m
pod/speaker-wl2lk 1/1 Running 0 59m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/metallb-svc LoadBalancer 10.96.143.217 11.0.1.111 80:31346/TCP 3m15s
service/metallb-webhook-service ClusterIP 10.107.36.172 <none> 443/TCP 59m
从输出可以看到,服务 metallb-svc 的类型是 LoadBalancer,并且已经成功获得了一个外部 IP 11.0.1.111。这标志着您的私有 Kubernetes 集群现在拥有了类似公有云的原生负载均衡器体验。
2.4 访问测试
现在,我们可以通过 MetalLB 分配的外部 IP 来访问服务了。首先在集群内部节点上进行 curl 测试。
# 在Master节点上通过External-IP访问
[root@k8s-master01 /data/manifests/add-one/01-metallb]# curl 11.0.1.111
<!-- 文件: nginx-site/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, Dinginx's website v1.0</h1>
<p>欢迎访问www.dinginx.org</p>
</body>
</html>
# 在集群外部另一台主机上访问测试
[root@harbor-club ~]# curl 11.0.1.111
<!-- 文件: nginx-site/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, Dinginx's website v1.0</h1>
<p>欢迎访问www.dinginx.org</p>
</body>
</html>
测试成功!无论是在集群内还是集群外,都能通过 11.0.1.111 这个 IP 地址访问到 Nginx 服务。这说明 MetalLB 的 L2 模式工作正常,它通过 ARP/NDP 协议将这个 IP 宣告到了本地网络。
2.5 浏览器访问测试
当然,我们也可以在浏览器中进行验证。访问 http://11.0.1.111/,您将看到部署的 Nginx 欢迎页面。
至此,您已经成功在私有 Kubernetes 集群中部署并验证了 MetalLB。它接管了类型为 LoadBalancer 的服务,并为其分配了外部可达的 IP 地址,省去了手动管理 NodePort 和外部负载均衡器的麻烦。如果您在部署过程中遇到问题,或者想了解更多高级配置(如 BGP 模式),欢迎到 云栈社区 的相关板块与大家交流探讨。