Ray 集群 TLS 认证配置指南:基于 KubeRay 手动管理证书的完整实践
2026/9/19 9:30:34 网站建设 项目流程

Ray 集群 TLS 认证配置指南:基于 KubeRay 手动管理证书的完整实践

【免费下载链接】rayRay is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.项目地址: https://gitcode.com/gh_mirrors/ra/ray

Ray 在默认情况下,客户端(client)、Head 进程与 Worker 进程之间的 gRPC 通道是明文传输的。通过为 Ray 配置 TLS(Transport Layer Security),可以让这些通道在握手阶段完成双向身份认证,并对其间交换的数据进行加密。本文以 KubeRay 场景为背景,基于 tls.md 的核心流程,完整讲解如何用 OpenSSL 生成 CA 与节点证书、通过 init 容器为每个 Pod 动态签发证书,以及如何设置RAY_USE_TLS等环境变量启用认证,并最终验证加密通道是否生效。读完本文,你将掌握一套可直接复制的 KubeRay TLS 手工配置方案,同时理解 Ray 底层 gRPC 对 TLS 凭据的实际加载逻辑。

TLS 认证的背景与适用场景

Ray 支持在其 gRPC 通道上启用 TLS(相关说明见 Ray 核心配置文档)。启用后:

  • 连接 Ray Head 需要提供合适的凭据(证书);
  • 客户端、Head、Worker 各进程之间交换的数据会被加密;
  • 使用自签名证书即可实现内网集群的身份互认,也可以选择使用公共可信 CA 签发的证书。

TLS 利用私钥(private key)与公钥(public key)完成加解密:密钥持有者保管私钥,公钥则通过数字证书公开。证书颁发机构(CA)负责证明公钥持有者的身份,证书中携带公钥、持有者身份信息与有效期。若不希望向 CA 申请证书,可以使用 OpenSSL 等工具生成自签名证书。Ray 在握手阶段要求额外完成双向认证(mutual authentication),因此需要为集群中的每个节点准备独立证书。

注意:启用 TLS 会带来额外开销。双向认证与加解密在小型负载下开销占比较高,在大型负载下相对占比会变小,具体开销取决于工作负载特性。

前置知识

在继续之前,建议先理解以下概念(详见 tls.md):

  • 私钥 / 公钥(private/public key)
  • CA(证书颁发机构,Certificate Authority)
  • CSR(证书签名请求,Certificate Signing Request)
  • 自签名证书(self-signed certificate)

快速上手(TL;DR)

本文方案面向 KubeRay 0.5.0 及以上版本。更早版本的配置方式可能不适用或需要额外修改。

KubeRay 社区提供了示例清单ray-cluster.tls.yaml,它一次性完成了本文的 Step 1~Step 3:

# 安装 KubeRay operator(按官方安装流程执行) # 下载 ray-cluster.tls.yaml curl -LO https://raw.githubusercontent.com/ray-project/kuberay/v1.7.0/ray-operator/config/samples/ray-cluster.tls.yaml # 创建 RayCluster kubectl apply -f ray-cluster.tls.yaml # 跳转到 Step 4 "Verify TLS authentication" 验证连接

该清单会创建以下资源:

  1. 一个 Kubernetes Secret,包含 CA 的私钥(ca.key)和自签名证书(ca.crt)——对应 Step 1;
  2. 一个 Kubernetes ConfigMap,包含脚本gencert_head.shgencert_worker.sh,用于让 Head 与 Worker Pod 在启动时生成各自的私钥(tls.key)和自签名证书(tls.crt)——对应 Step 2;
  3. 一个 RayCluster,带有一组合法的 TLS 环境变量配置——对应 Step 3。

证书体系的工作方式:每个 Pod 的证书(tls.crt)使用 CA 私钥(ca.key)签发加密,所有 Pod 都持有 CA 公钥(ca.crt),因此任意 Pod 都能验证来自其他 Pod 的证书。

安全警告ray-cluster.tls.yaml仅用于演示。切勿在生产环境中将 CA 私钥存入 Kubernetes Secret,否则任何能读取该 Secret 的人都可冒充集群中的任意节点。

Step 1:生成 CA 的私钥与自签名证书

本方案使用自签名证书,但读者也可以选择公共可信 CA 签发的证书用于生产环境。

# Step 1-1:为 CA 生成自签名证书与新的私钥文件 openssl req -x509 \ -sha256 -days 3650 \ -nodes \ -newkey rsa:2048 \ -subj "/CN=*.kuberay.com/C=US/L=San Francisco" \ -keyout ca.key -out ca.crt # Step 1-2:检查自签名证书中的 CA 公钥 openssl x509 -in ca.crt -noout -text # Step 1-3:将证书内容写入 Kubernetes Secret # 方法一:使用 `cat $FILENAME | base64` 编码 ca.key 与 ca.crt, # 然后把编码后的字符串粘贴到 ray-cluster.tls.yaml 的 Kubernetes Secret 中。 # 方法二:使用 kubectl 自动编码并创建 Secret # (注意:使用此方法时需注释掉 ray-cluster.tls.yaml 中已有的 Secret) kubectl create secret generic ca-tls --from-file=ca.key --from-file=ca.crt

