关于openelbl作为调度器实现k8s的Service的loadbalancer模式:
Kubernetes 原生不提供 LoadBalancer 类型 Service 的具体实现(尤其在裸机或私有云环境)。需要借助外部组件(如 OpenELB)来充当 4/7 层调度器,提供负载均衡能力,并能自动判断后端 Pod 的健康状态。
本文档记录了在 K8s 集群中部署 OpenELB 并测试 LoadBalancer Service 的完整过程及问题解决方法。
1.安装OpenELB
1.1下载资源清单
wgethttps://raw.githubusercontent.com/openelb/openelb/release-0.6/deploy/openelb.yaml1.2应用
[root@k8s-master01 ~]# kubectl apply -f openelb.yaml1.3 检验
[root@k8s-master01 ~]# kubectl get pod -n openelb-systemNAME READY STATUS RESTARTS AGE openelb-admission-create-8ndq20/1 ContainerCreating012s openelb-admission-patch-pn9n60/1 ContainerCreating012s openelb-controller-5cdcf556d4-rtvtg0/1 ContainerCreating012s openelb-speaker-4plq60/1 ContainerCreating012s openelb-speaker-b4qjf0/1 ContainerCreating012s openelb-speaker-c5hwc0/1 ContainerCreating012s2.配置 EIP(弹性 IP 地址池)
2.1 EIP 资源配置文件
apiVersion:network.kubesphere.io/v1alpha2kind:Eipmetadata:name:eip-sample-poolannotations:eip.openelb.kubesphere.io/is-default-eip:"true"spec:address:192.168.64.100-192.168.64.150# 可用的 IP 范围priority:100namespaces:-test-defaultnamespaceSelector:kubesphere.io/workspace:workspacedisable:falseprotocol:layer2# 使用二层协议(ARP/NDP)interface:ens160# 指定网络接口2.2 应用 &故障解决
[root@k8s-master01 ~]# kubectl apply -f eip.ymlError 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 tcp10.7.129.16:443: connect: connection refused原因是 OpenELB 的 Admission Webhook 无法正常提供服务,根本原因在于相关 Pod 未正常运行。
检测相关pod & 查看openelb-controller
[root@k8s-master01 ~]# kubectl get pod -n openelb-systemNAME READY STATUS RESTARTS AGE openelb-admission-create-8ndq20/1 ImagePullBackOff06m32s openelb-admission-patch-pn9n60/1 ErrImagePull06m32s openelb-controller-5cdcf556d4-rtvtg0/1 ContainerCreating06m32s openelb-speaker-4plq60/1 ContainerCreating06m32s openelb-speaker-b4qjf0/1 ContainerCreating06m32s openelb-speaker-c5hwc1/1 Running06m32s[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 failedforvolume"webhook-cert":secret"openelb-admission"not found解决问题(临时解决方案)
由于 Webhook 配置存在问题,导致 EIP 创建被拦截。可临时删除该 ValidatingWebhookConfiguration 以绕过校验
[root@k8s-master01 ~]# kubectl get validatingwebhookconfiguration | grep openelbopenelb-admission18m3s[root@k8s-master01 ~]#[root@k8s-master01 ~]# kubectl delete validatingwebhookconfiguration openelb-admissionvalidatingwebhookconfiguration.admissionregistration.k8s.io"openelb-admission"deleted验证
[root@k8s-master01 ~]# kubectl apply -f eip.ymleip.network.kubesphere.io/eip-sample-pool created[root@k8s-master01 ~]# kubectl get eipNAME CIDR USAGE TOTAL eip-sample-pool192.168.64.100-192.168.64.1503.部署&测试 LoadBalancer Service
3.1 编辑资源清单
[root@k8s-master01 ~]# cat test_loadbalancer.ymlapiVersion: apps/v1 kind: Deployment metadata: name: loadbalancer-deploy spec: replicas:3selector: 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:80targetPort:80selector: app: myapp3.2应用
[root@k8s-master01 ~]# kubectl apply -f test_loadbalancer.yml3.3检测
[root@k8s-master01 ~]# kubectl get eip,svc,podNAME CIDR USAGE TOTAL eip.network.kubesphere.io/eip-sample-pool192.168.64.100-192.168.64.150 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)AGE service/kubernetes ClusterIP10.0.0.1<none>443/TCP 9d service/loadbalancer-svc LoadBalancer10.10.18.79192.168.64.10080:32452/TCP 52s NAME READY STATUS RESTARTS AGE pod/loadbalancer-deploy-5c6f5f784d-lkvj21/1 Running052s pod/loadbalancer-deploy-5c6f5f784d-tls6p1/1 Running052s pod/loadbalancer-deploy-5c6f5f784d-wtm7b1/1 Running052s可用看到service的ip就是就是eip(IP地址池)设定的范围
[root@k8s-master01 ~]# curl 10.10.18.79hello jock|welcome to nginx!|version1.0[root@k8s-master01 ~]# curl 10.10.18.79/hostname.htmlloadbalancer-deploy-5c6f5f784d-wtm7b[root@k8s-master01 ~]# curl 10.10.18.79/hostname.htmlloadbalancer-deploy-5c6f5f784d-tls6p[root@k8s-master01 ~]# curl 10.10.18.79/hostname.htmlloadbalancer-deploy-5c6f5f784d-lkvj2[root@k8s-master01 ~]# curl 10.10.18.79/hostname.htmlloadbalancer-deploy-5c6f5f784d-wtm7b[root@k8s-master01 ~]# curl 10.10.18.79/hostname.htmlloadbalancer-deploy-5c6f5f784d-tls6p[root@k8s-master01 ~]# curl 10.10.18.79/hostname.htmlloadbalancer-deploy-5c6f5f784d-lkvj2[root@k8s-master01 ~]# curl 192.168.64.100/hostname.htmlloadbalancer-deploy-5c6f5f784d-lkvj2[root@k8s-master01 ~]# curl 192.168.64.100/hostname.htmlloadbalancer-deploy-5c6f5f784d-wtm7b[root@k8s-master01 ~]# curl 192.168.64.100/hostname.htmlloadbalancer-deploy-5c6f5f784d-tls6p可用看到3个pod轮询
可以在浏览器里面查看该EXTERNAL-IP
用了两个浏览器(谷歌/微软),本来应该有轮询效果的,是浏览器的机制问题,加载也不会变化。
浏览器开启 HTTP Keep‑Alive 复用 TCP 连接,K8s Service 轮询只在新建 TCP 连接时生效,同一个连接内所有请求固定发给同一个 Pod,所以刷新看不到轮询。
一些Tips:
值得注意的是,即使我们现在查看相关pod
[root@k8s-master01 ~]# kubectl get pod -n openelb-systemNAME READY STATUS RESTARTS AGE openelb-admission-create-8ndq20/1 ImagePullBackOff035m openelb-admission-patch-pn9n60/1 ImagePullBackOff035m openelb-controller-5cdcf556d4-rtvtg0/1 ContainerCreating035m openelb-speaker-4plq61/1 Running035m openelb-speaker-b4qjf1/1 Running035m openelb-speaker-c5hwc1/1 Running035m当前的 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就能正常工作。