Preventing containers from being unable to be deleted by HirazawaUi · Pull Request #4757 · opencontainers/runc (original) (raw)
I was unable to add integration tests for this PR without resorting to some hacky methods, but I tested whether this issue was resolved in the kubernetes-sigs/kind repository.
In brief, I discovered this issue while working in the kubernetes/kubernetes repo to propagate kubelet's context to the container runtime. The issue manifested as the test job being unable to tear down after the k/k repo's e2e tests completed, because the leaked runc init process and its corresponding systemd scope prevented systemd from shutting down.
Therefore, I opened a PR in the kubernetes-sigs/kind repo to debug this issue by manually replacing the containerd/runc binaries in the CI environment. After building the code from this PR and replacing the binaries in the CI environment, the test job no longer failed to tear down due to systemd being unable to shut down, as the leaked processes were resolved.
Ref: kubernetes-sigs/kind#3903 (Some job failures occurred due to the instability of the k/k repo e2e tests, but they are unrelated to this issue.)
I also conducted some manual tests targeting the scenarios where the leftover container is in the paused and stopped states.
Paused:
Inject sleep to allow us to control where the code is interrupted.
You can add a header
diff --git a/vendor/github.com/opencontainers/cgroups/systemd/v1.go b/vendor/github.com/opencontainers/cgroups/systemd/v1.go index 8453e9b4..bbe3524c 100644 --- a/vendor/github.com/opencontainers/cgroups/systemd/v1.go +++ b/vendor/github.com/opencontainers/cgroups/systemd/v1.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strings" "sync"
"time" systemdDbus "github.com/coreos/go-systemd/v22/dbus" "github.com/sirupsen/logrus"
@@ -361,6 +362,7 @@ func (m *LegacyManager) Set(r *cgroups.Resources) error { } } setErr := setUnitProperties(m.dbus, unitName, properties...)
time.Sleep(time.Second * 30) if needsThaw { if err := m.doFreeze(cgroups.Thawed); err != nil { logrus.Infof("thaw container after SetUnitProperties failed: %v", err)
1. Create a container:
./runc --systemd-cgroup create mycontainer
2. Check container processes:
ps -ef | grep runc
root 2944 694 0 15:36 pts/2 00:00:00 ./runc --systemd-cgroup create mycontainer
root 2956 2944 0 15:36 ? 00:00:00 ./runc init
root 2963 688 0 15:36 pts/1 00:00:00 grep runc
3. Kill the runc create process:
kill -9 2944
4. Check if the runc init process is left behind:
ps -ef | grep runc
root 2956 1 0 15:36 ? 00:00:00 ./runc init
root 2965 688 0 15:37 pts/1 00:00:00 grep runc
5. Check the current container state:
./runc list
ID PID STATUS BUNDLE CREATED OWNER
mycontainer 2953 paused /root/mycontainer 0001-01-01T00:00:00Z root
6. Delete the container:
./runc delete -f mycontainer
writing sync procError: write sync: broken pipe
EOF
7. Verify if the runc init process has been cleaned up:
ps -ef | grep runc
root 3067 688 0 15:39 pts/1 00:00:00 grep runc
stopped:
Inject sleep to allow us to control where the code is interrupted.
You can add a header
diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go index 96e3ca5f..350e3660 100644 --- a/libcontainer/process_linux.go +++ b/libcontainer/process_linux.go @@ -613,6 +613,7 @@ func (p *initProcess) start() (retErr error) { return fmt.Errorf("unable to apply cgroup configuration: %w", err) } }
time.Sleep(time.Second * 30) if p.intelRdtManager != nil { if err := p.intelRdtManager.Apply(p.pid()); err != nil { return fmt.Errorf("unable to apply Intel RDT configuration: %w", err)
1. Create a container:
./runc --systemd-cgroup create mycontainer
2. Check container processes:
ps -ef | grep runc
root 3124 694 0 15:45 pts/2 00:00:00 ./runc --systemd-cgroup create mycontainer
root 3132 3124 0 15:45 pts/2 00:00:00 ./runc init
root 3140 688 0 15:45 pts/1 00:00:00 grep runc
3. Kill the runc create process:
kill -9 3124
4. Check if the runc init process is left behind (There will be no runc init process left behind):
ps -ef | grep runc
root 3142 688 0 15:45 pts/1 00:00:00 grep runc
5. Check the current container state:
./runc list
ID PID STATUS BUNDLE CREATED OWNER
mycontainer 0 stopped /root/mycontainer 0001-01-01T00:00:00Z root
6. Delete the container:
./runc delete -f mycontainer