___Method of verification used

sudo apt install uvtool

sudo uvt-simplestreams-libvirt sync release=resolute arch=amd64

uvt-kvm create r8 release=resolute --cpu 8 --memory 8192 --disk 40
--password ubuntu

uvt-kvm ssh r8

sudo vi /etc/apt/sources.list.d/ubuntu.sources 
--------
Types: deb
URIs: http://archive.ubuntu.com/ubuntu
Suites: resolute resolute-updates resolute-backports resolute-proposed
Components: main universe restricted multiverse
--------

sudo apt update


apt-cache madison containerd
containerd | 2.2.2-0ubuntu1.2 | http://archive.ubuntu.com/ubuntu 
resolute-proposed/main amd64 Packages
containerd | 2.2.2-0ubuntu1.1 | http://archive.ubuntu.com/ubuntu 
resolute-updates/main amd64 Packages


____Prerequisites

cd /tmp
curl -fsSLo go.tgz https://go.dev/dl/go1.24.3.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go.tgz
echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bashrc
export PATH=$PATH:/usr/local/go/bin
go version


____Get crictl (CRI client)

cd /tmp
curl -fsSLo crictl.tgz 
https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.37.0/crictl-v1.37.0-linux-amd64.tar.gz
sudo tar -C /usr/local/bin -xzf crictl.tgz
crictl --version


sudo apt install containerd=2.2.2-0ubuntu1.2


___enable NRI

sudo mkdir -p /etc/containerd

sudo vi /etc/containerd/config.toml
--------
[plugins."io.containerd.nri.v1.nri"]
  disable = false
  socket_path = "/var/run/nri/nri.sock"
--------


sudo systemctl restart containerd

sudo systemctl status containerd

sudo containerd config dump


_________NRI listener must exist

sudo ls -l /var/run/nri/nri.sock



____Build the "failing" NRI plugin

mkdir -p ~/nri-fail
cd ~/nri-fail

vi go.mod
--------
module nri-fail

go 1.24

require github.com/containerd/nri v0.10.0
--------


# all 14 interface methods required by the stub
# only RunPodSandbox does anything interesting

vi main.go
--------
package main

import (
   "context"
   "fmt"
   "os"

   "github.com/containerd/nri/pkg/api"
   "github.com/containerd/nri/pkg/stub"
)

type failingPlugin struct{}

func (p *failingPlugin) Configure(_ context.Context, config, runtime, version 
string) (stub.EventMask, error) {
   fmt.Fprintf(os.Stderr, "nri-fail: connected to %s/%s\n", runtime, version)
   return 0, nil
}

func (p *failingPlugin) Synchronize(_ context.Context, pods []*api.PodSandbox, 
containers []*api.Container) ([]*api.ContainerUpdate, error) {
   return nil, nil
}

func (p *failingPlugin) Shutdown(_ context.Context) {}

