diff --git a/RELEASES.md b/RELEASES.md index 32c52e936..3f008679a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -396,18 +396,20 @@ against total impact. The deprecated features are shown in the following table: -| Component | Deprecation release | Target release for removal | Recommendation | -|----------------------------------------------------------------------------------|---------------------|----------------------------|------------------------------------------| -| Runtime V1 API and implementation (`io.containerd.runtime.v1.linux`) | containerd v1.4 | containerd v2.0 ✅ | Use `io.containerd.runc.v2` | -| Runc V1 implementation of Runtime V2 (`io.containerd.runc.v1`) | containerd v1.4 | containerd v2.0 ✅ | Use `io.containerd.runc.v2` | -| Built-in `aufs` snapshotter | containerd v1.5 | containerd v2.0 ✅ | Use `overlayfs` snapshotter | -| Container label `containerd.io/restart.logpath` | containerd v1.5 | containerd v2.0 ✅ | Use `containerd.io/restart.loguri` label | -| `cri-containerd-*.tar.gz` release bundles | containerd v1.6 | containerd v2.0 ✅ | Use `containerd-*.tar.gz` bundles | -| Pulling Schema 1 images (`application/vnd.docker.distribution.manifest.v1+json`) | containerd v1.7 | containerd v2.0 | Use Schema 2 or OCI images | -| CRI `v1alpha2` | containerd v1.7 | containerd v2.0 ✅ | Use CRI `v1` | -| Legacy CRI implementation of podsandbox support | containerd v2.0 | containerd v2.0 ✅ | | -| Go-Plugin library (`*.so`) as containerd runtime plugin | containerd v2.0 | containerd v2.1 | Use external plugins (proxy or binary) | +| Component | Deprecation release | Target release for removal | Recommendation | +|----------------------------------------------------------------------------------|---------------------|---------------------------------------|------------------------------------------| +| Runtime V1 API and implementation (`io.containerd.runtime.v1.linux`) | containerd v1.4 | containerd v2.0 ✅ | Use `io.containerd.runc.v2` | +| Runc V1 implementation of Runtime V2 (`io.containerd.runc.v1`) | containerd v1.4 | containerd v2.0 ✅ | Use `io.containerd.runc.v2` | +| Built-in `aufs` snapshotter | containerd v1.5 | containerd v2.0 ✅ | Use `overlayfs` snapshotter | +| Container label `containerd.io/restart.logpath` | containerd v1.5 | containerd v2.0 ✅ | Use `containerd.io/restart.loguri` label | +| `cri-containerd-*.tar.gz` release bundles | containerd v1.6 | containerd v2.0 ✅ | Use `containerd-*.tar.gz` bundles | +| Pulling Schema 1 images (`application/vnd.docker.distribution.manifest.v1+json`) | containerd v1.7 | containerd v2.1 (Disabled in v2.0 ✅) | Use Schema 2 or OCI images | +| CRI `v1alpha2` | containerd v1.7 | containerd v2.0 ✅ | Use CRI `v1` | +| Legacy CRI implementation of podsandbox support | containerd v2.0 | containerd v2.0 ✅ | | +| Go-Plugin library (`*.so`) as containerd runtime plugin | containerd v2.0 | containerd v2.1 | Use external plugins (proxy or binary) | +- Pulling Schema 1 images has been disabled in containerd v2.0, but it still can be enabled by setting an environment variable `CONTAINERD_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE=1` + until containerd v2.1. `ctr` users have to specify `--local` too (e.g., `ctr images pull --local`). ### Deprecated config properties The deprecated properties in [`config.toml`](./docs/cri/config.md) are shown in the following table: diff --git a/client/pull.go b/client/pull.go index 6908fee9c..060c729df 100644 --- a/client/pull.go +++ b/client/pull.go @@ -197,7 +197,10 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim ) if desc.MediaType == images.MediaTypeDockerSchema1Manifest && rCtx.ConvertSchema1 { - schema1Converter := schema1.NewConverter(store, fetcher) + schema1Converter, err := schema1.NewConverter(store, fetcher) + if err != nil { + return images.Image{}, fmt.Errorf("failed to get converter for %q: %w", ref, err) + } handler = images.Handlers(append(rCtx.BaseHandlers, schema1Converter)...) diff --git a/core/remotes/docker/schema1/converter.go b/core/remotes/docker/schema1/converter.go index e8a3534dd..e724e4e55 100644 --- a/core/remotes/docker/schema1/converter.go +++ b/core/remotes/docker/schema1/converter.go @@ -27,6 +27,7 @@ import ( "errors" "fmt" "io" + "os" "strconv" "strings" "sync" @@ -36,6 +37,7 @@ import ( "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/containerd/v2/pkg/archive/compression" + "github.com/containerd/containerd/v2/pkg/deprecation" "github.com/containerd/containerd/v2/pkg/labels" "github.com/containerd/errdefs" "github.com/containerd/log" @@ -67,14 +69,30 @@ type Converter struct { layerBlobs map[digest.Digest]ocispec.Descriptor } +var ErrDisabled = fmt.Errorf("Pulling Schema 1 images have been deprecated and disabled by default since containerd v2.0. "+ + "As a workaround you may set an environment variable `%s=1`, but this will be completely removed in containerd v2.1.", + deprecation.EnvPullSchema1Image) + // NewConverter returns a new converter -func NewConverter(contentStore content.Store, fetcher remotes.Fetcher) *Converter { +func NewConverter(contentStore content.Store, fetcher remotes.Fetcher) (*Converter, error) { + s := os.Getenv(deprecation.EnvPullSchema1Image) + if s == "" { + return nil, ErrDisabled + } + enable, err := strconv.ParseBool(s) + if err != nil { + return nil, fmt.Errorf("failed to parse `%s=%s`: %w", deprecation.EnvPullSchema1Image, s, err) + } + if !enable { + return nil, ErrDisabled + } + log.L.Warn(ErrDisabled) return &Converter{ contentStore: contentStore, fetcher: fetcher, blobMap: map[digest.Digest]blobState{}, layerBlobs: map[digest.Digest]ocispec.Descriptor{}, - } + }, nil } // Handle fetching descriptors for a docker media type diff --git a/integration/client/client_test.go b/integration/client/client_test.go index 691d07c7a..7e0fb208c 100644 --- a/integration/client/client_test.go +++ b/integration/client/client_test.go @@ -40,6 +40,7 @@ import ( "github.com/containerd/containerd/v2/defaults" imagelist "github.com/containerd/containerd/v2/integration/images" "github.com/containerd/containerd/v2/internal/testutil" + "github.com/containerd/containerd/v2/pkg/deprecation" "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/errdefs" "github.com/containerd/log" @@ -422,6 +423,7 @@ func TestImagePullSomePlatforms(t *testing.T) { } func TestImagePullSchema1(t *testing.T) { + t.Setenv(deprecation.EnvPullSchema1Image, "1") client, err := newClient(t, address) if err != nil { t.Fatal(err) diff --git a/integration/client/client_unix_test.go b/integration/client/client_unix_test.go index 59bea46a2..44c81ecce 100644 --- a/integration/client/client_unix_test.go +++ b/integration/client/client_unix_test.go @@ -23,6 +23,7 @@ import ( . "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/integration/images" + "github.com/containerd/containerd/v2/pkg/deprecation" "github.com/containerd/platforms" ) @@ -46,6 +47,7 @@ var ( ) func TestImagePullSchema1WithEmptyLayers(t *testing.T) { + t.Setenv(deprecation.EnvPullSchema1Image, "1") client, err := newClient(t, address) if err != nil { t.Fatal(err) diff --git a/integration/containerd_image_test.go b/integration/containerd_image_test.go index f56c0820a..af16e602d 100644 --- a/integration/containerd_image_test.go +++ b/integration/containerd_image_test.go @@ -28,6 +28,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/integration/images" "github.com/containerd/containerd/v2/internal/cri/labels" + "github.com/containerd/containerd/v2/pkg/deprecation" "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/errdefs" "github.com/stretchr/testify/assert" @@ -267,6 +268,7 @@ func TestContainerdSandboxImagePulledOutsideCRI(t *testing.T) { } func TestContainerdImageWithDockerSchema1(t *testing.T) { + t.Setenv(deprecation.EnvPullSchema1Image, "1") if goruntime.GOOS == "windows" { t.Skip("Skipped on Windows because the test image is not a multi-platform one.") } diff --git a/pkg/deprecation/deprecation.go b/pkg/deprecation/deprecation.go index 9b85e2d0b..64723a7b2 100644 --- a/pkg/deprecation/deprecation.go +++ b/pkg/deprecation/deprecation.go @@ -33,8 +33,13 @@ const ( CRIRegistryConfigs Warning = Prefix + "cri-registry-configs" ) +const ( + EnvPrefix = "CONTAINERD_ENABLE_DEPRECATED_" + EnvPullSchema1Image = EnvPrefix + "PULL_SCHEMA_1_IMAGE" +) + var messages = map[Warning]string{ - PullSchema1Image: "Schema 1 images are deprecated since containerd v1.7 and removed in containerd v2.0. " + + PullSchema1Image: "Schema 1 images are deprecated since containerd v1.7, disabled in containerd v2.0, and will be removed in containerd v2.1. " + `Since containerd v1.7.8, schema 1 images are identified by the "io.containerd.image/converted-docker-schema1" label.`, GoPluginLibrary: "Dynamically-linked Go plugins as containerd runtimes are deprecated since containerd v2.0 and removed in containerd v2.1.", CRIRegistryMirrors: "The `mirrors` property of `[plugins.\"io.containerd.grpc.v1.cri\".registry]` is deprecated since containerd v1.5 and will be removed in containerd v2.0." +