paint-brush
Kubernetes Secrets and ConfigMapsby@asadfaizi
7,992 reads
7,992 reads

Kubernetes Secrets and ConfigMaps

by Asad FaiziJanuary 25th, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Kubernetes uses ConfigMaps and Secrets to facilitate this need in containerized application development. The main purpose of using a ConfigMap is to decouple the application configuration data from the application itself. This separation improves the reusability of the container as a decoupled architecture enables developers to use and test containerized applications under different configurations. Secrets are designed to store sensitive application data such as passwords, tokens, etc. This disconnect essentially prevents the need to include confidential data within the application code.

People Mentioned

Mention Thumbnail
featured image - Kubernetes Secrets and ConfigMaps
Asad Faizi HackerNoon profile picture


As a comprehensive container orchestration platform, Kubernetes offers a fully-featured platform to support all your application needs from container lifecycle management to networking services, etc. Managing application configurations and sensitive data such as passwords is a core consideration in almost any software development. Kubernetes uses ConfigMaps and Secrets to facilitate this need in containerized application development.


Let’s assume there is an application container that requires database access. In that case, hardcoding a single database configuration within that container will not be a good solution as it will create a doubt on which database to specify. We cannot use the production database in the staging environment or staging databases in production with different credentials, which can cause security implications. In this instance, K8s ConfigMaps provides the ideal way to pass configuration data, while K8s Secrets provides a way to securely pass the database credentials within these two environments.

Why ConfigMap is used and when?


The main purpose of using a ConfigMap is to decouple the application configuration data from the application itself. This separation improves the reusability of the container as a decoupled architecture enables developers to use and test containerized applications under different configurations.


However, ConfigMaps are not designed to handle large amounts of data and are capped at 1MB. Developers need to look for other solutions such as volumes or external data sources if configuration data exceeds that limit. Thus, ConfigMaps are ideal for implementing non-sensitive configuration data less than 1MB in total size.

Why Secrets are used and when?


On the other hand, secrets provide the solution to decouple sensitive data from containers or pod configurations. This disconnect essentially prevents the need to include confidential data within the application code.


As an independent entity, secrets also ensure that this confidential data will not be exposed during the Pod creation or modification process. Kubernetes will also treat secrets differently and will abstain from writing them to nonvolatile storage. Kubernetes offers different kinds of secrets for specific use cases.

ConfigMap vs Secrets


The primary difference between these two is that while ConfigMaps are designed to store any type of non-sensitive application data, Secrets are designed to store sensitive application data such as passwords, tokens, etc. Moreover, Secrets must adhere to the specific secret types that determine which kind of data can be handled by the secret.

Creating ConfigMaps and Secrets


Both these K8s objects can be created either via kubectl or a YAML file independently of any other process or object. Now, let’s look at creating YAML-based configuration files to host our database connectivity data and authentication information.


ConfigMap YAML (Database Connectivity Data)


These ConfigMaps can also be created using different data sources such as files, Envfiles, etc. In this example, we will create a simple YAML that contains the data.


apiVersion: v1
kind: ConfigMap
# Metadata of the ConfigMap
metadata:
  name: app-database-config
  namespace: default
# The Configuration Data
data:
  server.host: "10.10.10.245"
  server.port: "3660"
  db.name: web-application

Secret YAML (Database Authentication Data)


As secrets are defined by type, let’s create a basic-auth type Secret that contains the database username and password.


apiVersion: v1
kind: Secret
# Metadata of the Secret
metadata:
  name: app-database-auth
  namespace: default
# Secret Type
type: kubernetes.io/basic-auth
# Secret Data (This changes depending on the type)
stringData:
  username: admin
  password: admin


Then these YAML and Secret can be created using the kubectl apply command as shown below.


kubectl apply -f .\\db-configmap.yaml
kubectl apply -f .\\db-secret.yaml

How to Read ConfigMaps and Secrets in Kubernetes?

Now you know how to create ConfigMaps and Secrets. Yet, how can you read these objects? We can simply use the kubectl describe command to view our objects.


Reading a ConfigMap

Use the following command with the appropriate ConfigMap name defined in the metadata section


