Image Security
In this tutorial, we are going to discuss about image security in Kubernetes.
We will start with the basics of image names and then work our way towards secure image repositories and how to configure your pods to use images from secure repositories.
Up to now, we deployed a number of different kinds of PODs hosting different kinds of applications throughout our tutorials like web apps and databases and Redis cache etc.
Let’s start with a simple POD definition file.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx-container
image: nginx
Image
Here we have used the nginx image to deploy an nginx container. Let’s take a closer look at this image name.
The name is nginx. But what is this image? and where is this image pulled from? This name follows Docker’s image naming convention. Here nginx is the image or the repository name.
When you say nginx, its actually nginx/nginx.
The first part stands for the user or account name. So if you don’t provide an user or account name, it assumes that it is the same as the given image name. Which in this case is nginx.
If you were to create your own account and create your own repositories or images under it then you would use a similar pattern.
Now where are these images stored and pulled from? Since we have not specified the location where these images are to be pulled from the docker default registry docker hub docker.io.
The registry, where the all images are stored. Whenever you create a new image or update an existing image, you pushed to the registry and every time if you deployed your application, it will pulled from that registry.
There are many other popular registries as well. For example, google registry (gcr.io) where all the Kubernetes related images that are stored. These are all public accessible images, that anyone can download and access.
When you have applications built in-house that shouldn’t be made available to the public Hosting an internal private registry may be a good solution.
Many cloud service providers such as AWS, Azure or GCP provide a private registry by default when you open account with them.
Private Repository
On any of these solutions be it on Docker hub or googles registry, or your internal private registry, You may choose to make a repository private. So that it can be accessed using a set of credentials.
From a Docker perspective to run a container using a private image, you first login to your private-registry using the docker log in command.
Input your credentials one successful run the application using the image from the private registry.
Going back to our pod definition file, to use an image from our private registry we replace the image name with the full path to the one in the private registry.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: private-registry.io/apps/internal-app
But how do we implement the authentication log in part. How does Kubernetes get the credentials to access the private registry.
Within Kubernetes, we know that the images are pulled and run by the docker runtime on the worker nodes.
How do you pass the credentials to the docker run time on the worker nodes? For that We first create a secret object with the credentials in it.
kubectl create secret docker-registry regcred \
--docker-server=private-registry.io \
--docker-username=ashok \
--docker-password=Ashok@123 \
--docker-email=contact@sh121.global.temp.domains
The secret is of type Docker registry and we name it Regcred. Docker registry is a built in secret type that was built for storing Docker credentials.
We then specify the secret inside our pod definition file under the image Pull secret section.
When the POD created Kubernetes or the kubelets on the worker node uses the credentials from the secret to pull images. Using this mechanism we can achieve image security.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: private-registry.io/apps/internal-app
imagePullSecrets:
- name: regcred