3、Kubernetes集群安全:API Server安全加固、RBAC权限模型、ServiceAccount管理、Secret管理最佳实践、etcd加密与访问控制
Kubernetes 集群安全,说白了就是守住三个核心:谁可以访问、能做什么、数据是否加密。我这些年帮金融机构做容器平台落地,踩过最多的坑,恰恰就是这几个看似基础的点。今天咱们一个一个拆开聊。
核心原则:K8s 安全不是单点防御,而是从 API 入口到数据存储的纵深防线。任何一个环节漏了,整个集群就可能被攻破。
3.1 API Server 安全加固
API Server 是整个集群的「大门」。你想想看,所有 kubectl 命令、所有 Pod 对集群的访问,都得经过它。所以这块必须加固。
第一,关闭匿名访问。 默认情况下,K8s 允许匿名用户访问某些 API。这在开发环境无所谓,但在生产环境——尤其是金融场景——必须关掉。我建议你在 kube-apiserver 的启动参数里加上:
--anonymous-auth=false
第二,启用 TLS 双向认证。 客户端访问 API Server 时,不光要验证服务端证书,客户端也得提供证书。这样能防止中间人攻击。我曾经在某个银行项目里,发现他们的 kubeconfig 文件居然用的是管理员证书直接分发——嗯,这相当于把大门钥匙复印了 100 份。
第三,限制 API Server 的监听地址。 别把它暴露在公网。只监听内网 IP,或者用 NodePort 配合防火墙规则。我个人习惯是:API Server 只监听 6443 端口,并且只允许内网负载均衡器访问。
小技巧:用 --etcd-servers 参数指定 etcd 地址时,尽量用 localhost 或内网 IP,别用 0.0.0.0。etcd 的端口 2379 如果暴露出去,等于把数据库裸奔了。
3.2 RBAC 权限模型
RBAC(基于角色的访问控制)是 K8s 里最核心的权限模型。说白了就是:谁(User/ServiceAccount)能对什么资源(Pod/Service/Secret)做什么操作(get/list/create)。
我见过很多团队,图省事直接给所有人绑定 cluster-admin 角色。这就像给每个员工发了把总经理办公室的钥匙——早晚出事。
RBAC 的核心要素:
- Role / ClusterRole:定义一组权限规则。Role 是命名空间级别的,ClusterRole 是集群级别的。
- RoleBinding / ClusterRoleBinding:把 Role 绑定到用户或 ServiceAccount 上。
举个例子,给某个开发人员只读权限:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dev
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: dev
subjects:
- kind: User
name: dev-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
避坑指南:我曾经遇到一个案例,运维人员给 CI/CD 系统绑定了 cluster-admin,结果某个流水线脚本被注入恶意代码,攻击者直接拿到了整个集群的控制权。所以,永远遵循最小权限原则——只给够用的权限,多一个都不行。
3.3 ServiceAccount 管理
ServiceAccount 是 Pod 用来访问 API Server 的身份凭证。每个 Pod 默认会挂载一个 ServiceAccount 的 token。但问题来了:默认的 ServiceAccount 往往权限过大。
最佳实践:
- 每个应用使用独立的 ServiceAccount,不要用
default。 - 显式指定
automountServiceAccountToken: false,除非 Pod 确实需要访问 API。 - 定期轮转 ServiceAccount 的 token。
我记得有一次审计,发现某个命名空间里 80% 的 Pod 都挂着 default ServiceAccount,而且这个 SA 居然有 get secrets 的权限。你想想看,任何一个被攻破的 Pod,都能直接读取所有 Secret——这太可怕了。
3.4 Secret 管理最佳实践
Secret 是用来存储敏感信息的,比如数据库密码、API 密钥。但很多人以为 Secret 是「安全」的——其实不是。Secret 只是做了 base64 编码,不是加密。谁都能解码。
我建议的做法:
- 启用 etcd 加密:这是最基础的。在 API Server 启动参数里加上
--encryption-provider-config,指定加密配置文件。这样 Secret 存到 etcd 里就是密文了。 - 使用外部密钥管理服务:比如 HashiCorp Vault、AWS KMS 或 Azure Key Vault。通过 CSI 驱动把密钥挂载到 Pod 里,而不是直接写在 YAML 里。
- 不要将 Secret 提交到 Git:这个我强调过无数次。用 Sealed Secrets 或 External Secrets Operator 来管理。
核心观点:Secret 的安全,取决于它存储在哪、怎么传输、谁可以访问。etcd 加密只是第一步,不是全部。
3.5 etcd 加密与访问控制
etcd 是 K8s 的「数据库」,所有集群状态都存里面。包括 Secret、ConfigMap、Pod 定义。如果 etcd 被攻破,整个集群就完了。
etcd 安全三要素:
| 安全维度 | 具体措施 | 我的建议 |
|---|---|---|
| 传输加密 | 启用 TLS 双向认证 | 必须做,etcd 的 peer 和 client 通信都要加密 |
| 存储加密 | 使用 --encryption-provider-config |
推荐使用 aescbc 或 kms 提供者 |
| 访问控制 | etcd 的 user/role 认证 | 限制只有 API Server 可以读写 etcd |
我曾经帮一个客户做安全加固,发现他们的 etcd 居然没有设置密码,任何人都可以用 etcdctl 直接连上去读数据。嗯,这相当于把保险柜的门开着,上面还贴了张纸条「请随意取用」。
加密配置示例:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {}
注意:加密密钥一定要妥善保管。如果密钥丢了,已经加密的 Secret 就永远解不开了。我建议把密钥存到硬件安全模块(HSM)或云 KMS 里。
知识体系总览
下面这张图,是我梳理的 K8s 集群安全核心逻辑。你可以把它当作一个检查清单:
好了,这一章的内容就到这里。K8s 集群安全是个系统工程,每个点都值得深挖。下一章咱们聊聊容器运行时安全——那又是另一片天地了。