kubectl describe configmap app-database-config

Reading a Secret

As secrets contain confidential data, the describe command does not expose this secret data even when the user query through the kubectl using the specific secret name.


kubectl describe secret app-database-auth


How to use ConfigMaps and Secrets in Kubernetes?


In this section, we will see how to use these K8s objects in our containerized applications.


Using ConfigMaps


ConfigMaps can be mounted as data volumes or configured as environmental variables using the configMapKeyRef flag. We can use both these approaches in our use case for database connectivity information. However, we will go ahead with mounting ConfigMaps as data volumes approach as those volumes are automatically updated.


apiVersion: v1
kind: Pod
metadata:
  name: test-web-app
  labels:
    app: test-web-app
spec:
  # Specify the Container Details
  containers:
    - name: ubuntu-app
      image: ubuntu:latest
      command: ["/bin/sleep", "3650d"]
      # Setup the volumeMounts
      volumeMounts:
      - name: database-config
        mountPath: /etc/config
      resources:
        requests:
          memory: "250Mi"
          cpu: "0.5"
        limits:
          memory: "1024Mi"
          cpu: "1"
  # Create a volume pointing to the ConfigMap
  volumes:
    - name: database-config
      configMap:
        name: app-database-config
  restartPolicy: Always


When mounting a ConfigMap as a volume, users need to specify the volume with the “configMap.name” field referencing the created ConfigMap and use the volume name to reference it within the container specifications.

Using Secrets

Secrets can also be mounted as volumes that update automatically when the underlying Secret is updated

.

apiVersion: v1
kind: Pod
metadata:
  name: test-web-app
  labels:
    app: test-web-app
spec:
  # Specify the Container Details
  containers:
    - name: ubuntu-app
      image: ubuntu:latest
      command: ["/bin/sleep", "3650d"]
      # Setup the volumeMounts
      volumeMounts:
      - name: database-authentication
        mountPath: /etc/authentication
        resources:
        requests:
          memory: "250Mi"
          cpu: "0.5"
        limits:
          memory: "1024Mi"
          cpu: "1"
  # Create a volume pointing to the Secret
  volumes:
    - name: database-authentication
      secret:
        secretName: app-database-auth
  restartPolicy: Always


Simply mount these as two distinct volumes as shown below to include both the ConfigMap and Secret so that all the details will be available for the application.


apiVersion: v1
kind: Pod
metadata:
  name: test-web-app
  labels:
    app: test-web-app
spec:
  containers:
    - name: ubuntu-app
      image: ubuntu:latest
      command: ["/bin/sleep", "3650d"]
      # Setup the volumeMounts
      volumeMounts:
      # ConfigMap Mount
      - name: database-config
        mountPath: /etc/config
      # Secret Mount
      - name: database-authentication
        mountPath: /etc/authentication
      resources:
        requests:
          memory: "250Mi"
          cpu: "0.5"
          limits:
          memory: "1024Mi"
          cpu: "1"
  volumes:
    # ConfigMap Volume
    - name: database-config
      configMap:
        name: app-database-config
    # Secret Volume
    - name: database-authentication
      secret:
        secretName: app-database-auth
  restartPolicy: Always

What are the problems with the built-in Secrets mechanism in Kubernetes?

The main issue with the built-in secret mechanism is the default unencrypted nature of etcd where data is stored. Usually, any administrative user will have direct access to the secret data. To mitigate this issue, users need to manually enable encryption at rest and configure role-based access control to limit access to etcd. Additionally, we can see the following common problems.


  • The users can see the values of the mounted secret when consuming the secrets in Pods.
  • Application is solely responsible for managing and securing the mounted secrets as K8s does not have a mechanism to secure data within the Pod.
  • Including secrets created as JSON or YAML files and encoded in base64 in a source control repo can introduce security risks as base64 is not an encryption method but a simple encoding method.

Conclusion

ConfigMaps and Secrets are core K8s objects that enable users to decouple non-sensitive and sensitive data respectively from other objects, creating a more reusable and secure architecture for your application.


Asad Faizi

Founder CEO

CloudPlex.io, Inc

[email protected]