关于openelbl作为调度器实现k8s的Service的loadbalancer模式:
Kubernetes 原生不提供 LoadBalancer 类型 Service 的具体实现(尤其在裸机或私有云环境)。需要借助外部组件(如 OpenELB)来充当 4/7 层调度器,提供负载均衡能力,并能自动判断后端 Pod 的健康状态。
本文档记录了在 K8s 集群中部署 OpenELB 并测试 LoadBalancer Service 的完整过程及问题解决方法。
1.安装OpenELB
1.1下载资源清单
bash
wget https://raw.githubusercontent.com/openelb/openelb/release-0.6/deploy/openelb.yaml
1.2应用
bash
[root@k8s-master01 ~]# kubectl apply -f openelb.yaml
1.3 检验
bash
[root@k8s-master01 ~]# kubectl get pod -n openelb-system
NAME READY STATUS RESTARTS AGE
openelb-admission-create-8ndq2 0/1 ContainerCreating 0 12s
openelb-admission-patch-pn9n6 0/1 ContainerCreating 0 12s
openelb-controller-5cdcf556d4-rtvtg 0/1 ContainerCreating 0 12s
openelb-speaker-4plq6 0/1 ContainerCreating 0 12s
openelb-speaker-b4qjf 0/1 ContainerCreating 0 12s
openelb-speaker-c5hwc 0/1 ContainerCreating 0 12s
2.配置 EIP(弹性 IP 地址池)
2.1 EIP 资源配置文件
yml
apiVersion: network.kubesphere.io/v1alpha2
kind: Eip
metadata:
name: eip-sample-pool
annotations:
eip.openelb.kubesphere.io/is-default-eip: "true"
spec:
address: 192.168.64.100-192.168.64.150 # 可用的 IP 范围
priority: 100
namespaces:
- test
- default
namespaceSelector:
kubesphere.io/workspace: workspace
disable: false
protocol: layer2 # 使用二层协议(ARP/NDP)
interface: ens160 # 指定网络接口
2.2 应用 &故障解决
bash
[root@k8s-master01 ~]# kubectl apply -f eip.yml
Error from server (InternalError): error when creating "eip.yml": Internal error occurred: failed calling webhook "validate.eip.network.kubesphere.io": failed to call webhook: Post "https://openelb-controller.openelb-system.svc:443/validate-network-kubesphere-io-v1alpha2-eip?timeout=10s": dial tcp 10.7.129.16:443: connect: connection refused
原因是 OpenELB 的 Admission Webhook 无法正常提供服务,根本原因在于相关 Pod 未正常运行。
检测相关pod & 查看openelb-controller
bash
[root@k8s-master01 ~]# kubectl get pod -n openelb-system
NAME READY STATUS RESTARTS AGE
openelb-admission-create-8ndq2 0/1 ImagePullBackOff 0 6m32s
openelb-admission-patch-pn9n6 0/1 ErrImagePull 0 6m32s
openelb-controller-5cdcf556d4-rtvtg 0/1 ContainerCreating 0 6m32s
openelb-speaker-4plq6 0/1 ContainerCreating 0 6m32s
openelb-speaker-b4qjf 0/1 ContainerCreating 0 6m32s
openelb-speaker-c5hwc 1/1 Running 0 6m32s
[root@k8s-master01 ~]# kubectl describe pod -n openelb-system openelb-controller-5cdcf556d4-rtvtg
.......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 7m default-scheduler Successfully assigned openelb-system/openelb-controller-5cdcf556d4-rtvtg to k8s-master01
Warning FailedMount 48s (x11 over 7m) kubelet MountVolume.SetUp failed for volume "webhook-cert" : secret "openelb-admission" not found
解决问题(临时解决方案)
由于 Webhook 配置存在问题,导致 EIP 创建被拦截。可临时删除该 ValidatingWebhookConfiguration 以绕过校验
bash
[root@k8s-master01 ~]# kubectl get validatingwebhookconfiguration | grep openelb
openelb-admission 1 8m3s
[root@k8s-master01 ~]#
[root@k8s-master01 ~]# kubectl delete validatingwebhookconfiguration openelb-admission
validatingwebhookconfiguration.admissionregistration.k8s.io "openelb-admission" deleted
验证
bash
[root@k8s-master01 ~]# kubectl apply -f eip.yml
eip.network.kubesphere.io/eip-sample-pool created
[root@k8s-master01 ~]# kubectl get eip
NAME CIDR USAGE TOTAL
eip-sample-pool 192.168.64.100-192.168.64.150
3.部署&测试 LoadBalancer Service
3.1 编辑资源清单
bash
[root@k8s-master01 ~]# cat test_loadbalancer.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: loadbalancer-deploy
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: loadbalancer-container
image: hb.reg.com/library/myapp:1.0 # 替换为实际可用镜像,这里是我是私人仓库
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: loadbalancer-svc
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: myapp
3.2应用
bash
[root@k8s-master01 ~]# kubectl apply -f test_loadbalancer.yml
3.3检测
bash
[root@k8s-master01 ~]# kubectl get eip,svc,pod
NAME CIDR USAGE TOTAL
eip.network.kubesphere.io/eip-sample-pool 192.168.64.100-192.168.64.150
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 9d
service/loadbalancer-svc LoadBalancer 10.10.18.79 192.168.64.100 80:32452/TCP 52s
NAME READY STATUS RESTARTS AGE
pod/loadbalancer-deploy-5c6f5f784d-lkvj2 1/1 Running 0 52s
pod/loadbalancer-deploy-5c6f5f784d-tls6p 1/1 Running 0 52s
pod/loadbalancer-deploy-5c6f5f784d-wtm7b 1/1 Running 0 52s
可用看到service的ip就是就是eip(IP地址池)设定的范围
bash
[root@k8s-master01 ~]# curl 10.10.18.79
hello jock | welcome to nginx! | version 1.0
[root@k8s-master01 ~]# curl 10.10.18.79/hostname.html
loadbalancer-deploy-5c6f5f784d-wtm7b
[root@k8s-master01 ~]# curl 10.10.18.79/hostname.html
loadbalancer-deploy-5c6f5f784d-tls6p
[root@k8s-master01 ~]# curl 10.10.18.79/hostname.html
loadbalancer-deploy-5c6f5f784d-lkvj2
[root@k8s-master01 ~]# curl 10.10.18.79/hostname.html
loadbalancer-deploy-5c6f5f784d-wtm7b
[root@k8s-master01 ~]# curl 10.10.18.79/hostname.html
loadbalancer-deploy-5c6f5f784d-tls6p
[root@k8s-master01 ~]# curl 10.10.18.79/hostname.html
loadbalancer-deploy-5c6f5f784d-lkvj2
[root@k8s-master01 ~]# curl 192.168.64.100/hostname.html
loadbalancer-deploy-5c6f5f784d-lkvj2
[root@k8s-master01 ~]# curl 192.168.64.100/hostname.html
loadbalancer-deploy-5c6f5f784d-wtm7b
[root@k8s-master01 ~]# curl 192.168.64.100/hostname.html
loadbalancer-deploy-5c6f5f784d-tls6p
可用看到3个pod轮询
可以在浏览器里面查看该EXTERNAL-IP

