平台基础设施安全:容器运行时安全、Kubernetes集群安全加固、节点与主机安全基线
好,咱们进入第二章。平台基础设施安全,说白了就是给PaaS平台打好地基。我见过太多团队,一上来就搞微服务、搞编排,结果底层容器和主机全是漏洞,跑起来心惊胆战。今天咱们就聊聊这三块硬骨头:容器运行时、K8s集群、还有节点主机。
容器运行时安全
容器不是轻量级虚拟机。这个观念我反复跟团队强调。你想想看,容器共享宿主机内核,一旦内核被突破,整个宿主机就沦陷了。所以运行时安全,核心就两件事:限制容器能做什么,以及监控它在做什么。
1. 使用非root用户运行容器
默认情况下,容器里的进程是root。但容器里的root,其实就是宿主机上的root。嗯,这里要注意。我建议在Dockerfile里显式指定用户:
FROM alpine:3.18
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
COPY --chown=appuser:appgroup ./app /app
CMD ["/app/entrypoint.sh"]
我在项目中遇到过,有团队直接把生产镜像里的root用户保留着,结果被攻破后攻击者直接拿到了宿主机root权限。后来我们强制要求所有基础镜像必须包含非root用户配置。
2. 只读根文件系统
容器运行时,根文件系统应该是只读的。临时数据挂载到tmpfs或emptyDir。这样就算容器被写入了恶意文件,重启后就没了。
核心原则:容器应该是不可变的。任何需要持久化的数据,都通过卷挂载进来。
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop: ["ALL"]
3. 限制Linux内核能力
容器不需要那么多capabilities。我习惯的做法是:先全部drop,再按需添加。比如一个Web服务,可能只需要NET_BIND_SERVICE就够了。
避坑指南:我曾经遇到过,开发说容器需要SYS_PTRACE来调试,结果上线后忘了去掉。攻击者利用这个能力绕过了AppArmor。所以,生产环境一定要最小化capabilities。
4. 使用Seccomp和AppArmor
Seccomp限制系统调用,AppArmor限制文件访问和网络。这两个配合使用,效果很好。K8s从1.19开始默认启用Seccomp,但很多团队不知道。
securityContext:
seccompProfile:
type: RuntimeDefault
appArmorProfile:
type: RuntimeDefault
Kubernetes集群安全加固
K8s集群安全,我把它分成三个层面:控制面安全、工作负载安全、网络策略。咱们一个一个说。
1. 控制面安全:API Server是第一道门
API Server是集群的大脑。谁控制了API Server,谁就控制了整个集群。我建议做以下几件事:
- 启用RBAC:别用ABAC,那玩意维护起来太痛苦。RBAC清晰明了。
- 禁用匿名访问:
--anonymous-auth=false,这个必须配。 - 使用ServiceAccount:每个应用用独立的ServiceAccount,别用default。
- 审计日志:开启审计日志,记录谁在什么时候做了什么。
注意:审计日志会占用大量磁盘空间。我建议只记录Metadata级别,除非你怀疑有攻击行为才提升到RequestResponse级别。
2. 工作负载安全:Pod安全标准
K8s从1.23开始引入了Pod Security Standards(PSS)。分三个级别:Privileged、Baseline、Restricted。我建议生产环境至少用Baseline,敏感业务用Restricted。
| 级别 | 说明 | 适用场景 |
|---|---|---|
| Privileged | 无限制,基本等于裸奔 | 系统组件、监控Agent |
| Baseline | 限制已知的提权路径 | 大多数业务应用 |
| Restricted | 最严格,强制非root、只读根文件系统等 | 金融、支付等敏感业务 |
你可以用Pod Security Admission来强制实施:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
3. 网络策略:默认拒绝一切
K8s默认网络是扁平的,所有Pod都能互相通信。这太危险了。我建议一开始就部署网络策略,默认拒绝所有入站和出站流量,然后按需开放。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
然后针对具体服务开放:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- port: 8080
节点与主机安全基线
节点是容器的家。家不安全,容器再安全也没用。我总结了一套基线,大家可以参考。
1. 操作系统加固
- 最小化安装:只装必要的包。别装编译器、调试工具。
- 禁用SSH密码登录:只用密钥,而且密钥要定期轮换。
- 内核参数调优:比如
net.ipv4.ip_forward=0,除非你用了网络插件。 - 启用SELinux或AppArmor:别关掉它们。很多人嫌麻烦直接关了,这是大忌。
个人经验:我习惯用CIS Benchmark来检查节点安全。跑一遍kube-bench,看看哪些项没通过。刚开始可能一堆红色,但别慌,一条条改就行。
2. 容器运行时守护进程安全
Docker或containerd的守护进程,默认监听在Unix socket上。别把它暴露到网络上。我见过有人把Docker socket挂载到容器里,结果容器里的进程直接控制了宿主机。
# 不要这样做!
volumes:
- name: dockersocket
hostPath:
path: /var/run/docker.sock
如果你确实需要管理容器,用K8s的API,别直接操作Docker。
3. 定期扫描与更新
节点上的内核和系统包,必须定期更新。我建议用自动化工具,比如Ansible或Terraform,来管理节点镜像。每次更新后,重新创建节点,而不是原地升级。
核心原则:节点应该是不可变的。一旦部署,就不应该手动登录上去改东西。所有变更都通过基础设施即代码来管理。
4. 监控与告警
节点安全不是配完就完了。你得持续监控。我建议关注这几个指标:
- Falco告警:检测异常系统调用,比如容器里执行了
chmod /etc/shadow。 - 节点资源异常:CPU或内存突然飙升,可能是挖矿程序在跑。
- 网络连接异常:容器突然连接了未知IP,可能是C2通信。
说白了,安全是个持续的过程。你不可能配一次就高枕无忧。我每次上线新业务,都会重新审视一遍这些基线。嗯,今天就聊到这儿。下一章咱们聊聊数据安全,那可是更刺激的话题。