func (p *failingPlugin) RunPodSandbox(_ context.Context, pod *api.PodSandbox) 
error {
   fmt.Fprintf(os.Stderr, "nri-fail: RunPodSandbox hook for pod %s (%s/%s) - 
failing deliberately\n",
      pod.GetId(), pod.GetNamespace(), pod.GetName())
   return fmt.Errorf("nri-fail: deliberate RunPodSandbox failure (containerd 
issue #13355 repro)")
}

func (p *failingPlugin) StopPodSandbox(_ context.Context, pod *api.PodSandbox) 
error { return nil }
func (p *failingPlugin) RemovePodSandbox(_ context.Context, pod 
*api.PodSandbox) error {
   return nil
}

func (p *failingPlugin) CreateContainer(_ context.Context, pod *api.PodSandbox, 
ctr *api.Container) (*api.ContainerAdjustment, []*api.ContainerUpdate, error) {
   return nil, nil, nil
}

func (p *failingPlugin) PostCreateContainer(_ context.Context, pod 
*api.PodSandbox, ctr *api.Container) error {
   return nil
}

func (p *failingPlugin) StartContainer(_ context.Context, pod *api.PodSandbox, 
ctr *api.Container) error {
   return nil
}

func (p *failingPlugin) PostStartContainer(_ context.Context, pod 
*api.PodSandbox, ctr *api.Container) error {
   return nil
}

func (p *failingPlugin) UpdateContainer(_ context.Context, pod *api.PodSandbox, 
ctr *api.Container, r *api.LinuxResources) ([]*api.ContainerUpdate, error) {
   return nil, nil
}

func (p *failingPlugin) PostUpdateContainer(_ context.Context, pod 
*api.PodSandbox, ctr *api.Container) error {
   return nil
}

func (p *failingPlugin) StopContainer(_ context.Context, pod *api.PodSandbox, 
ctr *api.Container) ([]*api.ContainerUpdate, error) {
   return nil, nil
}

func (p *failingPlugin) RemoveContainer(_ context.Context, pod *api.PodSandbox, 
ctr *api.Container) error {
   return nil
}

func (p *failingPlugin) onClose() {
   fmt.Fprintln(os.Stderr, "nri-fail: connection to the runtime lost, exiting")
   os.Exit(0)
}

func main() {
   s, err := stub.New(&failingPlugin{},
      stub.WithPluginName("nri-fail"),
      stub.WithPluginIdx("00"),
      stub.WithOnClose((&failingPlugin{}).onClose),
   )
   if err != nil {
      fmt.Fprintln(os.Stderr, "failed to create NRI stub:", err)
      os.Exit(1)
   }
   if err := s.Run(context.Background()); err != nil {
      fmt.Fprintln(os.Stderr, "NRI plugin exited:", err)
      os.Exit(1)
   }
}
--------


cd ~/nri-fail
go mod tidy
go build -o nri-fail .


________Run the plugin

rm /home/ubuntu/plugin.log

sudo nohup /home/ubuntu/nri-fail/nri-fail > /home/ubuntu/plugin.log 2>&1
&

tail -1 /home/ubuntu/plugin.log
time="2026-10-21T23:03:45Z" level=info msg="Started plugin 00-nri-fail..."


sudo journalctl -u containerd --no-pager | grep "registered as" | tail -1
Oct 21 23:03:45 r8 containerd[6434]: time="2026-10-21T23:03:45.032632847Z" 
level=info msg="plugin \"external:00-nri-fail[6601]\" registered as 
\"00-nri-fail\""


_______Trigger the bug

# Sandbox config with host networking (network: 2)
# so no CNI setup is needed and the request reaches the NRI hook


vi /home/ubuntu/sandbox.json
--------
{
  "metadata": { "name": "nri-leak-test", "namespace": "default", "uid": 
"leak-uid", "attempt": 0 },
  "linux": { "security_context": { "namespace_options": { "network": 2 } } }
}
--------


sudo crictl runp /home/ubuntu/sandbox.json

E1021 23:05:10.393698    6780 remote_runtime.go:325] "RunPodSandbox from 
runtime service failed" err="rpc error: code = Unknown desc = NRI RunPodSandbox 
failed: rpc error: code = Unknown desc = nri-fail: deliberate RunPodSandbox 
failure (containerd issue #13355 repro)"
ERRO[0000] run pod sandbox: rpc error: code = Unknown desc = NRI RunPodSandbox 
failed: rpc error: code = Unknown desc = nri-fail: deliberate RunPodSandbox 
failure (containerd issue #13355 repro) 


_______Check whether cleanup was done properly


grep -oE "pod [0-9a-f]+" /home/ubuntu/plugin.log | tail -1 | awk '{print $2}'
ab1e1e7c265424caff6b4d1e6816bb5ac5ca7633f507d8056b1a1c96fd517491

ID=$(grep -oE "pod [0-9a-f]+" /home/ubuntu/plugin.log | tail -1 | awk
'{print $2}')

ps -ef | grep "$ID" | grep -v grep
<EMPTY !!!!!>
#   containerd-shim-runc-v2 -namespace k8s.io -id <ID> ...          <---- no 
more leaked shim, not anymore

sudo mount | grep "$ID"
<EMPTY>
#   shm     on /run/containerd/io.containerd.grpc.v1.cri/sandboxes/<ID>/shm   
type tmpfs       <-- nothing stuck here
#   overlay on /run/containerd/io.containerd.runtime.v2.task/k8s.io/<ID>/rootfs 
type overlay    <-- nothing stuck here


sudo rm -rf /run/containerd/io.containerd.runtime.v2.task/k8s.io/$ID
<WORKS!!!!>

sudo rm -rf /run/containerd/io.containerd.grpc.v1.cri/sandboxes/$ID
<WORKS!!!!>

sudo -i
cd /
find -name ab1e1e7c265424caff6b4d1e6816bb5ac5ca7633f507d8056b1a1c96fd517491
<EMPTY>


# ___no more these uncleaned directories, not anymre
# ID=ab1e1e7c265424caff6b4d1e6816bb5ac5ca7633f507d8056b1a1c96fd517491
# /var/lib/containerd/io.containerd.grpc.v1.cri/sandboxes/$ID
# /var/lib/containerd/io.containerd.runtime.v2.task/k8s.io/$ID
# /run/containerd/io.containerd.grpc.v1.cri/sandboxes/$ID

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2170996

Title:
  containerd fatal on restart

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/containerd-app/+bug/2170996/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to