#!/bin/sh
set -o errexit
# 1. Create registry container unless it already existsreg_name='kind-registry'reg_port='5001'if [ "$(docker inspect -f '{{.State.Running}}'"${reg_name}" 2>/dev/null || true)" != 'true' ]; then docker run \
-d --restart=always -p "127.0.0.1:${reg_port}:5000" --network bridge --name "${reg_name}"\
registry:2
fi# 2. Create kind cluster with containerd registry config dir enabled## NOTE: the containerd config patch is not necessary with images from kind v0.27.0+# It may enable some older images to work similarly.# If you're only supporting newer relases, you can just use `kind create cluster` here.## See:# https://github.com/kubernetes-sigs/kind/issues/2875# https://github.com/containerd/containerd/blob/main/docs/cri/config.md#registry-configuration# See: https://github.com/containerd/containerd/blob/main/docs/hosts.mdcat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
EOF# 3. Add the registry config to the nodes## This is necessary because localhost resolves to loopback addresses that are# network-namespace local.# In other words: localhost in the container is not localhost on the host.## We want a consistent name that works from both ends, so we tell containerd to# alias localhost:${reg_port} to the registry container when pulling imagesREGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}"for node in $(kind get nodes); do docker exec "${node}" mkdir -p "${REGISTRY_DIR}" cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
[host."http://${reg_name}:5000"]
EOFdone# 4. Connect the registry to the cluster network if not already connected# This allows kind to bootstrap the network but ensures they're on the same networkif [ "$(docker inspect -f='{{json .NetworkSettings.Networks.kind}}'"${reg_name}")" = 'null' ]; then docker network connect "kind""${reg_name}"fi# 5. Document the local registry# https://github.com/kubernetes/enhancements/tree/master/keps/sig-cluster-lifecycle/generic/1755-communicating-a-local-registrycat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: local-registry-hosting
namespace: kube-public
data:
localRegistryHosting.v1: |
host: "localhost:${reg_port}"
help: "https://kind.sigs.k8s.io/docs/user/local-registry/"
EOF
First we’ll pull an image docker pull gcr.io/google-samples/hello-app:1.0
Then we’ll tag the image to use the local registry docker tag gcr.io/google-samples/hello-app:1.0 localhost:5001/hello-app:1.0
Then we’ll push it to the registry docker push localhost:5001/hello-app:1.0
And now we can use the image kubectl create deployment hello-server --image=localhost:5001/hello-app:1.0
If you build your own image and tag it like localhost:5001/image:foo and then use
it in kubernetes as localhost:5001/image:foo.
If for some reason you have code running inside of a pod within the cluster that
needs to use this registry directly (e.g. to build and push an image) then that
code will need to use the kind-registry:5000 HTTP endpoint directly, as the
code running inside your pod will not see the containerd config.
Pod manifests / pod specs / pod YAML should use localhost:5001,
which will be rerouted to match the same name as the host via the containerd config.
NOTE: A bit about “localhost” and containers …
“localhost” resolves to a loopback IP, which are network-namespace local.
Network-namespace local means that the 127.0.0.1 / localhost / ::1
inside your container is NOT the same as the one on your host
(unless using hostNetwork: true / --net=host).
KIND nodes are not--net=host and most pods are not, so really these
“localhosts” are local to your pod container, to your kind node, and to your
host machine in most cases.
However we can tell containerd that localhost:5001 should route to the
registry container such that the same name works on both the host and your machine.
We do this so you can conveniently push and pull from a “local”
address on your host and in your pod YAML.