Skip to content

Move core to containerd/v2 2.3 LTS by March 2027 (node containerd floor decision; unblocks containerd/api v1.11.1) #66

Description

Summary

core/ links github.com/containerd/containerd/v2 v2.2.7 (chosen in #64 over v2.3.4). This issue tracks moving to containerd 2.3 LTS, which is gated on raising the minimum supported node containerd version.

Retargeted from "2.3.x" to "2.3 LTS", with a hard deadline added. The original framing treated this as an open-ended "move when AKS and EKS catch up." Upstream's RELEASES.md support horizons make it time-bound: the compatible fallback path expires in March 2027, after which this move is forced regardless of what AKS and EKS ship.

Why the target is 2.3, and why 2.4 must be skipped

Release Status End of Life
2.0 LTS (extended) March 2027
2.1 End of Life July 3, 2026
2.2 — linked today Active (regular) November 6, 2026
2.3 — target LTS April 30, 2028
2.4 Future April 26, 2027 (tentative)

2.3 is the LTS line. 2.4 is a regular 8-month release whose EOL (Apr 2027) lands a year before 2.3's, so bumping to 2.4 when it lands would be strictly worse than 2.3 and should not be treated as a future target. Since containerd 2.3 (April 2026) minor releases follow a 4-month cadence with one LTS per year — so the next LTS after 2.3 is roughly a year out.

The blocker: bootstrap handshake format

A shim linked against 2.3.x cannot talk to a daemon older than 2.3. The shim writes its bootstrap params to stdout in a format the daemon parses:

Linked version pkg/shim/shim.go writes
v2.0.10 json.Marshal(&params)
v2.1.6 json.Marshal(&params)
v2.2.7 json.Marshal(&params) (shim.go:295)
v2.3.4 proto.Marshal(result) (shim.go:312)

Against the provisioner's containerd 2.0.5, a v2.3.4-linked shim fails at startup before any task service is reached:

failed to start shim: start failed: failed to create TTRPC connection:
unsupported protocol: ^H^C^RYunix

Those are protobuf wire bytes (\x08\x03 = Version 3, \x12\x59 = 89-byte string, then unix://...) being read as JSON. This surfaced as E2E tier 08/09/12/14/15 failures.

There is no supported way to build a v2.3.4-linked shim that emits legacy JSON. The shim-side compat layer (pkg/shim/compat.go, readBootstrapParamsFromDeprecatedFields) is input-only; the stdout write is unconditional.

The v2.3.4 daemon does accept legacy JSON, via an explicit fallback in core/runtime/v2/shim.go:236-245:

// Fallback to legacy parsing for backward compatibility with legacy shims that return the address as a plain string or JSON.

So daemon coverage is a strict superset in one direction, and staying on 2.2.7 remains correct today:

Shim linked against Runs on daemon
v2.2.7 (JSON) 2.0, 2.1, 2.2, and 2.3+
v2.3.4 (protobuf) 2.3+ only

The deadline this issue previously missed

Every JSON-emitting line is on its way out. After Nov 6, 2026 (2.2 EOL), the only supported JSON-emitting line is 2.0 LTS, and that ends March 2027.

now ──────── Nov 6 2026 ──────── Mar 2027 ──────── Apr 30 2028
 2.2.7 OK    2.2 EOL             2.0 LTS EOL       2.3 LTS EOL
             only 2.0 LTS        no supported
             still JSON          JSON line left
                                 → 2.3 forced

Continuing to link an EOL containerd means no upstream security backports for pkg/shim and the runc task service we embed. So the choice is not "move when convenient" — it is move to 2.3 LTS by March 2027, or knowingly ship an unsupported containerd library.

Note also that falling back to 2.0 LTS between Nov 2026 and Mar 2027 would mean regressing containerd/api v1.10.0 → v1.8.0 and is a dead end four months later. It is not a recommended path; it is listed only to show the fallback is exhausted.

Node-image situation (the original blocker, now self-clearing)

Platform containerd Upstream status 2.3-linked shim?
AKS Ubuntu 24.04 (node image 202601.27.0) 2.1.6 already EOL (Jul 3, 2026) ❌
EKS AL2023 (release v20260827) 2.2.5 EOL Nov 6, 2026 ❌
Ubuntu 22.04 / 24.04 distro package 2.2.1 EOL Nov 6, 2026 ❌
Brewlet provisioner (provisioner/Dockerfile:21) 2.0.5 LTS to Mar 2027 ❌
kind node base image 2.3.4 LTS to Apr 2028 ✅

Both managed offerings are running containerd that is already EOL or EOL within two months. They are being forced forward on roughly the same clock we are, and 2.3 LTS (supported to Apr 2028) is the natural landing spot for both. The blocker is likely to clear itself well before March 2027 — but the deadline holds either way.

Knock-on: containerd/api stays at v1.10.0

Each containerd line pins its own api: 2.0.10 → v1.8.0, 2.1.6 → v1.9.0, 2.2.7 → v1.10.0, 2.3.4 → v1.11.1.

Dependabot PR #51 originally tried to take api to v1.11.1; it was merged with an explicit pin to v1.10.0 because v1.11.1 was incompatible with the then-current containerd v1.7.34. #64 removed that manual pin (resolution is now driven by the containerd module), but the effective version is still v1.10.0. Reaching api v1.11.1 requires the 2.3 move, and therefore this same node-floor decision.

Expect Dependabot to keep proposing containerd/api v1.11.x until then; close those with a reference to this issue rather than merging.

Decision triggers

Move to containerd/v2 2.3.x when the earliest of these occurs:

  1. AKS and EKS default node images ship containerd 2.3+ — the clean path; recheck at the Nov 2026 checkpoint below.
  2. March 2027 — hard deadline. 2.0 LTS goes EOL and no supported JSON-emitting line remains. Move regardless of node images, accepting the floor raise.
  3. A deliberate earlier decision to raise Brewlet's documented minimum node containerd to 2.3+.

Checkpoint: November 2026. Re-read AKS and EKS node image release notes when 2.2 goes EOL and re-evaluate. Do not bump to 2.4 in the meantime (see above).

Work required when it happens

  • Bump core/go.mod to containerd/v2 v2.3.x and let api resolve to v1.11.1. The Go floor becomes 1.26.3; core/go.mod:3 currently declares go 1.26 and is the go-version-file for the ci, e2e and release workflows, which also build kubernetes/ (go 1.26.0) — raise deliberately and check GOTOOLCHAIN: local still resolves.
  • Raise CONTAINERD_VERSION in provisioner/Dockerfile:21 (currently 2.0.5).
  • Update the version gate in provisioner/entrypoint.sh (require_containerd_image_identity, die at line 427) and its test in provisioner/entrypoint_test.sh.
  • Update the 2.0+ prose in specs/SPECIFICATION.md:638, docs/installation.md:27, docs/troubleshooting.md, provisioner/README.md:13.
  • Re-verify E2E tiers 08, 09, 12, 14, 15 — the ones that caught this.

Original context: filed as follow-up to #64. Module-level version facts verified against upstream tags v2.0.10 / v2.1.6 / v2.2.2 / v2.2.7 / v2.3.4 on 2026-09-04. Support horizons and cadence re-verified against upstream RELEASES.md, and repository line references re-verified against main, on 2026-09-07.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    dependenciesPull requests that update a dependency filegoPull requests that update go code

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions