MariaDB & K8s: Create a Secret and use it in MariaDB deployment

In the previous blog we created a stateless application, deployed it with K8s resource Deployment, and exposed the root password, which, regarding security, is of course not recommended. K8s allows one to hide confidential data using specific K8s resources.

Let’s see how to use Secrets in K8s.

Secrets in K8s

In order to save confidential data one can use a K8s resource called Secret.

One can create Secret from the CLI by running kubectl create secret.

Here we will use two methods to create the secret. The first method will store users in one file and passwords in another file, and create the Secret object by reading from files. Data will be encrypted in base64.

$ echo -n 'root' >./username.txt
$ echo -n 'secret' >./password.txt 

# Create generic secret object with keys username and password from files
$ kubectl create secret generic mariadb-secret --from-file=username=./username.txt --from-file=password=./password.txt
secret/mariadb-secret created

To display the Secret one can use the following command

$ kubectl get secret mariadb-secret
NAME             TYPE     DATA   AGE
mariadb-secret   Opaque   2      61s

$ kubectl describe secret mariadb-secret
Name:         mariadb-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
username:  4 bytes
password:  6 bytes

Note that data are secured in case of an accidental display of Secret.

In order to decode the Secret, one can use

# Decode data field from secret using json output
$ kubectl get secret mariadb-secret -o jsonpath='{.data}'
{"password":"c2VjcmV0","username":"cm9vdA=="}

# Get data using yaml output
$ kubectl get secret mariadb-secret -o yaml
apiVersion: v1
data:
  password: c2VjcmV0
  username: cm9vdA==
kind: Secret
metadata:
  creationTimestamp: "2022-03-21T10:49:24Z"
  name: mariadb-secret
  namespace: default
  resourceVersion: "392508"
  uid: 25943f12-d47d-4042-b9c6-027646864d3b
type: Opaque

# Decode base64 encrypted data username
$ echo "cm9vdA=="|base64 -d # output 'root'

To delete the Secret, run

$ kubectl delete secret mariadb-secret
secret "mariadb-secret" deleted

The second method we want to point out here uses key/value literals:

$ kubectl create secret generic my-test-secret --from-literal=mariadb-root-password=secret

To get data again we can use output format (let’s use go-template in this case)

$ kubectl get secret my-test-secret -o go-template='{{.data}}'
[mariadb-root-password:c2VjcmV0]

Alternatively, one can use configuration files too. Example of configuration file (file on GitHub )

apiVersion: v1
kind: Secret
metadata:
    name: mariadb-secret
type: Opaque
data:
  # Encoded value: echo -n 'secret'|base64
  mariadb-root-password: c2VjcmV0 

To create the resource, run kubectl apply:

$ kubectl apply -f mariadb-secret.yaml 
secret/mariadb-secret created

To use the Secrets, secrets first needs to exist.

One can use it in a container for setting the root password, so to do that update the value for MARIADB_ROOT_PASSWORD (deployment file on GitHub):

        - name: MARIADB_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mariadb-secret
              key: mariadb-root-password

Let’s create the deployment configuration file containing the secret information and display the results.

$ kubectl  apply -f mariadb-deployment-from-secret.yaml 
deployment.apps/mariadb-deployment created

Now you can test on the Pod by running the kubectl exec command.

# Get the Pods
$ kubectl get all 
NAME                                      READY   STATUS    RESTARTS   AGE
pod/mariadb-deployment-7bcbb796f5-cfh8b   1/1     Running   0          6s
pod/mariadb-deployment-7bcbb796f5-gjtlj   1/1     Running   0          6s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   143d

NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/mariadb-deployment   2/2     2            2           6s

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/mariadb-deployment-7bcbb796f5   2         2         2       6s

# Run mariadb client
$ kubectl exec mariadb-deployment-7bcbb796f5-cfh8b -- mariadb -uroot -psecret -e "select version()"
version()
10.7.3-MariaDB-1:10.7.3+maria~focal

From the above, we can see a successful access of the MariaDB database.

Conclusion and future work

This blog showed how to create a Secret in K8s cluster and demonstrated the usage of basic kubectl commands to work with Secrets in K8s. Additionally, a Deployment was created and used in conjunction with a Secret. A Secret can be used to initialize encryption-at-rest using the MariaDB encryption plugin. In one of the next blogs we may cover this too.

In the next blog we are going to create deployments with Persistent Volumes.

You are welcome to chat about it on Zulip.