Skip to content

Feat/inject missing annot in shim#565

Open
jiwahn wants to merge 3 commits into
urunc-dev:mainfrom
jiwahn:feat/inject-missing-annot-in-shim
Open

Feat/inject missing annot in shim#565
jiwahn wants to merge 3 commits into
urunc-dev:mainfrom
jiwahn:feat/inject-missing-annot-in-shim

Conversation

@jiwahn
Copy link
Copy Markdown
Contributor

@jiwahn jiwahn commented Apr 17, 2026

Description

  • Add pre-processing logic in the urunc shim before TaskService.Create
  • Query containerd for manifest annotations and Config Labels
  • Patch config.json before starting urunc
  • Annotation precedence will be : existing annots in spec > manifest annotations > config labels

Related issues

How was this tested?

  1. Prepare OCI Image with manifest annotationㄴ which starts with com.urnc.unikernel
  2. Run a container
  3. Check config.json if annotations exists
╰─$ sudo ctr content get  sha256:2ec26de37d93716a87c7d8c82f9f78b14a9de69c7f40f318e10b937e16a277f2 | jq
WARN[0000] DEPRECATION: The `mirrors` property of `[plugins."io.containerd.grpc.v1.cri".registry]` is deprecated since containerd v1.5 and will be removed in containerd v2.1. Use `config_path` instead.
WARN[0000] DEPRECATION: The `configs` property of `[plugins."io.containerd.grpc.v1.cri".registry]` is deprecated since containerd v1.5 and will be removed in containerd v2.1. Use `config_path` instead.
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "digest": "sha256:8e44a687f2d52cecc211229a966559e279d6122d46a7d3e1a3e5661f20e016f8",
    "size": 1054
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:7319607d119c259e90382101fb3ed98ad62e29ed817338183b3775dcfb358140",
      "size": 3731518
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:3f1424bd4cc5d97c8f0d56294cc2b4ff75f0224203b7adc26f736e7c3fb1bbe4",
      "size": 321
    }
  ],
  "annotations": {
    "com.docker.official-images.bashbrew.arch": "amd64",
    "com.urunc.unikernel.binary": "/unikernel/nginx",
    "com.urunc.unikernel.hypervisor": "qemu",
    "com.urunc.unikernel.unikernelType": "unikraft",
    "org.opencontainers.image.base.digest": "sha256:b0cb30c51c47cdfde647364301758b14c335dea2fddc9490d4f007d67ecb2538",
    "org.opencontainers.image.base.name": "docker.io/library/alpine:3.20",
    "org.opencontainers.image.created": "2026-01-28T01:18:13Z",
    "org.opencontainers.image.revision": "b3f87708e5052e29737a251b2e9865e182dafe0c",
    "org.opencontainers.image.source": "https://github.com/alpinelinux/docker-alpine.git#b3f87708e5052e29737a251b2e9865e182dafe0c:x86_64",
    "org.opencontainers.image.url": "https://hub.docker.com/_/alpine",
    "org.opencontainers.image.version": "3.20.9"
  }
}
sudo ctr container create   --runtime io.containerd.urunc.v2   localhost:5000/test-urunc-annot:latest   test-urunc
sudo ctr task start test-urunc

LLM usage

GPT-5

Checklist

  • I have read the contribution guide.
  • The linter passes locally (make lint).
  • The e2e tests of at least one tool pass locally (make test_ctr, make test_nerdctl, make test_docker, make test_crictl).
  • If LLMs were used: I have read the llm policy.

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 17, 2026

Deploy Preview for urunc canceled.

Name Link
🔨 Latest commit 120172e
🔍 Latest deploy log https://app.netlify.com/projects/urunc/deploys/6a0c37b078ef2500081291e3

@jiwahn jiwahn force-pushed the feat/inject-missing-annot-in-shim branch 3 times, most recently from d7e4edb to 8057742 Compare April 24, 2026 05:05
@jiwahn jiwahn force-pushed the feat/inject-missing-annot-in-shim branch 2 times, most recently from 06775f9 to 3f10f25 Compare May 15, 2026 02:45
Signed-off-by: Jiwoo Ahn <ikwydls1314@gmail.com>
@jiwahn jiwahn force-pushed the feat/inject-missing-annot-in-shim branch from 3f10f25 to 5c3bbc8 Compare May 15, 2026 04:18
@jiwahn jiwahn marked this pull request as ready for review May 15, 2026 04:21
@jiwahn
Copy link
Copy Markdown
Contributor Author

jiwahn commented May 15, 2026

@cmainas Could you take a look at this and let me know what you think? And I'd like to get ur opinion on how to pass rootfs annotation.

Copy link
Copy Markdown
Contributor

@cmainas cmainas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @jiwahn ,

thank you for the PR. I have added some comments, some to resolve and others to discuss. Another thing is the use of FetchUruncAnnotations as a method for Sessions. I would prefer if we had a setup step in injectMissingAnnotations which fetches all the necessary containerd resources, and creates a struct which we use to fetch the annotations. In that way, the struct can contain only the necessary contianerd resources and nothing else. If I understand correctly the necessary resources are the namespace, contentClient and ctx. Therefore the struct could only contain these resources.

Comment thread pkg/unikontainers/config.go
Comment thread pkg/containerd-shim/task_service.go Outdated
Comment thread pkg/containerd-shim/task_service.go Outdated
Comment thread pkg/containerd-shim/task_service.go Outdated
Comment thread pkg/containerd-shim/containerd/annotations.go Outdated
Comment thread pkg/containerd-shim/containerd/annotations.go Outdated
sidneychang added a commit to sidneychang/urunc that referenced this pull request May 18, 2026
Run ChooseRootfs in the shim Create hook when bundle annotations are
available and persist the result as com.urunc.internal.rootfs.params in
config.json so the runtime can reuse the decision without probing mounts.

