如何查看Linux虚拟机上K8S Pod后台系统调用并排查权限错误
resource.getrlimit 触发PermissionError 问题背景
运行在Linux虚拟机上的K8S Pod已应用安全策略(限制系统调用),当执行Python代码resource.getrlimit(resource.RLIMIT_NOFILE)时触发PermissionError,需要定位被阻止的系统调用以加入允许列表。尝试查看/var/log/audit/audit.log仅得到无参考价值的加载/卸载日志:
type=UNKNOWN[1334] msg=audit(1723127982.604:3803): prog-id=484 op=LOAD type=UNKNOWN[1334] msg=audit(1723127982.608:3804): prog-id=485 op=LOAD type=UNKNOWN[1334] msg=audit(1723127982.608:3805): prog-id=486 op=LOAD ... type=UNKNOWN[1334] msg=audit(1723127982.648:3812): prog-id=493 op=LOAD type=UNKNOWN[1334] msg=audit(1723127991.012:3813): prog-id=486 op=UNLOAD type=UNKNOWN[1334] msg=audit(1723127991.180:3814): prog-id=491 op=UNLOAD ... type=UNKNOWN[1334] msg=audit(1723127991.532:3821): prog-id=484 op=UNLOAD type=UNKNOWN[1334] msg=audit(1723127991.532:3822): prog-id=488 op=UNLOAD
且Pod触发错误后立即终止,无法进入容器执行操作。
定位被阻止的系统调用方法
1. 明确Python resource.getrlimit 对应的系统调用
Python的resource.getrlimit()在Linux平台下直接调用getrlimit系统调用,部分Python版本也可能使用更通用的prlimit系统调用。但需通过实际追踪确认具体被阻止的调用。
2. 用bpftrace在宿主机追踪系统调用拒绝事件
在Pod启动前,在宿主机运行以下bpftrace命令,可实时捕获容器进程的系统调用拒绝情况:
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_getrlimit { printf("PID: %d, RLIMIT: %d\n", pid, args->resource); } tracepoint:syscalls:sys_exit_getrlimit { if (args->ret == -1) { printf("PID: %d, getrlimit failed: %s\n", pid, strerror(-args->ret)); } }'
若需范围更广的追踪,可捕获所有失败的系统调用:
sudo bpftrace -e 'tracepoint:syscalls:sys_exit_* { if (args->ret == -1) { printf("PID: %d, Syscall: %s, Error: %s\n", pid, probe, strerror(-args->ret)); } }'
启动Pod后,即可看到对应进程的系统调用失败信息,直接定位被阻止的调用。
3. 调整Audit规则记录系统调用拒绝事件
默认Audit规则未开启系统调用拒绝日志,需添加以下规则(替换<pod容器ID>为目标Pod的容器ID,可通过kubectl describe pod <pod-name>获取):
sudo auditctl -a exit,always -F arch=b64 -S all -F success=0 -F container=<pod容器ID>
添加后重新启动Pod,即可在/var/log/audit/audit.log中看到包含type=SYSCALL和res=denied的日志条目,明确被阻止的系统调用。
4. 查看容器运行时日志
容器运行时(如containerd、Docker)会记录系统调用拒绝事件:
- containerd:查看
/var/log/containerd/containerd.log,搜索seccomp或denied关键字。 - Docker:查看
/var/log/docker.log,同样搜索seccomp或denied。
后续处理
定位到被阻止的系统调用(通常是getrlimit)后,将其添加到Pod的Seccomp Profile或AppArmor策略的允许列表中,重新部署Pod即可解决PermissionError。
内容的提问来源于stack exchange,提问作者Gauraang Khurana

