Remove the need for a coordinated switch
Docker Hub pricing changes prompted a review of our dependency on the service. Hundreds of image references had accumulated across cluster manifests, CI, and developer workflows. Updating them all at once would have required coordination across many teams.
I proposed and implemented a migration that separated traffic redirection from source cleanup. Workloads could begin pulling through our registry before their owners changed the manifests.
Put a compatibility layer in front of the migration
I created pull-through cache repositories in AWS ECR for Docker Hub, then extended the pattern to other public registries. Credentials were managed centrally, lifecycle rules controlled cache growth, and organization-wide read access made the mirrors available to consumers.
Next I introduced Kyverno mutation policies that rewrite image references when Kubernetes admits a workload. A manifest can still name a Docker Hub image while the admitted pod uses the equivalent mirror path.
I rolled the policies out one namespace at a time. Teams continued deploying while image pulls moved through the mirror, which was serving hundreds of images within weeks. The cache configuration and rewrite policy are documented separately.
The mirror serves cached content from our cloud account. Cache fills and refreshes still depend on the upstream registry, so this reduces direct dependency on Docker Hub during routine pulls without making upstream availability irrelevant.
Finish the source migration without removing compatibility
Once the mirror was handling traffic, I updated the manifests in a focused sweep. The rewrite policy remained enabled to catch references that had been missed or were introduced later.
A year and a half later, the migration no longer needed its original explanatory note, so I removed that rationale from the policy document. The rule itself stayed: it continued to enforce the preferred registry path.
What changed
The Docker Hub subscription was cancelled. Image distribution gained centralized credentials and cache lifecycle rules, while Kubernetes workloads moved without a coordinated deployment freeze. The mirror layer also provided a distribution foundation for the internal image factory.