用了两个浏览器(谷歌/微软),本来应该有轮询效果的,是浏览器的机制问题,加载也不会变化。
浏览器开启 HTTP Keep‑Alive 复用 TCP 连接,K8s Service 轮询只在新建 TCP 连接时生效,同一个连接内所有请求固定发给同一个 Pod,所以刷新看不到轮询。
一些Tips:
值得注意的是,即使我们现在查看相关pod
bash
[root@k8s-master01 ~]# kubectl get pod -n openelb-system
NAME READY STATUS RESTARTS AGE
openelb-admission-create-8ndq2 0/1 ImagePullBackOff 0 35m
openelb-admission-patch-pn9n6 0/1 ImagePullBackOff 0 35m
openelb-controller-5cdcf556d4-rtvtg 0/1 ContainerCreating 0 35m
openelb-speaker-4plq6 1/1 Running 0 35m
openelb-speaker-b4qjf 1/1 Running 0 35m
openelb-speaker-c5hwc 1/1 Running 0 35m
当前的 Speaker 已正常运行,即使 admission 和 controller 有问题,你的 LoadBalancer Service 仍然可以工作。因为:
- Speaker:负责实际流量转发,已经正常工作
- Controller:主要负责 IP 分配和状态管理
- Admission:负责资源校验,已通过删除 webhook 绕过
如果你只需要基础功能,可以暂时忽略这些错误。但对于生产环境,建议解决所有组件的健康状态。
具体来说,结合本次实验:
Speaker是OpenELB的核心数据平面组件 ,它负责响应ARP请求将外部IP(如你实验中的192.168.64.100)绑定到节点MAC地址,并通过iptables/IPVS规则将到达该IP的流量负载均衡到后端Pod------这正是你实验中curl 192.168.64.100/hostname.html能够成功且轮询返回三个不同Pod名称的根本原因;而Controller仅负责初始的IP池管理和状态更新(你的EIP在创建时已分配好IP就不再需要它),Admission仅负责配置校验(你删除Webhook后配置已生效就无需它),这两个控制平面组件只在资源创建或变更时起作用,不影响已运行服务的流量转发,所以即便它们都异常,只要Speaker在运行,LoadBalancer Service就能正常工作。