Private Registries & Pull-Through Mirrors

Use registries.yaml to authenticate, mirror Docker Hub through a cache, and dodge public rate limits.

Every node that pulls images reads /etc/rancher/k3s/registries.yaml. Two features make it worth mastering: authenticated pulls and pull-through mirrors.

Rewrite mirrors

A mirrors entry redirects all pulls for a registry to a different endpoint — typically a caching proxy. This is how you stop hammering Docker Hub and escape its anonymous pull-rate limits: mirror docker.io through a local registry running in pull-through mode. Existing manifests need no changes; the rewrite is transparent.

Auth and TLS

The configs block holds credentials and TLS settings per registry host, including a custom CA for self-signed internal registries or insecure_skip_verify for lab setups.

Rollout discipline

  • The file must exist on every node that pulls images — servers and agents alike.
  • k3s reads it at startup, so systemctl restart k3s (or k3s-agent) after edits.
  • Verify the wiring with crictl pull, not just a Pod — you get the raw error immediately.

Example

Example · yaml
# /etc/rancher/k3s/registries.yaml (on EVERY node)
mirrors:
  docker.io:
    endpoint:
      - "https://registry-cache.internal:5000"
  registry.internal:5000:
    endpoint:
      - "https://registry.internal:5000"
configs:
  registry.internal:5000:
    auth:
      username: deploy
      password: s3cret
    tls:
      ca_file: /etc/ssl/certs/internal-ca.crt
# sudo systemctl restart k3s   (or k3s-agent on workers)
# sudo k3s crictl pull registry.internal:5000/app:1.0

When to use it

  • A team configures a pull-through cache for Docker Hub in registries.yaml to avoid hitting the Docker Hub anonymous pull rate limit in CI.
  • An air-gapped factory cluster points all image pulls to an internal Harbor instance so workers never need internet access.
  • An operator mirrors multiple public registries (docker.io, gcr.io, quay.io) through a single local proxy to reduce bandwidth and latency for edge sites.

More examples

Mirror Docker Hub through a local cache

Routes all docker.io and gcr.io image pulls through internal caching proxies to bypass rate limits and reduce latency.

Example · yaml
# /etc/rancher/k3s/registries.yaml
mirrors:
  docker.io:
    endpoint:
      - 'https://hub-cache.internal.example.com'
  gcr.io:
    endpoint:
      - 'https://gcr-cache.internal.example.com'

Add auth for a private registry

Authenticates to a private Harbor registry with a robot account and a custom CA certificate for TLS verification.

Example · yaml
# /etc/rancher/k3s/registries.yaml
configs:
  'registry.example.com':
    auth:
      username: robot$ci
      password: harbor-robot-token
    tls:
      ca_file: /etc/ssl/certs/harbor-ca.crt

Reload and test registry config

Restarts k3s to pick up registries.yaml changes, checks the logs for registry loading, and verifies a private image pull.

Example · bash
systemctl restart k3s
journalctl -u k3s -n 10 | grep -i 'registry\|mirror'
kubectl run ping --image=registry.example.com/myapp:v1 \
  --restart=Never --rm -it -- echo ok

Discussion

  • Be the first to comment on this lesson.