Problem Statement
Design comprehensive environment management strategy including environment types, configuration management, secrets handling, and environment parity.
Explanation
Environment strategy defines progression from development to production ensuring quality while managing complexity. Standard environments: local (developer machine), development (shared dev environment), staging (pre-production), production (live users). Optional: QA (dedicated testing), UAT (user acceptance), integration (service integration testing), performance (load testing), canary (progressive rollout).
Environment characteristics:
Local development:
```yaml
# docker-compose.yml for local
version: '3.8'
services:
app:
build: .
environment:
- NODE_ENV=development
- DATABASE_URL=postgresql://localhost:5432/dev
- REDIS_URL=redis://localhost:6379
- LOG_LEVEL=debug
volumes:
- ./src:/app/src # Hot reload
ports:
- "3000:3000"
postgres:
image: postgres:13
environment:
- POSTGRES_DB=dev
- POSTGRES_PASSWORD=dev
volumes:
- postgres-data:/var/lib/postgresql/data
redis:
image: redis:6
```
Development environment:
```yaml
# k8s/dev/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: development
spec:
replicas: 1
template:
spec:
containers:
- name: myapp
image: myapp:latest
env:
- name: ENVIRONMENT
value: "development"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
```
Staging environment (production-like):
```yaml
# k8s/staging/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: staging
spec:
replicas: 2 # Similar to production
template:
spec:
containers:
- name: myapp
image: myapp:v1.2.3 # Tagged version
env:
- name: ENVIRONMENT
value: "staging"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
affinity: # Similar to production
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: myapp
topologyKey: kubernetes.io/hostname
```
Production environment:
```yaml
# k8s/production/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: production
spec:
replicas: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
spec:
containers:
- name: myapp
image: myapp:v1.2.3
env:
- name: ENVIRONMENT
value: "production"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
```
Configuration management per environment:
```javascript
// config/index.js
const configs = {
development: {
api: {
baseUrl: 'http://localhost:3000',
timeout: 30000
},
features: {
newCheckout: true,
analytics: false
},
database: {
pool: { min: 2, max: 10 }
}
},
staging: {
api: {
baseUrl: 'https://api-staging.example.com',
timeout: 10000
},
features: {
newCheckout: true,
analytics: true
},
database: {
pool: { min: 5, max: 20 }
}
},
production: {
api: {
baseUrl: 'https://api.example.com',
timeout: 5000
},
features: {
newCheckout: false,
analytics: true
},
database: {
pool: { min: 10, max: 50 }
}
}
};
module.exports = configs[process.env.NODE_ENV || 'development'];
```
Secrets management:
```yaml
# Using Sealed Secrets (encrypted in Git)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: db-credentials
namespace: production
spec:
encryptedData:
url: AgBH7Vw8K... # Encrypted value
---
# Using External Secrets Operator (from Vault)
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: db-credentials
data:
- secretKey: url
remoteRef:
key: database/production
property: connection_url
```
Environment parity checklist:
1. Same infrastructure components (load balancer, database, cache)
2. Similar resource allocation (staging = 50% of production)
3. Same configuration structure (different values)
4. Same monitoring and logging
5. Same deployment process
6. Realistic data volumes in staging
Terraform workspaces for environment management:
```hcl
# main.tf
terraform {
backend "s3" {
bucket = "terraform-state"
key = "myapp/terraform.tfstate"
region = "us-east-1"
}
}
variable "environment" {
type = string
}
locals {
config = {
dev = {
instance_count = 1
instance_type = "t3.small"
db_instance = "db.t3.micro"
}
staging = {
instance_count = 2
instance_type = "t3.medium"
db_instance = "db.t3.small"
}
production = {
instance_count = 5
instance_type = "t3.large"
db_instance = "db.r5.large"
}
}
env_config = local.config[var.environment]
}
resource "aws_instance" "app" {
count = local.env_config.instance_count
instance_type = local.env_config.instance_type
tags = {
Environment = var.environment
}
}
```
CI/CD pipeline with environment progression:
```yaml
stages:
- build
- deploy-dev
- test-dev
- deploy-staging
- test-staging
- deploy-production
deploy-dev:
stage: deploy-dev
script:
- ./deploy.sh dev $CI_COMMIT_SHA
environment:
name: development
url: https://dev.example.com
only:
- branches
test-dev:
stage: test-dev
script:
- npm run test:integration -- --env=dev
deploy-staging:
stage: deploy-staging
script:
- ./deploy.sh staging $CI_COMMIT_SHA
environment:
name: staging
url: https://staging.example.com
only:
- main
test-staging:
stage: test-staging
script:
- npm run test:e2e -- --env=staging
- npm run test:performance -- --env=staging
deploy-production:
stage: deploy-production
script:
- ./deploy.sh production $CI_COMMIT_TAG
environment:
name: production
url: https://example.com
when: manual
only:
- tags
```
Best practices: maintain environment parity (staging mirrors production), automate environment provisioning (Infrastructure as Code), isolate environments (separate networks/accounts), use consistent naming, implement proper access control, document environment differences, use environment-specific configurations, test production deployment in staging first, maintain separate credentials per environment, implement cost controls (auto-shutdown dev environments), regular environment refresh (reset staging data). Understanding environment management ensures quality progression to production.