元鉴
返回中文阅读流

Kubernetes Blog

保护 Kubernetes 生产环境调试安全

生产调试常用广泛权限、共享跳板机或长期 SSH 密钥,虽便捷但审计困难且临时例外易常态化。

中文内容

已翻译official company source英文原文2026-03-18

保护 Kubernetes 生产环境调试安全

By Shridivya Sharma | Wednesday, March 18, 2026

在生产环境调试期间,最快的路径通常是使用广泛访问权限,例如 cluster-admin(一种授予管理员级访问权限的 ClusterRole)、共享堡垒机/跳板机,或长期有效的 SSH 密钥。这在当下确实有效,但会带来两个常见问题:审计变得困难,临时例外往往会演变成常规做法。

本文提出我对良好实践的建议,适用于现有 Kubernetes 环境,并且只需最少的工具变更:

  • 通过 RBAC 实现最小权限
  • 短期有效、与身份绑定的凭据
  • 用于云原生调试的 SSH 式握手模型

一种用于保护生产调试工作流的良好架构,是使用即时安全 shell 网关(通常作为集群中按需部署的 pod)。它充当 SSH 式的“前门”,使临时访问真正保持临时性。你可以使用短期有效、与身份绑定的凭据进行身份验证,建立到网关的会话;网关则使用 Kubernetes API 和 RBAC 来控制他们可以执行的操作,例如 pods/log、pods/exec 和 pods/portforward。会话会自动过期,并且网关日志与 Kubernetes 审计日志都会记录谁在何时访问了什么,而无需共享堡垒机账户或长期密钥。

1)在 Kubernetes RBAC 之上使用访问代理

RBAC 控制谁可以在 Kubernetes 中做什么。许多 Kubernetes 环境主要依赖 RBAC 进行授权,尽管 Kubernetes 也支持其他授权模式,例如 Webhook 授权。你可以直接使用 Kubernetes RBAC 强制执行访问控制,也可以在集群前放置一个访问代理,其底层仍依赖 Kubernetes 权限。在任一模型中,Kubernetes RBAC 仍然是 Kubernetes API 允许哪些操作以及在何种范围内允许的事实来源。

访问代理可以增加 RBAC 无法很好覆盖的控制。例如,它可以决定某个请求是自动批准还是需要人工批准、用户是否可以运行命令,以及会话中允许哪些命令。它还可以管理组成员资格,使你向组而不是单个用户授予权限。Kubernetes RBAC 可以允许 pods/exec 等操作,但无法限制 exec 会话中运行哪些命令。

在这种模型下,Kubernetes RBAC 定义用户或组允许执行的操作(例如,单个命名空间中的值班团队)。我建议你只定义向组或 ServiceAccount 授权的访问规则——绝不要向单个用户授权。然后由代理或身份提供方根据需要将用户加入或移出该组。

代理还可以在其上强制执行额外策略,例如交互式会话中允许哪些命令,以及哪些请求可以自动批准、哪些需要人工批准。该策略可以存放在 JSON 或 XML 文件中,并通过代码审查维护,因此更新会经过正式的 pull request,并像其他生产变更一样接受审查。

示例:命名空间级值班调试 Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: oncall-debug
  namespace: <namespace>
rules:
  # Discover what’s running
  - apiGroups: [""]
    resources: ["pods", "events"]
    verbs: ["get", "list", "watch"]

  # Read logs
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get"]

  # Interactive debugging actions
  - apiGroups: [""]
    resources: ["pods/exec", "pods/portforward"]
    verbs: ["create"]

  # Understand rollout/controller state
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets"]
    verbs: ["get", "list", "watch"]

  # Optional: allow kubectl debug ephemeral containers
  - apiGroups: [""]
    resources: ["pods/ephemeralcontainers"]
    verbs: ["update"]

将 Role 绑定到组(而不是单个用户),以便通过你的身份提供方管理成员资格:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: oncall-debug
  namespace: <namespace>
subjects:
  - kind: Group
    name: oncall-<team-name>
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: oncall-debug
  apiGroup: rbac.authorization.k8s.io

2)短期有效、与身份绑定的凭据

目标是使用短期有效、与身份绑定的凭据,将会话明确关联到真实人员,并快速过期。这些凭据可以包含用户身份以及其被允许执行操作的范围。它们通常使用由工程师持有的私钥进行签名,例如硬件支持的密钥(如 YubiKey),因此没有该密钥就无法伪造。

你可以使用 Kubernetes 原生身份验证(例如客户端证书或基于 OIDC 的流程)来实现,也可以让上一节中的访问代理代表用户签发短期凭据。在许多设置中,Kubernetes 仍使用 RBAC 根据已认证的身份和组/声明来执行权限控制。如果使用访问代理,它还可以在凭据中编码额外的范围约束,并在会话期间强制执行,例如该会话适用于哪个集群或命名空间,以及允许对 pod 或 node 执行哪些操作(或已批准的命令)。无论哪种情况,凭据都应由证书颁发机构(CA)签名,并且该 CA 应按固定计划轮换(例如每季度一次),以限制长期风险。

