OpenShift Environment Variables for Spring Boot

Learn how to configure environment variables in OpenShift for Spring Boot applications. Understand environment variable injection, property precedence, Spring Profiles, ConfigMaps, Secrets, and enterprise configuration best practices.


Introduction

Modern cloud-native applications should never hardcode environment-specific values inside source code.

For example:

  • Database URL
  • Kafka Brokers
  • Redis Host
  • API Gateway URL
  • Active Spring Profile
  • Feature Flags
  • Logging Level

These values change between Development, QA, UAT, and Production environments.

Instead of rebuilding applications for every environment, OpenShift allows developers to inject configuration using Environment Variables.

Spring Boot automatically maps these variables into the application, making deployments portable, secure, and cloud-native.


Learning Objectives

By the end of this article, you will understand:

  • What are Environment Variables?
  • Why they are important
  • Spring Boot property resolution
  • Environment variable architecture
  • ConfigMaps and Secrets integration
  • Spring Profiles
  • Configuration precedence
  • Enterprise configuration strategies
  • Best practices

Why Environment Variables?

Imagine a Spring Boot application.

spring.datasource.url=jdbc:postgresql://prod-db/payment

Problems:

  • Hardcoded values
  • Cannot deploy to Dev or QA
  • Requires rebuilding
  • Difficult to maintain

Better Approach

Use environment variables.

spring.datasource.url=${DATABASE_URL}

Now only the environment variable changes.


Environment Variable Architecture

flowchart LR
    ConfigMap --> EnvironmentVariables
    Secret --> EnvironmentVariables
    EnvironmentVariables --> Pod
    Pod --> SpringBoot

The application remains unchanged while configuration changes per environment.


Environment Variable Flow

sequenceDiagram
    participant Admin
    participant OpenShift
    participant Pod
    participant SpringBoot

    Admin->>OpenShift: Configure Environment Variables
    OpenShift->>Pod: Inject Variables
    Pod->>SpringBoot: Start Application
    SpringBoot-->>Pod: Load Configuration

Common Environment Variables

Variable Example
DATABASE_URL jdbc:postgresql://postgres/payment
DATABASE_USERNAME paymentuser
DATABASE_PASSWORD ********
KAFKA_SERVERS kafka:9092
REDIS_HOST redis
LOG_LEVEL INFO
SPRING_PROFILES_ACTIVE prod

Spring Boot Property Resolution

Spring Boot reads configuration from multiple locations.

flowchart TD
    CommandLine["Command Line Arguments"]
    Environment["Environment Variables"]
    ConfigFile["application.properties"]
    Default["Default Values"]

    CommandLine --> SpringBoot
    Environment --> SpringBoot
    ConfigFile --> SpringBoot
    Default --> SpringBoot

Higher priority sources override lower ones.


Property Precedence

Highest priority first:

Priority Source
1 Command Line Arguments
2 Environment Variables
3 ConfigMaps
4 application.properties
5 Default Values

Configure Environment Variables

Deployment YAML

apiVersion: apps/v1
kind: Deployment

metadata:
  name: payment-api

spec:

  template:

    spec:

      containers:

      - name: payment-api

        image: quay.io/codewithvenu/payment-api:1.0

        env:

        - name: DATABASE_URL
          value: jdbc:postgresql://postgres/payment

        - name: LOG_LEVEL
          value: INFO

Deploy:

oc apply -f deployment.yaml

Verify Environment Variables

oc rsh payment-api-xxxxx

Run:

env

Example:

DATABASE_URL=jdbc:postgresql://postgres/payment

LOG_LEVEL=INFO

Spring Boot Example

spring.datasource.url=${DATABASE_URL}

logging.level.root=${LOG_LEVEL}

Spring Boot automatically resolves these values.


Using @Value

@Value("${DATABASE_URL}")
private String databaseUrl;

@Value("${LOG_LEVEL}")
private String logLevel;

Using ConfigurationProperties

@ConfigurationProperties(prefix = "database")
public class DatabaseProperties {

    private String url;

    private String username;

    private String password;

}

Preferred for enterprise applications.


ConfigMaps + Environment Variables

flowchart LR
    ConfigMap
    --> EnvironmentVariables
    --> SpringBoot

Deployment:

env:

- name: DATABASE_URL

  valueFrom:

    configMapKeyRef:

      name: payment-config

      key: DATABASE_URL

