Skip to content

Add os.features support for EROFS native container images#13091

Merged
fuweid merged 5 commits intocontainerd:mainfrom
erofs:os_features
Apr 1, 2026
Merged

Add os.features support for EROFS native container images#13091
fuweid merged 5 commits intocontainerd:mainfrom
erofs:os_features

Conversation

@hsiangkao
Copy link
Copy Markdown
Member

@hsiangkao hsiangkao commented Mar 23, 2026

depends on #13080
supercedes #12784

Note that users still need to explicitly specify the EROFS snapshotter in order to run the EROFS native images by design; it only improves the user experence of the unpacking process

First, it enhances the transfer service: If no snapshotter is specified and os.features contains "erofs", unpacking should use the EROFS snapshotter and differ.

Second, if no snapshotter is specified, container run selects the default snapshotter. However, if os.features is set, we should always call checkSnapshotterSupport() so that containerd clients can report a clear error instead of the confusing layer extraction error out of overlayfs snapshotter.

Tested by the ubuntu-22.04 multi-manifest image ("linux/amd64" and "linux(+erofs)/amd64"):
ctr i pull --platform="linux(+erofs)" docker.io/hsiangkao/ubuntu:22.04-platforms
and
ctr run --platform="linux(+erofs)/amd64" --tty docker.io/hsiangkao/ubuntu:22.04-platforms test
and
ctr run --platform="linux(+erofs)/amd64" --snapshotter erofs --tty docker.io/hsiangkao/ubuntu:22.04-platforms test

Screenshot (docker.1ms.run is a connectable mirror of docker.io):
image

Add os.features support for EROFS native container images

Comment thread plugins/transfer/plugin.go Outdated
@dmcgowan dmcgowan added this to the 2.3 milestone Mar 23, 2026
@dmcgowan dmcgowan moved this from Needs Triage to Needs Reviewers in Pull Request Review Mar 23, 2026
Comment thread client/image.go
}

