K8s安全加固实战

阿里云教程2个月前发布
15 0 0

我按完成时间倒着把流程捋了一遍,谁什么时候做了什么、遇到啥坑、用了哪些命令都写清楚,方便你按着步骤实操一遍。先从审计和运行时检测开始讲起,这是我们把事情看见、追溯问题的最后一环,也是出事后能不能把责任和过程查清的关键。

K8s安全加固实战

在 API Server 上我们打开了审计功能,把记录等级按操作敏感度区分开。对 pods、secrets 这种重点资源,把请求头信息和元数据都记录下来;读操作只记元数据,写操作和高风险行为把请求体也记进来。审计策略文件放在
/etc/kubernetes/audit-policy.yaml,给 kube-apiserver 加两个启动参数:

–audit-policy-file=/etc/kubernetes/audit-policy.yaml

–audit-log-path=/var/log/kubernetes/audit.log

同时配置日志轮转,按团队合规设定保留期和大小限制。审计日志不能只放在控制平面节点上那样孤零零地躺着,必须推到聚焦化平台,跟 SIEM 组合起来做告警规则。举例:大量失败的 secret 创建、异常的权限提升、短时间内大量失败的登录都能触发告警。为了把实时异常和历史痕迹串起来,我们还部署了运行时检测工具 Falco,规则针对 exec、容器以 root 运行、可疑网络行为等。部署命令直接用:

kubectl apply -f https://download.falco.org/charts/falco-latest.yaml

把 Falco 的告警接入到告警平台后,出问题时能立刻拉事件单,查日志、看告警、回溯事件链条,这套组合比单靠审计日志要快得多。

往前倒,就是网络隔离了。把服务像分房间一样隔开,每个小网段只能进出被允许的流量。我们选了支持 NetworkPolicy 的 CNI,列如 Calico 或 Cilium,然后针对每个应用写准确策略。举个简单的例子,只允许前端访问后端的 8080 端口,后端不主动连外网:

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

name: front-to-back-8080

namespace: prod

spec:

podSelector:

matchLabels:

app: backend

policyTypes:

– Ingress

ingress:

– from:

– podSelector:

matchLabels:

app: frontend

ports:

– protocol: TCP

port: 8080

这些策略先在测试环境里验证,确认不会阻断正常流量再往生产推。对外暴露的服务放在边界层(ingress/外部负载均衡),再配合 WAF 或云厂商的网络策略做二次防护。写 NetworkPolicy 时要有白名单思维,不要写成“放行全部”,能封就封。

说到 Pod 运行时的安全,细节不少。我们明确要求镜像不能以 root 用户运行,容器的特权能力尽量去掉,文件系统能只读就只读,禁止特权容器。具体在 Pod spec 里写了安全上下文,列如:

securityContext:

runAsNonRoot: true

runAsUser: 1000

allowPrivilegeEscalation: false

readOnlyRootFilesystem: true

同时启用 seccomp 和把能力削减掉:

securityContext:

seccompProfile:

type: RuntimeDefault

capabilities:

drop: [“ALL”]

privileged 一律设为 false。对那些的确 需要 hostPath 或 HostNetwork 的工作负载,只在必要的 namespace 并且经过严格审批后放行。为了把这些规则统一起来,我们启用了 Kubernetes 的 Pod Security Admission,把重大命名空间标为强制级别:

kubectl label namespace prod pod-security.kubernetes.io/enforce=restricted

restricted 模式会自动拦掉许多不安全配置,实测能过滤掉许多“看不见的风险”。

镜像和仓库的把控也必须到位。禁止直接在生产上拉公有镜像,所有镜像先进 CI 做构建和扫描,合格后推到内部私有仓库(如 Harbor 或 Artifact Registry)。CI 阶段用 Trivy 扫描高危和严重漏洞,命令示例:

trivy image –severity HIGH,CRITICAL your-registry.example.com/project/app:latest

只有扫描通过的镜像才允许进入私有仓库。除此之外,我们用镜像签名把镜像和构建内容绑定,运行时通过 Admission Controller 拒绝未签名或未通过扫描的镜像。常见做法是把 Image Policy 加进 Admission chain,用 Cosign 做签名,或者结合 OPA/Gatekeeper 写策略:只允许来自白名单仓库并且通过扫描的镜像入场。这样能避免有人随手从外面拉来不受信任的镜像跑到生产。

