oci-ftrace-syscall-analyzer
is an experimental tool to trace syscalls inside containers without any debug tools in Pod. This tool uses ftrace to debug containers transparently.- Overview of
oci-ftrace-syscall-analyzer
is explained on https://speakerdeck.com/kentatada/debug-application-inside-kubernetes-using-linux-kernel-tools
- You need to mount tracefs to use this tool.
- You can launch the rootless container using this tool when you set the Linux capability of
CAP_DAC_OVERRIDE
to the binary of oci-ftrace-syscall-analyzer or modify permission to the directories of tracefs
- Please download the binary from the release page for amd64 like below.
$ wget https://github.com/KentaTada/oci-ftrace-syscall-analyzer/releases/download/v0.1.1/oci-ftrace-syscall-analyzer.amd64
$ sudo cp oci-ftrace-syscall-analyzer.amd64 /usr/local/bin/oci-ftrace-syscall-analyzer
$ sudo chmod a+x /usr/local/bin/oci-ftrace-syscall-analyzer
$ sudo setcap CAP_DAC_OVERRIDE+ep /usr/local/bin/oci-ftrace-syscall-analyzer
- You can build oci-ftrace-syscall-analyzer from the source code for architecture other than amd64.
- Building oci-ftrace-syscall-analyzer requires rustc version 1.32.0 or later.
- If you don't have rust yet, run:
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- If you have an old version, run:
$ rustup update
- Clone sources from git repo
$ git clone https://github.com/KentaTada/oci-ftrace-syscall-analyzer.git
- Build sources
$ cd oci-ftrace-syscall-analyzer
$ cargo build --release
- Install binary
$ sudo cp target/release/oci-ftrace-syscall-analyzer /usr/local/bin/
$ sudo chmod a+x /usr/local/bin/oci-ftrace-syscall-analyzer
$ sudo setcap CAP_DAC_OVERRIDE+ep /usr/local/bin/oci-ftrace-syscall-analyzer
- The binary built by the above method is dynamically linked binary. But the released binary is a static binary.
- If you want to build static binary, you need to get MUSL support.
- For example, on x86_64 architecture, run:
$ rustup target add x86_64-unknown-linux-musl
$ cargo build --target x86_64-unknown-linux-musl
- This tool is only executed inside container hooks without report --livedump option.
- The annotation is used to control trace settings from Kubernetes. When you set the key of "oci-ftrace-syscall-analyzer/trace" to "true" with --use-annots option, oci-ftrace-syscall-analyzer is executed.
You need to add the prestart and poststop hook in config.json.
"hooks": {
"prestart": [
{
"path": "/usr/local/bin/oci-ftrace-syscall-analyzer",
"args": [
"oci-ftrace-syscall-analyzer",
"record"
]
}
],
"poststop": [
{
"path": "/usr/local/bin/oci-ftrace-syscall-analyzer",
"args": [
"oci-ftrace-syscall-analyzer",
"report"
]
}
]
},
1. Set the Linux capability of CAP_DAC_OVERRIDE
to oci-ftrace-syscall-analyzer. Or change permission to the directories of tracefs.
# setcap CAP_DAC_OVERRIDE+ep /usr/local/bin/oci-ftrace-syscall-analyzer
$ mkdir rootless_trace
$ cd rootless_trace
$ mkdir rootfs
$ docker export $(docker create busybox) | tar -C rootfs -xvf -
$ runc spec --rootless
Add below to config.json.
"hooks": {
"prestart": [
{
"path": "/usr/local/bin/oci-ftrace-syscall-analyzer",
"args": [
"oci-ftrace-syscall-analyzer",
"record"
]
}
],
"poststop": [
{
"path": "/usr/local/bin/oci-ftrace-syscall-analyzer",
"args": [
"oci-ftrace-syscall-analyzer",
"report"
]
}
]
},
$ runc run 1
/ # ls
bin dev etc home proc root sys tmp usr var
/ # exit
$ tail -n 10 ftrace_syscalls_dump.log
(WIP) You need to add OCI hook settings.
(WIP) You need to prepare for the prestart and poststop settings in the CRI-O's oci-hooks.
$ cat /etc/containers/oci/hooks.d/ftrace-syscall-analyzer-prehook.json
{
"version": "1.0.0",
"hook": {
"path": "/usr/local/bin/oci-ftrace-syscall-analyzer",
"args": [
"oci-ftrcae-syscall-analyzer",
"record"
]
},
"when": {
"always": true
},
"stages": [
"prestart"
]
}
$ cat /etc/containers/oci/hooks.d/ftrace-syscall-analyzer-posthook.json
{
"version": "1.0.0",
"hook": {
"path": "/usr/local/bin/oci-ftrace-syscall-analyzer",
"args": ["oci-ftrcae-syscall-analyzer", "report", "--output", "/tmp/syscalllogs/ftrace_syscalls_dump.log"]
},
"when": {
"always": true
},
"stages": ["poststop"]
}
1. Set the Linux capability of CAP_DAC_OVERRIDE
to oci-ftrace-syscall-analyzer. Or change permission to the directories of tracefs.
# setcap CAP_DAC_OVERRIDE+ep /usr/local/bin/oci-ftrace-syscall-analyzer
- Modify "hooks_dir" of libpod.conf to specify the directory includes OCI hook configs
hooks_dir = ["/etc/containers/oci/hooks.d"]
- Create OCI hook configs for oci-ftrace-syscall-analyzer
$ cat /etc/containers/oci/hooks.d/ftrace-syscall-analyzer-prehook.json
{
"version": "1.0.0",
"hook": {
"path": "/usr/local/bin/oci-ftrace-syscall-analyzer",
"args": [
"oci-ftrcae-syscall-analyzer",
"record",
"--use-annots"
]
},
"when": {
"annotations": {
"oci-ftrace-syscall-analyzer/trace": "true"
}
},
"stages": [
"prestart"
]
}
$ cat /etc/containers/oci/hooks.d/ftrace-syscall-analyzer-posthook.json
{
"version": "1.0.0",
"hook": {
"path": "/usr/local/bin/oci-ftrace-syscall-analyzer",
"args": ["oci-ftrcae-syscall-analyzer", "report", "--output", "/tmp/syscall_logs/ftrace_syscalls_dump.log"]
},
"when": {
"annotations": {
"oci-ftrace-syscall-analyzer/trace": "true"
}
},
"stages": ["poststop"]
}
# podman run --annotation oci-ftrace-syscall-analyzer/trace="true" docker.io/alpine:latest /bin/ls
# tail -n 10 /tmp/syscalllogs/ftrace_syscalls_dump.log
(WIP) You can pass options to high level runtimes using annotations.
You can also get syscall logs while container is running. You can get the running container ID from some commands like kubectl describe pods and runc list and so on.
$ oci-ftrace-syscall-analyzer report --livedump [container-id]
--seccomp-profile option generates seccomp profiles by the traced syscalls. Notice: In crrent, generated profile is not accurate. The profile does not include syscalls that invoked from start of trace to start of container app.
Add below to config.json.
"hooks": {
"prestart": [
{
"path": "/usr/local/bin/oci-ftrace-syscall-analyzer",
"args": [
"oci-ftrace-syscall-analyzer",
"record"
]
}
],
"poststop": [
{
"path": "/usr/local/bin/oci-ftrace-syscall-analyzer",
"args": [
"oci-ftrace-syscall-analyzer",
"report"
"--seccomp-profile"
]
}
]
},
e.g. Execute ls command in container.
$ runc run 1
bin dev etc home proc root sys tmp usr var
$ cat seccomp.json
{
"defaultAction": "SCMP_ACT_ERRNO",
"syscalls": [
{
"names": [
"arch_prctl",
"brk",
"close",
"execve",
"exit_group",
"fstat",
"futex",
"getdents64",
"getuid",
"ioctl",
"newfstatat",
"open",
"stat",
"time",
"write"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
$ cat config.json
~~~~~
"linux": {
"seccomp": {
"defaultAction": "SCMP_ACT_ERRNO",
"syscalls": [
{
"names": [
"arch_prctl",
"brk",
"close",
"execve",
"exit_group",
"fstat",
"futex",
"getdents64",
"getuid",
"ioctl",
"newfstatat",
"open",
"stat",
"time",
"write"
],
"action": "SCMP_ACT_ALLOW"
}
]
},
~~~~~
$ runc run 1
bin dev etc home proc root sys tmp usr var