生成的产物:

  • ca.key:CA 私钥,必须严格保密;
  • ca.crt:CA 自签名证书,向集群所有节点公开。

该步骤是可选的ray-cluster.tls.yaml中已经内置了演示用的ca.keyca.crt,直接 apply 即可跳过此步。但在生产环境中请务必自行生成并妥善保管密钥,切勿复用演示凭据。

Step 2:为 Head 与 Worker Pod 分别生成私钥和自签名证书

为什么每个 Pod 需要独立的证书

ray-cluster.tls.yaml中,每个 Pod(Head 与 Worker)都在自己的 init 容器内生成独立的私钥文件(tls.key)和自签名证书文件(tls.crt)。原因是Worker Pod 没有确定性的 DNS 名称,无法在多个 Pod 间复用同一张证书,因此必须逐 Pod 签发。

清单中的 ConfigMap 名为tls,内含两个 Shell 脚本:

  • gencert_head.sh:为 Ray Head Pod 生成证书;
  • gencert_worker.sh:为 Ray Worker Pod 生成证书。

另一种做法是把这两个脚本直接预置(prebake)进 init 容器使用的 Docker 镜像中,从而摆脱对 ConfigMap 的依赖。

脚本内部的三个步骤

两个脚本的逻辑一致,均按以下顺序执行:

  1. 生成 2048 位 RSA 私钥,保存到/etc/ray/tls/tls.key
  2. 使用私钥tls.keycsr.conf配置文件生成证书签名请求(CSR);
  3. 使用 CA 私钥(ca.key)对 CSR 签名,生成自签名证书tls.crt

注意:configure.rst 中对第 3 步的描述为“使用 CA 密钥对(ca.keyca.crt)与 CSR 生成证书”,实际操作中签名所需的是 CA 私钥,CA 证书用于在验证端校验签名链路。请参见 Ray 核心配置文档。

两个脚本的唯一区别:[alt_names]

gencert_head.shgencert_worker.sh的唯一差异在于csr.confcert.conf中的[alt_names]段。Worker 使用 Head Kubernetes Service 的**完全限定域名(FQDN)**来连接 Head Pod,因此 Head 的证书必须把该 FQDN 写入 SAN(Subject Alternative Name);而 Head 侧则通过$POD_IP与 Worker 通信。

# gencert_head.sh 中的 [alt_names] [alt_names] DNS.1 = localhost DNS.2 = $FQ_RAY_IP IP.1 = 127.0.0.1 IP.2 = $POD_IP # gencert_worker.sh 中的 [alt_names] [alt_names] DNS.1 = localhost IP.1 = 127.0.0.1 IP.2 = $POD_IP

其中$FQ_RAY_IP是 Head Kubernetes Service 的 FQDN(形如service-ray-head.default.svc.cluster.local),$POD_IP由 init 容器动态读取。

在 Kubernetes 网络模型中,一个 Pod 看到自身的 IP 与其它 Pod 看到的该 Pod 的 IP 是相同的,这正是 Pod 能够“自行注册证书”的前提——每个 Pod 只需要知道自己的 IP,就能生成一张可被集群内其它 Pod 验证的证书。

Step 3:为 Ray 配置 TLS 环境变量

要在 Ray 集群中启用 TLS 认证,需要为 Head 与 Worker 进程设置以下环境变量(变量定义见 Ray 核心配置文档):

环境变量含义示例值
RAY_USE_TLS是否启用 TLS:1启用、0关闭。设为1时,以下所有变量必须同时设置。默认值01
RAY_TLS_SERVER_CERT向其它端点出示的证书文件路径,用于实现双向认证/etc/ray/tls/tls.crt
RAY_TLS_SERVER_KEY私钥文件路径,用于向其它端点证明你是该证书的合法持有者/etc/ray/tls/tls.key
RAY_TLS_CA_CERTCA 证书文件路径,用于校验对端证书是否由正确的 CA 签发/etc/ray/tls/ca.crt

在 KubeRay 的 YAML 清单中,这些变量通常通过env段注入到 Head 与 Worker 容器,证书文件则由 init 容器生成后写入共享的 emptyDir 卷/etc/ray/tls

Step 4:验证 TLS 认证