Secrets + Environment Variables

flowchart LR
    Secret
    --> EnvironmentVariables
    --> SpringBoot

Deployment:

env:

- name: DATABASE_PASSWORD

  valueFrom:

    secretKeyRef:

      name: payment-secret

      key: DATABASE_PASSWORD

Complete Configuration Architecture

flowchart TD
    ConfigMap

    --> EnvironmentVariables

    Secret

    --> EnvironmentVariables

    EnvironmentVariables

    --> SpringBoot

    SpringBoot

    --> PostgreSQL

    SpringBoot

    --> Kafka

    SpringBoot

    --> Redis

Spring Profiles

Applications often require different configuration per environment.

spring.profiles.active=${SPRING_PROFILES_ACTIVE}

Deployment:

env:

- name: SPRING_PROFILES_ACTIVE

  value: prod

Available profiles:

  • dev
  • qa
  • uat
  • prod

Profile Architecture

flowchart LR
    Dev["dev"]
    QA["qa"]
    UAT["uat"]
    Prod["prod"]

    Dev --> SpringBoot
    QA --> SpringBoot
    UAT --> SpringBoot
    Prod --> SpringBoot

Enterprise Banking Example

flowchart TD
    CONFIG["ConfigMap"]
    SECRET["Secret"]

    PAYMENT["Payment Service"]

    ORACLE[("Oracle Database")]
    KAFKA[("Kafka")]
    REDIS[("Redis")]

    CONFIG --> PAYMENT
    SECRET --> PAYMENT

    PAYMENT --> ORACLE
    PAYMENT --> KAFKA
    PAYMENT --> REDIS

All configuration is injected dynamically.


Feature Flags

Environment variables are commonly used for feature toggles.

env:

- name: ENABLE_REWARDS

  value: "true"

Spring Boot:

@Value("${ENABLE_REWARDS}")
private boolean rewardsEnabled;

Logging Configuration

env:

- name: LOG_LEVEL

  value: DEBUG

Spring Boot:

logging.level.root=${LOG_LEVEL}

Different environments can have different logging levels.


Update Environment Variables

Edit Deployment.

oc edit deployment payment-api

Restart:

oc rollout restart deployment/payment-api

Verify Deployment

oc describe deployment payment-api

Check:

  • Environment Variables
  • ConfigMaps
  • Secrets

Common Problems

Variable Not Found

Check:

env

inside the Pod.


Wrong Variable Name

Example:

${DATABASE_URL}

must match:

DATABASE_URL

Configuration Not Updated

Restart the Deployment.

oc rollout restart deployment/payment-api

Wrong Spring Profile

Verify:

echo $SPRING_PROFILES_ACTIVE

Best Practices

  • Keep configuration outside source code.
  • Use ConfigMaps for non-sensitive values.
  • Use Secrets for credentials.
  • Use Spring Profiles.
  • Use meaningful variable names.
  • Keep naming consistent across environments.
  • Version configuration with GitOps.
  • Document every environment variable.

Common Mistakes

❌ Hardcoding URLs.

❌ Storing passwords as environment variables directly in YAML instead of Secrets.

❌ Using different variable names across environments.

❌ Forgetting to restart Pods after changes.

❌ Mixing configuration with business logic.


Advantages

  • Environment independence
  • Easy deployments
  • Cloud-native configuration
  • Better security
  • Spring Boot integration
  • GitOps friendly
  • Faster releases
  • Enterprise ready

Summary

Environment Variables are the foundation of cloud-native configuration management.

Key takeaways:

  • Environment variables separate configuration from application code.
  • Spring Boot automatically maps environment variables to properties.
  • ConfigMaps and Secrets are the recommended sources for environment variables.
  • Spring Profiles enable environment-specific behavior.
  • Proper configuration management simplifies deployments across Dev, QA, UAT, and Production.

Interview Questions

  1. Why are environment variables used in OpenShift?
  2. How does Spring Boot read environment variables?
  3. What is the difference between ConfigMaps and Secrets?
  4. What is Spring Profile?
  5. How do you inject environment variables into a Pod?
  6. What is the property precedence order in Spring Boot?
  7. Why should applications avoid hardcoded configuration?
  8. How do you verify environment variables inside a running Pod?
  9. What are feature flags?
  10. What are the best practices for managing environment variables?