K8s实战: 用OpenELB破解Service外部访问难题

关于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就能正常工作。

相关推荐
Thneonl1 小时前
照着 CKS 教材做实验,把 apiserver 干瘫了 7 分钟
安全·kubernetes
AINative软件工程2 小时前
LLM 应用的 Graceful Shutdown 工程实践:正在进行的 AI 请求如何安全停止
云原生·ai编程
名字还没想好☜3 小时前
Kubernetes 用 kubectl port-forward 和 proxy 调试集群内服务:两者区别、断连自动重连与为什么别用在生产
运维·docker·kubernetes
武汉唯众智创12 小时前
云计算实训室建设指南(2026版):从技能大赛赛项标准反推架构、课程与落地路径
云原生·kubernetes·云计算·云计算实训室·云计算教学平台·职业技能大赛
wdfk_prog13 小时前
ROS教程:01 搭建 ROS1 Noetic Docker 开发环境
运维·缓存·docker·容器·ros
szephyr14 小时前
Docker + Compose 实战:把本地项目一键搬到云服务器,附完整配置
运维·docker·容器·部署·云服务器
wdfk_prog14 小时前
ros教程02:创建 catkin Workspace、Package 与第一个 ROS1 C++ Node
运维·缓存·docker·容器·ros
阿里云云原生16 小时前
剧透丨AI 原生研发组织的探索和实践
云原生
名字还没想好☜18 小时前
Docker 网络实战:bridge/host/none/自定义网络、容器互通与端口映射踩坑
运维·docker·kubernetes
探索云原生20 小时前
KubeClipper 1.7.0 发布:Operation 优化与 Kubernetes 1.37 支持
linux·docker·云原生·kubernetes·go