在国产麒麟 OS 上启用 SELinux 后容器无法启动,如何排障
解读
国产麒麟 OS(银河麒麟、中标麒麟)在政府、金融、运营商等关键行业大量部署,强制启用 SELinux 是等保 2.0 与关基防护的硬性要求。Docker 依赖内核的 overlayfs、netfilter、cgroups 等子系统,一旦 SELinux 策略与容器运行时标签不匹配,就会触发 avc: denied 拒绝,表现为容器卡在 create/containerd-shim 阶段或直接 Exit 127。面试官想考察的是:能否在“国产 OS + 强制策略”这一真实场景下,用最小权限思路快速定位并修复标签冲突,同时不破坏系统合规基线。
知识点
- 麒麟 OS 的 SELinux 策略栈:基于参考策略(refpolicy)叠加国产模块(kylin-module),默认启用 mls 敏感度标签,容器进程默认被划入 container_t 域。
- Docker 的 SELinux 上下文链:
daemon 域 → container_runtime_t → container_t → 容器内进程标签;
镜像层文件系统挂载时需打上 container_file_t 或 svirt_sandbox_file_t。 - 国产场景特有约束:
/var/lib/docker 如放在国产加密盘(中标麒麟安全卷)上,会被标记为 kylin_encrypted_t,与 container_file_t 不兼容;
麒麟内核 backport 了 overlayfs selinux xattr 补丁,但 4.19 之前版本对 “overlay.upperdir” 标签继承存在 bug。 - 排障三板斧:
ausearch -m avc -ts recent
sealert -a /var/log/audit/audit.log
sesearch --allow -s container_t -t kylin_encrypted_t - 最小修复原则:绝不直接 setenforce 0,而是通过 semodule -i mydocker.pp 加载自定义策略包,或使用 container-selinux 官方 rpm 升级策略模块。
答案
-
确认 SELinux 状态
getenforce 结果为 Enforcing 即符合现场约束;若返回 Permissive 需先请示甲方,不得私自降级。 -
抓取拒绝日志
ausearch -m avc -ts boot | grep -E '(docker|containerd|overlay)' > avc.log
典型日志:
avc: denied { mounton } for pid=1234 comm="dockerd" path="/var/lib/docker/overlay2/xxx/merged" scontext=system_u:system_r:container_runtime_t:s0 tcontext=system_u:object_r:kylin_encrypted_t:s0 tclass=dir -
分析标签冲突
使用 semanage fcontext -l | grep kylin_encrypted 发现麒麟加密卷默认标签与容器存储冲突;
使用 sesearch --allow 确认当前策略未允许 container_runtime_t 对 kylin_encrypted_t 执行 mounton。 -
给出三种合规修复方案
方案 A(推荐):把 Docker 根目录迁出加密卷
mkdir -p /data/docker && semanage fcontext -a -t container_var_lib_t '/data/docker(/.*)?'
restorecon -Rv /data/docker
修改 /etc/docker/daemon.json 新增 "data-root": "/data/docker",重启 daemon。方案 B:原地打标签(加密卷需甲方书面同意)
semanage fcontext -a -t container_file_t '/var/lib/docker(/.*)?'
restorecon -Rv /var/lib/docker
若仍拒绝,编译局部策略:
audit2allow -M mydocker < avc.log
semodule -i mydocker.pp方案 C:使用 --selinux-enabled=false 临时验证(仅定位,不投产)
dockerd --selinux-enabled=false 能启动则确认是 SELinux 问题,随后必须回退到 Enforcing 并按方案 A/B 修复。 -
回归测试
docker run --rm alpine echo ok
再执行 ausearch -m avc -ts boot 无新拒绝即闭环;
将操作步骤写入《麒麟 SELinux 加固适配报告》,提交等保测评方备案。
拓展思考
- 麒麟 OS 未来切换到 SELinux + KubeEdge 场景,容器运行时由 Docker 改为 containerd + cri-plugin,需关注 containerd-cri 使用的 label=disable 挂载选项是否被国产策略拦截;提前把 container_runtime_t 对 container_share_t 的 relabelfrom 权限加入基线策略。
- 多架构适配:银河麒麟 ARM64 版本内核裁剪了 overlayfs selinux xattr 部分 backport,建议优先使用 devicemapper + direct-lvm 模式,并在 –storage-opt dm.fs=ext4 时显式关闭 SELinux xattr 继承,避免容器内 ls -Z 出现问号标签。
- 合规审计:等保 2.0 要求“强制访问控制策略应覆盖主体与客体”,因此任何自定义 mydocker.pp 都必须通过 checkmodule -M -m 生成二进制模块后,由 semodule -l 统一编号,禁止现场直接 setsebool -P 关闭布尔值,防止测评时出现“策略缺失”高风险项。