December 8, 2020·6 min read·engineeringkubernetescriruntimesreleases

Kubernetes 1.20 deprecates its Docker runtime adapter

Dockershim deprecation concerns the kubelet's integration with Docker Engine, while OCI container images remain usable. Kubernetes 1.20 also stabilizes volume snapshots and changes exec probe timeout enforcement.

Kubernetes has two different agreements with container software. One describes the image that contains an application. The other describes how the kubelet asks a runtime to start and manage that application. Kubernetes 1.20 deprecates dockershim, its adapter for Docker's runtime integration. That change concerns the second agreement. The release explicitly states that Docker-produced images continue to work with CRI-compliant runtimes because they follow the OCI image specification.

The December 8 release announcement describes deprecation now and removal in a future release. Docker support does not disappear from 1.20 on release day. Operators have a planning task concerning the runtime on their nodes, while application authors retain the image format described by the announcement.

I value Kubernetes' separation between desired state and the components that implement it. A runtime interface is part of making that separation practical. The kubelet needs an implementation that can carry out container operations, and retaining a special adapter inside Kubernetes has an ongoing maintenance cost.

CRI established a runtime boundary

The project's December 2016 introduction to CRI explains the original problem. Docker and rkt had been integrated deeply into the kubelet through an internal interface that changed over time. Supporting a new runtime required understanding kubelet internals and maintaining that coupling. CRI supplied a defined protocol between the kubelet and a runtime implementation.

That historical design used protocol buffers and gRPC over Unix sockets, with kubelet as the client. ImageService supplied operations for pulling, inspecting, and removing images. RuntimeService supplied pod sandbox and container lifecycle operations, together with interfaces for interacting with running containers. These are execution responsibilities, distinct from the build tool used to create an image.

The original account also explains why CRI uses imperative container operations underneath a declarative Kubernetes API. Giving each runtime the entire Pod object and asking it to reconcile independently would duplicate kubelet behavior. Features such as restart backoff and init-container handling would become responsibilities every runtime had to reproduce.

Instead, kubelet retains that orchestration and calls runtime operations as needed. The desired-state loop remains in kubelet, while the runtime supplies execution mechanisms. This gives the current deprecation its architectural context. Kubernetes can preserve its pod model while changing which runtime implementation receives those operations.

An image does not require the Docker adapter

The 1.20 announcement describes dockershim as the CRI shim for Docker. Its deprecation does not change the stated compatibility of Docker-produced OCI images with CRI-compliant runtimes. The distinction lets teams reason separately about building application artifacts and selecting node execution software.

An image reference in a workload identifies an artifact to run. It does not declare that the node must use dockershim. The kubelet's configured runtime supplies the operations that pull and execute the artifact. A runtime migration therefore concerns node configuration and integration, even when the application manifest keeps the same image reference.

This does not establish that every workflow surrounding a node runtime is automatically portable. It establishes the compatibility claim the release actually makes about images. Any additional dependency on a particular runtime needs its own assessment. Treating image compatibility as proof about every operational integration would extend the announcement beyond its scope.

The deprecation gives operators a reason to identify which runtime their nodes use before removal occurs. It also gives maintainers a defined direction for the integration boundary. The release does not require rewriting an application simply because its artifact was built with Docker.

Snapshots need installed components

Volume snapshot operations become stable in the same release. The announcement describes a standard way to request snapshots across Kubernetes environments with supporting storage providers. That standard API can support more elaborate storage administration, including backup systems. The mechanism still needs an implementation supplied by the cluster and its storage integration.

The release lists the required pieces explicitly. A distributor needs to bundle the snapshot controller, snapshot CustomResourceDefinitions, and validation webhook. The cluster also needs a CSI driver that implements snapshot functionality. Installing Kubernetes 1.20 alone does not establish that every volume in a cluster can be snapshotted.

This is another useful example of the API and implementation relationship. A common request format makes clients more portable, but the chosen storage driver determines whether it can carry out the operation. The controller and validation components provide the Kubernetes-side machinery around that implementation.

I prefer to read a stable feature alongside its installation requirements. In this case, stability gives users a supported snapshot operation model. It does not remove the distributor's responsibility to provide the components or the driver's responsibility to support the storage action. Those are concrete dependencies a backup integration has to account for.

Exec probes now honor their deadlines

The exec probe timeout correction is immediately relevant to existing pod definitions. Before the fix, timeoutSeconds did not bound exec probes as intended. The announcement says a probe could continue indefinitely until it returned a result. In 1.20 the timeout is enforced, including the default of one second when the field is omitted.

That means an unchanged probe can behave differently after the upgrade. A command that needs more than one second may previously have completed because the implementation ignored the configured limit. Its prior success did not prove that it met the intended deadline. Correct enforcement can now expose that mismatch.

A probe fragment can state the time budget explicitly. This example assumes the image contains an executable health command at the given path and that the chosen budget fits that command's intended behavior.

livenessProbe:
  exec:
    command:
      - /app/healthcheck
  timeoutSeconds: 5

The value is illustrative, not a universal recommendation for health checks. Its purpose is to make the intended deadline visible instead of relying on omission and the one-second default. Choosing it requires understanding what the probe checks and how long that operation is allowed to take.

The release includes an ExecProbeTimeout feature gate that can restore the old behavior when set to false. It presents that as a temporary compatibility option and says the gate will be locked and removed in a later release. The supported direction is to have probes obey their specified timeout, with pod definitions that accurately express the required budget.

Debugging maturity differs from container maturity

The kubectl alpha debug command graduates to beta as kubectl debug. Its documented workflows include creating a copy of a crashing pod with a different image or command. It can also create a node debugging container using host namespaces and access to the host filesystem.

Debugging a minimal image has more than one supported route. The command can add diagnostic tooling in a copied pod, or use an ephemeral container in the existing pod. Ephemeral containers remain alpha and are not enabled by default, as the announcement explicitly states. The command's beta status therefore does not promote every underlying mechanism to beta.

There is also a command-resolution consequence. The new built-in kubectl debug takes precedence over a plugin named debug, so affected plugins need another name. Existing kubectl alpha debug invocations become deprecated. Scripts and operator tooling need to distinguish that command change from the maturity of the particular debugging workflow they invoke.

Node resources and shutdown gain controls

Process ID limits become generally available after a year enabled by default. The announcement explains why CPU and memory limits are insufficient to address PID exhaustion. Pods can consume the host's available tasks before reaching those other resource limits, affecting the runtime and kubelet as well as neighboring workloads.

Graceful node shutdown enters alpha. Its purpose is to make kubelet aware of a system shutdown so pods can receive graceful termination. This addresses a different node failure mode from runtime adapter deprecation, and its alpha status calls for a different expectation of maturity. Kubernetes 1.20 combines these changes with stable and beta mechanisms, each with its own prerequisites and scope.

API Priority and Fairness is another beta mechanism, enabled by default in this release after its introduction in 1.18. It lets the API server categorize incoming requests by priority level. This changes request handling in the control plane, separate from the node-side resource limits and lifecycle behavior. The release therefore includes controls at both locations, with different subjects and enforcement components.

For an operator planning this release, the exec probe change can alter behavior immediately, while dockershim deprecation starts a runtime migration horizon. Snapshot stability requires installed snapshot machinery and driver support. Those distinctions identify which changes affect existing workloads on upgrade and which require an additional configuration or infrastructure decision to take effect.