Secrets

Objects of type secret are intended to hold sensitive information, such as passwords, OAuth tokens, and ssh keys.

Module

Kubernetes secret objects let you store and manage sensitive information, such as passwords, OAuth tokens, and ssh keys.

Overview

At the end of this module, you will :

  • Learn to manage sensitive data within the cluster

  • Learn to deploy Secrets

  • Learn to access secrets data within a container

Prerequisites

Create the directory data/secrets in your home folder to manage the YAML file needed in this module.

mkdir ~/data/secrets

Create

A Secret is an object that contains a small amount of sensitive data such as a password, a token, or a key. Such information might otherwise be put in a Pod specification or in an image, putting it in a Secret object allows for more control over how it is used, and reduces the risk of accidental exposure.

Independently from the deployment method, the command line to create a Secrets should look like this :

kubectl create secret TYPE NAME SOURCES
  • TYPE define which kind of Secret to create :

    • docker-registry : Create a secret for use with a Docker registry

    • generic : Create a secret from a local file, directory or literal value

    • tls : Create a TLS secret

  • NAME define the name of the Secret, needed to attach it to a Pod

  • SOURCES define the data source for the Secret content to encode :

    • --from-literal : Specify a key and literal value to insert in secret (i.e. mykey=somevalue)

    • --from-file : Key files can be specified using their file path, in which case a default name will be given to

    • --from-env-file : Specify the path to a file to read lines of key=val pairs to create a secret

The create command can directly ask the API resource to create a Secret in command line or create a Secret object based on a yaml file definition.

From literal values

Multiple key-value pairs can be passed to the Kubectl client to create a single Secret. Each pair provided on the command line is represented as a separate entry in the data section of the Secret.

In this particular method, the key / value are explicitly defined in the command line and each key / value will generate a new entry in the Secret.

The command line for this kind of Secrets creation should look like this :

kubectl create secret generic SECRET_NAME --from-literal=KEY=NAME

Exercise n°1

Create a Secret called myfirstsecret in command line from a literal value to encode the key / value pair : password=myclearpassword

kubectl create secret generic myfirstsecret --from-literal=password=myclearpassword

This method is not recommended in production. It is recommended to version the Secrets files in a sources repository to manage it with a CI/CD tool.

From a file

Like any other object in Kubernetes, multiple Secrets can be created based on multiple files stocked in different directories. The Kubectl client take care to parse each file given to the command line to ensure that each content files are integrated as Secrets.

The command line for this kind of Secrets creation should look like this :

kubectl create secret generic SECRET_NAME --from-file=PATH_FILE

Exercise n°1

  1. Create on or more file with some sensitive data.

  2. Create a unique Secret based on the files created

# Create files needed for rest of example.
echo -n 'admin' > ~/data/secrets/username.txt
echo -n '1f2d1e2e67df' > ~/data/secrets/password.txt

# Create the Secrets based on the files created
kubectl create secret generic myfirstsecretfile --from-file=$HOME/data/secrets/username.txt --from-file=$HOME/data/secrets/password.txt

Manually

A Secret can be create manually thanks to a yaml file and the Kubernetes API. This is useful to manage it easily in a source repository and update it via a CI/CD tool.

Pay attention to the format of data in the yaml file definition, the content has to be encoded in base64 to be correctly understand by the Kubernetes API.

Exercise n°1

Create a Secret manually in declarative mode.

apiVersion: v1
kind: Secret
metadata:
  name: myfirstsecretmanual
type: Opaque
data:
  username: YWRtaW4=          # echo -n 'admin' | base64
  password: MWYyZDFlMmU2N2Rm  # echo -n '1f2d1e2e67df' | base64
kubectl apply  -f data/secrets/01_secrets.yaml

Get

The get command list the object asked. It could be a single object or a list of multiple objects comma separated. This command is useful to get the status of each object. The output can be formatted to only display some information based on some json search or external tools like tr, sort, uniq.

The default output display some useful information about each services :

  • Name : the name of the newly created resource

  • Type : the type of Secrets, indication of type of content in the object

  • Data : the count of keys in the Secrets

  • Age : the age since his creation

Exercise n°1

Get a list of existing Secrets in the default namespace.

kubectl get secrets

Describe

Once an object is running, it is inevitably a need to debug problems or check the configuration deployed.

