容器安全基础:从镜像到运行时的全链路防护

容器安全,说白了就是保护你的容器从生到死的全过程。我做了这么多年金融安全,见过太多团队只关注应用层安全,结果容器层被人捅成筛子。今天咱们就把这块补上。

核心观点:容器安全不是单点防护,而是从镜像构建、仓库存储、运行时监控到网络隔离的完整链条。任何一个环节出问题,整个集群都可能沦陷。

一、容器运行时安全

运行时安全,就是容器跑起来之后怎么防。我遇到过最典型的案例:某支付公司容器被植入挖矿程序,CPU跑满100%才发现。嗯,这就是运行时监控没到位。

1.1 运行时威胁模型

容器运行时面临的主要威胁包括:

  • 进程逃逸:利用内核漏洞突破容器隔离
  • 文件系统篡改:恶意修改容器内关键文件
  • 网络攻击:容器间横向移动、端口扫描
  • 资源滥用:挖矿、DDoS等消耗型攻击

1.2 运行时防护手段

我个人习惯用这几招:

  • Seccomp:限制容器能调用的系统调用。我曾经见过一个容器被植入反向shell,就是因为没限制execve调用
  • AppArmor/SELinux:强制访问控制,给容器戴上紧箍咒
  • Capabilities 裁剪:去掉不需要的Linux能力,比如NET_RAW、SYS_ADMIN
  • 只读根文件系统:容器启动后禁止写操作,防篡改

我的经验:运行时安全配置要遵循最小权限原则。你想想看,一个Web容器需要SYS_ADMIN能力吗?不需要。去掉它,攻击面就少了一大块。

二、镜像安全扫描

镜像安全,是容器安全的第一道防线。我经常跟团队说:别把漏洞带进生产环境

2.1 镜像扫描的核心要素

扫描维度 检查内容 常见问题
操作系统层 基础镜像漏洞、过期包 Alpine、Ubuntu等基础镜像未更新
应用依赖层 第三方库漏洞(npm、pip、maven) Log4j、lodash等经典漏洞
配置层 敏感信息泄露、错误权限 硬编码密码、SSH密钥
文件层 恶意文件、后门程序 挖矿脚本、反弹shell

2.2 扫描工具选型

我建议用这些工具:

  • Trivy:轻量、全面,适合CI/CD集成。我项目里一直用它
  • Clair:CoreOS出品,适合大规模部署
  • Anchore:策略引擎强大,能自定义合规规则
  • Docker Scout:Docker官方工具,集成度高

避坑指南:我曾经遇到过镜像扫描通过,但上线后依然被攻击的情况。为什么?因为扫描的是基础镜像,但运行时拉取的是latest标签,内容已经变了。记住:扫描和运行必须用同一个镜像摘要(digest)

三、容器逃逸防护

容器逃逸,是容器安全里最要命的问题。说白了,就是攻击者从容器里跑到了宿主机上。一旦发生,整个集群都危险了。

3.1 常见逃逸路径

  • 内核漏洞逃逸:利用Dirty Cow、CVE-2022-0847等漏洞
  • 配置不当逃逸:挂载了宿主机敏感目录(/proc、/sys、/var/run/docker.sock)
  • Capabilities滥用:给了SYS_ADMIN、SYS_PTRACE等危险能力
  • 特权容器:--privileged参数直接打开所有权限

3.2 防护策略

我总结了一套防护三板斧:

  1. 内核加固:升级内核、启用内核安全模块(LSM)
  2. 配置检查:禁止挂载宿主机敏感目录,特别是docker.sock
  3. 运行时监控:使用Falco等工具检测异常系统调用

关键点:容器逃逸防护的核心是纵深防御。不要指望单一手段能防住所有攻击。我见过最成功的案例是:即使攻击者突破了第一层,也被后续的AppArmor和Seccomp拦住了。

四、Kubernetes Pod安全策略(PSP/PSS)

Pod安全策略,是K8s里控制Pod权限的利器。不过要注意,PSP在1.25版本后被废弃了,现在推荐用PSS(Pod Security Standards)。

4.1 PSP vs PSS

特性 PSP(旧) PSS(新)
实现方式 集群级资源对象 内置准入控制器
配置复杂度 高,需要写大量RBAC 低,通过标签控制
策略级别 自定义策略 Privileged/Baseline/Restricted三级
推荐度 已废弃 强烈推荐

4.2 PSS实战配置

我个人习惯这样配置:

# 为命名空间设置PSS策略
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: baseline
    pod-security.kubernetes.io/warn: baseline
---
# 验证Pod是否符合策略
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: app
    image: nginx
    securityContext:
      runAsNonRoot: true
      seccompProfile:
        type: RuntimeDefault
      capabilities:
        drop: ["ALL"]

我的建议:生产环境用restricted级别,开发环境用baseline。privileged级别除非有特殊需求,否则别用。我曾经见过一个团队所有命名空间都用privileged,结果被攻破后整个集群沦陷。

五、容器网络策略(NetworkPolicy)

网络策略,是容器间通信的防火墙。你想想看,如果没有网络策略,任何一个Pod都能访问其他Pod,那跟裸奔有什么区别?

5.1 NetworkPolicy核心概念

  • Pod选择器:指定策略作用于哪些Pod
  • 入站规则(Ingress):控制谁可以访问目标Pod
  • 出站规则(Egress):控制目标Pod可以访问谁
  • 策略类型:允许/拒绝,默认拒绝所有

5.2 实战配置示例

# 拒绝所有入站流量,只允许前端访问后端
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

5.3 网络策略最佳实践

我总结了几条铁律:

  • 默认拒绝所有:先拒绝,再按需开放
  • 最小化开放端口:只开放业务需要的端口
  • 命名空间隔离:不同环境(dev/staging/prod)之间禁止通信
  • 监控网络流量:使用Cilium、Calico等工具可视化网络

避坑指南:我曾经遇到过配置了NetworkPolicy但没生效的情况。排查了半天,发现是CNI插件不支持。记住:NetworkPolicy需要CNI插件支持,比如Calico、Cilium、Weave等。Flannel默认不支持。

知识体系总览

下面这张图,是我梳理的容器安全知识体系。你可以把它当作一个检查清单,看看自己覆盖了哪些环节。

容器安全防护体系 镜像安全 漏洞扫描 基础镜像加固 运行时安全 Seccomp/AppArmor Capabilities裁剪 逃逸防护 内核加固 敏感目录保护 Pod安全策略(PSP/PSS) Privileged / Baseline / Restricted 准入控制 + 标签策略 容器网络策略 Ingress / Egress 规则 默认拒绝 + 最小化开放 监控与应急响应 Falco运行时监控 / 告警 / 自动隔离 日志审计 / 事件溯源 纵深防御:每一层都是防线,缺一不可

这张图展示了容器安全的五个核心环节。从镜像安全开始,到运行时防护、逃逸防御、Pod策略、网络隔离,最后是监控响应。每一层都是防线,缺一不可。

总结一句话:容器安全不是某个工具能搞定的,而是一套体系。从镜像构建到运行时监控,从Pod配置到网络隔离,每个环节都要做到位。我见过太多团队只关注其中一两项,结果被攻击者从薄弱环节突破。

最后分享一个习惯:我每次上线新服务,都会对照这张图逐项检查。镜像扫了吗?运行时加固了吗?网络策略配了吗?Pod安全级别设了吗?监控告警接了吗?全部通过才敢上线。

专注资料整理