资讯动态

在 Kubernetes 上零手动配置搭建 RethinkDB 集群:基于 Service Endpoint 自动发现的完整实战

发布时间:2026/10/7 2:05:38 来源:尧图企业网站定制
示例工程【免费下载链接】examplesKubernetes application example tutorials项目地址https://gitcode.com/gh_mirrors/examp/examples点击查看免费下载本篇指南围绕 Kubernetes 官方示例仓库gh_mirrors/examp/examples中归档的 RethinkDB 集群部署方案_archived/storage/rethinkdb/展开核心讲解如何利用 Kubernetes Service Endpoint 实现 RethinkDB 节点自动组网——新节点启动时无需人工指定集群成员即可自动发现并加入既有集群。读完本文你将掌握通过两个 YAML 文件快速启动首个节点、使用kubectl scale无缝扩容、搭建带外部负载均衡的 Web Admin 管理端以及容器内自动发现脚本的底层实现原理。方案总览为什么需要“自动发现”机制RethinkDB 原生支持多节点集群但传统组网方式要求每个新节点启动时显式指定一个已知的集群成员地址--join host:port。在 Kubernetes 动态环境中Pod 的 IP 是不断变化的手动维护成员地址列表既不现实也无法自动化扩容。该示例方案给出的答案是让 RethinkDB 节点自己向 Kubernetes API 查询服务端点Endpoints。README 中明确列出该方案的两大特性Auto configuration cluster by querying info from k8s—— 通过查询 Kubernetes 提供的服务信息自动完成集群配置Simple—— 部署过程保持简单无需额外的服务发现组件。整个方案的精髓在于Kubernetes Service 天然维护着一组 Pod 的 Endpoints 列表RethinkDB 容器启动时读取这份列表挑出一个“与自己不同”的节点地址作为--join目标如果列表里只有自己即第一个节点则直接以单实例模式启动。后续所有加入的节点都能沿这条链路自动互相感知最终收敛成一个完整集群。自动发现实现原理run.sh 源码剖析容器自动发现的全部逻辑都封装在镜像入口脚本_archived/storage/rethinkdb/image/run.sh中。脚本在容器每次启动时执行其核心流程如下POD_NAMESPACE${POD_NAMESPACE:-default} MYHOST$(ip addr | grep state UP -A2 | tail -n1 | awk {print $2} | cut -f1 -d/) URLhttps://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}/api/v1/namespaces/${POD_NAMESPACE}/endpoints/rethinkdb-driver token$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) IP$(curl -s ${URL} --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header Authorization: Bearer ${token} \ | jq -s -r --arg h ${MYHOST} .[0].subsets | .[].addresses | [ .[].ip ] | map(select(. ! $h)) | .[0]) || exit 1 if [[ -n ${IP} ]]; then ENDPOINT${IP}:29015 exec rethinkdb --bind all --join ${ENDPOINT} else exec rethinkdb --bind all fi逐段拆解其工作原理获取自身身份通过ip addr读取容器当前网卡的 IP 作为MYHOST用于后续排除“自己”构造 API 地址通过环境变量KUBERNETES_SERVICE_HOST与KUBERNETES_SERVICE_PORT定位 API Server请求路径为/api/v1/namespaces/{命名空间}/endpoints/rethinkdb-driver即查询名为rethinkdb-driver的 Service 当前对应的 Endpoints 列表鉴权与请求使用挂载在/var/run/secrets/kubernetes.io/serviceaccount/下的 ServiceAccount token 与 CA 证书调用 Kubernetes API这要求 Pod 运行在启用了 RBAC 与 ServiceAccount 自动挂载的集群中筛选成员用jq从 Endpoints 的subsets[].addresses[].ip中挑选第一个不等于自身 IP的地址作为集群成员若全是自己IP null则清空变量决定启动方式找到其他成员则以--join ${IP}:29015加入集群否则以--bind all启动单实例。这里的端口 29015 是 RethinkDB 的集群内部通信端口cluster port。配套的 Dockerfile_archived/storage/rethinkdb/image/Dockerfile基于官方rethinkdb:1.16.0镜像额外安装了curl发起 API 请求与jq解析 JSON 响应并将run.sh复制为镜像默认命令FROM rethinkdb:1.16.0 RUN apt-get update \ apt-get install -yq curl \ curl -L http://stedolan.github.io/jq/download/linux64/jq /usr/bin/jq \ chmod ux /usr/bin/jq COPY ./run.sh /usr/bin/run.sh RUN chmod ux /usr/bin/run.sh CMD /usr/bin/run.sh这一“查询 Endpoints 自动组网”的设计就是整个方案在扩容时无需任何人工配置的根本原因无论集群规模如何变化每个新 Pod 启动时都能从同一个 Service 的 Endpoints 中获得最新的成员视图。快速开始两步启动集群中的第一个节点Step 1先创建 driver 服务自动发现依赖 Service 提供的 Endpoints 信息因此必须先创建 Service再启动 Pod。执行$ kubectl create -f _archived/storage/rethinkdb/driver-service.yaml查看服务是否就绪$ kubectl get services NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE rethinkdb-driver 10.0.27.114 none 28015/TCP dbrethinkdb 10m [...]这里出现的关键信息是SELECTOR列为dbrethinkdbService 会收集所有带db: rethinkdb标签的 Pod 的 IP动态生成 Endpoints 列表供后续容器查询。Step 2启动第一个服务器$ kubectl create -f _archived/storage/rethinkdb/rc.yaml由于此时 Endpoints 列表中只有自己一个节点run.sh 会走else分支以单实例模式启动$ kubectl get pods NAME READY REASON RESTARTS AGE [...] rethinkdb-rc-r4tb0 1/1 Running 0 1mDone集群的第一个节点已经就绪。需要注意的是README 中特别提到如果想一次性启动多个节点只需要直接修改rc.yaml中的replicas字段即可无需其他操作。关键配置文件解读driver-service.yaml驱动端口暴露_archived/storage/rethinkdb/driver-service.yaml只做了一件事——把集群的 driver 端口28015客户端连接 RethinkDB 使用的端口暴露为集群内稳定的服务入口apiVersion: v1 kind: Service metadata: labels: db: rethinkdb name: rethinkdb-driver spec: ports: - port: 28015 targetPort: 28015 selector: db: rethinkdb这个 Service 同时也是自动发现的数据源run.sh 正是查询它的 Endpoints 来定位其他节点。rc.yaml节点模板与三个端口_archived/storage/rethinkdb/rc.yaml使用 ReplicationController 定义节点模板默认replicas: 1apiVersion: v1 kind: ReplicationController metadata: labels: db: rethinkdb name: rethinkdb-rc spec: replicas: 1 selector: db: rethinkdb role: replicas template: metadata: labels: db: rethinkdb role: replicas spec: containers: - image: registry.k8s.io/rethinkdb:1.16.0_1 name: rethinkdb env: - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ports: - containerPort: 8080 name: admin-port - containerPort: 28015 name: driver-port - containerPort: 29015 name: cluster-port volumeMounts: - mountPath: /data/rethinkdb_data name: rethinkdb-storage volumes: - name: rethinkdb-storage emptyDir: {}几个值得注意的细节镜像使用registry.k8s.io/rethinkdb:1.16.0_1示例仓库打包版本内置了 run.sh 自动发现逻辑POD_NAMESPACE环境变量通过fieldRef从 Pod 元数据注入当前命名空间run.sh 用它构造 Endpoints API 的查询 URL。这是自动发现能否命中的关键前提三个端口8080admin-portWeb 管理界面、28015driver-port客户端驱动连接、29015cluster-port节点间集群通信存储默认挂载emptyDir临时卷到/data/rethinkdb_data数据随 Pod 销毁而丢失如需持久化可参考后文的gen-pod.sh方案。集群扩容一条命令新节点自动加入集群的扩容操作简单到极致——不需要修改任何配置只需调整副本数$ kubectl scale rc rethinkdb-rc --replicas3 scaled $ kubectl get pods NAME READY REASON RESTARTS AGE [...] rethinkdb-rc-f32c5 1/1 Running 0 1m rethinkdb-rc-m4d50 1/1 Running 0 1m rethinkdb-rc-r4tb0 1/1 Running 0 3m新增的两个 Pod 启动时run.sh 会查询rethinkdb-driver的 Endpoints——此时列表中已包含第一个节点的 IP——于是自动以--join IP:29015加入既有集群README 明确说明“The new pod will join to the existing cluster automatically”。管理端 Web UI独立 admin Pod LoadBalancerRethinkDB 自带的 Web 管理界面运行在 8080 端口。示例特意强调需要一个带role: admin标签的独立 Pod 来承载 Web Admin UI而不是复用集群的 replica Podkubectl create -f _archived/storage/rethinkdb/admin-pod.yaml kubectl create -f _archived/storage/rethinkdb/admin-service.yaml查看服务$ kubectl get services NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE [...] rethinkdb-admin 10.0.131.19 104.197.19.120 8080/TCP dbrethinkdb,roleadmin 10m rethinkdb-driver 10.0.27.114 none 28015/TCP dbrethinkdb 20m两个管理端文件的要点_archived/storage/rethinkdb/admin-pod.yaml是一个独立 Pod镜像与 rc.yaml 相同registry.k8s.io/rethinkdb:1.16.0_1也暴露 8080/28015/29015 三个端口但标签为db: rethinkdb, role: admin从而与 replica Pod 区分开。_archived/storage/rethinkdb/admin-service.yaml则通过type: LoadBalancer申请外部负载均衡器将 8080 端口暴露到集群外部apiVersion: v1 kind: Service metadata: labels: db: rethinkdb name: rethinkdb-admin spec: ports: - port: 8080 targetPort: 8080 type: LoadBalancer selector: db: rethinkdb role: admin外部负载均衡器允许我们从防火墙之外通过外部 IP示例中为104.197.19.120访问该服务。如果运行在 Google Compute Engine 上还需要创建防火墙规则放行流量$ gcloud compute firewall-rules create rethinkdb --allowtcp:8080随后在浏览器中访问http://104.197.19.120:8080即可管理集群。为什么不直接复用 replicas 中的 Pod这是本方案一个非常关键的工程决策README 给出了明确解释kube-proxy 会充当负载均衡器把流量分发到不同的服务器。而 Web Admin UI 是有状态的——当浏览器会话被负载均衡到不同节点时会出现Connection not open on server错误。因此必须为管理界面单独创建“一对一”的 admin Pod 与服务确保 UI 流量始终落在同一个实例上。数据持久化gen-pod.sh 与节点调度rc.yaml默认使用emptyDirPod 重建后数据即丢失。如果需要持久化数据示例仓库提供了_archived/storage/rethinkdb/gen-pod.sh脚本用于为本地集群生成绑定宿主机目录的 Pod 模板。脚本用法为./gen-pod.sh name [node-name]核心逻辑包括命名生成的 Pod 名为rethinkdb-${NAME}-${VERSION}默认版本1.16.0admin 标记当第一个参数为admin时自动在标签中追加role: admin与上文管理端方案对齐节点亲和若传入第二个参数则在 Pod 模板中注入nodeSelector: { name: ${2} }强制 Kubernetes 将容器调度到指定节点脚本内注释强调必须先执行kubectl label nodes node-name name${2}给节点打标签nodeSelector 才能生效持久化存储与 rc.yaml 的emptyDir不同脚本生成的 Pod 使用hostPath将宿主机目录/data/db/rethinkdb挂载为容器的/data/rethinkdb_data从而把 RethinkDB 数据留在指定的宿主机磁盘上命名空间模板将 Pod 置于rethinkdb命名空间。该脚本生成的模板同样使用antmanler/rethinkdb:${VERSION}镜像三个端口8080/28015/29015与 rc.yaml 保持一致。注意事项与适用范围创建顺序必须先创建driver-service.yaml再创建 rc/admin Pod。因为容器的自动发现依赖 Service 的 Endpoints顺序颠倒会导致新节点查询不到成员列表而全部以单实例启动权限前提run.sh 通过 ServiceAccount token 调用 Kubernetes API集群需开启默认的 ServiceAccount 挂载与相应 RBAC 权限Pod 才能读取 Endpoints镜像差异rc.yaml / admin-pod.yaml 使用registry.k8s.io/rethinkdb:1.16.0_1而 gen-pod.sh 生成的模板使用antmanler/rethinkdb:${VERSION}两者均内置了自动发现的 run.sh 逻辑版本背景本示例面向 Kubernetes 早期版本ReplicationController、kubectl scale rc等均为旧式 API在当前版本 Kubernetes 中可将 ReplicationController 等价替换为 Deployment/StatefulSet自动发现机制本身仍然适用管理端单一实例Web Admin UI 是有状态服务务必保持 admin Pod 与 admin Service 一对一避免 kube-proxy 负载均衡导致Connection not open on server错误数据持久化默认emptyDir不持久化数据生产环境应参考gen-pod.sh的 hostPath 思路或改用 PVC/StatefulSet 方案。本示例的完整资源含 run.sh 自动发现脚本、Dockerfile、三个 YAML 与 gen-pod.sh均位于仓库_archived/storage/rethinkdb/目录下原方案的详细设计可参见 antmanler/rethinkdb-k8s 项目。赞分享示例工程【免费下载链接】examplesKubernetes application example tutorials项目地址https://gitcode.com/gh_mirrors/examp/examples点击查看免费下载相关推荐Mooncake 在 Kubernetes 上的部署指南基于 Deployment 与 Service 搭建共享 Store 集群Mooncake 在 Kubernetes 上的部署指南基于 Deployment 与 Service 搭建共享 Store 集群 Mooncake Stor人工智能大模型模型推理服务后端在 Kubernetes 上部署云原生 Hazelcast 集群基于 Service 发现与 Deployment 弹性伸缩的完整实践在 Kubernetes 上部署云原生 Hazelcast 集群基于 Service 发现与 Deployment 弹性伸缩的完整实践 本文以当前 Kuber示例工程Play with Kubernetes 在线零基础搭建 Kubernetes 集群实战指南Play with Kubernetes 在线零基础搭建 Kubernetes 集群实战指南 Play with Kubernetes简称 PWK是 Kub教程云原生容器编排上一篇ElasticJob任务重试机制终极指南指数退避与固定间隔策略深度对比下一篇CANN/ops-cv 边界框编码算子创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