3. API Server安全加固
kube-apiserver 是 Kubernetes 集群唯一的“总入口”:所有 kubectl 请求、控制器、kubelet、调度器以及外部系统都通过它读写集群状态。一旦 API Server 被绕过或降级,攻击者往往可以直接创建特权 Pod、读取 Secret、篡改 RBAC,从而接管整个集群。因此 API Server 的安全加固不是单点配置,而是一条从“请求进入”到“对象落库”的完整链路:认证(Authentication)→ 授权(Authorization)→ 准入控制(Admission Control)→ 持久化到 etcd。本节围绕这条链路,结合安全端口与启动参数,说明每一环的加固要点与可落地的配置方式。
一、认证:先确认“你是谁”
认证解决的是身份识别问题。API Server 支持多种认证方式,并按启动参数中配置的顺序依次尝试,任一方式成功即通过。常见方式包括:X.509 客户端证书、ServiceAccount Token、Bearer Token 文件、OIDC、Webhook 认证等。生产环境应遵循“最小可用”原则,只开启业务真正需要的认证方式。
需要特别注意的是 --anonymous-auth。当它被设为 true(部分旧版本默认值)时,未携带任何凭据的请求会被当作 system:anonymous 用户处理。如果同时存在宽松的 RBAC 绑定,就可能造成未授权访问。加固建议是显式关闭匿名认证:
--anonymous-auth=false
对于使用客户端证书的集群,证书中的 CN 映射为用户名,O 映射为组。例如 CN=kubernetes-admin、O=system:masters 的证书会直接获得超级权限,因此这类证书必须严格保管,不应分发给普通运维人员。ServiceAccount Token 则由 API Server 自动签发,绑定到具体命名空间的 ServiceAccount,是 Pod 内访问 API 的主要身份来源。
二、授权:再判断“你能做什么”
认证通过后进入授权阶段。API Server 通过 --authorization-mode 指定授权模式,多个模式以逗号分隔、按顺序匹配,任一模式允许即放行。可选模式主要有:AlwaysAllow、AlwaysDeny、ABAC、RBAC、Node、Webhook。
生产集群的推荐配置是:
--authorization-mode=Node,RBAC
其中 Node 模式用于约束 kubelet 只能读取与自己节点相关的资源(如 Pod、Secret、ConfigMap 等),防止一个被攻陷的节点横向读取全集群数据;RBAC 则承担绝大多数用户与工作负载的权限管理。务必避免使用 AlwaysAllow,它会让认证形同虚设。
RBAC 的核心是四个对象:Role/ClusterRole 定义权限,RoleBinding/ClusterRoleBinding 将权限授予主体。加固时应坚持最小权限,例如不要随意把 cluster-admin 绑定给普通用户,避免使用通配符 * 授予 verbs 或 resources。可以用如下命令快速排查高风险绑定:
kubectl get clusterrolebindings -o json | \
jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects'
三、准入控制:对象落库前的最后一道闸门
授权只判断“这个请求有没有权限”,而准入控制进一步检查“这个对象本身是否合规”。准入控制器在对象写入 etcd 之前运行,分为变更型(Mutating)和校验型(Validating)两类:前者可修改对象(如注入 sidecar、设置默认值),后者只做校验、拒绝不合规请求。执行顺序是:先所有变更型,再所有校验型。
通过 --enable-admission-plugins 启用插件,常见且建议开启的包括:
NamespaceLifecycle:阻止在正在删除的命名空间中创建对象,保护default、kube-system等系统命名空间。LimitRanger:为未声明资源的 Pod 设置默认 requests/limits,防止资源被无限占用。ServiceAccount:确保 Pod 使用的 ServiceAccount 存在,并自动挂载 Token。NodeRestriction:配合 Node 授权模式,限制 kubelet 只能修改自身节点相关对象。PodSecurity:按命名空间标签执行 Pod 安全标准(Privileged/Baseline/Restricted),替代已废弃的 PSP。ResourceQuota:限制命名空间的总资源用量与对象数量。
此外,MutatingAdmissionWebhook 与 ValidatingAdmissionWebhook 允许接入自定义策略(如 OPA Gatekeeper、Kyverno),实现“禁止特权容器”“强制镜像来自可信仓库”等组织级规则。需要注意的是,Webhook 配置中的 failurePolicy 若设为 Ignore,在 Webhook 不可用时请求会被放行,安全敏感场景应评估是否改为 Fail。
四、安全端口配置:关闭历史遗留的明文入口
早期 API Server 同时监听两个端口:--secure-port(默认 6443,HTTPS,走完整认证授权链)和 --insecure-port(默认 8080,HTTP 明文,不经过认证与授权)。8080 端口是历史上最危险的配置之一,任何能访问该端口的进程都可以直接操作集群。加固要求非常明确:
--insecure-port=0
--secure-port=6443
--tls-cert-file=/etc/kubernetes/pki/apiserver.crt
--tls-private-key-file=/etc/kubernetes/pki/apiserver.key
--client-ca-file=/etc/kubernetes/pki/ca.crt
在 Kubernetes 1.20 及以后版本中,--insecure-port 已被彻底移除,但升级遗留集群时仍需确认没有旧配置残留。此外,--client-ca-file 指定用于校验客户端证书的 CA,是双向 TLS 的基础;--kubelet-certificate-authority 则让 API Server 在访问 kubelet 时校验其证书,防止中间人攻击。
五、验证与排查
配置完成后,可通过以下方式确认加固是否生效。首先检查 API Server 进程参数:
ps -ef | grep kube-apiserver | tr ' ' '\n' | grep -E \
'authorization-mode|anonymous-auth|insecure-port|enable-admission'
其次用匿名请求验证 8080 是否已关闭、6443 是否拒绝匿名访问:
curl -k https://127.0.0.1:6443/api/v1/namespaces
# 预期返回 401 Unauthorized 或 403 Forbidden,而非资源列表
最后用 kubectl auth can-i 检查具体主体的权限边界,例如确认某个 ServiceAccount 不能创建特权 Pod:
kubectl auth can-i create pods --as=system:serviceaccount:dev:app-sa -n dev
kubectl auth can-i create clusterrolebindings --as=system:serviceaccount:dev:app-sa
--anonymous-auth=false;② --authorization-mode=Node,RBAC;③ 启用 NodeRestriction、PodSecurity、ResourceQuota 等准入插件;④ --insecure-port=0;⑤ 开启审计日志并定期审查 cluster-admin 绑定;⑥ 定期轮换客户端证书与 ServiceAccount Token。需要强调的是,这条链路上的每一环都是“与”关系:认证、授权、准入任何一环被削弱,整体安全性都会下降。实际加固时应结合集群版本、云厂商托管特性与业务需求,逐项确认参数,并通过审计日志持续观察异常请求,形成“配置加固 + 运行监控”的闭环。