
示例工程【免费下载链接】examplesKubernetes application example tutorials项目地址https://gitcode.com/gh_mirrors/examp/examples点击查看免费下载本文基于 kubernetes examples 仓库中_archived/selenium目录的完整示例讲解如何把 Selenium Grid 以主从master/worker模型部署到 Kubernetes用于解决 CI 流水线中 Selenium 资源争用的问题。读者将掌握Selenium Hub 与浏览器节点的部署配置、三种验证 Hub 的方式、Python 端执行远程测试任务、按需横向扩缩节点以及通过 VNC 调试挂起测试的完整流程。为什么要把 Selenium 部署到 KubernetesSelenium 是业界主流的浏览器自动化工具主要用于 Web 应用的自动化测试。当 Selenium 被引入 CI 流水线后多个构建任务同时跑测试时常常会围绕有限的 Selenium 资源浏览器实例、测试执行环境产生争用要么排队等待要么互相挤占资源导致测试不稳定。本示例给出的解法是把 Selenium Grid 搬进 Kubernetes利用其调度与弹性能力把浏览器执行环境做成可按需扩容、用完即弃的资源池。Selenium Grid 采用典型的主从模型Selenium Hub主节点网格的唯一入口负责接收测试请求并把任务分发给空闲的 worker。整个网格只需要一个 Hub但示例用 Deployment 保证它始终在运行。Selenium Nodes工作节点真正跑浏览器的 worker注意这里的 node 是 Selenium 概念与 Kubernetes 节点无关。示例提供 Chrome 与 Firefox 两类节点数量可按需伸缩。前置条件与资源规划在动手之前需要满足以下条件一个可用的 Kubernetes 集群以及配置好的kubectl客户端具体搭建方式可参考 Kubernetes 官方 Getting Started Guides。如果希望快速获得一个托管集群Google Container EngineGKE是较便捷的选择。集群资源要求要完整跑通本示例直到扩缩容部分集群至少需要4 CPU 和 6 GB RAM。从仓库中的部署文件可以看到Hub 与每个浏览器节点都声明了memory: 1000Mi、cpu: 0.5的资源上限见 selenium-hub-deployment.yaml 与 selenium-node-chrome-deployment.yaml加上节点默认 2 副本资源消耗是可预估的请据此规划节点规格。部署文件全景解析Hub 与服务仓库_archived/selenium目录下共包含 6 个文件其中 4 个 YAML 是部署的核心本文先看 Hub 相关的两个。Selenium Hub 的 Deployment 配置selenium-hub-deployment.yaml 使用apps/v1的 Deployment 来托管 Hub关键配置如下apiVersion: apps/v1 kind: Deployment metadata: name: selenium-hub labels: app: selenium-hub spec: replicas: 1 selector: matchLabels: app: selenium-hub template: metadata: labels: app: selenium-hub spec: containers: - name: selenium-hub image: selenium/hub:4.0 ports: - containerPort: 4444 - containerPort: 4443 - containerPort: 4442 resources: limits: memory: 1000Mi cpu: .5 livenessProbe: httpGet: path: /wd/hub/status port: 4444 initialDelaySeconds: 30 timeoutSeconds: 5 readinessProbe: httpGet: path: /wd/hub/status port: 4444 initialDelaySeconds: 30 timeoutSeconds: 5逐项说明镜像selenium/hub:4.0即 Selenium Grid 4 官方镜像。端口语义容器暴露三个端口——4444是 WebDriver 命令入口/wd/hub4442是事件总线发布publish端口4443是事件总线订阅subscribe端口。Selenium 4 中 Hub 内部的事件总线是节点注册与任务分发的通道。健康探针分别配置了livenessProbe存活探针判定容器是否需要重启与readinessProbe就绪探针判定流量是否可以进入均通过 HTTP GET/wd/hub/status检查 4444 端口initialDelaySeconds: 30表示容器启动 30 秒后才开始探测timeoutSeconds: 5表示探测超时时间为 5 秒。这两个探针是网格可用性的关键保障。Selenium Hub 的 Service 配置浏览器节点需要知道如何找到 Hub 才能注册为此示例创建了 selenium-hub-svc.yamlapiVersion: v1 kind: Service metadata: name: selenium-hub labels: app: selenium-hub spec: ports: - port: 4444 targetPort: 4444 name: port0 - port: 4443 targetPort: 4443 name: port1 - port: 4442 targetPort: 4442 name: port2 selector: app: selenium-hub type: NodePort sessionAffinity: None要点selector: app: selenium-hub与 Deployment 的labels匹配服务把流量路由到 Hub Pod。三个端口4444/4443/4442与容器的三个端口一一对应port与targetPort均为相同值。类型为NodePort既能让集群内节点通过内部 DNS 名称selenium-hub访问也能让集群外如浏览器节点所在的其他网络通过节点端口访问。sessionAffinity: None表示不做会话粘滞请求可分发到任意后端。创建 Hub 与服务的命令在仓库根目录执行以下命令即可完成部署示例文件归档在_archived/selenium目录下kubectl create --filename_archived/selenium/selenium-hub-deployment.yaml kubectl create --filename_archived/selenium/selenium-hub-svc.yaml第一条命令创建 Hub 的 Deployment第二条创建节点注册用的 Service。如果更习惯声明式管理也可以将create换成apply。验证 Hub 部署的三种方式部署完成后可以通过连接 Hub 的 Web 控制台来验证它是否正常工作。根据你的网络环境有三种验证路径。方式一Kubernetes 节点可达——直连 NodePort如果 Kubernetes 节点可以从你的网络直接访问通过kubectl describe svc selenium-hub可以查到节点端口号。下面的代码段利用 kubectl 的模板功能自动提取 NodePort 与第一个节点名称然后直接 curlexport NODEPORTkubectl get svc --selectorappselenium-hub --outputtemplate --template{{ with index .items 0}}{{with index .spec.ports 0 }}{{.nodePort}}{{end}}{{end}} export NODEkubectl get nodes --outputtemplate --template{{with index .items 0 }}{{.metadata.name}}{{end}} curl http://$NODE:$NODEPORT如果返回 Hub 的页面内容说明服务已正确路由到 Hub Pod。方式二Kubernetes 节点不可达——kubectl port-forward如果节点无法从你的网络访问可以通过 kubectl 代理访问。先拿到 Hub Pod 的名称export PODNAMEkubectl get pods --selectorappselenium-hub --outputtemplate --template{{with index .items 0}}{{.metadata.name}}{{end}} kubectl port-forward $PODNAME 4444:4444在另一个终端中验证curl http://localhost:4444port-forward会把本机 4444 端口转发到 Pod 的 4444 端口无需暴露任何 Service。方式三使用 Google Container Engine——暴露公网地址如果集群运行在 Google Container Engine 上还可以把 Hub 通过公网暴露出去。文档同时提醒这对多数场景都是个坏主意安全性差但确实可以这样做kubectl expose deployment selenium-hub --nameselenium-hub-external --labelsappselenium-hub,externaltrue --typeLoadBalancer等待几分钟selenium-hub-external服务会从 gcloud 获得一个负载均衡 IP。当kubectl get svc selenium-hub-external显示两个 IP 后运行以下代码段取出公网 IP 并验证export INTERNET_IPkubectl get svc --selectorappselenium-hub,externaltrue --outputtemplate --template{{with index .items 0}}{{with index .status.loadBalancer.ingress 0}}{{.ip}}{{end}}{{end}} curl http://$INTERNET_IP:4444/此后你以及互联网上的所有人都可以在浏览器中访问$INTERNET_IP打开 Hub 控制台——这也是文档强调坏主意的原因。部署 Firefox 与 Chrome 节点Hub 就绪后就可以部署 worker 了。示例默认部署 2 个 Chrome 节点与 2 个 Firefox 节点。kubectl create --filename_archived/selenium/selenium-node-chrome-deployment.yaml kubectl create --filename_archived/selenium/selenium-node-firefox-deployment.yamlPod 启动后它们会出现在 Selenium Hub 的界面中完成注册。Chrome 节点部署解析selenium-node-chrome-deployment.yaml 的完整结构如下apiVersion: apps/v1 kind: Deployment metadata: name: selenium-node-chrome labels: app: selenium-node-chrome spec: replicas: 2 selector: matchLabels: app: selenium-node-chrome template: metadata: labels: app: selenium-node-chrome spec: volumes: - name: dshm emptyDir: medium: Memory containers: - name: selenium-node-chrome image: selenium/node-chrome:4.0 ports: - containerPort: 5555 volumeMounts: - mountPath: /dev/shm name: dshm env: - name: SE_EVENT_BUS_HOST value: selenium-hub - name: SE_EVENT_BUS_SUBSCRIBE_PORT value: 4443 - name: SE_EVENT_BUS_PUBLISH_PORT value: 4442 resources: limits: memory: 1000Mi cpu: .5几个值得注意的设计/dev/shm内存卷dshm定义了一个emptyDir卷medium: Memory表示挂载为内存文件系统并挂载到容器的/dev/shm。Chrome 在容器中运行时常因共享内存不足而崩溃这一配置为浏览器提供了充足的内存化共享存储是浏览器节点稳定运行的常见做法。事件总线连接环境变量通过SE_EVENT_BUS_HOSTselenium-hub、SE_EVENT_BUS_SUBSCRIBE_PORT4443、SE_EVENT_BUS_PUBLISH_PORT4442三个环境变量告诉节点到哪里注册自己。从部署配置可以看出节点正是通过 Service DNS 名selenium-hub加上事件总线的发布/订阅端口与 Hub 建立通信的这与前文 Hub Service 暴露的 4442/4443 端口严格对应。端口与资源节点自身暴露 5555 端口Selenium 节点默认通信端口并声明memory: 1000Mi、cpu: .5的资源上限。Firefox 节点部署解析selenium-node-firefox-deployment.yaml 与 Chrome 版本结构完全一致差异仅在镜像selenium/node-firefox:4.0、Deployment 名称与标签。它同样带有 dshm 内存卷、5555 端口、SE_EVENT_BUS_*三件套环境变量与相同的资源上限这里不再重复贴出读者可直接对照查看。运行一次真实的 Selenium 任务节点注册完成后运行一个真实的 Selenium 任务来验证整个网格。准备 Python 运行环境先启动一个可交互的 Python 容器并进入其中这一步相当于申请一台临时执行机kubectl run selenium-python --tty -i --imagepython:slim bash进入容器后安装 Selenium 客户端库pip install selenium执行测试脚本启动 Python 解释器python然后粘贴仓库中 selenium-test.py 的内容完整源码如下from selenium import webdriver def check_browser(browser): if browser CHROME: options webdriver.ChromeOptions() elif browser FIREFOX: options webdriver.FirefoxOptions() driver webdriver.Remote( command_executorhttp://selenium-hub:4444/wd/hub, optionsoptions ) driver.get(http://www.google.com) assert google in driver.page_source driver.quit() print(Browser %s checks out! % browser) check_browser(FIREFOX) check_browser(CHROME)脚本逻辑解读根据浏览器类型构造对应的ChromeOptions/FirefoxOptions。关键点在于webdriver.Remotecommand_executor指向http://selenium-hub:4444/wd/hub——这是集群内通过 Service DNS 名访问 Hub 的标准方式也是 Hub Service 存在的意义。任务内容为访问http://www.google.com并断言页面源码中包含google通过则打印校验通过信息。脚本依次对 Firefox 与 Chrome 各执行一次从而验证两类节点都能正常接单。如果一切正常你会看到如下输出 check_browser(FIREFOX) Browser FIREFOX checks out! check_browser(CHROME) Browser CHROME checks out!恭喜你的 Selenium Hub 已经带着 Firefox 和 Chrome 节点稳定运行了。按需扩缩浏览器节点Selenium Grid 的可扩展性正是本示例的核心价值。当测试负载上来后硬件资源就是唯一的瓶颈。一条命令即可把节点数扩到任意规模kubectl scale deployment selenium-node-firefox --replicas10 kubectl scale deployment selenium-node-chrome --replicas10执行后你就有 10 个 Firefox 节点和 10 个 Chrome 节点了。Deployment 的声明式副本管理让扩容、缩容都只需改replicas一个数字新节点会自动通过事件总线注册到 Hub。当然扩容前请确认集群剩余资源满足各节点的资源上限每个节点约 0.5 CPU / 1000Mi 内存。通过 VNC 调试挂起的测试测试偶尔会挂起此时往往需要亲眼看看浏览器到底停在哪个页面。示例中每个节点 Pod 都运行了 VNC 服务。由于不想为每个 Pod 都暴露一个 Service且容器内的 VNC 密码较弱官方推荐用port-forward代理连接。把POD_NAME替换为想连接的 Pod 名称kubectl port-forward $POD_NAME 5900:5900然后用 VNC 客户端连接localhost:5900密码为secret即可实时看到该节点上浏览器正在执行的操作画面这是定位挂起测试最直观的手段。本示例改编自 SeleniumHQ 的 docker-selenium 项目网格的浏览器镜像即来自该项目。资源清理测试完毕删除本示例创建的所有资源kubectl delete deployment selenium-hub kubectl delete deployment selenium-node-chrome kubectl delete deployment selenium-node-firefox kubectl delete deployment selenium-python kubectl delete svc selenium-hub如果按方式三创建过外部服务还需要额外清理selenium-hub-external。至此一套完整的、可弹性扩缩的 Selenium Grid 就完成了从部署、验证、执行、扩容到清理的闭环。小结本示例展示了一条清晰的 Kubernetes 化 Selenium 路径用 Deployment 保障 Hub 与浏览器节点的高可用与可伸缩用 Service 提供节点注册与访问入口用探针保证网格健康用kubectl scale实现按需扩容用 VNC 提供测试排障手段。对于 CI 流水线中频繁出现的 Selenium 资源争用问题这套主从架构 弹性扩容的方案给出了开箱即用的参考答案。相关部署文件与测试脚本均可在仓库_archived/selenium目录下直接查看与复用。赞分享示例工程【免费下载链接】examplesKubernetes application example tutorials项目地址https://gitcode.com/gh_mirrors/examp/examples点击查看免费下载相关推荐KEDA Selenium Grid Scaler 实战指南基于会话队列实现浏览器节点弹性伸缩KEDA Selenium Grid Scaler 实战指南基于会话队列实现浏览器节点弹性伸缩 本指南围绕 KEDA 官方 selenium grid 触发器测试后端云原生容器编排可观测性从单节点到弹性集群Ludwig与Kubernetes的AI模型扩展实战从单节点到弹性集群Ludwig与Kubernetes的AI模型扩展实战 你是否还在为AI模型训练时的资源瓶颈发愁当数据集从GB级增长到TB级当模型参数量突人工智能深度学习机器学习大模型预训练微调LoRA多模态NLP计算机视觉模型推理服务Web-Dev-For-Beginners 浏览器扩展第一课从浏览器架构到碳排放追踪扩展的落地实战Web Dev For Beginners 浏览器扩展第一课从浏览器架构到碳排放追踪扩展的落地实战 本文基于 Web Dev For Beginners 仓库文档教程前端上一篇DeepSeek Harness 同 tick 回显修复Session Intent 草稿在受控输入下的同步刷新机制下一篇GBFR-Logs3步掌握《碧蓝幻想Relink》最强DPS分析工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考