if err := i.checkSnapshotterSupport(ctx, snapshotterName, manifest,
config.CheckPlatformSupported); err != nil {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It might be worth adding a note on UnpackConfig that containerd always checks snapshotter support if the image platform requires specific OSFeatures.

@Kern--
Copy link
Copy Markdown

Kern-- commented Mar 23, 2026

After thinking about this a bit more - this makes OSFeatures equivalent to "SnapshotterFeatures", doesn't it? Is there a use-case where an image would require a non-default/non-standard feature that the snapshotters wouldn't know or care about?

// Use EROFS snapshotter to extract EROFS native images
func erofsPlatformSpec() specs.Platform {
p := platforms.DefaultSpec()
p.OSFeatures = []string{"erofs"}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This was previously discussed in some OCI calls. The possible values for this field are not fully defined and its up to us as a runtime and user of the spec to experiment, validate, and propose changes to the spec. That won't happen unless there is successful adoption using this field.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hi @AkihiroSuda , as @dmcgowan said, yes and it's always a chicken-and-egg issue, but this PR is useful for user experence and multiple manifest images (e.g. one for OCI & one for erofs) for image publishers.

@hsiangkao
Copy link
Copy Markdown
Member Author

hsiangkao commented Mar 23, 2026

After thinking about this a bit more - this makes OSFeatures equivalent to "SnapshotterFeatures", doesn't it? Is there a use-case where an image would require a non-default/non-standard feature that the snapshotters wouldn't know or care about?

@Kern-- I think it might have, but currently we only have one (+erofs) for now; I think eventually we should differ from snapshotter features and other features.
But first any of this should be known by the containerd itself, or we should just refuse to pull/mount unknown features since they could be incompatible and unsupported by this os (for example gpu but without any gpu; all unknown features should be refused since all features should be considered as incompatible, including unknown features); so for now it doesn't matter; and yeah, I don't think we should accept arbitary os.features now.
Anyway, we could define another set of compatible os.features too in the future, but should with another format or prefix for example, and they should be filtered out and identified in other ways instead.

@dmcgowan should we define some prefix which should be considered as incompatible features now, and ignore the random os.features without any prefixes in platforms. I'm not sure if the current users already keep garbage data in os.features now, so we need to add some customized os.feature prefix to identify our concerned features in platforms, otherwise it might cause regressions that the previous images with garbaged os.feature refuse to mount by the new version.

@dmcgowan
Copy link
Copy Markdown
Member

After thinking about this a bit more - this makes OSFeatures equivalent to "SnapshotterFeatures", doesn't it? Is there a use-case where an image would require a non-default/non-standard feature that the snapshotters wouldn't know or care about?

Its more an image defines what it needs, the unpack configuration defines what the snapshotter provides. The feature could be provided by something other than a snapshotter, that is just the initial use case. Ultimately, it is the unpacker that has to make the decision about what is the best matching image for the current runtime configuration.

should we define some prefix which should be considered as incompatible features now

I don't think that is necessary right now, the feature is unambiguous and unlikely that the number of supported features would increase drastically.

@dmcgowan
Copy link
Copy Markdown
Member

@hsiangkao the previous PR was merged, can you rebase

@hsiangkao
Copy link
Copy Markdown
Member Author

@hsiangkao the previous PR was merged, can you rebase

done, thanks for reminder.

@Kern--
Copy link
Copy Markdown

Kern-- commented Mar 24, 2026

Its more an image defines what it needs, the unpack configuration defines what the snapshotter provides. The feature could be provided by something other than a snapshotter, that is just the initial use case. Ultimately, it is the unpacker that has to make the decision about what is the best matching image for the current runtime configuration.

This makes sense, but this current implementation requires snapshotters to be aware of every feature or it will be rejected by default. I suppose this would fail loudly and could be addressed in the future once there's a use case.

@hsiangkao
Copy link
Copy Markdown
Member Author

Its more an image defines what it needs, the unpack configuration defines what the snapshotter provides. The feature could be provided by something other than a snapshotter, that is just the initial use case. Ultimately, it is the unpacker that has to make the decision about what is the best matching image for the current runtime configuration.

This makes sense, but this current implementation requires snapshotters to be aware of every feature or it will be rejected by default. I suppose this would fail loudly and could be addressed in the future once there's a use case.

yes, I think if there is another non-snapshotter feature, we could address it then; no real difference for now.

@cpuguy83
Copy link
Copy Markdown
Member

Is this expected?
In this case it fetched both manifests (and configs).
It also failed to unpack, I'm guessing because it tried to use overlay?

❯ ctr images pull --platform="linux(+erofs)/amd64" docker.io/hsiangkao/ubuntu:22.04-platforms
docker.io/hsiangkao/ubuntu:22.04 platfor        fetching image content
└──index (eaee1eccf13b)                         complete        |++++++++++++++++++++++++++++++++++++++|
docker.io/hsiangkao/ubuntu:22.04 platfor        fetching image content
└──index (eaee1eccf13b)                         complete        |++++++++++++++++++++++++++++++++++++++|
   ├──manifest (06ae2788312e)                   complete        |++++++++++++++++++++++++++++++++++++++|
   │  ├──config (d46432b67d0a)                  complete        |++++++++++++++++++++++++++++++++++++++|
   │  └──layer (4d7f4447d249)                   extracting      |--------------------------------------|           0.0 B/43.2 MiB
   └──manifest (1c4cc37c10c4)                   complete        |++++++++++++++++++++++++++++++++++++++|
      └──config (9fa3e2b5204f)                  complete        |++++++++++++++++++++++++++++++++++++++|
application/vnd.oci.image.index.v1+json sha256:eaee1eccf13bc5234a49d439ef25b4664e7f653330b3837501db36476fbd1bbc                                                                               Pulling from OCI Registry (docker.io/hsiangkao/ubuntu:22.04-platforms)  elapsed: 2.2 s  total:  5.8 Ki  (2.6 KiB/s)
ctr: failed to extract layer (application/vnd.erofs.layer.v1 sha256:4d7f4447d249df0fee2efde9eada7e305cd2bb5f06758338fd19ba8e37edc1a7) to overlayfs as "extract-371010066-gzXq sha256:4d7f4447d249df0fee2efde9eada7e305cd2bb5f06758338fd19ba8e37edc1a7": failed to get stream processor for application/vnd.erofs.layer.v1: no processor for media-type

If no snapshotter is specified and `os.features` contains "erofs",
unpacking should use the EROFS snapshotter and differ.

This enhances the usability of native EROFS container images.

Signed-off-by: Gao Xiang <[email protected]>
Just use apitypes.OCIPlatformFromProto().

Suggested-by: Jin Dong <[email protected]>
Signed-off-by: Gao Xiang <[email protected]>
…e` is set

If no snapshotter is specified, container run selects the default
snapshotter.

However, if `os.features` is set, we should always call
`checkSnapshotterSupport()`.  This ensures containerd clients
report a clear error:

```
ctr: snapshotter overlayfs does not support platform
{amd64 linux  [erofs] } for image sha256:[]
```

instead of the confusing layer extraction error:

```
ctr: apply layer error for "": failed to extract layer sha256:[]:
failed to get stream processor for application/vnd.erofs.layer.v1:
no processor for media-type
```

Signed-off-by: Gao Xiang <[email protected]>
@hsiangkao
Copy link
Copy Markdown
Member Author

Is this expected? In this case it fetched both manifests (and configs). It also failed to unpack, I'm guessing because it tried to use overlay?

Now fixed as using platforms.OnlyOS() and it works.

@hsiangkao
Copy link
Copy Markdown
Member Author

@dmcgowan @fuweid @cpuguy83 could help review this again? thanks!

@github-project-automation github-project-automation Bot moved this from Needs Reviewers to Review In Progress in Pull Request Review Apr 1, 2026
@cpuguy83
Copy link
Copy Markdown
Member

cpuguy83 commented Apr 1, 2026

Do we know why the release CI triggered?

@hsiangkao
Copy link
Copy Markdown
Member Author

Do we know why the release CI triggered?

... Just random flakiness, retry again.

@hsiangkao
Copy link
Copy Markdown
Member Author

@containerd/committers could we get it merged? It's useful for end users.

@fuweid fuweid added this pull request to the merge queue Apr 1, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Apr 1, 2026
@fuweid fuweid added this pull request to the merge queue Apr 1, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Apr 1, 2026
@fuweid fuweid added this pull request to the merge queue Apr 1, 2026
Merged via the queue into containerd:main with commit 1f0b0c4 Apr 1, 2026
57 of 63 checks passed
@github-project-automation github-project-automation Bot moved this from Review In Progress to Done in Pull Request Review Apr 1, 2026
@hsiangkao hsiangkao deleted the os_features branch April 2, 2026 00:51
@hsiangkao hsiangkao mentioned this pull request Apr 8, 2026
10 tasks
@samuelkarp samuelkarp removed the area/snapshotters Snapshotters label Apr 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

10 participants