Using private docker registry inside kubernetes
Tags: kubernetes, docker, devops
Published: 2022-05-27 05:35:33

Configure a customer k8s cluster with Digital Ocean Container Registry. 

## Requirements 
-	Kubernetes cluster (Access to the cluster via _kubectl_)
-	Private docker registry (I use Digital Ocean for demo)
-	Docker image

Accessing public images in a public docker registry like __Dockerhub__ is the default behaviour of a kubernetes cluster, unless you want to integrate your own private registry to access private docker images for obvious security reasons. Cloud service providers like AWS, Digital Ocean provides easy integration between own docker registry to managed kubernetes.   
But configuring a __baremetal__ kubernetes cluster to access your private registry comes with couple of steps including updating the deployment/pod yaml. I am using digital ocean docker registry for the reference. But steps are same for most of the providers.

> If you don't have a cluster for demo. Check out [Kind](https://kind.sigs.k8s.io/). Kind helps you to run a kubernetes cluster locally in minutes. Or else you can use Katacoda or [Play with kubernetes](https://labs.play-with-k8s.com/)

## Step 1
### Dockerconfig.json
First we have to get the cluster configured to authenticate to the private registry. A Kubernetes cluster uses the Secret of `kubernetes.io/dockerconfigjson` type to authenticate with a container registry to pull a private image. We can do it in two methods. First method is to use the _config.json_ file and the second method requires your username, password and email. 
In digital ocean container registry you can download a read-only config file at container registry home _Actions_ button. The same file can be found in `~/.docker/config.json` when you login in to docker registry in your local machine. 

#### Using _config.json_
```shell
kubectl create secret generic registry-credential \
    --from-file=.dockerconfigjson=<path/to/.docker/config.json> \
    --type=kubernetes.io/dockerconfigjson
```

or

#### Using docker credentials
```shell
kubectl create secret docker-registry registry-credential --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>
```

Inspect created secret
```shell
kubectl get secret registry-credential --output=yaml
```

The output is similar to this:

```yaml
apiVersion: v1
kind: Secret
metadata:
  ...
  name: registry-credential
  ...
data:
  .dockerconfigjson: eyJodHRwczovL2luZGV4...
type: kubernetes.io/dockerconfigjson
```

The value of the `.dockerconfigjson` field is a base64 representation of your Docker credentials. To convert the data into readable format use the following command.

```shell
kubectl get secret registry-credential --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode
```

## Step 2
### Editing the pod
Once the secret is created we can update our pod config to use the created secret to pull images. Update the spec session of your pod as follows.

```yaml
spec:
  containers:
  - name: private-reg-container
    image: <your-private-image>
  imagePullSecrets:
  - name: registry-credential
```
To pull the image from the private registry, Kubernetes needs credentials. The `imagePullSecrets` field in the configuration file specifies that Kubernetes should get the credentials from a Secret named `registry-credential`.
Create a Pod that uses your Secret, and verify that the Pod is running

```shell
kubectl apply -f pod.yaml
kubectl get pod <pod-name>
```

If you don't want to add `imagePullSecrets` to your pod config or need to set different registries per namespace as default then go to __step 3__.
## Step 3
### Adding image pull secretes to service account
If you want to get a preview about service accounts checkout this [doc](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server)
To add our new secret to the namespace we have to modify the service account and push our new secret name to the _imagePullSecret_ array inside the service account.
We can download the service account manifest by
```shell
kubectl get serviceaccounts default -o yaml > ./service-account.yaml
```

then update it as follows:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2015-08-07T22:02:39Z
  name: default
  namespace: default
  uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
imagePullSecrets:
- name: registry-credential
```

Finally replace the service account with updated manifest file
```shell
kubectl replace serviceaccount default -f ./service-account.yaml
```

Now, when a new Pod is created in the current namespace and using the default ServiceAccount, the new Pod has its `spec.imagePullSecrets` field set automatically.
 
---

References:
[Pull an Image from a Private Registry](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/)
[Add image pull secret to service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-image-pull-secret-to-service-account)
Add image pull secret to service account