Day 35 - ConfigMaps and Secrets in K8s

Day 35 - ConfigMaps and Secrets in K8s

Let's see about ConfigMaps and Secrets in K8s ConfigMaps and Secrets in Kubernetes.🔒🔑🛡️

In Kubernetes, ConfigMaps and Secrets are used to store configuration data and secrets, respectively. ConfigMaps store configuration data as key-value pairs, while Secrets store sensitive data in an encrypted form.

Previewing Image attachment

ConfigMaps

What are ConfigMaps?

A ConfigMap is an API object used to store "non-confidential data" in key-value pairs. Pods can consume ConfigMaps as environment variables, command-line arguments, or as configuration files in a volume.

A ConfigMap allows you to decouple environment-specific configuration from your container images, so that your applications are easily portable.

ConfigMaps are often used to store configuration files in a key-value format, such as INI files, JSON, or YAML. When you create a ConfigMap, you specify the configuration data as key-value pairs. This data can then be mounted as volumes in your pods or injected into container environments as environment variables.

ConfigMaps are useful for managing the configuration of applications running in Kubernetes, particularly in microservices architectures where many small services may have their own unique configuration requirements.

NOTE: ConfigMap does not provide secrecy or encryption.

Docker / Kubernetes - Configure a Pod to Use a ConfigMap - 2021

ConfigMap Use Case

While creating Pod, we will use many environment variables. The values in the environment variables are tightly coupled with the Pod. The values are statically typed within the Pod definition.

Say, for example, you are using file location as an environment variable. The value for the file location is statically defined in the Pod definition. If you want to change the file location you have to edit the Pod definition. Assume you are using the file location variable in "many Pod" definitions. So you have to change all the Pod definition files. This is tedious work.

By using ConfigMap, we can define the file location as key-value pair. And the value for file location is injected into a Pod. So if you want to change the value, you can simply edit the ConfigMap. No need to edit each and every Pod definition file. This eases our work.

Advantages of using ConfigMaps

Using ConfigMaps provide two advantages: -

  1. Removes environment variables tight coupling with the Pod.

  2. We can re-use the config data at many different Pod definition files. So changing the value is easy.

Previewing Image attachment

Previewing Image attachment

Secrets

What are Secrets?

A Secret is an object that contains a small amount of sensitive data such as a password, a token, or a key.

Secrets are same as ConfigMaps, but they are used to store confidential/sensitive data.

Secrets can be created independently of the Pods that use them, there is less risk of the Secret (and its data) being exposed during the workflow of creating, viewing, and editing Pods.

In order to safely use Secrets, take at least the following steps: -

  1. Enable Encryption at Rest for Secrets.

  2. Enable or configure RBAC rules with least-privilege access to Secrets.

  3. Restrict Secret access to specific containers.

  4. Consider using external Secret store providers.

You can use Secrets for purposes such as the following: -

  1. Set environment variables for a container.

  2. Provide credentials such as SSH keys or passwords to Pods.

  3. Allow the kubelet to pull container images from private registries.

  4. The Kubernetes control plane also uses Secrets

There are several options to create a Secret: -

  1. Use kubectl

  2. Use a configuration file

  3. Use the Kustomize tool

Securing Kubernetes Secrets with Vault - VMware Cloud Blog

Secrets Use Cases

  1. dotfiles in a secret volume: You can make your data "hidden" by defining a key that begins with a dot. This key represents a dotfile or "hidden" file.

  2. Secret visible to one container in a Pod: Consider a program that needs to handle HTTP requests, do some complex business logic, and then sign some messages with an HMAC. Because it has complex application logic, there might be an unnoticed remote file reading exploit in the server, which could expose the private key to an attacker.

    This could be divided into two processes in two containers: a frontend container which handles user interaction and business logic, but which cannot see the private key; and a signer container that can see the private key, and responds to simple signing requests from the frontend (for example, over localhost networking).

Advantages of Secrets

  1. Data Storage: Secrets can store arbitrary key-value pairs of data. While they are commonly used for storing credentials, they can also be used for other types of sensitive data.

  2. Base64 Encoding: Data stored in a Secret is base64-encoded. While this encoding is not secure on its own, it provides a basic level of obfuscation. Note that Kubernetes Secrets are not meant to be a strong security solution for highly sensitive data. For more secure storage and management of secrets, you might consider using a specialized secret management tool.

Types of Secrets

  1. Opaque: is the default Secret type if you don't explicitly specify a type in a Secret manifest. When you create a Secret using kubectl, you must use the generic subcommand to indicate an Opaque Secret type.

     kubectl create secret generic empty-secret
    
  2. kubernetes.io/service-account-token: type of Secret is used to store a token credential that identifies a ServiceAccount. This is a legacy mechanism that provides long-lived ServiceAccount credentials to Pods.

  3. kubernetes.io/dockercfg: to store credentials for accessing a container image registry. The Secret data field contains a .dockercfg key whose value is the content of a base64 encoded ~/.dockercfg file.

  4. kubernetes.io/basic-auth: is provided for storing credentials needed for basic authentication. When using this Secret type, the data field of the Secret must contain one of the following two keys:

    • username: the user name for authentication

    • password: the password or token for authentication

