|

Spring Boot Configuration Management with Kubernetes ConfigMaps and Secrets

Managing application configurations is a critical part of deploying and maintaining software in a Kubernetes (K8s) environment. Kubernetes provides powerful tools like ConfigMaps and Secrets to externalize application settings and sensitive data, enabling better portability, scalability, and security. This guide explores the fundamentals of configuration management with Spring Boot in Kubernetes, including practical steps, best practices, and answers to frequently asked questions (FAQs).

Why Externalize Configurations in Kubernetes?

Externalizing configurations separates application code from its operational settings. This abstraction provides several benefits:

  • Environment Flexibility: Deploy the same application image across different environments (e.g., development, staging, production) with environment-specific configurations.
  • Scalability: Centralize configuration management, making it easier to update and roll out changes across distributed deployments.
  • Security: Keep sensitive data, like passwords and tokens, outside the application image.
  • Maintenance and Debugging: Dynamically update configurations without rebuilding and redeploying the application.

By combining Kubernetes ConfigMaps and Secrets with Spring Boot’s property injection capabilities, you can create robust configuration management for microservices.

Creating a ConfigMap and Mounting It as Environment Variables

Kubernetes ConfigMaps allow you to store non-sensitive configuration data, such as application properties or connection strings. These can be injected into a Spring Boot application as environment variables.

Step 1. Create a ConfigMap

You can create a ConfigMap using the Kubernetes CLI or a YAML manifest.

Using kubectl:

   kubectl create configmap app-config --from-literal=APP_ENV=production --from-literal=APP_NAME=SpringBootApp

Using YAML:

   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: app-config
   data:
     APP_ENV: production
     APP_NAME: SpringBootApp

Apply the YAML configuration:

   kubectl apply -f configmap.yaml

Step 2. Mount ConfigMap as Environment Variables

Update your deployment configuration to mount ConfigMap data into your Pods:

   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: springboot-deployment
   spec:
     replicas: 1
     template:
       spec:
         containers:
         - name: springboot-container
           image: springboot-app-image
           envFrom:
           - configMapRef:
               name: app-config

The application can now access these variables like so:

   @Value("${APP_ENV}")
   private String appEnvironment;

Step 3. Verify Injection

Run the following command to check injected values:

   kubectl exec <pod-name> -- printenv | grep APP_

YAML vs. ENV File Format

Kubernetes supports multiple formats for injecting configurations. Configurations in ConfigMaps can appear as key-value pairs in YAML or ENV format. Choosing between them depends on your organizational preference, but YAML provides better readability and structure for complex configurations.

Example Key-Value ENV Pair (ConfigMap):

   data:
     APP_NAME: "SpringBootApp"
     APP_VERSION: "1.0.0"

Example Key-Value ENV Parsed File (Env File):

   APP_NAME=SpringBootApp
   APP_VERSION=1.0.0

While both formats achieve the same goal, YAML aligns with Kubernetes declarative file management standards.

Using @Value and @ConfigurationProperties to Read Configurations

Spring Boot simplifies configuration injection with the @Value and @ConfigurationProperties annotations:

  • @Value – Injects individual properties:
   @Value("${APP_NAME}")
   private String appName;
  • @ConfigurationProperties – Binds multiple properties to a POJO class:
   @ConfigurationProperties(prefix = "app")
   public class AppConfig {
       private String name;
       private String version;
       // Getters and setters
   }

Annotate the POJO with @Component and enable the feature:

   @EnableConfigurationProperties(AppConfig.class)

Using Kubernetes Secrets for Passwords or Tokens

Sensitive data should never be stored in plain text. Kubernetes Secrets provide a secure way to manage and inject credentials.

Step 1. Create a Secret

Using kubectl:

   kubectl create secret generic db-credentials --from-literal=DB_USERNAME=admin --from-literal=DB_PASSWORD=secret123

Using YAML:

   apiVersion: v1
   kind: Secret
   metadata:
     name: db-credentials
   type: Opaque
   data:
     DB_USERNAME: YWRtaW4=  # Base64 encoded 'admin'
     DB_PASSWORD: c2VjcmV0MTIz # Base64 encoded 'secret123'

Step 2. Mount a Secret as Environment Variables

   envFrom:
   - secretRef:
       name: db-credentials

Or, mount the secret as a volume:

   volumeMounts:
   - name: secret-volume
     mountPath: /etc/secrets
   volumes:
   - name: secret-volume
     secret:
       secretName: db-credentials

Ensure sensitive files are referenced securely:

   cat /etc/secrets/DB_USERNAME

Encrypting Secrets Using Sealed Secrets

Sealed Secrets encrypt Kubernetes Secrets, making them safer for version control.

Encrypt the Secret

Generate a sealed version of your secret:

   kubectl create secret generic db-credentials --from-literal=DB_PASSWORD=supersecret --dry-run=client -o yaml |
   kubeseal > sealedsecret.yaml

The transformed sealedsecret.yaml can now be safely committed to version control.

Auto-Reloading Configurations with Spring Cloud Kubernetes

For dynamic Kubernetes deployments, you can enable auto-reloading of configurations with Spring Cloud Kubernetes:

  1. Add the dependency:
   <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-kubernetes-config</artifactId>
   </dependency>
  1. Combine it with Spring’s @RefreshScope to refresh beans:
   @RestController
   @RefreshScope
   public class TestController { /*...*/ }

Common Mistakes in Kubernetes Config Injection

  1. Injecting large ConfigMaps: Avoid committing excess data into ConfigMaps as it can overwhelm the API server.
  2. Exposing Secrets accidentally: Ensure Secrets are not logged.
  3. Not validating mounted files: Applications can fail if paths are incorrect.

Testing Configuration Propagation

Use the following steps to verify configuration accuracy:

  1. Validate ConfigMaps:
   kubectl get configmap app-config -o yaml
  1. Inspect injected environment variables:
   kubectl exec <pod-name> -- env | grep APP_
  1. Test auto-reloading by modifying ConfigMaps.

FAQ

What are ConfigMaps and Secrets used for?

  • ConfigMaps store non-sensitive configurations, while Secrets manage sensitive data like passwords and API keys.

How does encryption work with Sealed Secrets?

Sealed Secrets encrypt data at rest. Only the Kubernetes cluster holding the decryption key can decrypt the data.

How can I test if my Secret was injected correctly?

Check mounted secrets with:

   cat /etc/secrets/<key-name>

Can I create a Secret without base64 encoding?

Yes, Kubernetes CLI automatically encodes literals provided using kubectl create secret.

What happens if a ConfigMap or Secret is missing?

Pods referencing missing ConfigMaps or Secrets will not start unless you set optional=true for those references.

By following these steps and best practices, you can confidently manage configurations in your Spring Boot applications deployed on Kubernetes.

Similar Posts