AppArmor不支持为运行中容器动态嵌套加载新策略,仅在进程启动时按可执行文件路径匹配profile;嵌套控制需预设分层profile、显式加载并用Kubernetes注解分别绑定不同进程。
apparmor 本身不支持“为运行中容器动态嵌套加载新策略”——它只在进程启动时根据可执行文件路径匹配 profile,且策略绑定发生在 execve 阶段。所谓“嵌套访问控制”,实际是指:容器内进程(如 shell、脚本、子服务)在已有容器上下文中进一步受限,需通过提前设计分层 profile或组合运行时约束来实现,而非热更新。
确认底层机制已就绪
嵌套控制的前提是宿主机已启用 AppArmor 并正确加载基础策略:
- 运行 sudo aa-status,确认输出含 apparmor module is enabled: yes,且 profiles are loaded 列表里有容器运行时(如 /usr/bin/containerd、/usr/bin/runc 或 /opt/rancher/bin/k3s)
- 检查内核参数:cat /sys/module/apparmor/parameters/enabled 应返回 Y
- 若用 Kubernetes,确保节点上 kubectl describe node 输出中包含 AppArmor:true
为嵌套行为预设分层 profile
容器内启动的子进程(比如 /bin/sh、/usr/local/bin/entrypoint.sh)必须有对应 profile,不能依赖父容器策略自动继承:
- 在 /etc/apparmor.d/ 下创建子进程专用配置,命名严格按路径转点(如 /bin/sh → /etc/apparmor.d/bin.sh)
- profile 中显式 include 基础抽象(abstraction/base),再叠加限制项,例如:
profile bin.sh { #include <abstraction/base> deny /home/** w, deny /tmp/** rwk, /proc/sys/kernel/osrelease r, } - 用 sudo apparmor_parser -r /etc/apparmor.d/bin.sh 加载,再用 aa-status | grep bin.sh 确认已生效
在 Pod 中显式指定多级策略
Kubernetes 不支持单个容器挂多个 profile,但可通过注解将不同容器进程指向不同策略,形成事实上的嵌套控制:
- 主容器使用宽松 profile(如 localhost/nginx-base)
- 通过 initContainer 启动一个带严格 profile 的辅助进程(如 localhost/init-hardened),完成初始化后退出
- 若容器内需执行受限命令(如备份脚本),改用 securityContext.runAsUser + 单独 profile 绑定该二进制路径
- 注解示例(K8s v1.25+ 推荐方式):
annotations: container.apparmor.security.beta.kubernetes.io/main: localhost/nginx-base container.apparmor.security.beta.kubernetes.io init: localhost/init-hardened
调试与验证关键点
嵌套控制失效往往因路径匹配失败或 profile 未加载,排查要直击根源:
- 在容器内执行 aa-status --pid $(pidof sh),看当前 shell 进程是否处于预期 profile 下
- 查拒绝日志:sudo dmesg -t | grep apparmor 或 sudo journalctl | grep DENIED
- 临时切到 complain 模式调试:sudo aa-complain /etc/apparmor.d/bin.sh,再运行子进程,用 sudo aa-logprof 生成建议规则
- 注意:Docker 默认使用 docker-default profile,它不覆盖容器内自启动进程;K3s/Containerd 需显式注解才生效

