Include a temporary urunc-dev#565 annotation inject path (inject_missing_annotations)
until that PR merges. Keep runtime ChooseRootfs as fallback.

Fixes: urunc-dev#684
Signed-off-by: sidneychang <2190206983@qq.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@cmainas
Copy link
Copy Markdown
Contributor

cmainas commented May 18, 2026

Hello @jiwahn ,

I played around a bit with the shim and I found that the Labels field in https://pkg.go.dev/github.com/containerd/containerd/api@v1.11.0/services/containers/v1#Container does contain the config labels in the container (not the annotations though). Here is a diff:

diff --git a/pkg/containerd-shim/containerd/annotations.go b/pkg/containerd-shim/containerd/ann
otations.go
index 410ec4f..c9704b7 100644
--- a/pkg/containerd-shim/containerd/annotations.go
+++ b/pkg/containerd-shim/containerd/annotations.go
@@ -20,7 +20,9 @@ import (
        "fmt"
        "io"
        "strings"
+       "os"
 
+       "github.com/containerd/log"
        contentapi "github.com/containerd/containerd/api/services/content/v1"
        imagesapi "github.com/containerd/containerd/api/services/images/v1"
        typesapi "github.com/containerd/containerd/api/types"
@@ -47,6 +49,16 @@ func (s *Session) FetchUruncAnnotations(ctx context.Context) (map[string]string,
                // Docker-compatible path.
                return nil, fmt.Errorf("container %q has empty image ref", s.GetContainerID())
        }
+       containerLabels, err := json.Marshal(container.Labels)
+       if err != nil {
+               return nil, fmt.Errorf("failes to marshal contianer labels %v: %w", container.Labels, containerdErr(err))
+       }
+       os.WriteFile("/tmp/urunc_annots", containerLabels, 0644)
+       if len(container.Labels) == 0 {
+               log.G(ctx).Errorf("urunclabels do not exist")
+       } else {
+               log.G(ctx).Errorf("urunclabels %v", container.Labels)
+       }
 
        // Look up the image record and resolve its target to a concrete image manifest.
        imageResp, err := s.imagesClient().Get(withNamespace(ctx, s.GetNamespace()), &imagesapi.GetImageRequest{Name: container.Image})

then running a urunc container with sudo nerdctl run --name test --rm -it --runtime io.containerd.urunc.v2 harbor.nbfc.io/nubificus/urunc/net-hvt-mirage:latestI get

$ cat /tmp/urunc_annots 
{"com.urunc.unikernel.binary":"/.boot/kernel","com.urunc.unikernel.cmdline":"-l \"*:debug\"","com.urunc.unikernel.hypervisor":"hvt","com.urunc.unikernel.unikernelType":"mirage","com.urunc.unikernel.useDMBlock":"false","io.containerd.image.config.stop-signal":"SIGTERM","nerdctl/auto-remove":"true","nerdctl/dns":"{\"DNSServers\":null,\"DNSResolvConfOptions\":null,\"DNSSearchDomains\":null}","nerdctl/extraHosts":"[]","nerdctl/host-config":"{\"BlkioWeight\":0,\"CidFile\":\"\",\"Devices\":null}","nerdctl/hostname":"d11264b28b74","nerdctl/ipc":"{\"mode\":\"private\"}","nerdctl/log-config":"{\"driver\":\"json-file\",\"address\":\"/run/containerd/containerd.sock\"}","nerdctl/log-uri":"binary:///usr/local/bin/nerdctl?_NERDCTL_INTERNAL_LOGGING=%2Fvar%2Flib%2Fnerdctl%2F1935db59","nerdctl/name":"test","nerdctl/namespace":"default","nerdctl/networks":"[\"bridge\"]","nerdctl/platform":"linux/amd64","nerdctl/state-dir":"/var/lib/nerdctl/1935db59/containers/default/d11264b28b7423c454ea8faf335821e5c22a4952aee5fdc7cab0cd8a4420612f"}

which includes the labels. I have also seen the labels in k8s setup too:

$ cat /tmp/urunc_annots 
{"com.urunc.unikernel.binary":"/.boot/kernel","com.urunc.unikernel.cmdline":"-l \"*:debug\"","com.urunc.unikernel.hypervisor":"hvt","com.urunc.unikernel.unikernelType":"mirage","com.urunc.unikernel.useDMBlock":"false","io.cri-containerd.kind":"container","io.kubernetes.container.name":"net-mirage-urunc","io.kubernetes.pod.name":"net-mirage-urunc-57586bdbf9-zxsfn","io.kubernetes.pod.namespace":"default","io.kubernetes.pod.uid":"45c46b58-c6c5-45d1-b75d-8c51b3829386"}

So, maybe that could be a way to retrieve the labels. Further testing is necessary though.

Comment thread pkg/containerd-shim/task_service.go Outdated
sidneychang added a commit to sidneychang/urunc that referenced this pull request May 18, 2026
…nc-dev#565)

Merge com.urunc.unikernel.* keys from the container image into bundle
config.json when the OCI spec is missing them, using a containerd session
before task create.

Signed-off-by: sidneychang <2190206983@qq.com>
sidneychang added a commit to sidneychang/urunc that referenced this pull request May 18, 2026
…nc-dev#565)

Merge com.urunc.unikernel.* keys from the container image into bundle
config.json when the OCI spec is missing them, using a containerd session
before task create.

Signed-off-by: sidneychang <2190206983@qq.com>
@jiwahn
Copy link
Copy Markdown
Contributor Author

jiwahn commented May 19, 2026

Hey @cmainas and @sidneychang, I tried to resolve above comments. Please take a look at it again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate unreachable image annotations

3 participants