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 . 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. capped at 1MB 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 such as files, Envfiles, etc. In this example, we will create a simple YAML that contains the data. using different data sources 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 command to view our objects. kubectl describe 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 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. environmental variables using the configMapKeyRef 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 asad@cloudplex.io