Springboot 3.2.0集成CRaC在Kubernetes非特权模式下运行失败求助
背景
我正在运行一个简单的hello-world应用,测试Spring Boot 3.2.0中新集成的CRaC功能。在原生Docker中启动容器时,必须使用--privileged标志,否则会出现错误(尽管容器内的CRIU拥有root权限)。现在尝试在Kubernetes Job中运行该应用,以便对应用进行快照存储到AWS EFS,随后在Fargate上快速恢复应用执行。但我们的EKS实例因Kyverno策略限制,禁止以特权模式运行容器,这导致CRIU执行checkpoint时失败。
CRIU错误日志
(00.004537) Error (criu/vdso.c:304): vdso: Can't open 185/maps on procfs: Permission denied (00.004564) Error (criu/vdso.c:498): vdso: Failed to mmap compatible vdso with helper process (00.004571) Error (criu/vdso.c:620): vdso: Failed to fill compat vdso symtable (00.004573) Error (criu/kerndat.c:1607): kerndat_vdso_fill_symtable failed when initializing kerndat.
相关版本信息
- CRIU版本:3.17.1-crac
- Linux内核:5.10.192-183.736.amzn2.x86_64
- JDK镜像:azul/zulu-openjdk:17.0.9-17.46-jdk-crac
提问
是否有办法在非特权模式下让CRIU正常工作?
1. 配置容器所需的Linux能力
特权模式会赋予容器全部Linux能力,但CRIU仅需部分关键能力即可运行。可以在Kubernetes Job的Pod配置中添加以下能力,替代privileged: true:
CAP_SYS_PTRACE:用于追踪进程状态CAP_SYS_ADMIN:处理文件系统与命名空间操作CAP_IPC_LOCK:锁定内存中的关键数据CAP_NET_ADMIN:若涉及网络快照恢复则需要
Kubernetes配置示例:
securityContext: capabilities: add: ["SYS_PTRACE", "SYS_ADMIN", "IPC_LOCK", "NET_ADMIN"] runAsUser: 0 # 保持root用户运行,CRIU需要较高权限
2. 调整Procfs挂载权限
错误日志显示无法访问/proc/[pid]/maps,这是容器内procfs挂载权限受限导致的。可以在Pod配置中重新挂载主机的procfs,赋予容器访问权限:
volumeMounts: - name: proc mountPath: /proc mountPropagation: HostToContainer volumes: - name: proc hostPath: path: /proc type: Directory
注意:需确认节点procfs配置允许容器访问,同时评估该操作的安全风险。
3. 启用CRIU的非特权模式
部分CRIU版本支持--no-privileged参数,强制其在非特权模式下运行。如果通过Spring Boot CRaC触发快照,可通过环境变量传递该参数:
export CRAC_CRIU_OPTS="--no-privileged"
4. 升级CRIU版本
当前使用的3.17.1-crac版本对非特权模式的支持有限,升级到4.x系列的CRaC兼容版本,可减少对特权能力的依赖,同时配合对应版本的JDK镜像使用。
5. 调整Kyverno策略(若允许)
如果团队安全策略允许,可针对该Job的命名空间或特定Pod修改Kyverno规则,允许添加所需的Linux能力,而非完全禁止特权相关配置。例如创建例外规则,允许该应用Pod添加CAP_SYS_PTRACE等必要能力。
内容的提问来源于stack exchange,提问作者Massimiliano Fiori

