Initial commit: add .gitignore and README
This commit is contained in:
49
.gitignore
vendored
Normal file
49
.gitignore
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
.pnpm-store/
|
||||
vendor/
|
||||
|
||||
# Package manager lock files (optional: uncomment to ignore)
|
||||
# package-lock.json
|
||||
# yarn.lock
|
||||
|
||||
# Environment and secrets
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
*.env.backup
|
||||
.env.backup.*
|
||||
|
||||
# Logs and temp
|
||||
*.log
|
||||
logs/
|
||||
*.tmp
|
||||
*.temp
|
||||
*.tmp.*
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Build / output
|
||||
dist/
|
||||
build/
|
||||
.next/
|
||||
out/
|
||||
*.pyc
|
||||
__pycache__/
|
||||
.eggs/
|
||||
*.egg-info/
|
||||
.coverage
|
||||
htmlcov/
|
||||
|
||||
# Optional
|
||||
.reports/
|
||||
reports/
|
||||
86
README.md
Normal file
86
README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Infrastructure Monorepo
|
||||
|
||||
**Purpose**: Consolidated infrastructure as code for all projects
|
||||
**Status**: 🚧 Structure Complete - Ready for Consolidation
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This directory contains all infrastructure as code, organized for easy management and deployment.
|
||||
|
||||
---
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
infrastructure/
|
||||
├── terraform/ # Terraform modules and configurations
|
||||
│ ├── modules/ # Shared Terraform modules
|
||||
│ └── examples/ # Example configurations
|
||||
├── kubernetes/ # Kubernetes configurations
|
||||
│ ├── shared-cluster/ # Shared cluster setup
|
||||
│ └── dev-staging/ # Dev/staging cluster configs
|
||||
├── monitoring/ # Monitoring stack
|
||||
│ ├── prometheus/ # Prometheus/Grafana
|
||||
│ ├── loki/ # Loki logging
|
||||
│ └── alerts/ # Alerting rules
|
||||
├── api-gateway/ # API Gateway (Kong)
|
||||
├── event-bus/ # Event bus (NATS)
|
||||
├── identity/ # Identity provider (Keycloak)
|
||||
└── data-storage/ # Data storage (MinIO)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Terraform Modules
|
||||
|
||||
### Azure Modules
|
||||
- `azure/networking` - Virtual networks and subnets
|
||||
- `azure/keyvault` - Key Vault
|
||||
- `azure/storage` - Storage accounts
|
||||
|
||||
### Kubernetes Modules
|
||||
- `kubernetes/namespace` - Namespace with quotas
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
|
||||
### Monitoring
|
||||
```bash
|
||||
cd monitoring/prometheus && ./install.sh
|
||||
cd monitoring/loki && ./install.sh
|
||||
```
|
||||
|
||||
### API Gateway
|
||||
```bash
|
||||
cd api-gateway/kong && ./install.sh
|
||||
```
|
||||
|
||||
### Event Bus
|
||||
```bash
|
||||
cd event-bus/nats && ./install.sh
|
||||
```
|
||||
|
||||
### Identity
|
||||
```bash
|
||||
kubectl apply -f identity/keycloak/k8s-deployment.yaml
|
||||
```
|
||||
|
||||
### Data Storage
|
||||
```bash
|
||||
kubectl apply -f data-storage/minio/k8s-deployment.yaml
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Infrastructure Deployment Guide](../docs/INFRASTRUCTURE_DEPLOYMENT_GUIDE.md)
|
||||
- [Terraform Migration Guide](../docs/TERRAFORM_MIGRATION_GUIDE.md)
|
||||
|
||||
---
|
||||
|
||||
**Status**: 🚧 Structure Complete - Ready for Project Consolidation
|
||||
|
||||
39
api-gateway/kong/install.sh
Executable file
39
api-gateway/kong/install.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
# Install Kong API Gateway
|
||||
|
||||
set -e
|
||||
|
||||
NAMESPACE="api-gateway"
|
||||
|
||||
echo "🚪 Installing Kong API Gateway..."
|
||||
|
||||
# Check prerequisites
|
||||
command -v kubectl >/dev/null 2>&1 || { echo "❌ kubectl not found"; exit 1; }
|
||||
|
||||
# Create namespace
|
||||
echo "📦 Creating namespace: $NAMESPACE"
|
||||
kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# Create ConfigMap from kong.yaml
|
||||
echo "📝 Creating Kong configuration..."
|
||||
kubectl create configmap kong-config \
|
||||
--from-file=kong.yaml=kong.yaml \
|
||||
--namespace="$NAMESPACE" \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# Apply deployment
|
||||
echo "🚀 Deploying Kong..."
|
||||
kubectl apply -f k8s-deployment.yaml
|
||||
|
||||
# Wait for deployment
|
||||
echo "⏳ Waiting for Kong to be ready..."
|
||||
kubectl wait --for=condition=available --timeout=300s deployment/kong -n "$NAMESPACE"
|
||||
|
||||
echo "✅ Kong API Gateway installed successfully!"
|
||||
echo ""
|
||||
echo "📝 Access Kong Admin API:"
|
||||
echo " kubectl port-forward -n $NAMESPACE svc/kong-proxy 8001:8001"
|
||||
echo ""
|
||||
echo "📝 Access Kong Proxy:"
|
||||
echo " kubectl port-forward -n $NAMESPACE svc/kong-proxy 8000:80"
|
||||
|
||||
89
api-gateway/kong/k8s-deployment.yaml
Normal file
89
api-gateway/kong/k8s-deployment.yaml
Normal file
@@ -0,0 +1,89 @@
|
||||
# Kong API Gateway Kubernetes Deployment
|
||||
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: api-gateway
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: kong
|
||||
namespace: api-gateway
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: kong
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: kong
|
||||
spec:
|
||||
containers:
|
||||
- name: kong
|
||||
image: kong:3.4
|
||||
env:
|
||||
- name: KONG_DATABASE
|
||||
value: "off"
|
||||
- name: KONG_DECLARATIVE_CONFIG
|
||||
value: "/kong/kong.yaml"
|
||||
- name: KONG_PROXY_ACCESS_LOG
|
||||
value: /dev/stdout
|
||||
- name: KONG_ADMIN_ACCESS_LOG
|
||||
value: /dev/stdout
|
||||
- name: KONG_PROXY_ERROR_LOG
|
||||
value: /dev/stderr
|
||||
- name: KONG_ADMIN_ERROR_LOG
|
||||
value: /dev/stderr
|
||||
- name: KONG_ADMIN_LISTEN
|
||||
value: "0.0.0.0:8001"
|
||||
ports:
|
||||
- name: proxy
|
||||
containerPort: 8000
|
||||
- name: admin
|
||||
containerPort: 8001
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
volumeMounts:
|
||||
- name: kong-config
|
||||
mountPath: /kong/kong.yaml
|
||||
subPath: kong.yaml
|
||||
volumes:
|
||||
- name: kong-config
|
||||
configMap:
|
||||
name: kong-config
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: kong-proxy
|
||||
namespace: api-gateway
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8000
|
||||
protocol: TCP
|
||||
name: http
|
||||
- port: 443
|
||||
targetPort: 8443
|
||||
protocol: TCP
|
||||
name: https
|
||||
selector:
|
||||
app: kong
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: kong-config
|
||||
namespace: api-gateway
|
||||
data:
|
||||
kong.yaml: |
|
||||
# Kong configuration will be loaded from kong.yaml file
|
||||
|
||||
75
api-gateway/kong/kong.yaml
Normal file
75
api-gateway/kong/kong.yaml
Normal file
@@ -0,0 +1,75 @@
|
||||
# Kong API Gateway Configuration
|
||||
|
||||
_format_version: "3.0"
|
||||
|
||||
services:
|
||||
- name: example-service
|
||||
url: http://example-service:8080
|
||||
routes:
|
||||
- name: example-route
|
||||
paths:
|
||||
- /api/example
|
||||
methods:
|
||||
- GET
|
||||
- POST
|
||||
- PUT
|
||||
- DELETE
|
||||
strip_path: false
|
||||
preserve_host: true
|
||||
|
||||
plugins:
|
||||
- name: rate-limiting
|
||||
service: example-service
|
||||
config:
|
||||
minute: 100
|
||||
hour: 1000
|
||||
policy: local
|
||||
fault_tolerant: true
|
||||
hide_client_headers: false
|
||||
|
||||
- name: cors
|
||||
service: example-service
|
||||
config:
|
||||
origins:
|
||||
- "*"
|
||||
methods:
|
||||
- GET
|
||||
- POST
|
||||
- PUT
|
||||
- DELETE
|
||||
- OPTIONS
|
||||
headers:
|
||||
- Accept
|
||||
- Accept-Version
|
||||
- Content-Length
|
||||
- Content-MD5
|
||||
- Content-Type
|
||||
- Date
|
||||
- Authorization
|
||||
exposed_headers:
|
||||
- X-Auth-Token
|
||||
credentials: true
|
||||
max_age: 3600
|
||||
|
||||
- name: jwt
|
||||
service: example-service
|
||||
config:
|
||||
uri_param_names:
|
||||
- token
|
||||
cookie_names:
|
||||
- jwt
|
||||
claims_to_verify:
|
||||
- exp
|
||||
- iat
|
||||
secret_is_base64: false
|
||||
run_on_preflight: true
|
||||
|
||||
consumers:
|
||||
- username: api-consumer
|
||||
custom_id: api-consumer-001
|
||||
|
||||
jwt_secrets:
|
||||
- consumer: api-consumer
|
||||
key: api-key-001
|
||||
secret: your-secret-key-here
|
||||
|
||||
112
data-storage/data-catalog/README.md
Normal file
112
data-storage/data-catalog/README.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Data Catalog
|
||||
|
||||
**Purpose**: Unified data catalog for tracking and discovering datasets
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The data catalog provides a centralized registry for all datasets across the workspace, enabling discovery, access control, and metadata management.
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- Dataset registration
|
||||
- Metadata management
|
||||
- Search and discovery
|
||||
- Access control
|
||||
- Schema tracking
|
||||
- Lineage tracking
|
||||
|
||||
---
|
||||
|
||||
## Schema
|
||||
|
||||
See `metadata-schema.json` for the complete metadata schema.
|
||||
|
||||
### Key Fields
|
||||
|
||||
- **id**: Unique dataset identifier
|
||||
- **name**: Human-readable name
|
||||
- **source**: Source system/project
|
||||
- **storage**: Storage location details
|
||||
- **schema**: Data schema definition
|
||||
- **tags**: Categorization tags
|
||||
- **access**: Access control settings
|
||||
|
||||
---
|
||||
|
||||
## Implementation Options
|
||||
|
||||
### Option 1: Custom API
|
||||
- Build custom API using shared packages
|
||||
- Use PostgreSQL for metadata storage
|
||||
- Implement search using PostgreSQL full-text search
|
||||
|
||||
### Option 2: DataHub
|
||||
- Deploy DataHub (open-source)
|
||||
- Use existing metadata models
|
||||
- Leverage built-in features
|
||||
|
||||
### Option 3: Amundsen
|
||||
- Deploy Amundsen (open-source)
|
||||
- Use existing metadata models
|
||||
- Leverage built-in features
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
### Register Dataset
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "user-events-2025",
|
||||
"name": "User Events 2025",
|
||||
"description": "User interaction events for 2025",
|
||||
"source": "analytics-service",
|
||||
"storage": {
|
||||
"type": "minio",
|
||||
"bucket": "analytics",
|
||||
"path": "events/2025/"
|
||||
},
|
||||
"format": "parquet",
|
||||
"tags": ["events", "analytics", "2025"],
|
||||
"owner": "analytics-team",
|
||||
"access": {
|
||||
"level": "internal",
|
||||
"permissions": ["read"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Search Datasets
|
||||
|
||||
```bash
|
||||
# Search by tag
|
||||
GET /api/catalog/datasets?tag=analytics
|
||||
|
||||
# Search by source
|
||||
GET /api/catalog/datasets?source=analytics-service
|
||||
|
||||
# Full-text search
|
||||
GET /api/catalog/datasets?q=user+events
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Choose implementation option
|
||||
2. Set up metadata storage
|
||||
3. Implement registration API
|
||||
4. Implement search functionality
|
||||
5. Set up access control
|
||||
6. Integrate with projects
|
||||
|
||||
---
|
||||
|
||||
**Status**: 🚧 Planned - Schema and design complete, implementation pending
|
||||
|
||||
92
data-storage/data-catalog/metadata-schema.json
Normal file
92
data-storage/data-catalog/metadata-schema.json
Normal file
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"title": "Data Catalog Metadata Schema",
|
||||
"description": "Schema for data catalog metadata",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique identifier for the dataset"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Human-readable name of the dataset"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Description of the dataset"
|
||||
},
|
||||
"source": {
|
||||
"type": "string",
|
||||
"description": "Source system or project"
|
||||
},
|
||||
"storage": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["s3", "minio", "azure-blob", "gcs"],
|
||||
"description": "Storage type"
|
||||
},
|
||||
"bucket": {
|
||||
"type": "string",
|
||||
"description": "Bucket or container name"
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Path within bucket"
|
||||
}
|
||||
},
|
||||
"required": ["type", "bucket"]
|
||||
},
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"description": "Data schema definition"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": ["parquet", "json", "csv", "avro"],
|
||||
"description": "Data format"
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Tags for categorization"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string",
|
||||
"description": "Owner or team responsible"
|
||||
},
|
||||
"created": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Creation timestamp"
|
||||
},
|
||||
"updated": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Last update timestamp"
|
||||
},
|
||||
"access": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"level": {
|
||||
"type": "string",
|
||||
"enum": ["public", "internal", "restricted"],
|
||||
"description": "Access level"
|
||||
},
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": ["read", "write", "delete"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["id", "name", "source", "storage"]
|
||||
}
|
||||
|
||||
100
data-storage/minio/k8s-deployment.yaml
Normal file
100
data-storage/minio/k8s-deployment.yaml
Normal file
@@ -0,0 +1,100 @@
|
||||
# MinIO Object Storage Kubernetes Deployment
|
||||
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: data-storage
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: minio-secret
|
||||
namespace: data-storage
|
||||
type: Opaque
|
||||
stringData:
|
||||
MINIO_ROOT_USER: minioadmin
|
||||
MINIO_ROOT_PASSWORD: change-me-in-production
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: minio
|
||||
namespace: data-storage
|
||||
spec:
|
||||
serviceName: minio
|
||||
replicas: 4
|
||||
selector:
|
||||
matchLabels:
|
||||
app: minio
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: minio
|
||||
spec:
|
||||
containers:
|
||||
- name: minio
|
||||
image: minio/minio:latest
|
||||
args:
|
||||
- server
|
||||
- /data
|
||||
- --console-address
|
||||
- ":9001"
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: minio-secret
|
||||
ports:
|
||||
- containerPort: 9000
|
||||
name: api
|
||||
- containerPort: 9001
|
||||
name: console
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /data
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "500m"
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: standard
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: minio
|
||||
namespace: data-storage
|
||||
spec:
|
||||
clusterIP: None
|
||||
ports:
|
||||
- port: 9000
|
||||
targetPort: 9000
|
||||
name: api
|
||||
- port: 9001
|
||||
targetPort: 9001
|
||||
name: console
|
||||
selector:
|
||||
app: minio
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: minio-console
|
||||
namespace: data-storage
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- port: 9001
|
||||
targetPort: 9001
|
||||
name: console
|
||||
selector:
|
||||
app: minio
|
||||
|
||||
30
event-bus/nats/install.sh
Executable file
30
event-bus/nats/install.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
# Install NATS Event Bus
|
||||
|
||||
set -e
|
||||
|
||||
NAMESPACE="event-bus"
|
||||
|
||||
echo "📡 Installing NATS Event Bus..."
|
||||
|
||||
# Check prerequisites
|
||||
command -v kubectl >/dev/null 2>&1 || { echo "❌ kubectl not found"; exit 1; }
|
||||
|
||||
# Create namespace
|
||||
echo "📦 Creating namespace: $NAMESPACE"
|
||||
kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# Apply deployment
|
||||
echo "🚀 Deploying NATS..."
|
||||
kubectl apply -f k8s-deployment.yaml
|
||||
|
||||
# Wait for StatefulSet
|
||||
echo "⏳ Waiting for NATS to be ready..."
|
||||
kubectl wait --for=condition=ready --timeout=300s pod -l app=nats -n "$NAMESPACE"
|
||||
|
||||
echo "✅ NATS Event Bus installed successfully!"
|
||||
echo ""
|
||||
echo "📝 Access NATS monitoring:"
|
||||
echo " kubectl port-forward -n $NAMESPACE svc/nats 8222:8222"
|
||||
echo " Then visit: http://localhost:8222"
|
||||
|
||||
96
event-bus/nats/k8s-deployment.yaml
Normal file
96
event-bus/nats/k8s-deployment.yaml
Normal file
@@ -0,0 +1,96 @@
|
||||
# NATS Server Kubernetes Deployment
|
||||
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: event-bus
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nats-config
|
||||
namespace: event-bus
|
||||
data:
|
||||
nats.conf: |
|
||||
port: 4222
|
||||
http_port: 8222
|
||||
jetstream:
|
||||
store_dir: /data/jetstream
|
||||
max_mem: 2GB
|
||||
max_file: 10GB
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: nats
|
||||
namespace: event-bus
|
||||
spec:
|
||||
serviceName: nats
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nats
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nats
|
||||
spec:
|
||||
containers:
|
||||
- name: nats
|
||||
image: nats:2.10-alpine
|
||||
args:
|
||||
- -c
|
||||
- /etc/nats/nats.conf
|
||||
ports:
|
||||
- name: client
|
||||
containerPort: 4222
|
||||
- name: cluster
|
||||
containerPort: 6222
|
||||
- name: monitor
|
||||
containerPort: 8222
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/nats
|
||||
- name: data
|
||||
mountPath: /data/jetstream
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "200m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "500m"
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: nats-config
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: standard
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nats
|
||||
namespace: event-bus
|
||||
spec:
|
||||
clusterIP: None
|
||||
ports:
|
||||
- port: 4222
|
||||
targetPort: 4222
|
||||
name: client
|
||||
- port: 6222
|
||||
targetPort: 6222
|
||||
name: cluster
|
||||
- port: 8222
|
||||
targetPort: 8222
|
||||
name: monitor
|
||||
selector:
|
||||
app: nats
|
||||
|
||||
41
event-bus/nats/nats.yaml
Normal file
41
event-bus/nats/nats.yaml
Normal file
@@ -0,0 +1,41 @@
|
||||
# NATS Server Configuration
|
||||
|
||||
port: 4222
|
||||
http_port: 8222
|
||||
cluster:
|
||||
port: 6222
|
||||
routes:
|
||||
- nats://nats-1:6222
|
||||
- nats://nats-2:6222
|
||||
- nats://nats-3:6222
|
||||
|
||||
jetstream:
|
||||
store_dir: /data/jetstream
|
||||
max_mem: 2GB
|
||||
max_file: 10GB
|
||||
|
||||
logging:
|
||||
time: true
|
||||
debug: false
|
||||
trace: false
|
||||
logtime: true
|
||||
log_file: "/var/log/nats/nats.log"
|
||||
log_size_limit: 100MB
|
||||
|
||||
authorization:
|
||||
users:
|
||||
- user: api-user
|
||||
password: ${NATS_API_PASSWORD}
|
||||
permissions:
|
||||
publish:
|
||||
- ">"
|
||||
subscribe:
|
||||
- ">"
|
||||
- user: service-user
|
||||
password: ${NATS_SERVICE_PASSWORD}
|
||||
permissions:
|
||||
publish:
|
||||
- "events.>"
|
||||
subscribe:
|
||||
- "events.>"
|
||||
|
||||
109
identity/keycloak/k8s-deployment.yaml
Normal file
109
identity/keycloak/k8s-deployment.yaml
Normal file
@@ -0,0 +1,109 @@
|
||||
# Keycloak Identity Provider Kubernetes Deployment
|
||||
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: identity
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: keycloak-db-secret
|
||||
namespace: identity
|
||||
type: Opaque
|
||||
stringData:
|
||||
username: keycloak
|
||||
password: change-me-in-production
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: keycloak
|
||||
namespace: identity
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: keycloak
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: keycloak
|
||||
spec:
|
||||
containers:
|
||||
- name: keycloak
|
||||
image: quay.io/keycloak/keycloak:23.0
|
||||
args:
|
||||
- start
|
||||
- --hostname-strict=false
|
||||
- --proxy-headers=xforwarded
|
||||
- --http-relative-path=/
|
||||
env:
|
||||
- name: KEYCLOAK_ADMIN
|
||||
value: admin
|
||||
- name: KEYCLOAK_ADMIN_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: keycloak-admin-secret
|
||||
key: password
|
||||
- name: KC_DB
|
||||
value: postgres
|
||||
- name: KC_DB_URL
|
||||
value: jdbc:postgresql://postgres:5432/keycloak
|
||||
- name: KC_DB_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: keycloak-db-secret
|
||||
key: username
|
||||
- name: KC_DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: keycloak-db-secret
|
||||
key: password
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
resources:
|
||||
requests:
|
||||
memory: "1Gi"
|
||||
cpu: "500m"
|
||||
limits:
|
||||
memory: "2Gi"
|
||||
cpu: "1000m"
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /health/ready
|
||||
port: 8080
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /health/live
|
||||
port: 8080
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 10
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: keycloak
|
||||
namespace: identity
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app: keycloak
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: keycloak-admin-secret
|
||||
namespace: identity
|
||||
type: Opaque
|
||||
stringData:
|
||||
password: change-me-in-production
|
||||
|
||||
69
identity/user-management/keycloak-realm.json
Normal file
69
identity/user-management/keycloak-realm.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"realm": "workspace",
|
||||
"enabled": true,
|
||||
"displayName": "Workspace Realm",
|
||||
"displayNameHtml": "<div class=\"kc-logo-text\"><span>Workspace</span></div>",
|
||||
"users": [
|
||||
{
|
||||
"username": "admin",
|
||||
"enabled": true,
|
||||
"emailVerified": true,
|
||||
"firstName": "Admin",
|
||||
"lastName": "User",
|
||||
"email": "admin@example.com",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"value": "change-me-in-production",
|
||||
"temporary": false
|
||||
}
|
||||
],
|
||||
"realmRoles": ["admin", "user"]
|
||||
}
|
||||
],
|
||||
"roles": {
|
||||
"realm": [
|
||||
{
|
||||
"name": "admin",
|
||||
"description": "Administrator role"
|
||||
},
|
||||
{
|
||||
"name": "user",
|
||||
"description": "Standard user role"
|
||||
},
|
||||
{
|
||||
"name": "developer",
|
||||
"description": "Developer role"
|
||||
},
|
||||
{
|
||||
"name": "viewer",
|
||||
"description": "View-only role"
|
||||
}
|
||||
]
|
||||
},
|
||||
"clients": [
|
||||
{
|
||||
"clientId": "workspace-api",
|
||||
"enabled": true,
|
||||
"clientAuthenticatorType": "client-secret",
|
||||
"secret": "change-me-in-production",
|
||||
"redirectUris": ["*"],
|
||||
"webOrigins": ["*"],
|
||||
"protocol": "openid-connect",
|
||||
"publicClient": false,
|
||||
"standardFlowEnabled": true,
|
||||
"directAccessGrantsEnabled": true
|
||||
}
|
||||
],
|
||||
"identityProviders": [],
|
||||
"smtpServer": {
|
||||
"host": "smtp.example.com",
|
||||
"port": "587",
|
||||
"from": "noreply@example.com",
|
||||
"auth": true,
|
||||
"starttls": true,
|
||||
"user": "smtp-user",
|
||||
"password": "smtp-password"
|
||||
}
|
||||
}
|
||||
|
||||
48
identity/user-management/setup.sh
Executable file
48
identity/user-management/setup.sh
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
# Setup centralized user management in Keycloak
|
||||
|
||||
set -e
|
||||
|
||||
NAMESPACE="identity"
|
||||
KEYCLOAK_URL="${KEYCLOAK_URL:-http://keycloak.${NAMESPACE}.svc.cluster.local:8080}"
|
||||
ADMIN_USER="${KEYCLOAK_ADMIN:-admin}"
|
||||
ADMIN_PASSWORD="${KEYCLOAK_ADMIN_PASSWORD:-change-me-in-production}"
|
||||
|
||||
echo "👥 Setting up centralized user management..."
|
||||
|
||||
# Check if Keycloak is accessible
|
||||
if ! curl -s "${KEYCLOAK_URL}/health" > /dev/null; then
|
||||
echo "⚠️ Keycloak not accessible at $KEYCLOAK_URL"
|
||||
echo " → Ensure Keycloak is deployed and running"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get admin token
|
||||
echo "🔑 Getting admin token..."
|
||||
TOKEN=$(curl -s -X POST "${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" \
|
||||
-d "client_id=admin-cli" \
|
||||
-d "username=${ADMIN_USER}" \
|
||||
-d "password=${ADMIN_PASSWORD}" \
|
||||
-d "grant_type=password" | jq -r '.access_token')
|
||||
|
||||
if [ -z "$TOKEN" ] || [ "$TOKEN" == "null" ]; then
|
||||
echo "❌ Failed to get admin token"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create realm
|
||||
echo "🌍 Creating workspace realm..."
|
||||
curl -s -X POST "${KEYCLOAK_URL}/admin/realms" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @keycloak-realm.json
|
||||
|
||||
echo "✅ User management setup complete!"
|
||||
echo ""
|
||||
echo "📝 Next steps:"
|
||||
echo " 1. Access Keycloak admin console"
|
||||
echo " 2. Review realm configuration"
|
||||
echo " 3. Create additional users and roles"
|
||||
echo " 4. Configure identity providers (if needed)"
|
||||
echo " 5. Set up user federation (if needed)"
|
||||
|
||||
31
kubernetes/dev-staging/cluster-config.yaml
Normal file
31
kubernetes/dev-staging/cluster-config.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
# Development and Staging Kubernetes Cluster Configuration
|
||||
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: cluster-config
|
||||
namespace: kube-system
|
||||
data:
|
||||
environment: "dev-staging"
|
||||
cluster-type: "shared"
|
||||
node-pool:
|
||||
dev: "dev-pool"
|
||||
staging: "staging-pool"
|
||||
resource-quotas:
|
||||
dev: |
|
||||
requests.cpu: "4"
|
||||
requests.memory: "8Gi"
|
||||
limits.cpu: "8"
|
||||
limits.memory: "16Gi"
|
||||
staging: |
|
||||
requests.cpu: "8"
|
||||
requests.memory: "16Gi"
|
||||
limits.cpu: "16"
|
||||
limits.memory: "32Gi"
|
||||
storage-classes:
|
||||
dev: "standard"
|
||||
staging: "premium"
|
||||
network-policies: "enabled"
|
||||
monitoring: "enabled"
|
||||
logging: "enabled"
|
||||
|
||||
70
kubernetes/dev-staging/setup.sh
Executable file
70
kubernetes/dev-staging/setup.sh
Executable file
@@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
# Setup shared dev/staging Kubernetes clusters
|
||||
|
||||
set -e
|
||||
|
||||
echo "☸️ Setting up shared dev/staging Kubernetes clusters..."
|
||||
|
||||
# Check prerequisites
|
||||
command -v kubectl >/dev/null 2>&1 || { echo "❌ kubectl not found"; exit 1; }
|
||||
command -v helm >/dev/null 2>&1 || { echo "❌ helm not found"; exit 1; }
|
||||
|
||||
# Create namespaces
|
||||
echo "📦 Creating namespaces..."
|
||||
kubectl create namespace dev --dry-run=client -o yaml | kubectl apply -f -
|
||||
kubectl create namespace staging --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# Label namespaces
|
||||
kubectl label namespace dev environment=dev --overwrite
|
||||
kubectl label namespace staging environment=staging --overwrite
|
||||
|
||||
# Apply cluster configuration
|
||||
echo "⚙️ Applying cluster configuration..."
|
||||
kubectl apply -f cluster-config.yaml
|
||||
|
||||
# Set up resource quotas
|
||||
echo "📊 Setting up resource quotas..."
|
||||
|
||||
# Dev namespace quota
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: v1
|
||||
kind: ResourceQuota
|
||||
metadata:
|
||||
name: dev-quota
|
||||
namespace: dev
|
||||
spec:
|
||||
hard:
|
||||
requests.cpu: "4"
|
||||
requests.memory: 8Gi
|
||||
limits.cpu: "8"
|
||||
limits.memory: 16Gi
|
||||
persistentvolumeclaims: "10"
|
||||
services.loadbalancers: "2"
|
||||
EOF
|
||||
|
||||
# Staging namespace quota
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: v1
|
||||
kind: ResourceQuota
|
||||
metadata:
|
||||
name: staging-quota
|
||||
namespace: staging
|
||||
spec:
|
||||
hard:
|
||||
requests.cpu: "8"
|
||||
requests.memory: 16Gi
|
||||
limits.cpu: "16"
|
||||
limits.memory: 32Gi
|
||||
persistentvolumeclaims: "20"
|
||||
services.loadbalancers: "4"
|
||||
EOF
|
||||
|
||||
echo "✅ Shared dev/staging clusters configured!"
|
||||
echo ""
|
||||
echo "📝 Namespaces created:"
|
||||
echo " - dev"
|
||||
echo " - staging"
|
||||
echo ""
|
||||
echo "📝 Resource quotas configured"
|
||||
echo "📝 Cluster configuration applied"
|
||||
|
||||
82
kubernetes/shared-cluster/ingress-controller.yaml
Normal file
82
kubernetes/shared-cluster/ingress-controller.yaml
Normal file
@@ -0,0 +1,82 @@
|
||||
# NGINX Ingress Controller Configuration
|
||||
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: ingress-nginx
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: ingress-nginx
|
||||
namespace: ingress-nginx
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: ingress-nginx-controller
|
||||
namespace: ingress-nginx
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: ingress-nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: ingress-nginx
|
||||
spec:
|
||||
serviceAccountName: ingress-nginx
|
||||
containers:
|
||||
- name: controller
|
||||
image: registry.k8s.io/ingress-nginx/controller:v1.9.0
|
||||
args:
|
||||
- /nginx-ingress-controller
|
||||
- --configmap=$(POD_NAMESPACE)/nginx-configuration
|
||||
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
|
||||
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
|
||||
- --annotations-prefix=nginx.ingress.kubernetes.io
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
- name: https
|
||||
containerPort: 443
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ingress-nginx
|
||||
namespace: ingress-nginx
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
name: http
|
||||
- port: 443
|
||||
targetPort: 443
|
||||
protocol: TCP
|
||||
name: https
|
||||
selector:
|
||||
app: ingress-nginx
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nginx-configuration
|
||||
namespace: ingress-nginx
|
||||
data:
|
||||
enable-cors: "true"
|
||||
cors-allow-origin: "*"
|
||||
cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"
|
||||
cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization"
|
||||
ssl-protocols: "TLSv1.2 TLSv1.3"
|
||||
|
||||
63
kubernetes/shared-cluster/namespace-isolation.yaml
Normal file
63
kubernetes/shared-cluster/namespace-isolation.yaml
Normal file
@@ -0,0 +1,63 @@
|
||||
# Namespace Isolation Configuration
|
||||
# Network Policies and RBAC for shared clusters
|
||||
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: shared-services
|
||||
labels:
|
||||
name: shared-services
|
||||
type: shared
|
||||
---
|
||||
# Network Policy: Allow ingress from shared-services namespace
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-from-shared-services
|
||||
namespace: default
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: shared-services
|
||||
---
|
||||
# RBAC: Service Account for shared services
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: shared-services-sa
|
||||
namespace: shared-services
|
||||
---
|
||||
# Role: Limited permissions for shared services
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: shared-services-role
|
||||
namespace: shared-services
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods", "services"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["deployments"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
---
|
||||
# RoleBinding: Bind role to service account
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: shared-services-binding
|
||||
namespace: shared-services
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: shared-services-sa
|
||||
namespace: shared-services
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: shared-services-role
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
|
||||
27
kubernetes/shared-cluster/setup.sh
Executable file
27
kubernetes/shared-cluster/setup.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
# Setup shared Kubernetes cluster configuration
|
||||
|
||||
set -e
|
||||
|
||||
echo "☸️ Setting up shared Kubernetes cluster configuration..."
|
||||
|
||||
# Check prerequisites
|
||||
command -v kubectl >/dev/null 2>&1 || { echo "❌ kubectl not found"; exit 1; }
|
||||
|
||||
# Apply namespace isolation
|
||||
echo "🔒 Applying namespace isolation..."
|
||||
kubectl apply -f namespace-isolation.yaml
|
||||
|
||||
# Apply ingress controller
|
||||
echo "🚪 Setting up ingress controller..."
|
||||
kubectl apply -f ingress-controller.yaml
|
||||
|
||||
# Wait for ingress controller
|
||||
echo "⏳ Waiting for ingress controller to be ready..."
|
||||
kubectl wait --for=condition=available --timeout=300s deployment/ingress-nginx-controller -n ingress-nginx
|
||||
|
||||
echo "✅ Shared Kubernetes cluster configuration complete!"
|
||||
echo ""
|
||||
echo "📝 Ingress controller is ready"
|
||||
echo " Get external IP: kubectl get svc -n ingress-nginx ingress-nginx"
|
||||
|
||||
101
monitoring/alerts/prometheus-rules.yaml
Normal file
101
monitoring/alerts/prometheus-rules.yaml
Normal file
@@ -0,0 +1,101 @@
|
||||
# Prometheus Alerting Rules
|
||||
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: PrometheusRule
|
||||
metadata:
|
||||
name: shared-services-alerts
|
||||
namespace: monitoring
|
||||
labels:
|
||||
app: prometheus
|
||||
spec:
|
||||
groups:
|
||||
- name: kubernetes.rules
|
||||
interval: 30s
|
||||
rules:
|
||||
- alert: PodCrashLooping
|
||||
expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is crash looping"
|
||||
description: "Pod {{ $labels.namespace }}/{{ $labels.pod }} has restarted {{ $value }} times in the last 15 minutes"
|
||||
|
||||
- alert: PodNotReady
|
||||
expr: sum by (namespace, pod) (kube_pod_status_phase{phase!~"Running|Succeeded"}) > 0
|
||||
for: 10m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is not ready"
|
||||
description: "Pod {{ $labels.namespace }}/{{ $labels.pod }} has been in a non-ready state for more than 10 minutes"
|
||||
|
||||
- alert: HighMemoryUsage
|
||||
expr: (sum by (namespace, pod) (container_memory_usage_bytes) / sum by (namespace, pod) (kube_pod_container_resource_limits_memory_bytes)) > 0.9
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} memory usage is high"
|
||||
description: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is using {{ $value | humanizePercentage }} of its memory limit"
|
||||
|
||||
- alert: HighCPUUsage
|
||||
expr: (sum by (namespace, pod) (rate(container_cpu_usage_seconds_total[5m])) / sum by (namespace, pod) (kube_pod_container_resource_limits_cpu)) > 0.9
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} CPU usage is high"
|
||||
description: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is using {{ $value | humanizePercentage }} of its CPU limit"
|
||||
|
||||
- name: application.rules
|
||||
interval: 30s
|
||||
rules:
|
||||
- alert: HighErrorRate
|
||||
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.1
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "High error rate detected"
|
||||
description: "Error rate is {{ $value }} errors per second"
|
||||
|
||||
- alert: HighLatency
|
||||
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 1
|
||||
for: 10m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "High latency detected"
|
||||
description: "95th percentile latency is {{ $value }} seconds"
|
||||
|
||||
- alert: ServiceDown
|
||||
expr: up{job=~".+"} == 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "Service {{ $labels.job }} is down"
|
||||
description: "Service {{ $labels.job }} has been down for more than 1 minute"
|
||||
|
||||
- name: infrastructure.rules
|
||||
interval: 30s
|
||||
rules:
|
||||
- alert: NodeNotReady
|
||||
expr: kube_node_status_condition{condition="Ready",status="true"} == 0
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "Node {{ $labels.node }} is not ready"
|
||||
description: "Node {{ $labels.node }} has been in a not-ready state for more than 5 minutes"
|
||||
|
||||
- alert: DiskSpaceLow
|
||||
expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) < 0.1
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "Disk space low on {{ $labels.instance }}"
|
||||
description: "Disk {{ $labels.device }} on {{ $labels.instance }} has only {{ $value | humanizePercentage }} space available"
|
||||
|
||||
50
monitoring/event-monitoring/prometheus-rules.yaml
Normal file
50
monitoring/event-monitoring/prometheus-rules.yaml
Normal file
@@ -0,0 +1,50 @@
|
||||
# Event Bus Monitoring Rules
|
||||
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: PrometheusRule
|
||||
metadata:
|
||||
name: event-bus-alerts
|
||||
namespace: event-bus
|
||||
labels:
|
||||
app: nats
|
||||
spec:
|
||||
groups:
|
||||
- name: nats.rules
|
||||
interval: 30s
|
||||
rules:
|
||||
- alert: NATSConnectionFailure
|
||||
expr: nats_connz_connections{state!="OPEN"} > 0
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "NATS connection failure detected"
|
||||
description: "NATS has {{ $value }} non-open connections"
|
||||
|
||||
- alert: NATSHighMessageRate
|
||||
expr: rate(nats_varz_in_msgs[5m]) > 10000
|
||||
for: 10m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "High NATS message rate"
|
||||
description: "NATS is processing {{ $value }} messages per second"
|
||||
|
||||
- alert: NATSJetStreamStorageFull
|
||||
expr: (nats_jetstream_varz_store_bytes / nats_jetstream_varz_store_max_bytes) > 0.9
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "NATS JetStream storage nearly full"
|
||||
description: "JetStream storage is {{ $value | humanizePercentage }} full"
|
||||
|
||||
- alert: NATSPodDown
|
||||
expr: up{job="nats"} == 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "NATS pod is down"
|
||||
description: "NATS pod has been down for more than 1 minute"
|
||||
|
||||
19
monitoring/event-monitoring/setup.sh
Executable file
19
monitoring/event-monitoring/setup.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
# Setup event monitoring
|
||||
|
||||
set -e
|
||||
|
||||
echo "📡 Setting up event monitoring..."
|
||||
|
||||
# Apply Prometheus rules
|
||||
echo "📊 Applying Prometheus rules for event bus..."
|
||||
kubectl apply -f prometheus-rules.yaml
|
||||
|
||||
echo "✅ Event monitoring configured!"
|
||||
echo ""
|
||||
echo "📝 Monitoring:"
|
||||
echo " - NATS connection metrics"
|
||||
echo " - Message rate metrics"
|
||||
echo " - JetStream storage metrics"
|
||||
echo " - Pod health metrics"
|
||||
|
||||
36
monitoring/loki/install.sh
Executable file
36
monitoring/loki/install.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# Install Loki Stack for Logging
|
||||
|
||||
set -e
|
||||
|
||||
NAMESPACE="monitoring"
|
||||
RELEASE_NAME="loki"
|
||||
|
||||
echo "📊 Installing Loki Stack..."
|
||||
|
||||
# Check prerequisites
|
||||
command -v helm >/dev/null 2>&1 || { echo "❌ helm not found"; exit 1; }
|
||||
command -v kubectl >/dev/null 2>&1 || { echo "❌ kubectl not found"; exit 1; }
|
||||
|
||||
# Create namespace
|
||||
echo "📦 Creating namespace: $NAMESPACE"
|
||||
kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# Add Grafana Helm repo
|
||||
echo "📥 Adding Grafana Helm repository..."
|
||||
helm repo add grafana https://grafana.github.io/helm-charts
|
||||
helm repo update
|
||||
|
||||
# Install Loki Stack
|
||||
echo "🚀 Installing Loki Stack..."
|
||||
helm upgrade --install "$RELEASE_NAME" grafana/loki-stack \
|
||||
--namespace "$NAMESPACE" \
|
||||
--create-namespace \
|
||||
--values values.yaml \
|
||||
--wait
|
||||
|
||||
echo "✅ Loki Stack installed successfully!"
|
||||
echo ""
|
||||
echo "📝 Access Grafana:"
|
||||
echo " kubectl port-forward -n $NAMESPACE svc/$RELEASE_NAME-grafana 3000:80"
|
||||
|
||||
87
monitoring/loki/values.yaml
Normal file
87
monitoring/loki/values.yaml
Normal file
@@ -0,0 +1,87 @@
|
||||
# Loki Stack Helm Values
|
||||
|
||||
loki:
|
||||
enabled: true
|
||||
persistence:
|
||||
enabled: true
|
||||
storageClassName: standard
|
||||
size: 50Gi
|
||||
resources:
|
||||
requests:
|
||||
memory: 1Gi
|
||||
cpu: 500m
|
||||
limits:
|
||||
memory: 2Gi
|
||||
cpu: 1000m
|
||||
config:
|
||||
schema_config:
|
||||
configs:
|
||||
- from: 2020-10-24
|
||||
store: boltdb-shipper
|
||||
object_store: filesystem
|
||||
schema: v11
|
||||
index:
|
||||
prefix: index_
|
||||
period: 24h
|
||||
storage_config:
|
||||
boltdb_shipper:
|
||||
active_index_directory: /loki/boltdb-shipper-active
|
||||
cache_location: /loki/boltdb-shipper-cache
|
||||
shared_store: filesystem
|
||||
filesystem:
|
||||
directory: /loki/chunks
|
||||
limits_config:
|
||||
ingestion_rate_mb: 10
|
||||
ingestion_burst_size_mb: 20
|
||||
max_query_length: 0h
|
||||
max_query_parallelism: 32
|
||||
max_streams_per_user: 10000
|
||||
|
||||
promtail:
|
||||
enabled: true
|
||||
config:
|
||||
clients:
|
||||
- url: http://loki:3100/loki/api/v1/push
|
||||
scrape_configs:
|
||||
- job_name: kubernetes-pods
|
||||
kubernetes_sd_configs:
|
||||
- role: pod
|
||||
relabel_configs:
|
||||
- source_labels:
|
||||
- __meta_kubernetes_pod_controller_name
|
||||
regex: ([0-9a-z-.]+?)(-[0-9a-f]{8,10})?
|
||||
action: replace
|
||||
target_label: __tmp_controller_name
|
||||
- source_labels:
|
||||
- __meta_kubernetes_pod_label_app_kubernetes_io_name
|
||||
- __meta_kubernetes_pod_label_app
|
||||
- __tmp_controller_name
|
||||
- __meta_kubernetes_pod_name
|
||||
regex: ^;*([^;]+)(;.*)?$
|
||||
action: replace
|
||||
target_label: app
|
||||
- source_labels:
|
||||
- __meta_kubernetes_pod_label_app_kubernetes_io_instance
|
||||
- __meta_kubernetes_pod_label_release
|
||||
regex: ^;*([^;]+)(;.*)?$
|
||||
action: replace
|
||||
target_label: instance
|
||||
- source_labels:
|
||||
- __meta_kubernetes_pod_label_app_kubernetes_io_component
|
||||
- __meta_kubernetes_pod_label_component
|
||||
regex: ^;*([^;]+)(;.*)?$
|
||||
action: replace
|
||||
target_label: component
|
||||
|
||||
grafana:
|
||||
enabled: true
|
||||
datasources:
|
||||
datasources.yaml:
|
||||
apiVersion: 1
|
||||
datasources:
|
||||
- name: Loki
|
||||
type: loki
|
||||
access: proxy
|
||||
url: http://loki:3100
|
||||
isDefault: false
|
||||
|
||||
151
monitoring/metrics-dashboard/grafana-dashboard.json
Normal file
151
monitoring/metrics-dashboard/grafana-dashboard.json
Normal file
@@ -0,0 +1,151 @@
|
||||
{
|
||||
"dashboard": {
|
||||
"title": "Integration & Streamlining Success Metrics",
|
||||
"tags": ["metrics", "success", "integration"],
|
||||
"timezone": "browser",
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Infrastructure Cost Reduction",
|
||||
"type": "stat",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "infrastructure_cost_reduction_percent",
|
||||
"legendFormat": "Cost Reduction"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "percent",
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{ "value": 0, "color": "red" },
|
||||
{ "value": 30, "color": "yellow" },
|
||||
{ "value": 40, "color": "green" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Shared Infrastructure Adoption",
|
||||
"type": "stat",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "shared_infrastructure_adoption_percent",
|
||||
"legendFormat": "Adoption"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "percent",
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{ "value": 0, "color": "red" },
|
||||
{ "value": 60, "color": "yellow" },
|
||||
{ "value": 80, "color": "green" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Shared Packages Usage",
|
||||
"type": "stat",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "shared_packages_count",
|
||||
"legendFormat": "Packages"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "short",
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{ "value": 0, "color": "red" },
|
||||
{ "value": 7, "color": "yellow" },
|
||||
{ "value": 10, "color": "green" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"title": "Deployment Time Reduction",
|
||||
"type": "stat",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "deployment_time_reduction_percent",
|
||||
"legendFormat": "Time Reduction"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "percent",
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{ "value": 0, "color": "red" },
|
||||
{ "value": 30, "color": "yellow" },
|
||||
{ "value": 50, "color": "green" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"title": "CI/CD Adoption",
|
||||
"type": "stat",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "cicd_adoption_percent",
|
||||
"legendFormat": "Adoption"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "percent",
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{ "value": 0, "color": "red" },
|
||||
{ "value": 70, "color": "yellow" },
|
||||
{ "value": 90, "color": "green" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"title": "Service Uptime",
|
||||
"type": "stat",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "service_uptime_percent",
|
||||
"legendFormat": "Uptime"
|
||||
}
|
||||
],
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "percent",
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{ "value": 0, "color": "red" },
|
||||
{ "value": 99, "color": "yellow" },
|
||||
{ "value": 99.9, "color": "green" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"refresh": "30s",
|
||||
"schemaVersion": 27,
|
||||
"version": 1
|
||||
}
|
||||
}
|
||||
|
||||
32
monitoring/metrics-dashboard/setup.sh
Executable file
32
monitoring/metrics-dashboard/setup.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
# Setup metrics dashboard in Grafana
|
||||
|
||||
set -e
|
||||
|
||||
NAMESPACE="monitoring"
|
||||
DASHBOARD_FILE="grafana-dashboard.json"
|
||||
|
||||
echo "📊 Setting up Metrics Dashboard in Grafana..."
|
||||
|
||||
# Check if Grafana is accessible
|
||||
if ! kubectl get svc -n "$NAMESPACE" | grep -q grafana; then
|
||||
echo "⚠️ Grafana not found in namespace $NAMESPACE"
|
||||
echo " → Deploy Grafana first: cd ../prometheus && ./install.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create ConfigMap with dashboard
|
||||
echo "📝 Creating dashboard ConfigMap..."
|
||||
kubectl create configmap metrics-dashboard \
|
||||
--from-file=dashboard.json="$DASHBOARD_FILE" \
|
||||
-n "$NAMESPACE" \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
echo "✅ Metrics dashboard configured!"
|
||||
echo ""
|
||||
echo "📝 Next steps:"
|
||||
echo " 1. Access Grafana: kubectl port-forward -n $NAMESPACE svc/prometheus-grafana 3000:80"
|
||||
echo " 2. Import dashboard from ConfigMap"
|
||||
echo " 3. Configure data sources"
|
||||
echo " 4. Set up metrics collection"
|
||||
|
||||
47
monitoring/prometheus/install.sh
Executable file
47
monitoring/prometheus/install.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
# Install Prometheus/Grafana Stack
|
||||
|
||||
set -e
|
||||
|
||||
NAMESPACE="monitoring"
|
||||
RELEASE_NAME="prometheus"
|
||||
|
||||
echo "📊 Installing Prometheus/Grafana Stack..."
|
||||
|
||||
# Check if helm is installed
|
||||
if ! command -v helm &> /dev/null; then
|
||||
echo "❌ Helm not found. Please install Helm first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if kubectl is installed
|
||||
if ! command -v kubectl &> /dev/null; then
|
||||
echo "❌ kubectl not found. Please install kubectl first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create namespace
|
||||
echo "📦 Creating namespace: $NAMESPACE"
|
||||
kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# Add Prometheus Helm repo
|
||||
echo "📥 Adding Prometheus Helm repository..."
|
||||
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
|
||||
helm repo update
|
||||
|
||||
# Install Prometheus Stack
|
||||
echo "🚀 Installing Prometheus Stack..."
|
||||
helm upgrade --install "$RELEASE_NAME" prometheus-community/kube-prometheus-stack \
|
||||
--namespace "$NAMESPACE" \
|
||||
--create-namespace \
|
||||
--values values.yaml \
|
||||
--wait
|
||||
|
||||
echo "✅ Prometheus/Grafana Stack installed successfully!"
|
||||
echo ""
|
||||
echo "📝 Access Grafana:"
|
||||
echo " kubectl port-forward -n $NAMESPACE svc/$RELEASE_NAME-grafana 3000:80"
|
||||
echo ""
|
||||
echo "📝 Access Prometheus:"
|
||||
echo " kubectl port-forward -n $NAMESPACE svc/$RELEASE_NAME-kube-prom-prometheus 9090:9090"
|
||||
|
||||
86
monitoring/prometheus/values.yaml
Normal file
86
monitoring/prometheus/values.yaml
Normal file
@@ -0,0 +1,86 @@
|
||||
# Prometheus Stack Helm Values
|
||||
# For use with kube-prometheus-stack
|
||||
|
||||
prometheus:
|
||||
prometheusSpec:
|
||||
retention: 30d
|
||||
retentionSize: 50GB
|
||||
storageSpec:
|
||||
volumeClaimTemplate:
|
||||
spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: standard
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Gi
|
||||
resources:
|
||||
requests:
|
||||
memory: 2Gi
|
||||
cpu: 1000m
|
||||
limits:
|
||||
memory: 4Gi
|
||||
cpu: 2000m
|
||||
serviceMonitorSelectorNilUsesHelmValues: false
|
||||
podMonitorSelectorNilUsesHelmValues: false
|
||||
ruleSelectorNilUsesHelmValues: false
|
||||
|
||||
grafana:
|
||||
enabled: true
|
||||
adminPassword: "admin" # Change in production
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 10Gi
|
||||
resources:
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 100m
|
||||
limits:
|
||||
memory: 512Mi
|
||||
cpu: 500m
|
||||
dashboardProviders:
|
||||
dashboardproviders.yaml:
|
||||
apiVersion: 1
|
||||
providers:
|
||||
- name: 'default'
|
||||
orgId: 1
|
||||
folder: ''
|
||||
type: file
|
||||
disableDelete: false
|
||||
editable: true
|
||||
options:
|
||||
path: /var/lib/grafana/dashboards/default
|
||||
dashboards:
|
||||
default:
|
||||
kubernetes-cluster:
|
||||
gnetId: 7249
|
||||
revision: 1
|
||||
datasource: Prometheus
|
||||
|
||||
alertmanager:
|
||||
enabled: true
|
||||
config:
|
||||
global:
|
||||
resolve_timeout: 5m
|
||||
route:
|
||||
group_by: ['alertname']
|
||||
group_wait: 10s
|
||||
group_interval: 10s
|
||||
repeat_interval: 12h
|
||||
receiver: 'default'
|
||||
receivers:
|
||||
- name: 'default'
|
||||
email_configs:
|
||||
- to: 'alerts@example.com'
|
||||
from: 'prometheus@example.com'
|
||||
smarthost: 'smtp.example.com:587'
|
||||
auth_username: 'prometheus'
|
||||
auth_password: 'password'
|
||||
headers:
|
||||
Subject: 'Prometheus Alert'
|
||||
|
||||
kubeStateMetrics:
|
||||
enabled: true
|
||||
|
||||
nodeExporter:
|
||||
enabled: true
|
||||
|
||||
103
terraform/README.md
Normal file
103
terraform/README.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Shared Terraform Infrastructure
|
||||
|
||||
**Last Updated**: 2025-01-27
|
||||
**Purpose**: Centralized Terraform modules and infrastructure configurations
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This directory contains shared Terraform modules and infrastructure configurations that can be used across multiple projects.
|
||||
|
||||
---
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
infrastructure/terraform/
|
||||
├── modules/ # Reusable Terraform modules
|
||||
│ ├── azure/ # Azure-specific modules
|
||||
│ ├── multi-cloud/ # Multi-cloud modules
|
||||
│ └── shared/ # Shared utilities
|
||||
├── environments/ # Environment-specific configurations
|
||||
│ ├── dev/ # Development environment
|
||||
│ ├── staging/ # Staging environment
|
||||
│ └── prod/ # Production environment
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Modules (Planned)
|
||||
|
||||
### Azure Modules
|
||||
|
||||
#### networking
|
||||
- Virtual networks
|
||||
- Subnets
|
||||
- Network security groups
|
||||
- Application Gateway
|
||||
|
||||
#### kubernetes
|
||||
- AKS cluster
|
||||
- Node pools
|
||||
- Networking integration
|
||||
|
||||
#### storage
|
||||
- Storage accounts
|
||||
- Containers
|
||||
- File shares
|
||||
|
||||
#### keyvault
|
||||
- Azure Key Vault
|
||||
- RBAC configuration
|
||||
- Private endpoints
|
||||
|
||||
#### monitoring
|
||||
- Log Analytics
|
||||
- Application Insights
|
||||
- Alert rules
|
||||
|
||||
### Multi-Cloud Modules
|
||||
|
||||
#### azure
|
||||
- Azure-specific resources
|
||||
|
||||
#### aws
|
||||
- AWS-specific resources
|
||||
|
||||
#### gcp
|
||||
- GCP-specific resources
|
||||
|
||||
#### onprem-hci
|
||||
- On-premises HCI resources
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
### Using Shared Modules
|
||||
|
||||
```hcl
|
||||
module "networking" {
|
||||
source = "../../infrastructure/terraform/modules/azure/networking"
|
||||
|
||||
environment = var.environment
|
||||
location = var.location
|
||||
# ... module variables
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration Status
|
||||
|
||||
- **Planning Phase**: Module inventory completed
|
||||
- **Next Steps**: Begin module consolidation
|
||||
- **Target**: Standardized, reusable modules
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-01-27
|
||||
**Status**: Planning Phase
|
||||
|
||||
76
terraform/examples/namespace-example/main.tf
Normal file
76
terraform/examples/namespace-example/main.tf
Normal file
@@ -0,0 +1,76 @@
|
||||
# Example: Using Kubernetes Namespace Module
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.0"
|
||||
|
||||
required_providers {
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "~> 2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
# Configure your Kubernetes provider
|
||||
# config_path = "~/.kube/config"
|
||||
}
|
||||
|
||||
# Namespace Module
|
||||
module "namespace" {
|
||||
source = "../../modules/kubernetes/namespace"
|
||||
|
||||
name = "my-app"
|
||||
|
||||
labels = {
|
||||
app = "my-app"
|
||||
env = "production"
|
||||
managed = "terraform"
|
||||
team = "platform"
|
||||
}
|
||||
|
||||
annotations = {
|
||||
description = "Namespace for my-app production environment"
|
||||
}
|
||||
|
||||
resource_quota = {
|
||||
"requests.cpu" = "4"
|
||||
"requests.memory" = "8Gi"
|
||||
"limits.cpu" = "8"
|
||||
"limits.memory" = "16Gi"
|
||||
"persistentvolumeclaims" = "10"
|
||||
"services.loadbalancers" = "2"
|
||||
}
|
||||
|
||||
limit_range = {
|
||||
default = {
|
||||
"cpu" = "500m"
|
||||
"memory" = "1Gi"
|
||||
}
|
||||
default_request = {
|
||||
"cpu" = "100m"
|
||||
"memory" = "128Mi"
|
||||
}
|
||||
max = {
|
||||
"cpu" = "2"
|
||||
"memory" = "4Gi"
|
||||
}
|
||||
min = {
|
||||
"cpu" = "50m"
|
||||
"memory" = "64Mi"
|
||||
}
|
||||
max_limit_request_ratio = {
|
||||
"cpu" = "4"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Outputs
|
||||
output "namespace_name" {
|
||||
value = module.namespace.namespace_name
|
||||
}
|
||||
|
||||
output "namespace_id" {
|
||||
value = module.namespace.namespace_id
|
||||
}
|
||||
|
||||
96
terraform/examples/networking-example/main.tf
Normal file
96
terraform/examples/networking-example/main.tf
Normal file
@@ -0,0 +1,96 @@
|
||||
# Example: Using Azure Networking Module
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.0"
|
||||
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "azurerm" {
|
||||
features {}
|
||||
}
|
||||
|
||||
# Resource Group
|
||||
resource "azurerm_resource_group" "example" {
|
||||
name = "rg-example"
|
||||
location = "eastus"
|
||||
}
|
||||
|
||||
# Networking Module
|
||||
module "networking" {
|
||||
source = "../../modules/azure/networking"
|
||||
|
||||
resource_group_name = azurerm_resource_group.example.name
|
||||
location = azurerm_resource_group.example.location
|
||||
vnet_name = "vnet-example"
|
||||
address_space = ["10.0.0.0/16"]
|
||||
|
||||
subnets = {
|
||||
frontend = {
|
||||
name = "snet-frontend"
|
||||
address_prefixes = ["10.0.1.0/24"]
|
||||
service_endpoints = ["Microsoft.Storage"]
|
||||
}
|
||||
backend = {
|
||||
name = "snet-backend"
|
||||
address_prefixes = ["10.0.2.0/24"]
|
||||
service_endpoints = []
|
||||
}
|
||||
database = {
|
||||
name = "snet-database"
|
||||
address_prefixes = ["10.0.3.0/24"]
|
||||
service_endpoints = ["Microsoft.Sql"]
|
||||
}
|
||||
}
|
||||
|
||||
network_security_groups = {
|
||||
frontend_nsg = {
|
||||
name = "nsg-frontend"
|
||||
subnet_key = "frontend"
|
||||
security_rules = [
|
||||
{
|
||||
name = "AllowHTTP"
|
||||
priority = 100
|
||||
direction = "Inbound"
|
||||
access = "Allow"
|
||||
protocol = "Tcp"
|
||||
source_port_range = "*"
|
||||
destination_port_range = "80"
|
||||
source_address_prefix = "*"
|
||||
destination_address_prefix = "*"
|
||||
},
|
||||
{
|
||||
name = "AllowHTTPS"
|
||||
priority = 110
|
||||
direction = "Inbound"
|
||||
access = "Allow"
|
||||
protocol = "Tcp"
|
||||
source_port_range = "*"
|
||||
destination_port_range = "443"
|
||||
source_address_prefix = "*"
|
||||
destination_address_prefix = "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
tags = {
|
||||
Environment = "example"
|
||||
ManagedBy = "Terraform"
|
||||
}
|
||||
}
|
||||
|
||||
# Outputs
|
||||
output "vnet_id" {
|
||||
value = module.networking.vnet_id
|
||||
}
|
||||
|
||||
output "subnet_ids" {
|
||||
value = module.networking.subnet_ids
|
||||
}
|
||||
|
||||
156
terraform/modules/README.md
Normal file
156
terraform/modules/README.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# Shared Terraform Modules
|
||||
|
||||
**Purpose**: Reusable Terraform modules for infrastructure provisioning
|
||||
**Last Updated**: 2025-01-27
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This directory contains shared Terraform modules that can be used across all projects to ensure consistency and reduce duplication.
|
||||
|
||||
---
|
||||
|
||||
## Module Structure
|
||||
|
||||
```
|
||||
modules/
|
||||
├── azure/ # Azure-specific modules
|
||||
│ ├── networking/ # Virtual networks, subnets, NSGs
|
||||
│ ├── kubernetes/ # AKS clusters
|
||||
│ ├── keyvault/ # Key Vault with RBAC
|
||||
│ ├── storage/ # Storage accounts
|
||||
│ └── monitoring/ # Monitoring resources
|
||||
├── kubernetes/ # Kubernetes modules (multi-cloud)
|
||||
│ ├── namespace/ # Namespace creation
|
||||
│ ├── ingress/ # Ingress configuration
|
||||
│ └── service/ # Service configuration
|
||||
└── monitoring/ # Monitoring modules
|
||||
├── prometheus/ # Prometheus deployment
|
||||
├── grafana/ # Grafana deployment
|
||||
└── loki/ # Loki deployment
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
### Example: Using Azure Networking Module
|
||||
|
||||
```hcl
|
||||
module "networking" {
|
||||
source = "../../modules/azure/networking"
|
||||
|
||||
resource_group_name = "rg-example"
|
||||
location = "eastus"
|
||||
vnet_name = "vnet-example"
|
||||
address_space = ["10.0.0.0/16"]
|
||||
|
||||
subnets = [
|
||||
{
|
||||
name = "subnet-1"
|
||||
address_prefix = "10.0.1.0/24"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Example: Using Kubernetes Namespace Module
|
||||
|
||||
```hcl
|
||||
module "namespace" {
|
||||
source = "../../modules/kubernetes/namespace"
|
||||
|
||||
name = "example-namespace"
|
||||
labels = {
|
||||
environment = "production"
|
||||
project = "example"
|
||||
}
|
||||
annotations = {}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Module Development Guidelines
|
||||
|
||||
### 1. Standard Structure
|
||||
|
||||
Each module should follow this structure:
|
||||
|
||||
```
|
||||
module-name/
|
||||
├── main.tf # Main resources
|
||||
├── variables.tf # Input variables
|
||||
├── outputs.tf # Output values
|
||||
├── README.md # Module documentation
|
||||
└── versions.tf # Provider versions
|
||||
```
|
||||
|
||||
### 2. Documentation
|
||||
|
||||
Each module must include:
|
||||
- Purpose and use cases
|
||||
- Input variables documentation
|
||||
- Output values documentation
|
||||
- Usage examples
|
||||
- Requirements
|
||||
|
||||
### 3. Versioning
|
||||
|
||||
- Use semantic versioning (v1.0.0, v1.1.0, etc.)
|
||||
- Tag releases in git
|
||||
- Document breaking changes
|
||||
|
||||
---
|
||||
|
||||
## Available Modules
|
||||
|
||||
### Azure Modules
|
||||
|
||||
#### networking
|
||||
**Purpose**: Create virtual networks, subnets, and network security groups
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
#### kubernetes
|
||||
**Purpose**: Deploy AKS clusters
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
#### keyvault
|
||||
**Purpose**: Create Key Vault with RBAC
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
#### storage
|
||||
**Purpose**: Create storage accounts and containers
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
### Kubernetes Modules
|
||||
|
||||
#### namespace
|
||||
**Purpose**: Create Kubernetes namespaces
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
#### ingress
|
||||
**Purpose**: Configure ingress controllers
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
### Monitoring Modules
|
||||
|
||||
#### prometheus
|
||||
**Purpose**: Deploy Prometheus
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
#### grafana
|
||||
**Purpose**: Deploy Grafana
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
---
|
||||
|
||||
## Migration Plan
|
||||
|
||||
See [TERRAFORM_MODULES_CONSOLIDATION.md](../../../docs/TERRAFORM_MODULES_CONSOLIDATION.md) for detailed migration plan.
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025-01-27
|
||||
|
||||
61
terraform/modules/azure/keyvault/README.md
Normal file
61
terraform/modules/azure/keyvault/README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Azure Key Vault Module
|
||||
|
||||
**Purpose**: Create Azure Key Vault with RBAC
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```hcl
|
||||
module "keyvault" {
|
||||
source = "../../modules/azure/keyvault"
|
||||
|
||||
resource_group_name = "rg-example"
|
||||
location = "eastus"
|
||||
keyvault_name = "kv-example"
|
||||
|
||||
access_policies = [
|
||||
{
|
||||
object_id = var.service_principal_id
|
||||
key_permissions = ["Get", "List"]
|
||||
secret_permissions = ["Get", "List"]
|
||||
}
|
||||
]
|
||||
|
||||
tags = {
|
||||
Environment = "production"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Inputs
|
||||
|
||||
| Name | Description | Type | Default | Required |
|
||||
|------|-------------|------|---------|----------|
|
||||
| resource_group_name | Name of the resource group | string | - | yes |
|
||||
| location | Azure region | string | - | yes |
|
||||
| keyvault_name | Name of the Key Vault | string | - | yes |
|
||||
| sku_name | SKU name (standard or premium) | string | "standard" | no |
|
||||
| enabled_for_deployment | Enable for VM deployment | bool | false | no |
|
||||
| enabled_for_disk_encryption | Enable for disk encryption | bool | false | no |
|
||||
| enabled_for_template_deployment | Enable for template deployment | bool | false | no |
|
||||
| access_policies | List of access policies | list(object) | [] | no |
|
||||
| tags | Tags to apply | map(string) | {} | no |
|
||||
|
||||
---
|
||||
|
||||
## Outputs
|
||||
|
||||
| Name | Description |
|
||||
|------|-------------|
|
||||
| keyvault_id | Key Vault ID |
|
||||
| keyvault_uri | Key Vault URI |
|
||||
| keyvault_name | Key Vault name |
|
||||
|
||||
---
|
||||
|
||||
**Status**: 🚧 Planned - Module structure ready, implementation pending
|
||||
|
||||
61
terraform/modules/azure/keyvault/main.tf
Normal file
61
terraform/modules/azure/keyvault/main.tf
Normal file
@@ -0,0 +1,61 @@
|
||||
# Azure Key Vault Module
|
||||
# Main resources
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Key Vault
|
||||
resource "azurerm_key_vault" "main" {
|
||||
name = var.keyvault_name
|
||||
location = var.location
|
||||
resource_group_name = var.resource_group_name
|
||||
tenant_id = var.tenant_id
|
||||
sku_name = var.sku_name
|
||||
|
||||
enabled_for_deployment = var.enabled_for_deployment
|
||||
enabled_for_disk_encryption = var.enabled_for_disk_encryption
|
||||
enabled_for_template_deployment = var.enabled_for_template_deployment
|
||||
|
||||
network_acls {
|
||||
default_action = var.network_acls.default_action
|
||||
bypass = var.network_acls.bypass
|
||||
ip_rules = var.network_acls.ip_rules
|
||||
virtual_network_subnet_ids = var.network_acls.virtual_network_subnet_ids
|
||||
}
|
||||
|
||||
tags = var.tags
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
# Access Policies
|
||||
resource "azurerm_key_vault_access_policy" "policies" {
|
||||
for_each = { for idx, policy in var.access_policies : idx => policy }
|
||||
|
||||
key_vault_id = azurerm_key_vault.main.id
|
||||
tenant_id = var.tenant_id
|
||||
object_id = each.value.object_id
|
||||
|
||||
key_permissions = each.value.key_permissions
|
||||
secret_permissions = each.value.secret_permissions
|
||||
certificate_permissions = each.value.certificate_permissions
|
||||
storage_permissions = each.value.storage_permissions
|
||||
}
|
||||
|
||||
# RBAC (if enabled)
|
||||
resource "azurerm_role_assignment" "rbac" {
|
||||
for_each = var.enable_rbac ? var.rbac_assignments : {}
|
||||
|
||||
scope = azurerm_key_vault.main.id
|
||||
role_definition_name = each.value.role_definition_name
|
||||
principal_id = each.value.principal_id
|
||||
}
|
||||
|
||||
17
terraform/modules/azure/keyvault/outputs.tf
Normal file
17
terraform/modules/azure/keyvault/outputs.tf
Normal file
@@ -0,0 +1,17 @@
|
||||
# Azure Key Vault Module Outputs
|
||||
|
||||
output "keyvault_id" {
|
||||
description = "Key Vault ID"
|
||||
value = azurerm_key_vault.main.id
|
||||
}
|
||||
|
||||
output "keyvault_uri" {
|
||||
description = "Key Vault URI"
|
||||
value = azurerm_key_vault.main.vault_uri
|
||||
}
|
||||
|
||||
output "keyvault_name" {
|
||||
description = "Key Vault name"
|
||||
value = azurerm_key_vault.main.name
|
||||
}
|
||||
|
||||
95
terraform/modules/azure/keyvault/variables.tf
Normal file
95
terraform/modules/azure/keyvault/variables.tf
Normal file
@@ -0,0 +1,95 @@
|
||||
# Azure Key Vault Module Variables
|
||||
|
||||
variable "resource_group_name" {
|
||||
description = "Name of the resource group"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "location" {
|
||||
description = "Azure region"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "keyvault_name" {
|
||||
description = "Name of the Key Vault"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "tenant_id" {
|
||||
description = "Azure tenant ID"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "sku_name" {
|
||||
description = "SKU name (standard or premium)"
|
||||
type = string
|
||||
default = "standard"
|
||||
}
|
||||
|
||||
variable "enabled_for_deployment" {
|
||||
description = "Enable for VM deployment"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "enabled_for_disk_encryption" {
|
||||
description = "Enable for disk encryption"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "enabled_for_template_deployment" {
|
||||
description = "Enable for template deployment"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "network_acls" {
|
||||
description = "Network ACLs configuration"
|
||||
type = object({
|
||||
default_action = string
|
||||
bypass = string
|
||||
ip_rules = list(string)
|
||||
virtual_network_subnet_ids = list(string)
|
||||
})
|
||||
default = {
|
||||
default_action = "Deny"
|
||||
bypass = "AzureServices"
|
||||
ip_rules = []
|
||||
virtual_network_subnet_ids = []
|
||||
}
|
||||
}
|
||||
|
||||
variable "access_policies" {
|
||||
description = "List of access policies"
|
||||
type = list(object({
|
||||
object_id = string
|
||||
key_permissions = list(string)
|
||||
secret_permissions = list(string)
|
||||
certificate_permissions = list(string)
|
||||
storage_permissions = list(string)
|
||||
}))
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "enable_rbac" {
|
||||
description = "Enable RBAC for Key Vault"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "rbac_assignments" {
|
||||
description = "RBAC role assignments"
|
||||
type = map(object({
|
||||
role_definition_name = string
|
||||
principal_id = string
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
description = "Tags to apply to resources"
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
13
terraform/modules/azure/keyvault/versions.tf
Normal file
13
terraform/modules/azure/keyvault/versions.tf
Normal file
@@ -0,0 +1,13 @@
|
||||
# Azure Key Vault Module - Provider Versions
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.0"
|
||||
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
86
terraform/modules/azure/networking/README.md
Normal file
86
terraform/modules/azure/networking/README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Azure Networking Module
|
||||
|
||||
**Purpose**: Create Azure Virtual Network with subnets and network security groups
|
||||
**Status**: ✅ Complete
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```hcl
|
||||
module "networking" {
|
||||
source = "../../modules/azure/networking"
|
||||
|
||||
resource_group_name = "rg-example"
|
||||
location = "eastus"
|
||||
vnet_name = "vnet-example"
|
||||
address_space = ["10.0.0.0/16"]
|
||||
|
||||
subnets = {
|
||||
frontend = {
|
||||
name = "snet-frontend"
|
||||
address_prefixes = ["10.0.1.0/24"]
|
||||
service_endpoints = ["Microsoft.Storage"]
|
||||
}
|
||||
backend = {
|
||||
name = "snet-backend"
|
||||
address_prefixes = ["10.0.2.0/24"]
|
||||
service_endpoints = []
|
||||
}
|
||||
}
|
||||
|
||||
network_security_groups = {
|
||||
frontend_nsg = {
|
||||
name = "nsg-frontend"
|
||||
subnet_key = "frontend"
|
||||
security_rules = [
|
||||
{
|
||||
name = "AllowHTTP"
|
||||
priority = 100
|
||||
direction = "Inbound"
|
||||
access = "Allow"
|
||||
protocol = "Tcp"
|
||||
source_port_range = "*"
|
||||
destination_port_range = "80"
|
||||
source_address_prefix = "*"
|
||||
destination_address_prefix = "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
tags = {
|
||||
Environment = "production"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Inputs
|
||||
|
||||
| Name | Description | Type | Default | Required |
|
||||
|------|-------------|------|---------|----------|
|
||||
| resource_group_name | Name of the resource group | string | - | yes |
|
||||
| location | Azure region | string | - | yes |
|
||||
| vnet_name | Name of the virtual network | string | - | yes |
|
||||
| address_space | Address space for the virtual network | list(string) | - | yes |
|
||||
| subnets | Map of subnets to create | map(object) | {} | no |
|
||||
| network_security_groups | Map of network security groups | map(object) | {} | no |
|
||||
| tags | Tags to apply | map(string) | {} | no |
|
||||
|
||||
---
|
||||
|
||||
## Outputs
|
||||
|
||||
| Name | Description |
|
||||
|------|-------------|
|
||||
| vnet_id | Virtual network ID |
|
||||
| vnet_name | Virtual network name |
|
||||
| subnet_ids | Map of subnet names to IDs |
|
||||
| subnet_names | Map of subnet names |
|
||||
| nsg_ids | Map of NSG names to IDs |
|
||||
|
||||
---
|
||||
|
||||
**Status**: ✅ Complete - Ready for use
|
||||
73
terraform/modules/azure/networking/main.tf
Normal file
73
terraform/modules/azure/networking/main.tf
Normal file
@@ -0,0 +1,73 @@
|
||||
# Azure Networking Module
|
||||
# Main resources
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Virtual Network
|
||||
resource "azurerm_virtual_network" "main" {
|
||||
name = var.vnet_name
|
||||
address_space = var.address_space
|
||||
location = var.location
|
||||
resource_group_name = var.resource_group_name
|
||||
tags = var.tags
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
# Subnets
|
||||
resource "azurerm_subnet" "subnets" {
|
||||
for_each = var.subnets
|
||||
|
||||
name = each.value.name
|
||||
resource_group_name = var.resource_group_name
|
||||
virtual_network_name = azurerm_virtual_network.main.name
|
||||
address_prefixes = each.value.address_prefixes
|
||||
service_endpoints = each.value.service_endpoints
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
# Network Security Groups
|
||||
resource "azurerm_network_security_group" "nsgs" {
|
||||
for_each = var.network_security_groups
|
||||
|
||||
name = each.value.name
|
||||
location = var.location
|
||||
resource_group_name = var.resource_group_name
|
||||
tags = var.tags
|
||||
|
||||
dynamic "security_rule" {
|
||||
for_each = each.value.security_rules
|
||||
content {
|
||||
name = security_rule.value.name
|
||||
priority = security_rule.value.priority
|
||||
direction = security_rule.value.direction
|
||||
access = security_rule.value.access
|
||||
protocol = security_rule.value.protocol
|
||||
source_port_range = security_rule.value.source_port_range
|
||||
destination_port_range = security_rule.value.destination_port_range
|
||||
source_address_prefix = security_rule.value.source_address_prefix
|
||||
destination_address_prefix = security_rule.value.destination_address_prefix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Associate NSGs with subnets
|
||||
resource "azurerm_subnet_network_security_group_association" "nsg_associations" {
|
||||
for_each = var.network_security_groups
|
||||
|
||||
subnet_id = azurerm_subnet.subnets[each.value.subnet_key].id
|
||||
network_security_group_id = azurerm_network_security_group.nsgs[each.key].id
|
||||
}
|
||||
|
||||
27
terraform/modules/azure/networking/outputs.tf
Normal file
27
terraform/modules/azure/networking/outputs.tf
Normal file
@@ -0,0 +1,27 @@
|
||||
# Azure Networking Module Outputs
|
||||
|
||||
output "vnet_id" {
|
||||
description = "Virtual network ID"
|
||||
value = azurerm_virtual_network.main.id
|
||||
}
|
||||
|
||||
output "vnet_name" {
|
||||
description = "Virtual network name"
|
||||
value = azurerm_virtual_network.main.name
|
||||
}
|
||||
|
||||
output "subnet_ids" {
|
||||
description = "Map of subnet names to IDs"
|
||||
value = { for k, v in azurerm_subnet.subnets : k => v.id }
|
||||
}
|
||||
|
||||
output "subnet_names" {
|
||||
description = "Map of subnet names"
|
||||
value = { for k, v in azurerm_subnet.subnets : k => v.name }
|
||||
}
|
||||
|
||||
output "nsg_ids" {
|
||||
description = "Map of NSG names to IDs"
|
||||
value = { for k, v in azurerm_network_security_group.nsgs : k => v.id }
|
||||
}
|
||||
|
||||
58
terraform/modules/azure/networking/variables.tf
Normal file
58
terraform/modules/azure/networking/variables.tf
Normal file
@@ -0,0 +1,58 @@
|
||||
# Azure Networking Module Variables
|
||||
|
||||
variable "resource_group_name" {
|
||||
description = "Name of the resource group"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "location" {
|
||||
description = "Azure region"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "vnet_name" {
|
||||
description = "Name of the virtual network"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "address_space" {
|
||||
description = "Address space for the virtual network"
|
||||
type = list(string)
|
||||
}
|
||||
|
||||
variable "subnets" {
|
||||
description = "Map of subnets to create"
|
||||
type = map(object({
|
||||
name = string
|
||||
address_prefixes = list(string)
|
||||
service_endpoints = list(string)
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "network_security_groups" {
|
||||
description = "Map of network security groups to create"
|
||||
type = map(object({
|
||||
name = string
|
||||
subnet_key = string
|
||||
security_rules = list(object({
|
||||
name = string
|
||||
priority = number
|
||||
direction = string
|
||||
access = string
|
||||
protocol = string
|
||||
source_port_range = string
|
||||
destination_port_range = string
|
||||
source_address_prefix = string
|
||||
destination_address_prefix = string
|
||||
}))
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
description = "Tags to apply to resources"
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
13
terraform/modules/azure/networking/versions.tf
Normal file
13
terraform/modules/azure/networking/versions.tf
Normal file
@@ -0,0 +1,13 @@
|
||||
# Azure Networking Module - Provider Versions
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.0"
|
||||
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
58
terraform/modules/azure/storage/README.md
Normal file
58
terraform/modules/azure/storage/README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Azure Storage Module
|
||||
|
||||
**Purpose**: Create storage accounts and containers
|
||||
**Status**: 🚧 Planned
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```hcl
|
||||
module "storage" {
|
||||
source = "../../modules/azure/storage"
|
||||
|
||||
resource_group_name = "rg-example"
|
||||
location = "eastus"
|
||||
storage_account_name = "stexample"
|
||||
|
||||
containers = [
|
||||
{
|
||||
name = "container1"
|
||||
access_type = "private"
|
||||
}
|
||||
]
|
||||
|
||||
tags = {
|
||||
Environment = "production"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Inputs
|
||||
|
||||
| Name | Description | Type | Default | Required |
|
||||
|------|-------------|------|---------|----------|
|
||||
| resource_group_name | Name of the resource group | string | - | yes |
|
||||
| location | Azure region | string | - | yes |
|
||||
| storage_account_name | Name of the storage account | string | - | yes |
|
||||
| account_tier | Storage account tier | string | "Standard" | no |
|
||||
| account_replication_type | Replication type | string | "LRS" | no |
|
||||
| containers | List of containers to create | list(object) | [] | no |
|
||||
| tags | Tags to apply | map(string) | {} | no |
|
||||
|
||||
---
|
||||
|
||||
## Outputs
|
||||
|
||||
| Name | Description |
|
||||
|------|-------------|
|
||||
| storage_account_id | Storage account ID |
|
||||
| storage_account_name | Storage account name |
|
||||
| primary_connection_string | Primary connection string (sensitive) |
|
||||
|
||||
---
|
||||
|
||||
**Status**: 🚧 Planned - Module structure ready, implementation pending
|
||||
|
||||
81
terraform/modules/azure/storage/main.tf
Normal file
81
terraform/modules/azure/storage/main.tf
Normal file
@@ -0,0 +1,81 @@
|
||||
# Azure Storage Module
|
||||
# Main resources
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Storage Account
|
||||
resource "azurerm_storage_account" "main" {
|
||||
name = var.storage_account_name
|
||||
resource_group_name = var.resource_group_name
|
||||
location = var.location
|
||||
account_tier = var.account_tier
|
||||
account_replication_type = var.account_replication_type
|
||||
account_kind = var.account_kind
|
||||
|
||||
enable_https_traffic_only = var.enable_https_traffic_only
|
||||
min_tls_version = var.min_tls_version
|
||||
|
||||
blob_properties {
|
||||
delete_retention_policy {
|
||||
days = var.blob_delete_retention_days
|
||||
}
|
||||
container_delete_retention_policy {
|
||||
days = var.container_delete_retention_days
|
||||
}
|
||||
}
|
||||
|
||||
network_rules {
|
||||
default_action = var.network_rules.default_action
|
||||
bypass = var.network_rules.bypass
|
||||
ip_rules = var.network_rules.ip_rules
|
||||
virtual_network_subnet_ids = var.network_rules.virtual_network_subnet_ids
|
||||
}
|
||||
|
||||
tags = var.tags
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
# Containers
|
||||
resource "azurerm_storage_container" "containers" {
|
||||
for_each = var.containers
|
||||
|
||||
name = each.value.name
|
||||
storage_account_name = azurerm_storage_account.main.name
|
||||
container_access_type = each.value.access_type
|
||||
}
|
||||
|
||||
# File Shares
|
||||
resource "azurerm_storage_share" "shares" {
|
||||
for_each = var.file_shares
|
||||
|
||||
name = each.value.name
|
||||
storage_account_name = azurerm_storage_account.main.name
|
||||
quota = each.value.quota
|
||||
}
|
||||
|
||||
# Queues
|
||||
resource "azurerm_storage_queue" "queues" {
|
||||
for_each = var.queues
|
||||
|
||||
name = each.value.name
|
||||
storage_account_name = azurerm_storage_account.main.name
|
||||
}
|
||||
|
||||
# Tables
|
||||
resource "azurerm_storage_table" "tables" {
|
||||
for_each = var.tables
|
||||
|
||||
name = each.value.name
|
||||
storage_account_name = azurerm_storage_account.main.name
|
||||
}
|
||||
|
||||
34
terraform/modules/azure/storage/outputs.tf
Normal file
34
terraform/modules/azure/storage/outputs.tf
Normal file
@@ -0,0 +1,34 @@
|
||||
# Azure Storage Module Outputs
|
||||
|
||||
output "storage_account_id" {
|
||||
description = "Storage account ID"
|
||||
value = azurerm_storage_account.main.id
|
||||
}
|
||||
|
||||
output "storage_account_name" {
|
||||
description = "Storage account name"
|
||||
value = azurerm_storage_account.main.name
|
||||
}
|
||||
|
||||
output "primary_connection_string" {
|
||||
description = "Primary connection string (sensitive)"
|
||||
value = azurerm_storage_account.main.primary_connection_string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "primary_access_key" {
|
||||
description = "Primary access key (sensitive)"
|
||||
value = azurerm_storage_account.main.primary_access_key
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "primary_blob_endpoint" {
|
||||
description = "Primary blob endpoint"
|
||||
value = azurerm_storage_account.main.primary_blob_endpoint
|
||||
}
|
||||
|
||||
output "container_names" {
|
||||
description = "Map of container names"
|
||||
value = { for k, v in azurerm_storage_container.containers : k => v.name }
|
||||
}
|
||||
|
||||
115
terraform/modules/azure/storage/variables.tf
Normal file
115
terraform/modules/azure/storage/variables.tf
Normal file
@@ -0,0 +1,115 @@
|
||||
# Azure Storage Module Variables
|
||||
|
||||
variable "resource_group_name" {
|
||||
description = "Name of the resource group"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "location" {
|
||||
description = "Azure region"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "storage_account_name" {
|
||||
description = "Name of the storage account"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "account_tier" {
|
||||
description = "Storage account tier (Standard or Premium)"
|
||||
type = string
|
||||
default = "Standard"
|
||||
}
|
||||
|
||||
variable "account_replication_type" {
|
||||
description = "Replication type (LRS, GRS, RAGRS, ZRS)"
|
||||
type = string
|
||||
default = "LRS"
|
||||
}
|
||||
|
||||
variable "account_kind" {
|
||||
description = "Account kind (StorageV2, BlobStorage, etc.)"
|
||||
type = string
|
||||
default = "StorageV2"
|
||||
}
|
||||
|
||||
variable "enable_https_traffic_only" {
|
||||
description = "Enable HTTPS traffic only"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "min_tls_version" {
|
||||
description = "Minimum TLS version"
|
||||
type = string
|
||||
default = "TLS1_2"
|
||||
}
|
||||
|
||||
variable "blob_delete_retention_days" {
|
||||
description = "Blob delete retention days"
|
||||
type = number
|
||||
default = 7
|
||||
}
|
||||
|
||||
variable "container_delete_retention_days" {
|
||||
description = "Container delete retention days"
|
||||
type = number
|
||||
default = 7
|
||||
}
|
||||
|
||||
variable "network_rules" {
|
||||
description = "Network rules configuration"
|
||||
type = object({
|
||||
default_action = string
|
||||
bypass = list(string)
|
||||
ip_rules = list(string)
|
||||
virtual_network_subnet_ids = list(string)
|
||||
})
|
||||
default = {
|
||||
default_action = "Allow"
|
||||
bypass = ["AzureServices"]
|
||||
ip_rules = []
|
||||
virtual_network_subnet_ids = []
|
||||
}
|
||||
}
|
||||
|
||||
variable "containers" {
|
||||
description = "Map of containers to create"
|
||||
type = map(object({
|
||||
name = string
|
||||
access_type = string
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "file_shares" {
|
||||
description = "Map of file shares to create"
|
||||
type = map(object({
|
||||
name = string
|
||||
quota = number
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "queues" {
|
||||
description = "Map of queues to create"
|
||||
type = map(object({
|
||||
name = string
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "tables" {
|
||||
description = "Map of tables to create"
|
||||
type = map(object({
|
||||
name = string
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
description = "Tags to apply to resources"
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
13
terraform/modules/azure/storage/versions.tf
Normal file
13
terraform/modules/azure/storage/versions.tf
Normal file
@@ -0,0 +1,13 @@
|
||||
# Azure Storage Module - Provider Versions
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.0"
|
||||
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
81
terraform/modules/kubernetes/namespace/README.md
Normal file
81
terraform/modules/kubernetes/namespace/README.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Kubernetes Namespace Module
|
||||
|
||||
**Purpose**: Create Kubernetes namespace with resource quotas and limit ranges
|
||||
**Status**: ✅ Complete
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```hcl
|
||||
module "namespace" {
|
||||
source = "../../modules/kubernetes/namespace"
|
||||
|
||||
name = "my-app"
|
||||
|
||||
labels = {
|
||||
app = "my-app"
|
||||
env = "production"
|
||||
managed = "terraform"
|
||||
}
|
||||
|
||||
annotations = {
|
||||
description = "Namespace for my-app"
|
||||
}
|
||||
|
||||
resource_quota = {
|
||||
"requests.cpu" = "4"
|
||||
"requests.memory" = "8Gi"
|
||||
"limits.cpu" = "8"
|
||||
"limits.memory" = "16Gi"
|
||||
}
|
||||
|
||||
limit_range = {
|
||||
default = {
|
||||
"cpu" = "500m"
|
||||
"memory" = "1Gi"
|
||||
}
|
||||
default_request = {
|
||||
"cpu" = "100m"
|
||||
"memory" = "128Mi"
|
||||
}
|
||||
max = {
|
||||
"cpu" = "2"
|
||||
"memory" = "4Gi"
|
||||
}
|
||||
min = {
|
||||
"cpu" = "50m"
|
||||
"memory" = "64Mi"
|
||||
}
|
||||
max_limit_request_ratio = {
|
||||
"cpu" = "4"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Inputs
|
||||
|
||||
| Name | Description | Type | Default | Required |
|
||||
|------|-------------|------|---------|----------|
|
||||
| name | Namespace name | string | - | yes |
|
||||
| labels | Labels to apply | map(string) | {} | no |
|
||||
| annotations | Annotations to apply | map(string) | {} | no |
|
||||
| resource_quota | Resource quota limits | map(string) | {} | no |
|
||||
| limit_range | Limit range configuration | object | {} | no |
|
||||
|
||||
---
|
||||
|
||||
## Outputs
|
||||
|
||||
| Name | Description |
|
||||
|------|-------------|
|
||||
| namespace_name | Namespace name |
|
||||
| namespace_id | Namespace UID |
|
||||
| resource_quota_id | Resource quota ID (if created) |
|
||||
|
||||
---
|
||||
|
||||
**Status**: ✅ Complete - Ready for use
|
||||
55
terraform/modules/kubernetes/namespace/main.tf
Normal file
55
terraform/modules/kubernetes/namespace/main.tf
Normal file
@@ -0,0 +1,55 @@
|
||||
# Kubernetes Namespace Module
|
||||
# Main resources
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "~> 2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Namespace
|
||||
resource "kubernetes_namespace" "main" {
|
||||
metadata {
|
||||
name = var.name
|
||||
labels = var.labels
|
||||
annotations = var.annotations
|
||||
}
|
||||
}
|
||||
|
||||
# Resource Quota (if specified)
|
||||
resource "kubernetes_resource_quota" "quota" {
|
||||
count = length(var.resource_quota) > 0 ? 1 : 0
|
||||
|
||||
metadata {
|
||||
name = "${var.name}-quota"
|
||||
namespace = kubernetes_namespace.main.metadata[0].name
|
||||
}
|
||||
|
||||
spec {
|
||||
hard = var.resource_quota
|
||||
}
|
||||
}
|
||||
|
||||
# Limit Range (if specified)
|
||||
resource "kubernetes_limit_range" "limits" {
|
||||
count = length(var.limit_range) > 0 ? 1 : 0
|
||||
|
||||
metadata {
|
||||
name = "${var.name}-limits"
|
||||
namespace = kubernetes_namespace.main.metadata[0].name
|
||||
}
|
||||
|
||||
spec {
|
||||
limit {
|
||||
default = var.limit_range.default
|
||||
default_request = var.limit_range.default_request
|
||||
max = var.limit_range.max
|
||||
min = var.limit_range.min
|
||||
max_limit_request_ratio = var.limit_range.max_limit_request_ratio
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
17
terraform/modules/kubernetes/namespace/outputs.tf
Normal file
17
terraform/modules/kubernetes/namespace/outputs.tf
Normal file
@@ -0,0 +1,17 @@
|
||||
# Kubernetes Namespace Module Outputs
|
||||
|
||||
output "namespace_name" {
|
||||
description = "Namespace name"
|
||||
value = kubernetes_namespace.main.metadata[0].name
|
||||
}
|
||||
|
||||
output "namespace_id" {
|
||||
description = "Namespace UID"
|
||||
value = kubernetes_namespace.main.metadata[0].uid
|
||||
}
|
||||
|
||||
output "resource_quota_id" {
|
||||
description = "Resource quota ID (if created)"
|
||||
value = length(kubernetes_resource_quota.quota) > 0 ? kubernetes_resource_quota.quota[0].metadata[0].uid : null
|
||||
}
|
||||
|
||||
43
terraform/modules/kubernetes/namespace/variables.tf
Normal file
43
terraform/modules/kubernetes/namespace/variables.tf
Normal file
@@ -0,0 +1,43 @@
|
||||
# Kubernetes Namespace Module Variables
|
||||
|
||||
variable "name" {
|
||||
description = "Namespace name"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "labels" {
|
||||
description = "Labels to apply to namespace"
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "annotations" {
|
||||
description = "Annotations to apply to namespace"
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "resource_quota" {
|
||||
description = "Resource quota limits"
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "limit_range" {
|
||||
description = "Limit range configuration"
|
||||
type = object({
|
||||
default = map(string)
|
||||
default_request = map(string)
|
||||
max = map(string)
|
||||
min = map(string)
|
||||
max_limit_request_ratio = map(string)
|
||||
})
|
||||
default = {
|
||||
default = {}
|
||||
default_request = {}
|
||||
max = {}
|
||||
min = {}
|
||||
max_limit_request_ratio = {}
|
||||
}
|
||||
}
|
||||
|
||||
13
terraform/modules/kubernetes/namespace/versions.tf
Normal file
13
terraform/modules/kubernetes/namespace/versions.tf
Normal file
@@ -0,0 +1,13 @@
|
||||
# Kubernetes Namespace Module - Provider Versions
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.0"
|
||||
|
||||
required_providers {
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "~> 2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user