Configure Secrets
In this tutorial, we will discuss about how to configure Secrets in Kubernetes.
In the previous tutorials, we discussed how to define environment variables and configure configmaps in a POD definition file.
Let us assume we have a simple python web application that connects to a MySQL database.
import os from flask import Flask app = Flask(__name__) @app.route("/") def main(): mysql.connector.connect(host="mysql", database="ashok", user="ashok", password="ashok123") return render_template("hellp.html", color=fetchcolor()) if __name__ == __main__: app.run(host="0.0.0.0", port="8080")
If you look closely into the code you will see the host name, user name and password hard coded. This is of course not good idea.
As we discussed in the previous tutorial, one option would be to move these values into a ConfigMap.
apiVersion: v1 kind: ConfigMap metadata: name: app-config data: DB_HOST: mysql DB_USER: ashok DB_DATABASE: ashok DB_PASSWORD: ashok123
The ConfigMap stores configuration data in plain text format. So while it would be okay to move the host name, database and user name into ConfigMap. But it is definitely not the right place to store password in ConfigMap. This is where secrets coming.
Secrets are used to store sensitive information like passwords or keys. They’re similar to ConfigMap except that they’re stored in an encoded or hashed format.
As with ConfigMaps, there are 2 steps involved in working with secrets. First create the secret and second injected into POD.
There are 2 ways of creating a secret. The imperative way – without using secret definition file and the declarative way by using a secret definition file.
Imperative method
With the imperative method, you can directly specify the key value pairs in the command line itself.
To create a secret of the given values, run the following command.
$ kubectl create secret generic <secret-name> --from-literal=<key>=<value>
E.g
$ kubectl create secret generic app-secret --from-literal=DB_HOST=mysql
If you wish to add additional key value pairs then simply specify the –from-leteral options multiple times
$ kubectl create secret generic app-secret --from-literal=DB_HOST=mysql --from-literal=DB_USER=ashok --from-literal=DB_PASSWORD=ashok123
However this will get complicated when you have too many configuration items. Another way to input configuration data is through a file.
$ kubectl create secret generic <secret-name> --from-file=app-secret.properties
$ kubectl create secret generic app-secret --from-file=<path-to-file>
Declarative Approach
In this approach we create a definition file just like how we did for the ConfigMap. The file has apiVersion, kind, metadata and data.
apiVersion: v1 kind: ConfigMap metadata: name: app-secret data: DB_HOST=mysql DB_USER=ashok DB_PASSWORD=ashok123
However one thing we discussed about secrets was that used to store sensitive data and are stored in an encoded format.
Here we have specified the data in plain text which is not very safe. So while creating a secret with declarative approach you must specify the secret values in a hashed format.
So you must specify the data in an encoded form like as below,
apiVersion: v1 kind: ConfigMap metadata: name: app-secret data: DB_HOST=bXlzcWw= DB_USER=YXNob2s= DB_PASSWORD=YXNob2sxMjM=
But how do you convert the data from plain text to an encoded format? On a Linux host run the command echo -n followed by the text you are trying to convert, which is mysql in this case and pipe that to the base64 utility.
$ echo -n mysql | base64 bXlzcWw= $ echo -n ashok | base64 YXNob2s= $ echo -n ashok123 | base64 YXNob2sxMjM=
To view secrets run the following command
$ kubectl get secrets NAME TYPE DATA AGE default-token-kdm9m kubernetes.io/service-account-token 3 8h app-secret Opaque 3 2h
Above command lists the newly created secret along with another secret previously created by Kubernetes for its internal purpose.
To view more information on the newly created secret, run the following command.
$ kubectl describe secrets
The above command shows the attributes in the secret. But hides the value themselves. To view the values as well, run the following command.
$ kubectl get secret app-secret -o yaml
The above command will display YAML format. You can now see the hashed values as well. So how do you decode these hashed values?
Use the same base64 command used earlier to encode it. But this time add a decode option to it.
$ echo -n bXlzcWw= | base64 --decode mysql $ echo -n YXNob2s= | base64 --decode ashok $ echo -n YXNob2sxMjM= | base64 --decode ashok123
Now that we have secret created. Let us proceed with step 2, configuring it with a POD.
apiVersion: v1 kind: Pod metadata: name: my-web-app spec: containers: - name: my-web-app-container image: my-web-app ports: - containerPort: 8080 envFrom: - secretRef: name: app-secret