选项 A:短期有效的 OIDC token

许多托管 Kubernetes 集群已经为你提供短期 token。关键是确保你的 kubeconfig 会自动刷新它们,而不是把长期 token 复制到文件中。

例如:

users:
- name: oncall
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1
      command: cred-helper
      args: ["--cluster=prod", "--ttl=30m"]

选项 B:短期客户端证书(X.509)

如果你的 API server(或上一节中的访问代理)被设置为信任某个客户端 CA,你就可以使用短期客户端证书进行调试访问。思路是:

  • 私钥在工程师的机器上创建并保存(理想情况下由硬件支持,例如 YubiKey/PIV token 中不可导出的密钥)
  • 签发短期证书(通常通过 CertificateSigningRequest API,或通过上一节中的访问代理,并设置 TTL)。
  • RBAC 将已认证身份映射到最小化 Role

这可以通过 Kubernetes CertificateSigningRequest API 直接实现运营化。

在本地生成密钥和 CSR:

# Generate a private key.
# This could instead be generated within a hardware token;
# OpenSSL and several similar tools include support for that.
openssl genpkey -algorithm Ed25519 -out oncall.key

openssl req -new -key oncall.key -out oncall.csr \
  -subj "/CN=user/O=oncall-payments"

创建带有短到期时间的 CertificateSigningRequest:

apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: oncall-<user>-20260218
spec:
  request: <base64-encoded oncall.csr>
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 1800  # 30 minutes
  usages:
    - client auth

CSR 获批并签名后,你提取已签发的证书,并将其与私钥一起用于身份验证,例如通过 kubectl。

3)使用即时访问网关运行调试命令

一旦拥有短期凭据,就可以用它们打开到即时访问网关的安全 shell 会话,该网关通常通过 SSH 暴露并按需创建。如果网关通过 SSH 暴露,常见模式是为工程师签发一个用于该会话的短期 OpenSSH 用户证书。网关信任你的 SSH 用户 CA,在连接时验证工程师身份,然后在代表用户发起 Kubernetes API 调用之前应用已批准的会话策略。OpenSSH 证书与 Kubernetes X.509 客户端证书是分开的,因此通常将它们视为不同层。

生成的会话也应限定范围,使其不能在已批准范围之外重复使用。例如,网关或代理可以将其限制到特定集群和命名空间,并可选择进一步限制到更窄的目标,例如某个 pod 或 node。这样,即使有人试图重复使用该访问权限,也无法在预期范围之外生效。会话建立后,网关只执行允许的操作,并记录发生的情况以便审计。

示例:命名空间范围的 RoleBinding

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: jit-debug
  namespace: <namespace>
  annotations:
    kubernetes.io/description: >
      Colleagues performing semi-privileged debugging, with access provided
      just in time and on demand.
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: jit-debug
  namespace: <namespace>
subjects:
  - kind: Group
    name: jit:oncall:<namespace>   # mapped from the short-lived credential (cert/OIDC)
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: jit-debug
  apiGroup: rbac.authorization.k8s.io

这些 RBAC 对象及其定义的规则只允许在指定命名空间内进行调试;尝试访问其他命名空间将不被允许。

示例:集群范围的 RoleBinding

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: jit-cluster-read
rules:
  - apiGroups: [""]
    resources: ["nodes", "namespaces"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jit-cluster-read
subjects:
  - kind: Group
    name: jit:oncall:cluster
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: jit-cluster-read
  apiGroup: rbac.authorization.k8s.io

这些 RBAC 规则授予集群范围的读取访问权限(例如访问 node 和 namespace),应仅用于确实需要集群级资源的工作流。

更细粒度的限制,例如“仅限此 pod/node”或“仅限这些命令”,通常由访问网关/代理在会话期间强制执行,但 Kubernetes 也提供其他选项,例如用于限制写入的 ValidatingAdmissionPolicy,以及用于跨动词自定义授权的 webhook 授权。

在访问控制更严格的环境中,你可以增加一个额外的短期会话中介层,将会话建立与特权操作分离。两层都是临时的,使用与身份绑定且会过期的凭据,并生成独立的审计轨迹。中介层处理会话建立/转发,而执行层只执行经 RBAC 授权的 Kubernetes 操作。这种分离可以通过缩小职责范围、按步骤限定凭据范围,并强制端到端会话过期来降低暴露面。

参考资料

  • 正文:Authorization
  • 正文:Using RBAC Authorization
  • 正文:Authenticating
  • 正文:Certificates and Certificate Signing Requests
  • 正文:Issue a Certificate for a Kubernetes API Client Using a CertificateSigningRequest
  • 正文:Role Based Access Control Good Practices

免责声明:本文表达的观点仅代表作者本人,不反映作者雇主或任何其他组织的观点。

  • 下一篇 →

原文标题

Securing Production Debugging in Kubernetes