身份和权限管理是另一条红线。把“不给普通人超级权限”当作第一条原则。不要把 kube-admin 当成日常账号,管理用账号和日常用账号分开。按最小权限原则给权限,举个只读 pods 的 Role 示例:

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

namespace: prod

name: pods-viewer

rules:

– apiGroups: [“”]

resources: [“pods”]

verbs: [“get”,”list”,”watch”]

绑定时只把具体用户绑到这个角色:

apiVersion: rbac.authorization.k8s.io/v1

kind: RoleBinding

metadata:

name: read-pods-alice

namespace: prod

subjects:

– kind: User

name: “alice@company.com”

apiGroup: rbac.authorization.k8s.io

roleRef:

kind: Role

name: pods-viewer

apiGroup: rbac.authorization.k8s.io

上线后跑一次全量检查,看看谁有 cluster-admin 权限,列出来逐一确认:

kubectl get clusterrolebinding -o yaml | grep -E “cluster-admin|system:masters” -n

把不该有的绑定收回,替换成最小权限角色。权限管理容易出错,记得把角色和绑定写成代码放版本控制里,变更走审批流程。

控制面和节点的加固也做了。API Server 强制 TLS,客户端证书只发给受信任的运维机或管理网络,管理端口只在内网可达,外网不直通控制平面。Kubelet 的认证和授权打开,禁止匿名访问,启用客户端证书机制并接入 RBAC 授权。节点上禁止开放不必要端口,把 kubelet 的只读端口关掉。凭证和证书实现自动化轮换,轮换流程写成脚本或用工具调度,减少手工失误导致的过期风险。etcd 的访问限制在控制平面网络里,etcd 数据也做了加密。

备份与灾备不能偷懒。我们定了定期的 etcd 快照,快照存到异地,并把恢复流程写成文档和自动化脚本,定期做恢复演练。备份策略里包括快照频率、保留天数、完整性校验和恢复演练窗口。除了 etcd,还把关键配置和 manifest(CRD、RBAC、NetworkPolicy 等)都版本化,遇到集群被破坏时能更快重建环境。

为方便日常检查,把可重复跑的清单放运维仓库里。关键命令示例都写清楚:

– 检查集群高权限绑定:

kubectl get clusterrolebinding -o yaml | grep -E “cluster-admin|system:masters” -n

– 查看命名空间的 Pod Security 标签:

kubectl get namespace prod -o jsonpath=”{.metadata.labels}”

– 验证 NetworkPolicy 生效(在测试 Pod 间做流量试验)

– 扫描镜像:

trivy image –severity HIGH,CRITICAL registry/app:tag

– 审计配置检查:

ps aux | grep kube-apiserver (确认审计参数是否被加载)

– 检查 Falco 是否在监控:

kubectl get pods -n falco

把这些命令放到 CI 或巡检脚本里,定期跑并把结果上报到运维面板,发现异常就触发工单。

做这套工作时也踩了不少坑,记录下来给大家参考。常见误区有几条:把 kube-admin 当日常账号;只扫描镜像但不管来源;以为 NetworkPolicy 一次写好就万无一失;不做恢复演练;审计日志只存在本地。对应的补救办法:查出高权限绑定并替换成最小角色,把私有仓库和 Admission 策略捆绑,定期把 NetworkPolicy 纳入变更管理并做流量验证,把恢复演练写进季度计划,把审计日志推到聚焦平台并设置告警。

过程中有两次小插曲值得一提:把 PodSecurityAdmission 强制到 restricted 时,有个老旧作业被拦截,临时把它移到隔离 namespace 跑旧流程,开发改好镜像后才迁回;启用 NetworkPolicy 后发现监控 agent 没被允许访问后端,补了白名单后恢复。这些都写进变更单,作为后续改善材料。

最后把所有检查表和自动化脚本放到版本控制里:权限、镜像策略、Pod 安全规则、NetworkPolicy、审计配置、备份脚本都以代码形式管理,变更有审批、有记录,能回滚也能追溯。保留好这些痕迹,出事时才好查。

© 版权声明

相关文章

暂无评论

none
暂无评论...