手把手教你用sysdig写Lua脚本:自定义监控K8s Pod的异常文件访问

张开发
2026/4/13 1:26:53 15 分钟阅读

分享文章

手把手教你用sysdig写Lua脚本:自定义监控K8s Pod的异常文件访问
手把手教你用sysdig写Lua脚本自定义监控K8s Pod的异常文件访问在Kubernetes集群中安全团队经常需要监控特定业务Pod是否存在异常文件访问行为比如读取敏感配置文件或频繁扫描日志目录。传统监控工具往往难以实现细粒度的文件操作追踪而sysdig的Chisel框架配合Lua脚本开发能力可以完美解决这一痛点。本文将带你从零开发一个定制化文件监控脚本覆盖需求分析、脚本编写到生产集成的全流程。1. 需求分析与监控方案设计假设我们需要监控名为payment-service的Pod是否存在以下异常行为访问/etc/secrets/目录下的敏感配置文件频繁读取/var/log/下的非预期日志文件异常文件删除或修改操作首先需要明确sysdig的事件捕获机制。当容器进程执行文件操作时Linux内核会产生open、read、write等系统调用事件。我们可以通过组合以下过滤器精准捕获目标事件container.namepayment-service and (evt.type in (open,openat,unlink,rename) and (fd.name contains /etc/secrets/ or fd.name contains /var/log/))这个过滤器会捕获payment-service容器中所有针对敏感路径的文件打开、删除和重命名操作。实际开发时建议先通过命令行验证过滤条件sysdig -pc \ container.namepayment-service and evt.typeopen and fd.name contains /etc/secrets/2. Lua脚本核心结构解析一个完整的sysdig Chisel脚本包含三个关键回调函数2.1 初始化阶段(on_init)-- 脚本元信息 description 监控指定容器的敏感文件访问 short_description K8s文件访问监控 category security -- 定义可配置参数 args { { name container_name, description 目标容器名称, argtype string, optional false }, { name sensitive_paths, description 敏感路径列表(逗号分隔), argtype string, default /etc/secrets/,/var/log/ } } -- 初始化回调 function on_init() -- 申请需要的字段 f_container chisel.request_field(container.name) f_evttype chisel.request_field(evt.type) f_fdname chisel.request_field(fd.name) f_procname chisel.request_field(proc.name) -- 构建过滤器 paths {} for path in string.gmatch(args.sensitive_paths, [^,]) do table.insert(paths, fd.name contains ..path..) end path_filter table.concat(paths, or ) filter string.format( container.name%s and evt.type in (open,openat,unlink,rename) and (%s), args.container_name, path_filter) chisel.set_filter(filter) return true end2.2 事件处理阶段(on_event)-- 定义告警阈值 local ALERT_THRESHOLD 10 local access_counts {} function on_event() local fdname evt.field(f_fdname) local procname evt.field(f_procname) -- 统计各文件的访问频次 if not access_counts[fdname] then access_counts[fdname] 0 end access_counts[fdname] access_counts[fdname] 1 -- 实时输出异常访问 if access_counts[fdname] ALERT_THRESHOLD then print(string.format( [ALERT] %s 频繁访问 %s (次数: %d), procname, fdname, access_counts[fdname])) end return true end2.3 捕获结束阶段(on_capture_end)function on_capture_end() print(\n 文件访问统计报告 ) for fdname, count in pairs(access_counts) do if count ALERT_THRESHOLD then print(string.format(%-40s %5d 次 (异常), fdname, count)) else print(string.format(%-40s %5d 次, fdname, count)) end end return true end3. 高级功能实现技巧3.1 动态阈值调整通过添加运行时参数支持动态调整告警阈值args { -- ...其他参数... { name alert_threshold, description 触发告警的访问次数阈值, argtype int, default 10 } } function on_set_arg(name, val) if name alert_threshold then ALERT_THRESHOLD tonumber(val) return true end -- 其他参数处理... end使用时可通过-a参数指定阈值sysdig -c file_monitor.lua -a container_namepayment-service -a alert_threshold53.2 上下文信息增强在事件中添加上下文信息便于后续分析function on_event() local pid evt.field(proc.pid) local exe evt.field(proc.exe) local args evt.field(proc.args) local timestamp evt.field(evt.datetime) -- 构建完整事件记录 local event { time timestamp, process string.format(%s (PID: %d), exe, pid), command args, file evt.field(f_fdname), operation evt.field(f_evttype) } -- 可输出JSON格式便于ELK收集 print(json.encode(event)) end3.3 性能优化建议处理高频事件时需注意性能问题字段缓存提前缓存常用字段索引local f_container nil local f_evttype nil function on_init() f_container chisel.request_field(container.name) f_evttype chisel.request_field(evt.type) -- ... end采样控制对高频事件进行采样local SAMPLE_RATE 0.1 -- 10%采样率 function on_event() if math.random() SAMPLE_RATE then return true end -- 事件处理逻辑... end批量处理使用sysdig -n限制处理事件数量4. 生产环境集成方案4.1 CI/CD流水线集成将脚本检查作为部署流程的一部分# 在Helm部署命令后添加监控 helm upgrade payment-service ./chart \ sysdig -c file_monitor.lua -a container_namepayment-service -w /monitor/payment-service.scap4.2 Prometheus监控集成通过sysdig的prometheus输出格式暴露指标function on_capture_end() -- 输出Prometheus格式指标 print(# HELP file_access_count Total file access count) print(# TYPE file_access_count counter) for fdname, count in pairs(access_counts) do local metric_name string.gsub(fdname, [^a-zA-Z0-9_], _) print(string.format( file_access_count{file%s} %d, metric_name, count)) end end4.3 告警规则配置结合Falco实现自动告警- rule: SensitiveFileAccess desc: 检测敏感文件访问 condition: container.name payment-service and evt.type in (open,openat) and fd.name startswith /etc/secrets/ output: 敏感文件被访问 (user%user.name process%proc.name file%fd.name) priority: WARNING5. 实战调试技巧5.1 常见问题排查问题1脚本未捕获预期事件检查过滤器语法chisel.get_filter()验证容器名称大小写K8s容器名通常为小写确认路径匹配规则containsvsendswith问题2脚本性能低下使用-n 1000限制事件数量进行测试添加-v参数查看详细日志减少字段请求数量5.2 调试工具推荐sysdig-cli实时验证过滤器sysdig -pc container.namepayment-service and evt.typeopencsysdig可视化分析事件sysdig -r capture.scap -c csysdigLua调试器使用mobdebug进行远程调试local mobdebug require(mobdebug) mobdebug.start()5.3 性能对比测试不同实现方式的性能基准测试环境10000个事件实现方式处理时间(ms)内存占用(MB)基础Lua脚本120050带采样(10%)15045字段缓存优化90040C插件20030对于生产环境建议先使用优化后的Lua脚本在性能不满足时考虑开发C插件。

更多文章