KubeArmor 运行时策略与主机保护
一个平台团队把“禁止容器内运行包管理器”的 KubeArmorPolicy 发布到生产 namespace,策略对象能正常查询,Operator、Controller、Relay 和节点 Daemon 也都是 Ready。演练人员进入目标 Pod 后,apt --version 却照常返回。追查才发现新节点镜像没有激活 BPF-LSM,Snitch 只能让 Daemon 进入观测模式;Kubernetes API 接受了策略,不代表节点内核已经具备拒绝动作的执行器。
另一个团队把默认文件姿态从 audit 一次性改成 block,希望快速收紧基线。某个应用启动时读取动态生成的证书路径,该路径没有进入 allow 规则,滚动发布后的新 Pod 全部启动失败。值班人员先删除策略,拒绝仍短暂持续,因为工作负载、节点 profile 与控制器状态并不是同一瞬间消失。缺少灰度节点池、受控反例和回退顺序,让一次安全加固变成了业务故障。
先分清策略对象、观测与执行
KubeArmor 在工作负载已经运行之后观察并约束进程、文件、网络和 Linux capability 行为。它不是准入控制器:准入策略回答“这个 Pod 声明能否写入集群”,KubeArmor 回答“这个进程运行后能否执行某个二进制、访问某条路径或使用某项能力”。镜像签名、清单合规和运行时阻断是三层证据,任何一层通过都不能替代另外两层。
KubeArmor 提供三类策略对象。KubeArmorPolicy,常简称 KSP,用 namespace 内的 label selector 选择 Pod;KubeArmorClusterPolicy,常简称 CSP,在集群范围选择工作负载;KubeArmorHostPolicy,常简称 HSP,面向节点和宿主进程。KSP/CSP 不应被拿来假装主机策略,HSP 也不能证明容器策略已经绑定到目标 Pod。官方策略类型说明可用于核对目标版本支持的对象与字段。
动作也要拆开理解。Audit 允许操作继续并产生事件;Block 请求底层执行器拒绝匹配行为;Allow 通常参与白名单模型,而未匹配行为最终如何处理还取决于 default posture。默认姿态为 audit 时,漏写一条 allow 往往只告警;改为 block 后,同一个遗漏会成为真实拒绝。策略 YAML、默认姿态、活动 LSM 和返回码共同决定结果。
运行机制经过哪些组件
Operator 读取 KubeArmorConfig 并协调安装;Snitch 探测节点的 LSM 与容器运行时;节点 Daemon 关联 Pod 身份、接收策略并驱动 runtime enforcer;Controller 处理 Kubernetes 侧的工作负载与策略协调;Relay 汇聚各节点 Daemon 的 alert、telemetry 和 log,向 CLI 或下游提供单一 gRPC 入口。Daemon 说明和 Runtime Enforcer 说明给出了这条分工线。
这条链有三个不能互相替代的健康信号:Operator 能创建对象,说明控制协调面工作;Daemon 在目标节点加载支持的执行器,说明内核执行面可能成立;Relay 能收到事件,说明集中遥测入口可用。Relay Ready 不证明节点已阻断,Daemon Ready 也不证明 Active LSM 非空。生产探针应把这三类状态分开监控。
当 Relay 故障时,最直接受影响的是集中消费和 SIEM 交付;已经加载到节点的策略是否继续执行,要用目标版本的受控阻断动作确认。官方没有承诺 Relay 具备 Exactly Once、断点续传或无损多副本语义,因此不能根据 Deployment 副本数推导事件一定不丢或不重。
逐节点确认 LSM 与平台能力
KubeArmor 可使用 BPF-LSM、AppArmor 或 SELinux,但三者不是字段完全等价的可互换后端。安装前先按节点池保留内核、发行版、容器运行时和活动 LSM 证据,尤其不能只在一个运维节点运行 uname 就代表整个集群。
kubectl get nodes -o wide
uname -r
grep -E 'CONFIG_(BPF|BPF_SYSCALL|BPF_LSM|SECURITY)=' \
/boot/config-"$(uname -r)" 2>/dev/null || true
cat /sys/kernel/security/lsmBPF-LSM 需要内核编译并激活相关能力;仅看到较新的内核版本仍不够。预期证据是配置中存在所需选项,活动 LSM 列表中包含 bpf,安装后 karmor probe 也报告对应 Active LSM。修改内核启动参数或 LSM 顺序通常涉及节点重启,必须以节点池灰度、PodDisruptionBudget 和可用容量为前提,不能在全体节点上同时处理。
AppArmor 需要宿主内核和发行版工具链正确启用,嵌套 Kind 环境还可能缺少 securityfs 暴露。它与 BPF-LSM 的网络语义并不完全相同,官方 FAQ 特别提示 AppArmor 下的 ICMP block/audit 行为限制。SELinux 在 KubeArmor 的官方差异说明中主要用于 host protection,不能据此宣称所有容器策略都与 BPF-LSM 等价。支持矩阵与官方 FAQ应成为节点池准入检查的一部分。
固定稳定版本并拆开安装权限
下面采用 KubeArmor 稳定发行线 v1.7.4。不要只调用 GitHub latest 接口决定生产版本,因为 release 名称可能是 RC;还要交叉检查语义化版本名、Release 页面与 Helm 索引。karmor CLI 和 Relay 各有独立版本线,也不能假设它们与服务端版本号同步。KubeArmor Releases和官方 Chart 索引提供可复核入口。
安装者需要创建 CRD、ClusterRole、ClusterRoleBinding、webhook、DaemonSet 和 Deployment 等集群级资源。运行时则应分别审计 Operator、Controller、Daemon 与 Relay 的 ServiceAccount。先确认上下文和安装权限,再固定 Chart;不要把集群管理员凭证留给日常日志读取者。
kubectl config current-context
kubectl auth can-i create customresourcedefinitions.apiextensions.k8s.io
kubectl auth can-i create clusterroles.rbac.authorization.k8s.io
kubectl auth can-i create daemonsets.apps -n kubearmor
helm repo add kubearmor https://kubearmor.github.io/charts
helm repo update kubearmor
helm show chart kubearmor/kubearmor-operator --version v1.7.4
helm show values kubearmor/kubearmor-operator --version v1.7.4 \
> kubearmor-operator-values-reference.yamlKubeArmor Daemon 已不要求笼统的 privileged: true,但仍需 BPF/LSM、securityfs、procfs、容器运行时和若干 Linux capabilities。非 privileged 不等于低权限。Operator 的集群权限、Controller 的 patch/update 能力、Relay 对 Pod/Service 的 watch,以及 Daemon 的宿主访问都应进入 RBAC diff;未使用的工作负载注解或 patch 能力应在 values 中关闭。
用可复核配置完成 Operator 部署
先安装 Operator,再准备 KubeArmorConfig。官方 v1.7.4 sample 适合了解结构,但其中组件可能仍使用 stable 等可变 tag,且 imagePullPolicy: Always 会让同一声明在不同时间解析成不同镜像。生产配置应把 KubeArmor、init、Controller 和 Relay 分别固定到经过验证的 tag 或 digest,并保存 Pod 实际 imageID。
helm upgrade --install kubearmor-operator kubearmor/kubearmor-operator \
--namespace kubearmor \
--create-namespace \
--version v1.7.4 \
--values kubearmor-operator-values.yaml \
--wait --timeout 10m
curl -fsSLo kubearmor-config.yaml \
https://raw.githubusercontent.com/kubearmor/KubeArmor/v1.7.4/pkg/KubeArmorOperator/config/samples/sample-config.yml
grep -nE 'image:|tag:|imagePullPolicy|default|visibility|alert' kubearmor-config.yaml
# 评审并固定组件镜像后再应用,禁止原样把可变 tag 带入生产。
kubectl apply -f kubearmor-config.yaml官方 v1.7.4 配置样例用于确认字段;Operator values用于审查控制器、RBAC 与镜像设置。defaultFilePosture、defaultCapabilitiesPosture、defaultNetworkPosture 决定未匹配行为的处理方向;defaultVisibility 决定默认采集资源类型;alertThrottling 与 maxAlertPerSec 决定告警洪峰时能看到多少证据。默认文件可见性没有全开时,看不到文件事件不能直接归因为策略未命中。
用四层证据验收安装
第一层确认 CRD、Config 与控制组件存在;第二层确认目标 Linux 节点都有 Daemon;第三层确认每个节点实际选择的 enforcer;第四层用匹配和不匹配动作确认事件与返回码。检查命令应保留节点名、镜像摘要和日志时间窗,便于升级后对比。
kubectl get kubearmorconfig -n kubearmor -o yaml
kubectl get ds,deploy,svc,pods -n kubearmor -o wide
kubectl get crd | grep -i kubearmor
kubectl get pods -n kubearmor -o jsonpath='{range .items[*]}{.spec.nodeName}{"\t"}{range .status.containerStatuses[*]}{.imageID}{"\n"}{end}{end}'
karmor probe
kubectl logs -n kubearmor -l kubearmor-app=kubearmor --tail=200 \
| grep -Ei 'enforcer|LSM|BPF|AppArmor|SELinux|audit|error|warning'karmor probe 中 Active LSM 为空,或 Daemon 日志明确表示只运行 Audit/Observability,是“可观测但不能执行 Block”的直接信号。异构节点池还应按节点记录 BPF-LSM 与 AppArmor 分布;一份策略在不同执行器上可能产生不同网络和参数匹配结果。
先跑 Audit 正向实验
先在隔离 namespace 用 Audit 学习选择器、可见性和事件字段,不要把第一次策略测试做成阻断。下面创建 nginx 工作负载,打开 process/file/network 可见性,并对读取 nginx 配置文件产生审计事件。
kubectl create namespace kubearmor-lab
kubectl create deployment nginx -n kubearmor-lab --image=nginx:1.27
kubectl wait -n kubearmor-lab --for=condition=Available deployment/nginx --timeout=180s
kubectl annotate namespace kubearmor-lab \
kubearmor-visibility='process,file,network' --overwrite
kubectl get pods -n kubearmor-lab --show-labelsapiVersion: security.kubearmor.com/v1
kind: KubeArmorPolicy
metadata:
name: audit-nginx-config
namespace: kubearmor-lab
spec:
selector:
matchLabels:
app: nginx
file:
matchDirectories:
- dir: /etc/nginx/
recursive: true
action: Audit应用策略后执行一次读取,并在另一个终端查看结构化事件:
kubectl apply -f audit-nginx-config.yaml
kubectl exec -n kubearmor-lab deployment/nginx -- \
cat /etc/nginx/nginx.conf >/dev/null
karmor logs -n kubearmor-lab --json预期命令退出码为 0,事件中能关联 namespace、Pod、容器、策略名、资源路径、Action: Audit 与通过结果。若命令成功但没有事件,依次检查 selector、namespace visibility、Relay/CLI 连接、字段是否被当前 enforcer 支持,以及 alert throttling;不要为了“看见结果”直接把动作改为 Block。
用阻断反例证明执行器真实存在
阻断实验选择实验容器里的包管理器,只在 kubearmor-lab 生效。它要证明的是 LSM 拒绝链,而不是证明包管理器本身存在;因此先确认路径,再发布策略。镜像变更导致 /usr/bin/apt 不存在时,应换成该镜像里确定存在的无害测试程序,不能把 command not found 当作阻断成功。
apiVersion: security.kubearmor.com/v1
kind: KubeArmorPolicy
metadata:
name: block-package-manager
namespace: kubearmor-lab
spec:
selector:
matchLabels:
app: nginx
process:
matchPaths:
- path: /usr/bin/apt
- path: /usr/bin/apt-get
action: Blockkubectl exec -n kubearmor-lab deployment/nginx -- test -x /usr/bin/apt
kubectl apply -f block-package-manager.yaml
kubectl exec -n kubearmor-lab deployment/nginx -- apt --version
echo "exit_code=$?"
karmor logs -n kubearmor-lab --json执行成立时,预期 apt 返回非零码或 permission denied,KubeArmor 事件包含目标 policy、Action: Block、实际 Enforcer 和拒绝结果。关键反例是:Policy 存在,apt 却成功,同时 karmor probe 的 Active LSM 为空。此时只能得出“策略控制对象已创建、节点仍处于观测模式”,不能把一条 Audit 告警包装成阻断。
还要增加不匹配动作,例如读取 /etc/hostname 或执行 nginx 自身命令,确认窄策略没有扩大故障半径。返回码、业务状态和 KubeArmor alert 三类证据必须一致;只看告警中的 Block 字样不足以证明目标操作没有发生。
把策略接入发布与回退流程
业务团队应维护 namespace 级 KSP,平台团队维护跨租户 CSP 与节点 HSP,并通过 owner 和代码评审避免多方同时控制同一行为。策略发布先走 Audit,收集一个完整业务周期的匹配路径,再对单一节点池或小比例 workload 切换 Block。default posture 的改变比单条 deny 策略更宽,应单独变更、单独回滚。
回退时先把 default posture 从 block 恢复为 audit,再删除 allow-list 或 Block 策略,等待目标工作负载与节点状态收敛,最后用原动作复测。删除 CRD 或卸载 Operator 不是紧急回退手段,因为控制器消失后可能留下 profile、webhook 或无法协调的对象。
kubectl annotate namespace kubearmor-lab \
kubearmor-file-posture=audit \
kubearmor-network-posture=audit \
kubearmor-capabilities-posture=audit --overwrite
kubectl delete kubearmorpolicy -n kubearmor-lab block-package-manager
kubectl exec -n kubearmor-lab deployment/nginx -- apt --version
karmor logs -n kubearmor-lab --json预期回退后受控命令恢复,旧策略不再产生新的 Block 事件。若仍拒绝,应检查 Pod 是否刷新、节点 enforcer/profile 是否仍加载、是否还有 CSP/HSP 命中,以及其他 LSM 或安全产品是否同时执行。双执行器并行时,删除 KubeArmor 策略不一定解除另一产品的拒绝。
事件字段是敏感资产
KubeArmor alert 可能包含命令参数、路径、容器 ID、镜像、namespace、Pod 身份和进程上下文。参数可能夹带 token,路径可能暴露租户名、证书位置或商业目录结构。Relay、CLI、日志平台和工单系统都应按敏感数据处理:启用 mTLS,限制 Service 暴露,使用最小读取 RBAC,在进入 SIEM 前做字段分级和脱敏,并为原始事件设置短于聚合指标的保留期。
不要在示例 values、命令行或提示词中放真实 gRPC 凭证、内部域名和租户标识。调试时扩大 visibility 也属于数据采集变更,必须有时限和自动恢复。官方从 v1.3 起提供的 mTLS 能力需要连同证书签发、轮换和失败策略一起验证,不能只看到 Secret 存在就认定传输安全。
用事件预算设计容量与 HA
DaemonSet 的首要可用性指标是目标节点覆盖率,以及各实例是否加载了有效 enforcer。事件容量至少按节点数、每节点进程/文件/网络/capability 事件率、Audit/Block 比例、平均事件大小、Relay 连接数和下游写入延迟建模。alertThrottling 会保护组件,也会制造证据缺口;仪表盘应同时显示输出事件数与被节流数。
Relay 聚合入口可能随连接和事件积压增长内存,应设置 requests/limits,观察 working set、OOM、断连和下游延迟。把 Relay replicas 改为 2 不能自动获得去重、顺序、补发和无损切换。采用多副本前,应在测试环境缩容一个副本或暂停下游,记录事件是否重复、丢失以及恢复耗时。
异构 LSM 集群的高可用更复杂:同一 YAML 可能在 BPF-LSM 节点完整执行,在 AppArmor 节点部分执行,在无 Active LSM 节点仅观测。平台应按节点 label 建立兼容池,把策略能力、调度约束和应用 SLO 一起验收,而不是追求一份跨所有节点的表面统一配置。
升级要把 Chart、CRD、镜像和 CLI 视为一个事务
升级前导出 Operator values、KubeArmorConfig、三类策略、CRD schema 和实际镜像摘要。候选版本先进入与生产内核、CRI 和 LSM 相同的 canary 节点池,重复 Audit、Block、Relay 故障与回退实验。只升级 Chart 而忽略 Config 内的组件镜像,可能留下混合版本;只回滚镜像而不回滚 CRD 和策略字段,也可能无法恢复旧语义。
helm get values kubearmor-operator -n kubearmor -o yaml \
> kubearmor-operator-values-before.yaml
kubectl get kubearmorconfig -n kubearmor -o yaml \
> kubearmor-config-before.yaml
kubectl get kubearmorpolicies,kubearmorclusterpolicies,kubearmorhostpolicies \
-A -o yaml > kubearmor-policies-before.yaml
helm upgrade kubearmor-operator kubearmor/kubearmor-operator \
--namespace kubearmor \
--version v1.7.4 \
--values kubearmor-operator-values.yaml \
--atomic --timeout 10m回滚合同必须记录 Helm revision、兼容的 Config/CRD、CLI 与 Relay 组合,以及节点 profile 恢复判据。升级完成不以 Deployment Available 结束,而以节点覆盖、Active LSM、正反动作、事件字段、节流和下游交付全部恢复结束。
安全退出要先解除拒绝再拆控制面
退出前先将 default posture 灰度恢复为 audit,删除或停用 Block/allow-list 策略,并在每类节点执行受控动作,证明业务行为已恢复。然后删除 KubeArmorConfig,观察 Daemon、Controller 和 Relay 退出,再卸载 Operator。CRD、ClusterRole、webhook、TLS Secret、namespace 和外部日志索引是否删除,要根据回装与留存要求分别决定。
kubectl get kubearmorpolicies,kubearmorclusterpolicies,kubearmorhostpolicies -A
kubectl delete kubearmorpolicy -n kubearmor-lab --all
kubectl delete namespace kubearmor-lab
kubectl delete kubearmorconfig -n kubearmor kubearmorconfig-default
kubectl get ds,deploy,pods -n kubearmor -w
helm uninstall kubearmor-operator -n kubearmor
kubectl get crd,clusterrole,clusterrolebinding | grep -i kubearmor || true
kubectl get validatingwebhookconfiguration,mutatingwebhookconfiguration \
| grep -i kubearmor || true最后按节点运行 probe,检查受控命令、CRI/LSM 状态和残留工作负载。官方没有提供一条能证明所有节点内核策略都已清空的统一命令,所以退出证据必须按节点池组合:Kubernetes 对象消失、Daemon 退出、目标行为恢复、旧事件停止、外部凭证撤销、日志与账单按计划核销。到这里,KubeArmor 才从“装过一个安全组件”变成一套可以安装、证明、回退和退出的运行时约束能力。
