1

I'm learning Kubernetes and want to set up a Docker registry to run within my cluster, deploy any custom code to this private registry, then have my nodes pull images from this private registry to create pods. I've described my setup in this StackOverflow question

Originally I was caught up trying to figure out SSL certificates, but for now I've postponed that and I'm trying to work with an insecure registry. To that end I've created the following pod to run my registry (I know it's a pod and not a replica set or deployment -- this is only for experimental purposes and I'll make it cleaner once it's working):

apiVersion: v1
kind: Pod
metadata:
  name: docker-registry
  labels:
    app: docker-registry
spec:
  containers:
    - name: docker-registry
      image: registry:2
      ports:
        - containerPort: 80
          hostPort: 80
      env:
        - name: REGISTRY_HTTP_ADDR
          value: 0.0.0.0:80

I then created the following NodePort service:

apiVersion: v1
kind: Service
metadata:
  name: docker-registry-external
  labels:
    app: docker-registry
spec:
  type: NodePort
  ports:
    - targetPort: 80
      port: 80
      nodePort: 32000
  selector:
    app: docker-registry

I have a load balancer set up in front of my Kubernetes cluster which I configured to route traffic on port 80 to port 32000. So I can hit this registry at http://example.com

I then updated my local /etc/docker/daemon.json as follows:

{
  "insecure-registries": ["example.com"]
}

With this I was able to push an image to my registry successfully:

> docker pull ubuntu
> docker tag ubuntu example.com/my-ubuntu
> docker push exapmle.com/my-ubuntu
The push refers to repository [example.com/my-ubuntu]
cc9d18e90faa: Pushed 
0c2689e3f920: Pushed 
47dde53750b4: Pushed 
latest: digest: sha256:1d7b639619bdca2d008eca2d5293e3c43ff84cbee597ff76de3b7a7de3e84956 size: 943

Now I want to try and pull this image when creating a pod. So I created the following ClusterIP service to make my registry accessible within my cluster:

apiVersion: v1
kind: Service
metadata:
  name: docker-registry-internal
  labels:
    app: docker-registry
spec:
  type: ClusterIP
  ports:
    - targetPort: 80
      port: 80
  selector:
    app: docker-registry

Then I created a secret:

apiVersion: v1
kind: Secret
metadata:
  name: local-docker
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ewoJImluc2VjdXJlLXJlZ2lzdHJpZXMiOiBbImRvY2tlci1yZWdpc3RyeS1pbnRlcm5hbCJdCn0K

The base64 bit decodes to:

{
    "insecure-registries": ["docker-registry-internal"]
}

Finally, I created the following pod:

apiVersion: v1
kind: Pod
metadata:
  name: test-docker
  labels:
    name: test
spec:
  imagePullSecrets:
    - name: local-docker
  containers:
  - name: test
    image: docker-registry-internal/my-ubuntu

When I tried to create this pod (kubectl create -f test-pod.yml) and looked at my cluster, this is what I saw:

> kubectl get pods
NAME             READY  STATUS        RESTARTS  AGE
test-docker      0/1    ErrImagePull  0         4s
docker-registry  1/1    Running       0         34m
> kubectl describe pod test-docker
...
...
Events:
  Type     Reason          Age                    From               Message
  ----     ------          ----                   ----               -------
  Normal   Scheduled       3m33s                  default-scheduler  Successfully assigned default/test-docker to pool-uqa-dev-3sli8
  Normal   Pulling         3m22s (x2 over 3m32s)  kubelet            Pulling image "docker-registry-internal/my-ubuntu"
  Warning  Failed          3m22s (x2 over 3m32s)  kubelet            Failed to pull image "docker-registry-internal/my-ubuntu": rpc error: code = Unknown desc = Error response from daemon: pull access denied for docker-registry-internal/my-ubuntu, repository does not exist or may require 'docker login'
  Warning  Failed          3m22s (x2 over 3m32s)  kubelet            Error: ErrImagePull
  Normal   SandboxChanged  3m19s (x7 over 3m32s)  kubelet            Pod sandbox changed, it will be killed and re-created.
  Normal   BackOff         3m18s (x6 over 3m30s)  kubelet            Back-off pulling image "docker-registry-internal/my-ubuntu"
  Warning  Failed          3m18s (x6 over 3m30s)  kubelet            Error: ImagePullBackOff

It's clearly failing to find the host "docker-registry-internal", despite the ClusterIP service.

I tried inspecting a pod from the inside using a trick I found online:

> kubectl run -i --tty --rm debug --image=ubuntu --restart=Never -- bash
If you don't see a command prompt, try pressing enter.
root@debug:/# cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.244.1.67     debug

It doesn't seem like ClusterIP services are being added to the /etc/hosts file, so I'm not sure how services are supposed to find one another?

I tried watching several Kubernetes tutorials on general service communication (e.g. an app pod communicating with a redis pod) and every time all they did was supply the service name as a host and it magically connected. I'm not sure if I'm missing something. Bear in mind I'm brand new to Kubernetes so the internals are still mystical to me.

stevendesu
  • 15,753
  • 22
  • 105
  • 182
  • You have to edit all /etc/docker/daemon.json files on all nodes to include insecure registries. – Burak Serdar Nov 02 '20 at 02:01
  • 1. Does the dockerconfigjson secret not modify the docker config that way? 2. The error I got didn't say "received HTTP response", it said "repository does not exist or requires docker login", which makes me think it's a networking issue and not a configuration issue – stevendesu Nov 02 '20 at 02:11
  • 1. No. dockerconfigjson is for keeping docker login secrets. Docker pull happens at the node level, you have to update node docker config and restart docker daemon, 2) Without insecure registries, it will try to connect tls, not http. – Burak Serdar Nov 02 '20 at 02:15
  • @BurakSerdar Due to auto-scaling nodes may be randomly added to or removed from my cluster at any time. How can I ensure they all trust insecure registries? I tried creating a DaemonSet to create the `/etc/docker/daemon.json` file (which worked), but the new settings don't take effect until you restart the Docker service. The problem is that restarting the Docker service also restarts the Daemon pod, creating an infinite loop. – stevendesu Nov 03 '20 at 01:55
  • I didn't find a solution to this, but I was graced with a work-around. I'm running my Kubernetes cluster on DigitalOcean. Shortly after I started having this issue, DigitalOcean rolled out an update: the DigitalOcean private repository. Upload your Docker images there and you can access them from your Kubernetes clusters! – stevendesu Mar 22 '21 at 16:02

0 Answers0