The describe command display a lot of configuration information about the Secrets (labels, resource requirements, etc.) or any other Kubernetes objects, as well as status information about the Secrets and Pod (state, readiness, restart count, events, etc.).

This command is really useful to introspect and debug an object deployed in a cluster.

Exercise n°1

Describe one of the existing Secrets in the default namespace.

kubectl describe secrets myfirstsecretfile

Attach

Once a Secret is created, it has to be attach to a pod to be able to read the data within it.

The data can be attach as :

  • Environment variable : The application in the container has to be able to read data from those environment variables.

  • File : The application in the container has to be able to read the content in the specific files and find the needed keys to get the right value.

Multiple Secrets can be defined in a Pod, this is useful when the configuration has to be managed by different teams.

In environment variable

Inside a container that consumes a secret in an environment variables, the secret keys appear as normal environment variables containing the base-64 decoded values of the secret data.

Exercise n°1

Based on the previous Secrets created, create a Pod using the busybox image to display some part of the Secret in single environment variables.

apiVersion: v1
kind: Pod
metadata:
  name: myfirstsecretenv
spec:
  containers:
  - name: busybox
    image: busybox
    command: [ "/bin/sh", "-c", "env" ]
    env:
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: myfirstsecret
            key: password

Create the resource based on the previous yaml file definition.

kubectl apply  -f data/secrets/02_pods.yaml

Get the environment variable to ensure the configuration.

kubectl logs myfirstsecretenv

In file path

With this method, the data of a Secrets is directly connected as a Volume to a Pod in a specific path in the container to be readable by the application deployed.

Exercise n°1

Based on the previous Secrets created, create a Pod using the busybox image to display some part of the Secret in single file.

apiVersion: v1
kind: Pod
metadata:
  name: myfirstsecretfile
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: myfirstsecretmount
      mountPath: "/data/sensitive"
      readOnly: true
  volumes:
  - name: myfirstsecretmount
    secret:
      secretName: myfirstsecret
      items:
      - key: password
        path: myapp/my-password

Create the resource based on the previous yaml file definition.

kubectl apply  -f data/secrets/03_pods.yaml

Get the volume mount information.

kubectl exec -it myfirstsecretfile cat /data/sensitive/myapp/my-password

Explain

Kubernetes come with a lot of documentation about his objects and the available options in each one. Those information can be fin easily in command line or in the official Kubernetes documentation.

The explain command allows to directly ask the API resource via the command line tools to display information about each Kubernetes objects and their architecture.

Exercise n°1

Get the documentation of a specific field of a resource.

kubectl explain secrets

Add the --recursive flag to display all of the fields at once without descriptions.

Delete

The delete command delete resources by filenames, stdin, resources and names, or by resources and label selector.

A Secrets can only be deleted when it is not attached to a Pod.

Note that the delete command does NOT do resource version checks, so if someone submits an update to a resource right when you submit a delete, their update will be lost along with the rest of the resource.

Exercise n°1

Delete the previous Secrets created.

# Delete Pods created
kubectl delete pods myfirstsecretenv myfirstsecretfile
# Delete Secrets created
kubectl delete secrets myfirstsecret myfirstsecretfile

Module exercise

The purpose of this section is to manage each steps of the lifecycle of an application to better understand each concepts of the Kubernetes course.

The main objective in this module is to understand how to externalized some sensitive data of an application to simplify the development and the lifecycle of both application and secrets.

For more information about the application used all along the course, please refer to the Exercise App > Voting App link in the left panel.

Based on the principles explain in this module, try by your own to handle this steps. The development of a yaml file is recommended.

The file developed has to be stored in this directory : ~/data/votingapp/06_secrets

  1. Delete the db, result and worker Deployment to be able to update the Secrets management

  2. Create a Secrets resource to externalize some part of the vote Pods :

    1. Named the Secrets db

    2. The Secrets must manage those data :

      1. name: voting

      2. password: mypassword

      3. user: voting

  3. Update the Deployment of the vote Pods to attach the Secrets as environment variables :

    1. The name of the name environment variable has to be POSTGRESQL_DATABASE

    2. The name of the password environment variable has to be POSTGRESQL_PASSWORD

    3. The name of the user environment variable has to be POSTGRESQL_USERNAME

External documentation

Those documentations can help you to go further in this topic :

Last updated