Initial commit: add .gitignore and README

This commit is contained in:
defiQUG
2026-02-09 21:51:46 -08:00
commit b970b4fc51
52 changed files with 3362 additions and 0 deletions

49
.gitignore vendored Normal file
View 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
View 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
View 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"

View 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

View 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

View 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

View 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"]
}

View 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
View 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"

View 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
View 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.>"

View 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

View 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"
}
}

View 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)"

View 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
View 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"

View 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"

View 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

View 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"

View 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"

View 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"

View 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
View 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"

View 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

View 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
}
}

View 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"

View 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"

View 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
View 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

View 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
}

View 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
View 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

View 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

View 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
}

View 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
}

View 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 = {}
}

View 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"
}
}
}

View 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

View 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
}

View 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 }
}

View 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 = {}
}

View File

@@ -0,0 +1,13 @@
# Azure Networking Module - Provider Versions
terraform {
required_version = ">= 1.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}

View 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

View 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
}

View 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 }
}

View 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 = {}
}

View File

@@ -0,0 +1,13 @@
# Azure Storage Module - Provider Versions
terraform {
required_version = ">= 1.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}

View 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

View 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
}
}
}

View 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
}

View 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 = {}
}
}

View File

@@ -0,0 +1,13 @@
# Kubernetes Namespace Module - Provider Versions
terraform {
required_version = ">= 1.0"
required_providers {
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.0"
}
}
}