K8s: ConfigMaps & Secrets

What are ConfigMaps in K8s?

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.

Note:

ConfigMap does not provide secrecy or encryption. If the data you want to store are confidential, use a Secret rather than a ConfigMap, or use additional (third party) tools to keep your data private.

Key Features:

  • Decouples configuration data from the application code.

  • Allows sharing of configuration across multiple pods.

  • Can be used to inject configuration as environment variables or files inside containers.

Pods use config maps through environment variables and configMap volumes.

Why we need ConfigMap?

Applications often need configuration data that changes between environments (e.g., development, testing, production). Hardcoding these values into your application makes it less portable and harder to manage across environments.

Using ConfigMap allows you to store non-sensitive configuration data separately, making your application flexible and environment-independent.

  • Example: Configuration values like API endpoints, external service URLs, application settings, etc., vary depending on the environment in which the app is deployed. These values can be dynamically provided using ConfigMaps.

Deploying the same pod manifest and different config map manifests in different environments:

What are Secrets in K8s?

A Secret in Kubernetes stores sensitive data like passwords, tokens, or keys securely, so you don't have to include them in your application's code or Pod specification. Secrets are stored in a base64-encoded format and ensure encryption when transferred or stored. This reduces the risk of exposing sensitive information during application setup or changes.

  • Key Features:

    • Secures sensitive data such as passwords, API keys, and certificates.

    • Can be mounted as environment variables or files in containers.

    • Supports encryption to prevent accidental exposure of sensitive data.

When to use Secrets?

Secrets are used to store sensitive information, such as passwords, API tokens, or SSH keys, in a secure manner. Kubernetes Secrets keep this data encrypted and ensure that only authorized applications have access to it, enhancing security.

  • Example: A database password, an API key for third-party services, or TLS certificates would all be stored securely in a Kubernetes Secret.

How to Use ConfigMap and Secrets in Real-time Projects:

In Kubernetes, ConfigMaps and Secrets are stored as objects within the cluster's etcd database.

  • ConfigMaps store non-sensitive configuration data in plain text.

  • Secrets store sensitive data, such as passwords, in base64-encoded format and can be encrypted at rest using encryption at the cluster level.

You create a ConfigMap and inject its values into your application via environment variables or mounted files.

ConfigMaps and Secrets in Kubernetes can be used in several ways:

  1. As Environment Variables: You can inject data from ConfigMaps or Secrets into Pods by referencing them as environment variables.

  2. Mounted as Volumes: Both ConfigMaps and Secrets can be mounted as files in containers, allowing applications to read configuration or sensitive data directly from a file system.

  3. In Command-line Arguments: ConfigMaps can also be used to pass configuration as arguments when starting a container, offering more control over dynamic setups.

Industry Preference in Real-Time:

  • Environment Variables are the preferred method for most cloud-native, microservice, and modern application deployments due to their simplicity and wide support in modern frameworks.

  • Mounted Volumes are used in cases where file-based configuration is mandatory, or when handling sensitive information that should not be exposed through environment variables.

  • Command-line Arguments are less common in web applications but are used for specialized workflows like scheduled jobs or processes that require argument-based customization.

Here are the example ConfigMap and Secrets YAML files along with the necessary changes to your MySQL DB Deployment and PetClinic App Deployment to reference them as environment variables.

ConfigMap (app-config.yaml)

  • This ConfigMap stores non-sensitive environment variables, such as database name, JDBC URL, etc.
CopyapiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: dev
data:
  MYSQL_URL: jdbc:mysql://mysql-service:3306/petclinic
  MYSQL_DATABASE: petclinic

Secrets (db-secrets.yaml)

This Secret stores sensitive information like MySQL credentials.

CopyapiVersion: v1
kind: Secret
metadata:
  name: db-secrets
  namespace: dev
type: Opaque
data:
  MYSQL_USER: cGV0Y2xpbmlj # base64 encoded value of 'petclinic'
  MYSQL_PASSWORD: cGV0Y2xpbmlj # base64 encoded value of 'petclinic'
  MYSQL_ROOT_PASSWORD: cm9vdA== # base64 encoded value of 'root'

To generate base64 encoded values for your secrets, you can use this command:

Copyecho -n "your-value" | base64

MySQL DB Service: mysql-service.yaml

CopyapiVersion: v1
kind: Service
metadata:
  name: mysql-service
  namespace: dev
spec:
  type: ClusterIP  
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql

MySQL DB Deployment: mysql-deployment.yaml

CopyapiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-db
  namespace: dev
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.4
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: db-secrets
              key: MYSQL_USER
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secrets
              key: MYSQL_PASSWORD
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secrets
              key: MYSQL_ROOT_PASSWORD
        - name: MYSQL_DATABASE
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: MYSQL_DATABASE
        volumeMounts:
        - mountPath: /var/lib/mysql
          name: mysql-persistent-storage   
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pvc

PetClinic App Service: petclinic-service.yaml

CopyapiVersion: v1
kind: Service
metadata:
  name: petclinic-service
  namespace: dev
spec:
  type: NodePort  
  ports:
    - port: 8080
      targetPort: 8080
      nodePort: 30007  
  selector:
    app: petclinic

PetClinic App Deployment

CopyapiVersion: apps/v1
kind: Deployment
metadata:
  name: petclinic-app
  namespace: dev
