Kubernetes secrets manage information in key-value formats with the value encoded. With secrets, users don't have to set values in the configuration file or type them in CLI. When secrets are used properly, they can reduce the risk of credential leak and make our resource configurations more organized.
Currently, there are three types of secret:
Opaque is the default type. We will put service account tokens and the authentication of Docker in the remark part.
Before using our credentials with secrets, some precautions must be taken First, secrets have a 1 MB size limitation. It works fine for defining several key-value pairs in a single secret. But, be aware that the total size should not exceed 1 MB. Next, secret acts like a volume for containers, so secrets should be created prior to dependent pods.
We can only generate secrets by using configuration files. In this recipe, we will deliver a simple template file and focus on the functionality. For various template designs, please take a look at the Working with configuration files recipe in Chapter 3, Playing with Containers.
The configuration file of secrets contains secret type and data:
// A simple file for configuring secret # cat secret-test.json { "kind": "Secret", "apiVersion": "v1", "metadata": { "name": "secret-test" }, "type": "Opaque", "data": { "username": "YW15Cg==", "password": " UGEkJHcwcmQhCg==" } }
The secret type Opaque
is the default one, which simply indicates that the data is not shown. The other types, service account token and Docker authentication, are applied when using the values kubernetes.io/service-account-token
and kubernetes.io/dockercfg
at the type item stage, respectively.
The data username
and password
are customized keys. Their corresponding values are base64-encoded string. You can get your encoded value through these pipe commands:
# echo "amy" | base64 YW15Cg==
The resource annotation and management of secrets is similar to other resource types. Feel free to create a secret and check its status by using common subcommands:
# kubectl create -f secret-test.json secret "secret-test" created # kubectl get secret NAME TYPE DATA AGE secret-test Opaque 2 39s # kubectl describe secret secret-test Name: secret-test Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== password: 10 bytes username: 4 bytes
As you can see, although secret hides the information, we can get the amount of data, the data name and also the size of the value.
In order to let the pod get the secret information, secret data is mounted as a file in the container. The key-value pair data will be shown in plain-text file format, which takes a key name as the file name and the decoded value as the file content. Therefore, we create the pod by configuration file, where the container's mounting volume is pointed to secret:
# cat pod-secret.json { "kind": "Pod", "apiVersion": "v1", "metadata": { "name": "pod-with-secret" }, "spec": { "volumes": [ { "name": "secret-volume", "secret": { "secretName": "secret-test" } } ], "containers": [ { "name": "secret-test-pod", "image": "nginx", "volumeMounts": [ { "name": "secret-volume", "readOnly": true, "mountPath": "/tmp/secret-volume" } ] } ] } }
For the previous template, we defined a volume called secret-volume
which includes physical files with the content of the secret secret-test
; the containers' mounting point is also defined along with the location, where to put secret files, and bound with secret-volume
. In this case, the container could access secrets in its local file system by using /tmp/secrets/<SECRET_KEY>
.
To verify the content is decrypted for the usage of the container program, let's take a look at the specific container on the node:
// login to node and enable bash process with new tty # docker exec -it <CONTAINER_ID> bash root@pod-with-secret:/# ls /tmp/secrets/ password username root@pod-with-secret:/# cat /tmp/secrets/password Pa$$w0rd! root@pod-with-secret:/# cat /tmp/secrets/username amy
In order to reduce the risk of leaking the secrets' content, the Kubernetes system never saves the data of secrets on disk. Instead, secrets are stored in the memory. For a more accurate statement, the Kubernetes API server pushes secret to the node on which the demanded container is running. The node stores the data in tmpfs
, which will be flashed if the container is destroyed.
Go and check the node, which has container with secrets running on it:
// check the disk df -h --type=tmpfs Filesystem Size Used Avail Use% Mounted on tmpfs 920M 0 920M 0% /dev/shm tmpfs 920M 17M 903M 2% /run tmpfs 920M 0 920M 0% /sys/fs/cgroup tmpfs 184M 0 184M 0% /run/user/2007 tmpfs 920M 8.0K 920M 1% /var/lib/kubelet/pods/2edd4eb4-b39e-11e5-9663-0200e755981f/volumes/kubernetes.io~secret/secret-volume
Furthermore, I suggest that you avoid creating a large-size secret or many small-size secrets. Since secrets are kept in the memory of nodes, reducing the total size of secrets could help to save resources and maintain good performance.
In the previous sections, secret is configured in the default service account. The service account can make processes in containers in contact with the API server. You could have different authentication by creating different service accounts.
Let's see how many service accounts we currently have:
$ kubectl get serviceaccounts NAME SECRETS AGE default 0 18d
Kubernetes will create a default service account. Let's see how to create our own one:
# example of service account creation $ cat serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: test-account # create service account named test-account $ kubectl create -f serviceaccount.yaml serviceaccount "test-account" created
After creation, let's list the accounts by kubectl
:
$ kubectl get serviceaccounts NAME SECRETS AGE default 0 18d test-account 0 37s
We can see there is a new service account named test-account
in the list now.
Each service account could have its own API token, image pull secrets and mountable secrets.
Similarly, we could delete the service account by using kubectl
:
$ kubectl delete serviceaccount test-account serviceaccount "test-account" deleted
On the other hand, Docker authentication can also be saved as a secret data for pulling images. We will discuss the usage in Working with the private Docker registry recipe in Chapter 5, Building a Continuous Delivery Pipeline.