Pull a Docker image from a private Gitlab registry from a Kubernetes pod

Posted by ZedTuX 0n R00t on January 21, 2019

You may face a permission issue when deploying a Pod to your Kubernetes cluster which refers to a Docker image hosted in a private Docker registry, and we will see how to deal with that in this blog article.

Typically your build script will have a build stage, which will login to the Gitlab registry, using the docker login command and pushing the image :

1
2
3
4
docker login -u "$CI_REGISTRY_USER" \
             -p "$CI_REGISTRY_PASSWORD" \
             "$CI_REGISTRY"
docker push registry.gitlab.com/nickname/projet:latest

All is working fine as you get the credentials from Gitlab.

Let’s assume the next stage is to run the tests in the Kubernetes cluster, you will have to deploy the services (database and so on) and finally this image where you’ll run your tests. But deploying this to Kubernetes fails due to a permission error because Kubernetes isn’t aware of the Gitlab credentials.

To solve this issue, you need to create a Kubernetes docker-registry secrete and tell Kubernetes to use it in order to pull the image.

Create/Update a docker-registry secret

Let’s create the docker-registry secret using the Gitlab credentials :

1
2
3
4
5
6
7
kubectl create secret --namespace=$KUBERNETES_NAMESPACE \
                      docker-registry gitlab-registry \
                      --docker-server=$CI_REGISTRY \
                      --docker-username=$CI_REGISTRY_USER \
                      --docker-password=$CI_BUILD_TOKEN \
                      --docker-email=$GITLAB_USER_EMAIL \
                      --output yaml --dry-run | kubectl apply -n $KUBERNETES_NAMESPACE -f -

As I described in my previous blog article kubectl : Use multiple account accesses, I have a ci ServiceAccount and a ci Namespace so the KUBERNETES_NAMESPACE variable is equal to ci in my case.

The other variables are the one from Gitlab, nothing specials.

What is important here is the secret name which is gitlab-registry. You will need the secret name in order to refer to it.

Pull image using the Kubernetes secret

Now let see how to use this k8s secret.

You have two options to do so :

  • Use the imagePullSecrets in all your pods giving the gitlab-registry name
  • Assign the gitlab-registry secret to the ServiceAccount

Assigning the secret to the ServiceAccount will allow you to link it to your pod and the imagePullSecrets will be automatically assigned.

Assigning the secret to the ServiceAccount

Given the ci ServiceAccount exists in your Kubernetes cluster, in order to assign the secret to it, run the following command :

1
2
$ kubectl patch serviceaccount ci -p '{"imagePullSecrets": [{"name": "gitlab-registry"}]}'

Finally use the --serviceaccount=ci when running your pod and Kubernetes will be able to fetch the image from the Gitlab registry :

1
2
3
4
5
6
$ kubectl run myPod --image=registry.gitlab.com/zedtux/k8s-demo:latest \
                    --namespace=ci \
                    --restart=Never \
                    --rm \
                    --serviceaccount=ci \
                    demo.sh