# 登录 Worker Pod kubectl exec -it ${WORKER_POD} -- bash # Worker 通过 Head Service 地址连接 Head。 # Head 证书的 SAN 中包含 $FQ_RAY_IP,因此 TLS 校验成功。 # ray health-check 命令的退出码应为 0。 ray health-check --address $FQ_RAY_IP:6379 echo $? # 0 # Head 证书的 SAN 中不包含 $RAY_IP,因此 TLS 校验失败。 # 会看到 TLS 校验错误,错误信息会提示 Pod IP($RAY_IP)不在证书中。 ray health-check --address $RAY_IP:6379 # 若在 gencert_head.sh 的 [alt_names] 中补充 `DNS.3 = $RAY_IP`, # 重新生成的 Head 证书就会包含 $RAY_IP 对应的 SAN 条目。 # # 对于 KubeRay 0.5.0 之前的版本,该步骤是必需的,因为早期版本的 # Ray Worker 使用 $RAY_IP 连接 Head。

验证思路的核心是:连接地址必须落在对端证书的 SAN 范围内。连接成功(退出码 0)说明双向 TLS 握手完整通过;连接失败并报“not in certificate”类错误,恰恰证明 TLS 校验在真实生效——证书与地址不匹配时连接会被拒绝。

源码视角:Ray 如何加载 TLS 凭据

理解了运维侧的配置,再来看 Ray 的 Python 侧是如何消费这四个环境变量的。核心实现位于 python/ray/_common/tls_utils.py:

  • load_certs_from_env()(L85-L99)读取RAY_TLS_SERVER_CERTRAY_TLS_SERVER_KEYRAY_TLS_CA_CERT三个变量指向的文件内容;若RAY_USE_TLS已开启但三者缺一,会抛出RuntimeError,提示“If the environment variable RAY_USE_TLS is set to true then RAY_TLS_SERVER_CERT, RAY_TLS_SERVER_KEY and RAY_TLS_CA_CERT must also be set.”——这印证了文档中“三个变量必须同时设置”的约束。
  • add_port_to_grpc_server()(L70-L82)根据RAY_USE_TLS(取值1true视为开启)决定创建安全端口还是非安全端口。开启时使用grpc.ssl_server_credentials加载服务端证书链与私钥,并把 CA 证书作为root_certificates,同时设置require_client_auth=True,强制客户端也出示证书——这正是“双向认证(mTLS)”的机制来源。
  • 该模块还提供了generate_self_signed_tls_certs()(L14-L67),可用cryptography库在测试场景中快速生成 2048 位 RSA 密钥与包含localhost、本机 IP 等 SAN 的自签名证书对,方便在本地验证 TLS 行为。

从源码结构可以推断:只要这些环境变量在 Ray 进程(ray start/ray.init())启动前就绪,Head、Worker 以及客户端(如 Python 驱动)建立的 gRPC 通道都会自动套用加密与双向认证逻辑,无需在业务代码中做任何改动。

性能影响与取舍

启用 TLS 的代价来自双向认证与加密的开销:

  • 加密/解密进程间流量会产生额外 CPU 开销;
  • 对通信密集型负载影响最明显,尤其是频繁的大对象传输和高调用频率的小任务;
  • 对以计算为主、数据移动较少的负载,开销可以忽略。

因此在决定是否启用 TLS 时,需要根据集群网络信任边界与工作负载特征综合权衡。对于跨公网或不可信网络部署的场景,TLS 是必要的安全基线;对于纯内网、负载高度敏感的场景,可以评估收益与开销后决定。

进阶方案:KubeRay 自动化 mTLS

本文介绍的是手工管理证书的方式。KubeRay v1.7 起引入了RayClusterMTLSfeature gate,通过 cert-manager 自动签发并轮换证书,可以免去手动生成 CA、编写 init 脚本等全部工作。两种方案的关系如下:

  • 手动方式(本文):完全掌控 CA 与证书生命周期,适合已有自建 CA 或强合规要求的场景;
  • 自动方式(mTLS):设置spec.tlsOptions.enabled: true即可,operator 会自动创建IssuerCertificate等资源并注入 TLS 环境变量,适合希望降低运维负担的场景。

自动方式的完整配置与验证步骤见 kuberay-mtls.md。

总结

本文完整覆盖了在 KubeRay 上为 Ray 配置 TLS 认证的四个核心步骤:生成 CA 密钥对、通过 init 容器为每个 Pod 动态签发证书、注入四个 TLS 环境变量、使用ray health-check验证双向认证是否生效。同时,从 tls_utils.py 的源码层面解释了 Ray 如何读取环境变量、构造 gRPC 安全凭据并强制客户端认证。生产部署时请牢记两条原则:不要将 CA 私钥存入 Secret确保连接地址始终落在对端证书的 SAN 内。若希望进一步降低证书管理的运维成本,可参考 kuberay-mtls.md 改用 cert-manager 自动化方案。

【免费下载链接】rayRay is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.项目地址: https://gitcode.com/gh_mirrors/ra/ray

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询