Both values for the above two keys are base64 encoded strings.

  1. kubernetes.io/ssh-auth: is provided for storing data used in SSH authentication. When using this Secret type, you will have to specify a ssh-privatekey key-value pair in the data (or stringData) field as the SSH credential to use.

  2. The kubernetes.io/tls: is for storing a certificate and its associated key that are typically used for TLS. This data is primarily used with TLS termination of the Ingress resource, but may be used with other resources or directly by a workload. When using this type of Secret, the tls.key and the tls.crt key must be provided in the data (or stringData) field of the Secret configuration

  3. bootstrap.kubernetes.io/token: is for tokens used during the node bootstrap process. It stores tokens used to sign well-known ConfigMaps.

    A bootstrap token Secret is usually created in the kube-system namespace and named in the form bootstrap-token-<token-id> where <token-id> is a 6 character string of the token ID.

Previewing Image attachment

Set Up MySQL Client using ConfigMap and Secrets

First, We will create a ConfigMap for our Deployment using a file or the command line.

Step 1: We are taking todo-app from our Day-32 blog. Refer to Deploy a sample todo app.

Step 2: vim configMap.yml.

#configMap.yml

kind: ConfigMap 
apiVersion: v1 
metadata: 
    name: mysql-config 
    labels: 
        app: todo 
data: 
    MYSQL_DB: "todo-db"

Step 3: Now apply the ConfigMap.

kubectl apply -f configMap.yml

Step 4: Verify that the ConfigMap has been created by checking the status of the ConfigMaps in your Namespace using the below command: -

kubectl get configmap

Now, Create a Secret for our Deployment using a file or the command line.

Step 5: vim secret.yml

#secret.yml

apiVersion: v1
kind: Secret
metadata:
    name: mysql-secret
type: Opaque
data:
    password: dHJhaW53aXRoc2h1YmhhbQ==

Step 6: We can Encode & decode the Base64 key by ourselves.

# To Decode Base64 key
echo "dHJhaW53aXRoc2h1YmhhbQ==" | base64 --decode

# To Encode Base64 key
echo "test@123" | base64

Step 7: Now, apply the secret.

kubectl apply -f secret.yml

Step 8: Verify that the Secret has been created by checking the status of the Secrets in your Namespace by using the below command: -

kubectl get secrets

Step 9: Now update the deployment.yml file to include the ConfigMap & Secret.

#deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: password
        - name: MYSQL_DATABASE
          valueFrom:
            configMapKeyRef:
              name: mysql-config
              key: MYSQL_DB

Step 10: Apply the updated deployment using the command:

kubectl apply -f deployment.yml

Step 11: To verify the MySQL pods are running, we can get the MySQL pod by running the following command.

kubectl get pods

Step 12: To expose the MySQL use the K8s service, Create a service.yml file and make the configuration by headless service.

#service.yml

apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  ports:
  - name: mysql
    port: 3306
  clusterIP: None
  selector:
    app: mysql

Step 13: Now apply for the service, so that the pod is exposed.

kubectl apply -f service.yml

Step 14: Now on the Worker Node, install the MySQL client on it.

sudo apt install mysql-client-core-8.0

Step 15: Now connect the MySQL to the Master node using the below command

# Get inside of the mysql pod 
kubectl exec -it mysql-b7f864b95-stmsw /bin/sh

# Now connect the mysql using username root and password from Secret
mysql -u root -p${MYSQL_ROOT_PASSWORD}

Step 16: Now we are finally in MySQL console, so we can do CRUD operation in it. And use the todo-db that we had created before and that is listed in the databases.

Conclusion

In Kubernetes, ConfigMaps and Secrets are essential resources for managing configuration data and sensitive information within applications deployed in a cluster.

  • ConfigMaps: ConfigMaps are used to store configuration data in key-value pairs. They are versatile and can store plain text, configuration files, or environment variables. ConfigMaps help in decoupling configuration from application code, making it easier to manage and update configurations without modifying the application itself.

  • Secrets: Secrets are dedicated to managing sensitive information such as passwords, API keys, and other confidential data. Kubernetes encrypts and stores Secrets securely, ensuring that sensitive information is not exposed in plaintext. Secrets provide a way to share confidential data between containers and pods while maintaining security.

Both ConfigMaps and Secrets enhance the flexibility and maintainability of Kubernetes applications by allowing developers and operators to separate configuration concerns from application logic. They contribute to a more scalable and secure approach to handling configuration data and sensitive information in containerized environments.

Hope you find it helpful🤞 So I encourage you to try this on your own and let me know in the comment section👇 about your learning experience.✨

*👆The information presented above is based on my interpretation. Suggestions are always welcome.*😊

~Smriti Sharma✌