K8s安全机制全解析:从认证授权到准入控制与审计加固
发布时间:2026/9/23 11:28:41 作者:尧图编辑部 阅读量:1,286

64个K8s安全机制我来给你捋一遍Kubernetes的安全机制算是云原生领域最劝退的一块内容了网上资料要么是官方文档那种正确但看不懂的风格要么是只讲了一两个点的碎片化教程。我自己从裸奔集群一路踩坑到现在把认证、授权、准入控制、网络策略、Secret管理、审计日志这一整套东西摸了个遍这篇就把K8s安全机制从原理到实操完整拆一遍。这篇内容适合谁看一种是刚搭好集群不知道下一步该做什么的运维另一种是已经被RBAC、PodSecurity、NetworkPolicy这些名词绕晕的开发还有一种是正在做等保合规、想给集群整体加固的同学。看完你能收获一套可以直接抄作业的加固清单以及每个关键选择背后的为什么这么干。K8s的安全机制说白了就是回答三个问题你是谁、你能干什么、你干的事合不合规矩。围绕这三个问题衍生出一整套组件和流程我按实际操作的顺序来聊。1. 先搞清楚K8s到底在防什么安全威胁模型1.1 为什么K8s安全机制这么容易绕晕很多初学者上来就背RBAC的YAML结果还是不知道怎么配本质原因是没理解K8s的信任边界。Kubernetes不像传统单体应用那样只有一个入口它由控制面API Server、etcd、Scheduler、Controller Manager和工作节点kubelet、kube-proxy、容器运行时组成每一层通信都存在被利用的可能。我把常见的攻击路径梳理了一下大致有这几类未授权访问API Server这是最致命的拿到API Server权限等于拿到整个集群的root可以任意创建Pod、读取Secret、删除资源。恶意镜像或漏洞容器开发者从公共仓库拉了个有后门的镜像或者镜像里的依赖存在远程代码执行漏洞容器一旦跑起来就被攻破。容器逃逸攻击者先打穿应用再借助内核漏洞或错误配置逃出容器边界直接落到宿主机。横向移动集群内Pod之间没有任何隔离攻击者拿下A服务后通过Service或者Pod IP直接扫内网把整个集群打穿。数据泄露Secret明文存在于etcd中或者RBAC配置过宽任何服务账号都能读所有命名空间的密钥。供应链攻击镜像构建过程被污染依赖源被替换或者镜像仓库本身被入侵。理解了这些路径你就知道为什么K8s的安全机制这么多层。它不是为了解决某一个漏洞而是要做纵深防御。就算某一道防线被突破后面还有好几道拦住攻击者。1.2 K8s安全的三个核心命题纵深防御落到K8s其实就是三层问题第一层是认证Authentication解决你是谁。K8s里面身份分两种一种是人类用户通过kubeconfig里的证书或token识别另一种是Pod里的服务身份ServiceAccount。API Server接到的每一个请求第一步永远是认证。第二层是授权Authorization解决你能干什么。K8s默认开启RBAC基于角色的访问控制通过Role、ClusterRole、RoleBinding、ClusterRoleBinding四件套来控制权限范围。RBAC是K8s安全里最核心、也最容易被配错的模块。第三层是准入控制Admission Control解决你干的事合不合规矩。请求过了认证和授权之后在对象持久化到etcd之前会被一串准入控制器拦截检查。你可以在这里强制要求所有Pod必须带资源限制、所有镜像必须来自私有仓库、禁止特权容器等等。这三层之外还有网络策略NetworkPolicy、Secret加密、PodSecurity标准、审计日志等配套机制。接下来每一层我都给你拆开讲附上可以直接用的配置。2. 认证与授权把你是谁和你能干嘛管明白2.1 认证体系kubeconfig、ServiceAccount与TLS证书K8s的认证方式有好几种但实际生产里最常见的是两种X509客户端证书和ServiceAccount token。先说客户端证书。集群初始化时比如用kubeadm或KubeKey会生成一套CA管理员用它签出admin证书。之后你创建新用户流程是生成私钥和证书签名请求用集群CA签发然后把CA证书、客户端证书、私钥打包进kubeconfig配置文件。API Server验证请求时通过CA公钥校验客户端证书是否由可信CA签发并从这个证书里提取CN字段作为用户名。实战中我建议你在每台需要访问集群的机器上都单独配置kubeconfig不要为了图省事把admin的kubeconfig到处拷。有个小技巧用kubectl config set-credentials配合--embed-certstrue可以把证书嵌进kubeconfig文件但注意这个文件一定要用chmod 600限制权限否则泄露出去等于把集群管理权限拱手送人。再讲ServiceAccount。这是Pod访问API Server的身份凭证它比客户端证书更适合给工作负载用。每个Namespace默认有一个default ServiceAccount但很多团队就直接用default跑业务这其实隐患很大。因为default ServiceAccount往往被赋予了比较大的权限取决于你集群里绑定的Role而且所有没显式指定ServiceAccount的Pod都会用它一旦一个Pod被攻破攻击者就能借用这个身份继续横向移动。我自己的习惯是每个应用单独建一个ServiceAccount只绑定最小权限Pod的spec里显式声明serviceAccountName。这条看起来不起眼但能在真实事故里把爆炸半径缩小一大截。2.2 RBAC授权实战从一次真实配置说起RBAC的配置思路很清晰先定义角色Role或ClusterRole再把角色绑定到用户或ServiceAccountRoleBinding或ClusterRoleBinding。区分Role和ClusterRole的核心是作用范围Role只作用于某个NamespaceClusterRole作用于整个集群。我拿一个真实场景举例给一个日志采集的DaemonSet配权限它需要读取集群里所有Namespace的Pod和节点信息但不需要修改任何资源。这时候应该建一个ClusterRole配置如下apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: log-collector-reader rules: - apiGroups: [] resources: [pods, services, nodes] verbs: [get, list, watch]然后把这个ClusterRole绑定到日志采集组件的ServiceAccount上apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: log-collector-binding subjects: - kind: ServiceAccount name: log-aggregator namespace: kube-system roleRef: kind: ClusterRole name: log-collector-reader apiGroup: rbac.authorization.k8s.io这里有个特别容易踩的坑roleRef一旦确定就不能再改绑定的Role只能删除重建Binding。所以如果你后续要调整权限别想着原地改直接新建一个ClusterRole再替换Binding。RBAC排查时最常用的命令是这两个# 查看当前用户/ServiceAccount能执行哪些操作 kubectl auth can-i --list --assystem:serviceaccount:default:log-aggregator # 模拟执行某个操作看是否被允许 kubectl auth can-i get pods --assystem:serviceaccount:default:log-aggregator -n kube-system这两个命令可以让你不用瞎猜权限够不够直接验证。每次配完RBAC我都建议用kubectl auth can-i自检一遍再上线比等用户反馈快得多。2.3 ServiceAccount的自动挂载与Token过期问题在K8s 1.24之前创建ServiceAccount会自动生成一个永不过期的Secret token这个设计一直被安全圈诟病。后来K8s引入了TokenRequest API支持生成有过期时间的短期token1.24版本开始不再自动创建Secret。如果你还在用旧版本的自动挂载token建议尽快迁移到Bound Service Account Token。检查一下Pod里的token挂载情况如果发现不需要访问API Server的工作负载也挂了token可以在Pod的spec里加一行automountServiceAccountToken: false这个配置我最早是在极简安全的加固清单里看到的实测能把大部分Pod的攻击面瞬间缩小。因为大多数业务Pod根本不需要直接调API Servertoken挂在里面就是一颗定时炸弹容器一旦被攻破攻击者直接就能用这个token尝试访问集群资源。3. 准入控制与策略落地把规矩定在前面3.1 Admission Controller对象持久化之前最后一道闸门认证过了、授权也过了不代表请求就一定合法。准入控制器Admission Controller在请求被持久化到etcd之前运行可以修改或拒绝请求。Kubernetes默认开启了很多内置的准入控制器你可以在API Server的启动参数里通过--enable-admission-plugins开启更多。生产环境我强烈建议开启这几个NamespaceLifecycle防止在正在终止的Namespace里创建新资源。LimitRanger强制Namespace里的Pod遵守资源配额限制。ResourceQuota给Namespace设置总体资源上限。PodSecurity这是Pod Security Standards的落地准入控制器用来强制执行特权限制。NodeRestriction限制kubelet只能修改自身的节点和Pod对象。ServiceAccount自动给Pod注入ServiceAccount。其中与日常安全最相关的是PodSecurity标准在K8s v1.25之前是PodSecurityPolicy现在已弃用。它定义了三个级别级别安全要求适用场景privileged不限制特权系统组件、需要裸设备访问的特殊工作负载baseline禁止特权容器、禁止hostNetwork等大部分中间件和业务应用restricted最严格限制capabilities、seccomp等严格合规场景多租户集群举个例子如果你想强制某个命名空间的所有Pod遵守restricted标准给命名空间打上标签kubectl label namespace production pod-security.kubernetes.io/enforcerestricted kubectl label namespace production pod-security.kubernetes.io/auditrestricted kubectl label namespace production pod-security.kubernetes.io/warnrestricted这三个标签分别是enforce拒绝不合规Pod、audit记录审计日志但不拦截、warn仅返回警告。我建议刚从privileged迁移到restricted的团队先用warn和audit模式跑一段时间观察有哪些存量工作负载不合规改完再切enforce。直接切enforce可能导致线上服务起不来这个坑我踩过。3.2 NetworkPolicy网络层面的微隔离默认情况下K8s集群里所有Pod可以互相通信这和数据中心时代的扁平网络一样攻破一个点就能横扫全网。NetworkPolicy就是用来打破这种默认互信的。它的实现原理依赖网络插件CNI。Calico、Cilium等主流插件都支持NetworkPolicy但Flannel默认不支持如果你用的是Flannel就得先换CNI或者加装Calico。我拿一个典型的三层架构举例前端Pod只允许被Ingress访问前端访问后端后端访问数据库数据库不接受任何外部流量。可以这样配后端服务的入站策略apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: backend-allow-frontend namespace: production spec: podSelector: matchLabels: app: backend policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: frontend ports: - protocol: TCP port: 8080再配一条数据库的入站策略只允许后端访问它的3306端口apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: db-allow-backend namespace: production spec: podSelector: matchLabels: app: database policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: backend ports: - protocol: TCP port: 3306配NetworkPolicy有几个关键点要记住。第一podSelector为空时匹配该命名空间下的所有Pod第二NetworkPolicy是作用在命名空间内的跨命名空间访问要用namespaceSelector第三如果一条NetworkPolicy的policyTypes只写Ingress那默认不限制Egress反之亦然。3.3 OPA/Gatekeeper把安全策略变成代码内置的PodSecurity标准能解决通用问题但真正精细化的策略还得靠OPA Gatekeeper这类策略引擎。比如强制要求所有镜像必须从公司私有仓库拉取这种规则用PodSecurity就做不到但用Gatekeeper可以。Gatekeeper的思路是把策略写成ConstraintTemplate模板再通过Constraint约束指定作用于哪些资源、匹配哪些规则。下面这个约束可以禁止所有Pod以root用户运行apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8srequiredrunasnonroot spec: crd: spec: names: kind: K8sRequiredRunAsNonRoot targets: - target: admission.k8s.gatekeeper.sh rego: | package k8srequiredrunasnonroot violation[{msg: msg}] { container : input.review.object.spec.containers[_] not container.securityContext.runAsNonRoot msg : 容器必须设置 runAsNonRoottrue }然后定义一个约束把这个模板应用在所有命名空间apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sRequiredRunAsNonRoot metadata: name: require-run-as-non-root spec: match: kinds: - apiGroups: [apps] kinds: [Deployment] - apiGroups: [] kinds: [Pod]Gatekeeper的Rego语法有学习门槛但日常场景你不需要写太多复杂规则网上有开源的policy-libraryGatekeeper官方库直接复用场景模板就行。我个人建议第一阶段先做这三条禁止latest镜像标签、强制runAsNonRoot、限制宿主机路径挂载。4. 数据与运行时的安全细节别让你的密钥裸奔4.1 Secret的正确打开方式很多团队的Secret管理方式让我看了直摇头——直接把明文密码写进YAML文件然后提交Git仓库。从K8s安全机制的角度来说Secret对象本身只是base64编码这不是加密任何能读Secret的人都能秒解出来。用Secret的正确姿势是用kubectl create secret命令创建避免明文写文件的习惯。例如kubectl create secret generic db-credentials \ --from-literalusernameadmin \ --from-literalpasswordPssw0rd!配合外部密钥管理服务比如Vault、AWS Secrets Manager、阿里云KMS让K8s从外部系统动态拉取密钥etcd里不落盘。写业务代码时通过CSI Secret Store Driver或External Secrets Operator把云厂商的密钥同步成K8s的Secret。etcd中存储的Secret要开加密配置API Server的--encryption-provider-config参数使用aesgcm或secretbox加密。我还想强调一个容易被忽视的点Secret的权限控制。Secret所在的Namespace里任何拥有get权限的人都能看到明文哪怕他没有写权限。所以不要把Secret放在共享的命名空间里要给敏感应用单独开命名空间并且严格限制get/list权限。我在实际项目中遇到过这么一个事故一个开发同学为了排查问题用admin权限把生产环境所有Secret导出了里面有数据库密码、第三方API密钥、私钥证书全都截图发到了群里。后来整个集群的密钥全部轮换了一遍。从那以后我就强制规定生产环境的高危Secret只允许特定ServiceAccount读取任何bulk导出操作都要走审计流程。4.2 镜像与容器运行时安全镜像安全是K8s安全里最容易忽视、但也是攻击者最爱利用的环节。镜像构建完成后应该做几件事用Trivy或Clair扫描已知漏洞把镜像签名cosign或Notation运行时用只读根文件系统启动。扫描漏洞这个步骤在日常CI流水线里就能接入。以Trivy为例trivy image --severity HIGH,CRITICAL registry.example.com/myapp:v1.0.0 trivy image --exit-code 1 --severity CRITICAL registry.example.com/myapp:v1.0.0在CI里加上第二行命令一旦发现严重漏洞就终止构建。这个策略我用下来效果很好能阻断绝大多数明知有洞还上线的情况。运行时安全也有几个关键配置。一是不要在容器里跑成root尽量用非root用户启动进程二是去掉容器不需要的Linux capabilities比如NET_RAW、SYS_ADMIN三是挂载只读根文件系统在securityContext里配置securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: [ALL]drop所有capabilities这个操作我特别推荐能显著降低容器逃逸成功的概率。但要注意一些基础镜像里的进程可能需要某些能力比如监听80端口不需要额外capability但执行ping需要NET_RAW具体根据应用实际需要再添加。4.3 节点证书过期与自动续签集群最大的定时炸弹很多生产集群出问题都不是因为复杂的攻击而是因为证书过期。K8s的控制面组件通信用的TLS证书都有有效期如果不清不楚过了期整个集群的kubectl命令马上就不好使了现象千奇百怪有时是APIServer报x509错误有时是kubelet连不上有时是scheduler一直报错。用kubeadm搭的集群证书有效期默认是一年但kubeadm提供了一套自动续签的机制。生产实践里我建议这样做先检查当前证书的过期时间kubeadm certs check-expiration在kubeadm配置里开启自动续签。新版kubeadm会在证书剩余时间少于180天时通过kubeadm-controller-manager的证书续签功能自动处理。如果你用的是KubeKeyKubeSphere的部署工具搭的集群它自带的证书管理组件同样支持自动续签配置项在集群的cluster configuration里。对于手动管理证书的集群建议用CronJob定期检查证书剩余时间临近过期时自动执行续签脚本。续签命令是kubeadm certs renew all kubeadm init phase kubeconfig --configkubeadm-config.yaml续签完要重启控制面组件的Poddocker restart $(docker ps -q --filter nameetcd --filter namekube-apiserver --filter namekube-scheduler --filter namekube-controller-manager)或者如果你用的是containerd用crictl来重启对应的容器。我自己管理的一批集群就曾经因为证书过期导致整个生产环境API Server不可用当时值班同学凌晨两点打电话说kubectl全部报错。从那以后我就在每个集群的monitoring里加了一个证书过期时间的监控指标在证书剩余时间小于60天时触发告警。这件事放在安全机制里说是因为证书过期本质上是认证体系的失效影响面等同于认证被攻破。4.4 单节点与GPU场景的安全要点关于热词里提到的单节点K8s和K8s调用GPU这里也补充两个安全要点。单节点集群由于控制面和数据面都在同一台机器上攻击面其实是更大的因为一旦宿主机被攻破整个集群的控制面也就沦陷了。单节点环境至少要做三件事关闭kubelet的匿名认证--anonymous-authfalse给kubelet配置只读端口为0--read-only-port0以及严格控制SSH的访问来源。很多人觉得单节点测试环境无所谓但攻击者拿到内网权限后第一步就是扫描集群端口匿名认证如果开着就直接拿下了。GPU节点在生产里很常见比如跑AI推理它的安全关注点主要在设备插件和驱动。NVIDIA的设备插件运行在kube-system里需要访问宿主机的/dev/nvidia*设备和驱动目录。给GPU工作负载配置Pod时要确保没有给容器挂载宿主机目录的权限否则攻击者可以通过宿主机路径绕过只读根文件系统的限制。另外GPU节点尽量打上污点taint只允许AI相关的Pod调度上去不要和其他业务混跑。5. 可观测与攻击检测安全审计不能靠猜5.1 审计日志记录每一次可疑动作审计日志是安全机制里最不起眼但最重要的一块。它记录了对K8s的所有API请求包括谁、什么时间、对什么资源做了什么操作。一旦集群里发生异常审计日志是追踪攻击路径的第一手资料。我的审计日志配置文件audit-policy.yaml长这样apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Metadata # 记录所有读写操作但仅记录元数据 resources: - group: resources: [secrets, configmaps, serviceaccounts] - level: RequestResponse users: [system:admin] # admin的操作都要记录且保留请求和响应体 - level: Metadata verbs: [create, delete, patch, update] # 写操作默认全部记录 - level: None # 健康检查和静态资源不记录 users: [system:kube-proxy, kubelet, system:serviceaccount:kube-system:...],然后需要在API Server启动参数里指定策略文件和日志输出位置--audit-policy-file/etc/kubernetes/audit/audit-policy.yaml --audit-log-path/var/log/kubernetes/audit/audit.log --audit-log-maxsize100 --audit-log-maxbackup10审计日志文件建议接入到你的日志平台比如ELK或Loki定期对它做告警分析。重点关注的告警规则同一IP频繁调用get secret、创建特权Pod、尝试访问不存在的资源可能是攻击者在探测。5.2 Prometheus监控K8s安全指标从热词里挖重点k8s集群搭建prometheus是热词榜上的常客大家都想监控集群但很多人的监控只关注CPU和内存安全指标完全缺失。我强烈建议你的Prometheus里补充以下几组安全相关的指标kube-apiserver的认证和授权失败次数apiserver_authentication_attempts apiserver_authorization_attempts_total{decisionforbid}这个数值异常升高往往意味着有人在暴力破解或撞库。kubelet的启动异常和证书过期剩余时间kubelet_certificate_manager_rotation_errors_total kube_certificates_certificate_expiration_seconds工作负载的非root运行比例。通过组合kube-state-metrics的label和自定义exporter来算专门用来做安全合规度量。deployment副本数和预期不符。如果某个Deployment的可用副本突然变大很可能是被恶意扩容用来挖矿。配合Grafana做一张安全看板把所有安全相关指标放一起每天看一眼就能快速发现异常。这套方案比等安全通告再查日志要主动得多。我在实践时还发现一个问题Prometheus本身也是一个高权限的组件如果它被攻破攻击者可以通过它的ServiceAccount访问大量集群元数据。所以Prometheus的RBAC权限一定不要配过大只让它读metrics相关的资源就够不要给它get secret之类的权限。6. 一套可以直接抄作业的加固清单6.1 从裸奔集群到生产安全基线的十五个检查项我把日常检查的安全项目整理成了一份清单每次新集群上线前按这个过一遍基本能覆盖90%的常见风险序号检查项检查命令或位置期望结果1匿名请求是否关闭kubectl get clusterrolebinding | grep anon无绑定anonymous的ClusterRoleBinding2kubelet匿名认证查看kubelet配置--anonymous-authfalse3kubelet只读端口--read-only-port04是否开启RBACAPI Server参数--authorization-mode包含RBAC5etcd访问是否需TLS查看etcd监听端口只监听本机且启用TLS6Secret是否加密API Server参数--encryption-provider-config已配置7PodSecurity标签kubectl get ns --show-labels生产namespace已设enforce级别8NetworkPolicy覆盖kubectl get netpol -A关键命名空间有入站和出站策略9默认ServiceAccount使用率检查Pod的serviceAccountName业务Pod不用default10特权容器数量kubectl get pods -A -o jsonpath查securityContext无特权容器或已单独放行11镜像tagkubectl get deploy -A -o jsonpath没有latest标签12容器运行用户securityContext.runAsNonRoottrue或未设置但镜像默认非root13节点SSH来源限制查看安全组/防火墙策略只允许跳板机访问14审计日志落盘ls /var/log/kubernetes/audit/有日志滚转文件15证书过期时间kubeadm certs check-expiration剩余时间大于180天6.2 安全运维必备的常用命令速查日常安全运维离不开的命令这里整理一份速查K8s安全排查高频场景覆盖# 查看当前上下文和用户 kubectl config get-contexts kubectl config view --minify # 查看某个ServiceAccount是否有权限做某项操作 kubectl auth can-i create pod --assystem:serviceaccount:prod:my-sa -n prod # 查看集群里所有ClusterRoleBinding检查有没有不该存在的绑定 kubectl get clusterrolebinding -o wide # 查看所有Pod是否挂载了宿主机路径 kubectl get pods -A -o jsonpath{range .items[?(.spec.hostPath)]}{.metadata.namespace}{ }{.metadata.name}{\n}{end} # 查看所有特权容器 kubectl get pods -A -o jsonpath{range .items[?(.spec.containers[*].securityContext.privilegedtrue)]}{.metadata.namespace}{ }{.metadata.name}{\n}{end} # 查看Secret是否有非预期读取者配合RBAC审计 kubectl get rolebindings -A -o wide | grep secret # 查看审计日志中的敏感操作 grep -E verb:(get|list) /var/log/kubernetes/audit/audit.log | grep secret这里我特别说下第二个命令它是排查权限问题的神器。比如你配置好了RBAC但是服务就是报403用kubectl auth can-i --list --assystem:serviceaccount:命名空间:服务账号可以一眼看到这个服务账号能干什么不能干什么省去大量试错时间。6.3 从热词看大家问得最多的安全误区综合K8s常用命令控制器管理工具这些热词我来统一回答几个被问爆的安全相关问题。第一控制器controller本身安全吗Deployment、StatefulSet这类控制器只是API Server里的控制循环它们本身不直接处理外部请求但它们创建的Pod如果有安全配置缺陷比如特权模式、admin权限就等于给攻击者留了门。所以控制器的安全要落到Pod模板的securityContext上。第二管理工具比如KubeSphere、Rancher、Lens安全吗这类工具有很好的可视化能力但也引入了额外的攻击面。我的原则是管理工具的登录账号必须接企业SSO和MFA管理工具的命名空间要单独隔离管理工具的RBAC要遵循最小权限。我见过有人把KubeSphere的admin密码设置成123456集群直接等同裸奔这种习惯非常要不得。第三k8s和docker区别这个热词背后其实也有安全含义。K8s在docker之上额外增加了大量的安全边界RBAC、准入控制、NetworkPolicy这些都是docker不具备的。所以在docker里跑一下测试没问题但直接把docker容器原封不动搬到K8s上必须过一遍安全配置否则就是带着裸奔配置上了生产。7. 我踩过的坑和给你最后的建议安全机制这东西光看文档记不住最好是自己亲手把集群打穿一次才能真正理解每层防护的价值。我早期的做法是在测试环境故意弱化配置然后用各种攻击工具比如kube-hunter扫描自己集群看能扫出什么结果再针对性地修复。这个过程比读十遍文档都管用。最后分享一个我真实踩过的坑有一次我在生产环境给某个命名空间开启了PodSecurity的restricted级别结果当天就收到告警说某核心服务一直CrashLoopBackOff。排查半天发现是这个服务需要在容器里临时创建子进程而restricted级别的allowPrivilegeEscalation: false禁止了setuid这类操作。最后只能给这个特定Deployment的ServiceAccount单独授权一个baseline的策略。这个经历告诉我安全策略落地最好分阶段走先用audit模式观察兼容性再逐步收紧不要一步到位切enforce。毕竟安全的目标是保障业务不是让业务跑不起来。按照这套思路去加固你的K8s集群不敢说绝对安全但至少能挡住99%的初级攻击和大部分中级攻击。剩下的1%就交给持续监控和快速响应了。