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
- Why are environment variables used in OpenShift?
- How does Spring Boot read environment variables?
- What is the difference between ConfigMaps and Secrets?
- What is Spring Profile?
- How do you inject environment variables into a Pod?
- What is the property precedence order in Spring Boot?
- Why should applications avoid hardcoded configuration?
- How do you verify environment variables inside a running Pod?
- What are feature flags?
- What are the best practices for managing environment variables?