spec:
  replicas: 2
  selector:
    matchLabels:
      app: petclinic
  template:
    metadata:
      labels:
        app: petclinic
    spec:
      containers:
      - name: petclinic
        image: subbu7677/petclinic-spring-app:v1  
        ports:
        - containerPort: 8080
        env:
        - name: MYSQL_URL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: MYSQL_URL
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: db-secrets
              key: MYSQL_USER  
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secrets
              key: MYSQL_PASSWORD
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secrets
              key: MYSQL_ROOT_PASSWORD
        - name: MYSQL_DATABASE
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: MYSQL_DATABASE
        volumeMounts:
        - mountPath: /tmp/cache
          name: cache-volume
      volumes:
      - name: cache-volume
        emptyDir: {}

Summary:

  • ConfigMap (app-config.yaml):

    • Stores non-sensitive data like MYSQL_URL and MYSQL_DATABASE.

    • These are used in the PetClinic and MySQL deployments to dynamically inject configuration.

  • Secrets (db-secrets.yaml):

    • Stores sensitive information such as the MySQL username, password, and root password.

    • The values are base64-encoded to ensure secure management in Kubernetes.

  • Deployment Updates:

    • MySQL Deployment:

      • The environment variables MYSQL_USER, MYSQL_PASSWORD, and MYSQL_ROOT_PASSWORD now refer to the Secrets.

      • MYSQL_DATABASE refers to the ConfigMap.

    • PetClinic Deployment:

      • The environment variables for MYSQL_URL, MYSQL_DATABASE refer to the ConfigMap.

      • The MYSQL_USER, MYSQL_PASSWORD, and MYSQL_ROOT_PASSWORD refer to the Secrets for security.

Our Project ConfigMap & Secrete Objects:

Persistent Volume and Persistent Volume Claim:

All Resources along with MySQL-DB-Deployment and Petclinic-Deployment:

We have successfully deployed our PetClinic application along with the MySQL database using ConfigMap and Secret objects, avoiding hard-coded environment variables. The application is accessible outside the cluster, allowing us to create new owners and pets, and fully explore its features.

Best Practices in Real-time Projects

  1. Separation of Concerns: Keep configuration and sensitive information out of your container images and store them in ConfigMaps and Secrets.

  2. Environment-specific Configurations: Use ConfigMaps and Secrets to handle environment-specific settings, allowing the same container image to run in multiple environments.

  3. Security: Regularly rotate Secrets and ensure they are encrypted at rest and in transit. Limit access to Secrets to only those containers that require it.

  4. Auditing: Enable audit logs to track access to Secrets.

  5. Backup & Recovery: Ensure that both ConfigMaps and Secrets are part of your disaster recovery plan.


Best Use Cases for Kubernetes ConfigMap

  1. Application Configuration Across Environments:

    • Use Case: Manage environment-specific settings like URLs, log levels, etc., that change between development, staging, and production.

    • Example: Storing API_URL or LOG_LEVEL as environment variables.

  2. External Services Configuration:

    • Use Case: Apps that connect to external services like APIs or message queues need to adjust settings across environments.

    • Example: Storing API or message broker URLs in a ConfigMap.

  3. Tuning Application Settings Without Rebuilding:

    • Use Case: Modify settings like timeouts or cache sizes without rebuilding the app.

    • Example: Changing REQUEST_TIMEOUT or MAX_CONNECTIONS through a ConfigMap.

  4. Configuration Sharing Across Pods:

    • Use Case: Multiple instances of an app share the same configuration.

    • Example: Microservices using the same API keys or service discovery URLs.

  5. Injecting Configuration Files:

    • Use Case: Some apps require configuration files instead of environment variables.

    • Example: Injecting application.properties or config.json into pods.


Best Use Cases for Kubernetes Secrets

  1. Database Credentials Management:

    • Use Case: Securely store database credentials like usernames and passwords.

    • Example: Inject DB_USERNAME and DB_PASSWORD from Secrets.

  2. API Keys and Tokens:

    • Use Case: Safely store API keys and tokens needed for third-party services.

    • Example: Injecting API keys for services like Stripe or PayPal.

  3. TLS/SSL Certificates:

    • Use Case: Provide certificates for secure communication (HTTPS).

    • Example: Storing SSL certificates in a Secret and using them in web servers.

  4. SSH Keys for Secure Access:

    • Use Case: Securely store SSH keys to access servers or services.

    • Example: Injecting SSH keys for secure connections.

  5. Docker Registry Credentials:

    • Use Case: Authenticate to private Docker registries.

    • Example: Storing Docker credentials to pull private images.

  6. Encrypting Sensitive Settings:

    • Use Case: Securely manage sensitive configuration like encryption keys.

    • Example: Store and access encryption keys or session tokens using Secrets.

  7. Securing Access to Cloud Services:

    • Use Case: Safely store cloud service credentials.

    • Example: Inject AWS or GCP credentials to access cloud services.

"The capacity to learn is a gift, the ability to learn is a skill, the willingness to learn is a choice." — Brian Herbert

Thank you, Happy Learning!

0
Subscribe to my newsletter

Read articles from Subbu Tech Tutorials directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Subbu Tech Tutorials
Subbu Tech Tutorials