chore(rebar): Pier_T_rebar 작업 폴더 초기 구성 및 외부 의존 파일 통합
- Code\rebar_pipeline, review_pipeline, pier-program을 정션에서 실제 폴더로 전환 - Code\rhino_mcp 및 CLAUDE_rhino배경.md 추가, .mcp.json은 PYTHONPATH로 새 위치 사용 - pier-program 내부 .git 제거(이력은 backup\pier-program_20261028.bundle에 보관) - worktree 가이드 반영(CLAUDE.local.md, HANDOFF.md) - D:\Rhino-MCP 경로 참조를 새 위치로 치환 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
964a841de1
3978 files changed
+58013356
No files matched your search
@@ -0,0 +1,87 @@
|
||||
# ArgoCD Application — Auto-generated by hmcmkit infra-architect
|
||||
# GitOps: Git Repo → ArgoCD Sync → Kubernetes Apply
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: ${project_name}-${environment}
|
||||
namespace: argocd
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: hmcmkit
|
||||
finalizers:
|
||||
- resources-finalizer.argocd.argoproj.io
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: ${git_repo_url}
|
||||
targetRevision: ${target_branch}
|
||||
path: infra/k8s/overlays/${environment}
|
||||
helm:
|
||||
valueFiles:
|
||||
- values.yaml
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: ${environment}
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
allowEmpty: false
|
||||
syncOptions:
|
||||
- CreateNamespace=true
|
||||
- PrunePropagationPolicy=foreground
|
||||
retry:
|
||||
limit: 3
|
||||
backoff:
|
||||
duration: 5s
|
||||
factor: 2
|
||||
maxDuration: 3m
|
||||
---
|
||||
# Argo Rollout for Canary Deploy (Production only)
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Rollout
|
||||
metadata:
|
||||
name: ${project_name}-api
|
||||
namespace: ${environment}
|
||||
spec:
|
||||
replicas: 3
|
||||
strategy:
|
||||
canary:
|
||||
steps:
|
||||
- setWeight: 10
|
||||
- pause: { duration: 2m }
|
||||
- setWeight: 25
|
||||
- pause: { duration: 2m }
|
||||
- setWeight: 50
|
||||
- pause: { duration: 5m }
|
||||
- setWeight: 100
|
||||
canaryService: ${project_name}-api-canary
|
||||
stableService: ${project_name}-api-stable
|
||||
analysis:
|
||||
templates:
|
||||
- templateName: success-rate
|
||||
startingStep: 2
|
||||
args:
|
||||
- name: service-name
|
||||
value: ${project_name}-api
|
||||
selector:
|
||||
matchLabels:
|
||||
app: ${project_name}-api
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: ${project_name}-api
|
||||
spec:
|
||||
containers:
|
||||
- name: api
|
||||
image: ${ecr_registry}/${project_name}:latest
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
resources:
|
||||
requests: { cpu: "250m", memory: "256Mi" }
|
||||
limits: { cpu: "500m", memory: "512Mi" }
|
||||
livenessProbe:
|
||||
httpGet: { path: /health, port: 3000 }
|
||||
initialDelaySeconds: 10
|
||||
readinessProbe:
|
||||
httpGet: { path: /ready, port: 3000 }
|
||||
initialDelaySeconds: 5
|
||||
@@ -0,0 +1,86 @@
|
||||
# GitHub Actions — Dynamic Level Deploy
|
||||
# Auto-generated by hmcmkit /pdca deploy
|
||||
# Docker Build + Push + Deploy
|
||||
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop, 'release/**']
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
test-and-lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
- run: npm test
|
||||
|
||||
security-scan:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-and-lint
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
scan-ref: '.'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
exit-code: '1'
|
||||
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-and-lint, security-scan]
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
|
||||
deploy-dev:
|
||||
if: github.ref == 'refs/heads/develop'
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-push
|
||||
environment: development
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Deploy to DEV (Docker Compose)
|
||||
run: |
|
||||
echo "Deploying to DEV environment"
|
||||
# docker compose -f docker-compose.yml up -d
|
||||
|
||||
deploy-staging:
|
||||
if: startsWith(github.ref, 'refs/heads/release/')
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-push
|
||||
environment: staging
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Deploy to STAGING
|
||||
run: |
|
||||
echo "Deploying to STAGING environment"
|
||||
# Add staging deploy commands
|
||||
@@ -0,0 +1,174 @@
|
||||
# GitHub Actions — Enterprise Level Deploy
|
||||
# Auto-generated by hmcmkit /pdca deploy
|
||||
# EKS + ArgoCD + Canary (Argo Rollouts) + Security Scan
|
||||
|
||||
name: Enterprise Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop, 'release/**']
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
AWS_REGION: ap-northeast-2
|
||||
ECR_REGISTRY: ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.ap-northeast-2.amazonaws.com
|
||||
IMAGE_NAME: ${{ github.event.repository.name }}
|
||||
ARGOCD_SERVER: ${{ secrets.ARGOCD_SERVER }}
|
||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
|
||||
jobs:
|
||||
test-and-lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npm run lint
|
||||
- run: npm test -- --coverage
|
||||
- name: Coverage gate (80%+)
|
||||
run: |
|
||||
COVERAGE=$(npx nyc report --reporter=text-summary | grep 'Statements' | awk '{print $3}' | tr -d '%')
|
||||
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
|
||||
echo "Coverage $COVERAGE% is below 80% threshold"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
security-scan:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-and-lint
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: SAST — Semgrep
|
||||
uses: returntocorp/semgrep-action@v1
|
||||
with:
|
||||
config: 'p/owasp-top-ten'
|
||||
- name: Container Scan — Trivy
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
exit-code: '1'
|
||||
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-and-lint, security-scan]
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
|
||||
aws-region: ${{ env.AWS_REGION }}
|
||||
- uses: aws-actions/amazon-ecr-login@v2
|
||||
- uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.ECR_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
|
||||
${{ env.ECR_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
- name: Sentry Release — Create release & upload sourcemaps
|
||||
uses: getsentry/action-release@v1
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ env.SENTRY_AUTH_TOKEN }}
|
||||
SENTRY_ORG: ${{ env.SENTRY_ORG }}
|
||||
SENTRY_PROJECT: ${{ env.SENTRY_PROJECT }}
|
||||
with:
|
||||
environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
|
||||
version: ${{ github.sha }}
|
||||
sourcemaps: './apps/web/.next'
|
||||
set_commits: auto
|
||||
|
||||
deploy-dev:
|
||||
if: github.ref == 'refs/heads/develop'
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-push
|
||||
environment: development
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Deploy to DEV (Docker Compose on EC2)
|
||||
run: |
|
||||
echo "Deploying to DEV via Docker Compose"
|
||||
# ssh deploy@dev-server "cd /app && docker compose pull && docker compose up -d"
|
||||
|
||||
deploy-staging:
|
||||
if: startsWith(github.ref, 'refs/heads/release/')
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-push
|
||||
environment: staging
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Update Helm values for staging
|
||||
run: |
|
||||
sed -i "s|image.tag:.*|image.tag: ${{ github.sha }}|" infra/k8s/overlays/staging/values.yaml
|
||||
- name: Commit and push (ArgoCD auto-sync)
|
||||
run: |
|
||||
git config user.name "hmcmkit-deploy"
|
||||
git config user.email "deploy@hmcmkit.dev"
|
||||
git add infra/
|
||||
git commit -m "chore(deploy): update staging image to ${{ github.sha }}"
|
||||
git push
|
||||
|
||||
deploy-prod:
|
||||
if: github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-push
|
||||
environment:
|
||||
name: production
|
||||
url: https://app.example.com
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Update Helm values for production (Canary)
|
||||
run: |
|
||||
sed -i "s|image.tag:.*|image.tag: ${{ github.sha }}|" infra/k8s/overlays/prod/values.yaml
|
||||
- name: Commit and push (ArgoCD + Argo Rollouts canary)
|
||||
run: |
|
||||
git config user.name "hmcmkit-deploy"
|
||||
git config user.email "deploy@hmcmkit.dev"
|
||||
git add infra/
|
||||
git commit -m "chore(deploy): canary prod image to ${{ github.sha }}"
|
||||
git push
|
||||
|
||||
post-deploy-monitoring:
|
||||
if: github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
needs: deploy-prod
|
||||
steps:
|
||||
- name: Wait for canary stabilization
|
||||
run: sleep 300 # 5min — canary 10% traffic period
|
||||
|
||||
- name: Verify Sentry — no new critical issues
|
||||
run: |
|
||||
ISSUES=$(curl -s -H "Authorization: Bearer ${{ env.SENTRY_AUTH_TOKEN }}" \
|
||||
"https://sentry.io/api/0/projects/${{ env.SENTRY_ORG }}/${{ env.SENTRY_PROJECT }}/issues/?query=is:unresolved+release:${{ github.sha }}&statsPeriod=5m" \
|
||||
| jq 'length')
|
||||
echo "New unresolved issues: $ISSUES"
|
||||
if [ "$ISSUES" -gt "5" ]; then
|
||||
echo "::error::Too many new issues ($ISSUES) — triggering rollback"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Verify Prometheus — error rate check
|
||||
run: |
|
||||
ERROR_RATE=$(curl -s "http://${{ secrets.PROMETHEUS_URL }}/api/v1/query?query=rate(http_requests_total{status=~\"5..\"}[5m])/rate(http_requests_total[5m])" \
|
||||
| jq '.data.result[0].value[1]' -r 2>/dev/null || echo "0")
|
||||
echo "Current error rate: $ERROR_RATE"
|
||||
if (( $(echo "$ERROR_RATE > 0.01" | bc -l) )); then
|
||||
echo "::error::Error rate $ERROR_RATE exceeds 1% threshold"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: On failure — trigger auto-rollback
|
||||
if: failure()
|
||||
run: |
|
||||
echo "::warning::Post-deploy checks failed — triggering Argo Rollouts abort"
|
||||
curl -X PUT "${{ env.ARGOCD_SERVER }}/api/v1/applications/${{ env.IMAGE_NAME }}/rollback" \
|
||||
-H "Authorization: Bearer ${{ secrets.ARGOCD_TOKEN }}"
|
||||
@@ -0,0 +1,116 @@
|
||||
# kube-prometheus-stack Helm Values — Auto-generated by hmcmkit
|
||||
# helm install monitoring prometheus-community/kube-prometheus-stack -f values.yaml
|
||||
|
||||
prometheus:
|
||||
prometheusSpec:
|
||||
retention: 15d
|
||||
resources:
|
||||
requests: { cpu: "500m", memory: "1Gi" }
|
||||
limits: { cpu: "1", memory: "2Gi" }
|
||||
serviceMonitorSelector: {}
|
||||
podMonitorSelector: {}
|
||||
|
||||
grafana:
|
||||
enabled: true
|
||||
adminPassword: "${GRAFANA_ADMIN_PASSWORD}"
|
||||
dashboardProviders:
|
||||
dashboardproviders.yaml:
|
||||
apiVersion: 1
|
||||
providers:
|
||||
- name: default
|
||||
folder: ''
|
||||
type: file
|
||||
options:
|
||||
path: /var/lib/grafana/dashboards/default
|
||||
datasources:
|
||||
datasources.yaml:
|
||||
apiVersion: 1
|
||||
datasources:
|
||||
- name: Prometheus
|
||||
type: prometheus
|
||||
url: http://monitoring-kube-prometheus-prometheus:9090
|
||||
isDefault: true
|
||||
- name: Loki
|
||||
type: loki
|
||||
url: http://loki:3100
|
||||
- name: Tempo
|
||||
type: tempo
|
||||
url: http://tempo:3100
|
||||
- name: Sentry
|
||||
type: sentry
|
||||
url: "${SENTRY_API_URL}"
|
||||
jsonData:
|
||||
orgSlug: "${SENTRY_ORG_SLUG}"
|
||||
secureJsonData:
|
||||
authToken: "${SENTRY_AUTH_TOKEN}"
|
||||
|
||||
# Pre-built dashboards
|
||||
dashboards:
|
||||
default:
|
||||
service-health:
|
||||
json: |
|
||||
# Service Health Dashboard — Error Rate + Latency + Sentry Issues
|
||||
# Auto-generated by hmcmkit enterprise
|
||||
error-tracking:
|
||||
json: |
|
||||
# Error Tracking Dashboard — Sentry integration
|
||||
# Panels: Unresolved issues, Error rate trend, Top errors, Affected users
|
||||
|
||||
alertmanager:
|
||||
config:
|
||||
route:
|
||||
receiver: 'slack-notifications'
|
||||
group_by: ['alertname', 'namespace']
|
||||
group_wait: 30s
|
||||
group_interval: 5m
|
||||
repeat_interval: 4h
|
||||
routes:
|
||||
- match:
|
||||
severity: critical
|
||||
receiver: 'pagerduty-critical'
|
||||
- match:
|
||||
severity: warning
|
||||
receiver: 'slack-notifications'
|
||||
receivers:
|
||||
- name: 'slack-notifications'
|
||||
slack_configs:
|
||||
- api_url: "${SLACK_WEBHOOK_URL}"
|
||||
channel: '#error-alerts'
|
||||
title: '[{{ .Status }}] {{ .CommonLabels.alertname }}'
|
||||
text: '{{ .CommonAnnotations.description }}'
|
||||
- name: 'pagerduty-critical'
|
||||
pagerduty_configs:
|
||||
- service_key: "${PAGERDUTY_SERVICE_KEY}"
|
||||
severity: critical
|
||||
- name: 'self-healing-webhook'
|
||||
webhook_configs:
|
||||
- url: "${SELF_HEALING_WEBHOOK_URL}"
|
||||
send_resolved: true
|
||||
|
||||
# Custom PrometheusRules for Self-Healing triggers
|
||||
additionalPrometheusRules:
|
||||
- name: self-healing-rules
|
||||
groups:
|
||||
- name: error-detection
|
||||
rules:
|
||||
- alert: HighErrorRate
|
||||
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.01
|
||||
for: 2m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
description: "Error rate > 1% for {{ $labels.service }} — Self-Healing candidate"
|
||||
- alert: CriticalErrorRate
|
||||
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
|
||||
for: 2m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
description: "Error rate > 5% for {{ $labels.service }} — Auto-Rollback triggered"
|
||||
- alert: HighLatency
|
||||
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 0.5
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
description: "P95 latency > 500ms for {{ $labels.service }}"
|
||||
@@ -0,0 +1,27 @@
|
||||
# Loki + Promtail Helm Values — Auto-generated by hmcmkit
|
||||
# helm install loki grafana/loki-stack -f loki-stack.values.yaml
|
||||
|
||||
loki:
|
||||
enabled: true
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 10Gi
|
||||
config:
|
||||
table_manager:
|
||||
retention_deletes_enabled: true
|
||||
retention_period: 168h # 7 days
|
||||
|
||||
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_label_app]
|
||||
target_label: app
|
||||
- source_labels: [__meta_kubernetes_namespace]
|
||||
target_label: namespace
|
||||
@@ -0,0 +1,86 @@
|
||||
# OpenTelemetry Collector + Tempo — Auto-generated by hmcmkit
|
||||
# Distributed tracing: App → OTel Collector → Tempo → Grafana
|
||||
|
||||
# OpenTelemetry Collector
|
||||
# helm install otel open-telemetry/opentelemetry-collector -f otel-tempo.values.yaml
|
||||
opentelemetry-collector:
|
||||
mode: deployment
|
||||
config:
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc: { endpoint: "0.0.0.0:4317" }
|
||||
http: { endpoint: "0.0.0.0:4318" }
|
||||
processors:
|
||||
batch:
|
||||
timeout: 5s
|
||||
send_batch_size: 1024
|
||||
exporters:
|
||||
otlp:
|
||||
endpoint: "tempo:4317"
|
||||
tls: { insecure: true }
|
||||
prometheus:
|
||||
endpoint: "0.0.0.0:8889"
|
||||
connectors:
|
||||
spanmetrics:
|
||||
histogram:
|
||||
explicit:
|
||||
buckets: [5ms, 10ms, 25ms, 50ms, 100ms, 250ms, 500ms, 1s, 2.5s]
|
||||
dimensions:
|
||||
- name: http.method
|
||||
- name: http.status_code
|
||||
- name: service.name
|
||||
service:
|
||||
pipelines:
|
||||
traces:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [otlp]
|
||||
traces/sentry:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [sentry]
|
||||
metrics:
|
||||
receivers: [otlp, spanmetrics]
|
||||
processors: [batch]
|
||||
exporters: [prometheus]
|
||||
|
||||
# Sentry Exporter — Forward error spans to Sentry for correlation
|
||||
# Traces with error status → Sentry issue linkage
|
||||
sentry-exporter:
|
||||
dsn: "${SENTRY_DSN}"
|
||||
environment: "${ENVIRONMENT}"
|
||||
insecure: false
|
||||
|
||||
# Tempo (Trace Backend)
|
||||
# helm install tempo grafana/tempo -f otel-tempo.values.yaml
|
||||
tempo:
|
||||
persistence:
|
||||
enabled: true
|
||||
size: 10Gi
|
||||
config:
|
||||
server:
|
||||
http_listen_port: 3100
|
||||
distributor:
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc: {}
|
||||
storage:
|
||||
trace:
|
||||
backend: local
|
||||
local:
|
||||
path: /var/tempo/traces
|
||||
|
||||
# Blackbox Exporter (Uptime Monitoring)
|
||||
# helm install blackbox prometheus-community/prometheus-blackbox-exporter
|
||||
blackbox-exporter:
|
||||
config:
|
||||
modules:
|
||||
http_2xx:
|
||||
prober: http
|
||||
timeout: 5s
|
||||
http:
|
||||
valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
|
||||
valid_status_codes: [200, 301, 302]
|
||||
follow_redirects: true
|
||||
@@ -0,0 +1,130 @@
|
||||
# Security Layer Templates — Auto-generated by hmcmkit security-architect
|
||||
# 8 Security Components for Enterprise deployments
|
||||
|
||||
---
|
||||
# 1. CloudFront Distribution
|
||||
apiVersion: cloudfront
|
||||
kind: Distribution
|
||||
spec:
|
||||
origins:
|
||||
- domainName: ${alb_domain}
|
||||
originProtocolPolicy: https-only
|
||||
defaultCacheBehavior:
|
||||
viewerProtocolPolicy: redirect-to-https
|
||||
allowedMethods: [GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE]
|
||||
webACLId: ${waf_acl_arn}
|
||||
comment: "hmcmkit-managed CDN + DDoS protection"
|
||||
|
||||
---
|
||||
# 2. AWS WAF — OWASP Top 10
|
||||
# Apply via Terraform: aws_wafv2_web_acl
|
||||
waf_rules:
|
||||
- name: AWSManagedRulesCommonRuleSet
|
||||
priority: 1
|
||||
vendor: AWS
|
||||
- name: AWSManagedRulesSQLiRuleSet
|
||||
priority: 2
|
||||
vendor: AWS
|
||||
- name: AWSManagedRulesKnownBadInputsRuleSet
|
||||
priority: 3
|
||||
vendor: AWS
|
||||
- name: rate-limit
|
||||
priority: 10
|
||||
limit: 2000 # requests per 5 minutes per IP
|
||||
|
||||
---
|
||||
# 3. VPC Design
|
||||
vpc:
|
||||
cidr: "10.0.0.0/16"
|
||||
subnets:
|
||||
public:
|
||||
- "10.0.1.0/24" # ALB, NAT Gateway
|
||||
- "10.0.2.0/24"
|
||||
private:
|
||||
- "10.0.10.0/24" # EKS nodes, application
|
||||
- "10.0.11.0/24"
|
||||
database:
|
||||
- "10.0.20.0/24" # RDS (no internet access)
|
||||
- "10.0.21.0/24"
|
||||
nat_gateway: single # staging: single, prod: per-az
|
||||
|
||||
---
|
||||
# 4. IAM — IRSA (IAM Roles for Service Accounts)
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: ${project_name}-api
|
||||
namespace: ${environment}
|
||||
annotations:
|
||||
eks.amazonaws.com/role-arn: arn:aws:iam::${aws_account_id}:role/${project_name}-${environment}-api
|
||||
|
||||
---
|
||||
# 5. Network Policy (Calico/Cilium)
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: ${project_name}-api-policy
|
||||
namespace: ${environment}
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: ${project_name}-api
|
||||
policyTypes: [Ingress, Egress]
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: ingress-nginx
|
||||
ports:
|
||||
- port: 3000
|
||||
egress:
|
||||
- to:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: ${environment}
|
||||
ports:
|
||||
- port: 5432 # PostgreSQL
|
||||
- port: 6379 # Redis
|
||||
|
||||
---
|
||||
# 6. ACM + cert-manager
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-prod
|
||||
spec:
|
||||
acme:
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-prod-key
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
class: nginx
|
||||
|
||||
---
|
||||
# 7. Secrets Rotation Policy
|
||||
secrets_rotation:
|
||||
provider: aws-secrets-manager
|
||||
rotation_interval: 30d
|
||||
secrets:
|
||||
- name: db-credentials
|
||||
type: rds
|
||||
auto_rotate: true
|
||||
- name: api-keys
|
||||
type: custom
|
||||
auto_rotate: false # manual rotation
|
||||
|
||||
---
|
||||
# 8. Backup & DR
|
||||
backup:
|
||||
rds:
|
||||
retention_period: 7 # days (staging)
|
||||
# retention_period: 35 # days (production)
|
||||
copy_to_region: ap-northeast-1 # Cross-region backup
|
||||
snapshot_schedule: "cron(0 3 * * ? *)" # Daily 3AM UTC
|
||||
s3:
|
||||
versioning: true
|
||||
lifecycle_rule:
|
||||
transition_to_ia: 30 # days
|
||||
transition_to_glacier: 90
|
||||
@@ -0,0 +1,73 @@
|
||||
# Staging EKS On-Demand — Auto-generated by hmcmkit
|
||||
# Creates EKS cluster for PR/release testing, destroys after verification
|
||||
# Cost optimization: ~$10-30/month vs $150+/month always-on
|
||||
|
||||
name: Staging EKS On-Demand
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
types: [opened, synchronize]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
action:
|
||||
description: 'create or destroy'
|
||||
required: true
|
||||
default: 'create'
|
||||
type: choice
|
||||
options: [create, destroy]
|
||||
|
||||
env:
|
||||
CLUSTER_NAME: staging-${{ github.event.pull_request.number || 'manual' }}
|
||||
AWS_REGION: ap-northeast-2
|
||||
|
||||
jobs:
|
||||
create-staging:
|
||||
if: github.event_name == 'pull_request' || github.event.inputs.action == 'create'
|
||||
runs-on: ubuntu-latest
|
||||
environment: staging
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
|
||||
aws-region: ${{ env.AWS_REGION }}
|
||||
|
||||
- name: Create EKS cluster (eksctl)
|
||||
run: |
|
||||
eksctl create cluster \
|
||||
--name ${{ env.CLUSTER_NAME }} \
|
||||
--region ${{ env.AWS_REGION }} \
|
||||
--version 1.29 \
|
||||
--nodegroup-name staging-nodes \
|
||||
--node-type t3.medium \
|
||||
--nodes 2 \
|
||||
--nodes-min 1 \
|
||||
--nodes-max 3 \
|
||||
--managed \
|
||||
--spot \
|
||||
--tags "Environment=staging,ManagedBy=hmcmkit,PR=${{ github.event.pull_request.number }}"
|
||||
|
||||
- name: Deploy application
|
||||
run: |
|
||||
kubectl apply -f infra/k8s/overlays/staging/
|
||||
echo "Staging deployed: ${{ env.CLUSTER_NAME }}"
|
||||
|
||||
- name: Run verification
|
||||
run: |
|
||||
echo "Waiting for pods to be ready..."
|
||||
kubectl wait --for=condition=ready pod -l app --timeout=300s
|
||||
echo "Staging verification complete"
|
||||
|
||||
destroy-staging:
|
||||
if: github.event.action == 'closed' || github.event.inputs.action == 'destroy'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
|
||||
aws-region: ${{ env.AWS_REGION }}
|
||||
- name: Destroy EKS cluster
|
||||
run: |
|
||||
eksctl delete cluster --name ${{ env.CLUSTER_NAME }} --region ${{ env.AWS_REGION }} --wait
|
||||
echo "Staging cluster destroyed: ${{ env.CLUSTER_NAME }}"
|
||||
@@ -0,0 +1,83 @@
|
||||
# Terraform Main — Auto-generated by hmcmkit infra-architect
|
||||
# Level: Enterprise | Provider: AWS
|
||||
#
|
||||
# Usage:
|
||||
# cd infra/terraform/environments/{env}
|
||||
# terraform init
|
||||
# terraform plan
|
||||
# terraform apply
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.5"
|
||||
required_providers {
|
||||
aws = { source = "hashicorp/aws", version = "~> 5.0" }
|
||||
}
|
||||
backend "s3" {
|
||||
bucket = "${project_name}-terraform-state"
|
||||
key = "${environment}/terraform.tfstate"
|
||||
region = "${aws_region}"
|
||||
dynamodb_table = "${project_name}-terraform-locks"
|
||||
encrypt = true
|
||||
}
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
region = var.aws_region
|
||||
default_tags {
|
||||
tags = {
|
||||
Project = var.project_name
|
||||
Environment = var.environment
|
||||
ManagedBy = "terraform"
|
||||
GeneratedBy = "hmcmkit"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ── Modules ──
|
||||
|
||||
module "vpc" {
|
||||
source = "../../modules/vpc"
|
||||
project_name = var.project_name
|
||||
environment = var.environment
|
||||
vpc_cidr = var.vpc_cidr
|
||||
}
|
||||
|
||||
module "eks" {
|
||||
source = "../../modules/eks"
|
||||
project_name = var.project_name
|
||||
environment = var.environment
|
||||
vpc_id = module.vpc.vpc_id
|
||||
private_subnets = module.vpc.private_subnet_ids
|
||||
cluster_version = var.eks_cluster_version
|
||||
node_instance_types = var.node_instance_types
|
||||
depends_on = [module.vpc]
|
||||
}
|
||||
|
||||
module "rds" {
|
||||
source = "../../modules/rds"
|
||||
project_name = var.project_name
|
||||
environment = var.environment
|
||||
vpc_id = module.vpc.vpc_id
|
||||
db_subnets = module.vpc.database_subnet_ids
|
||||
engine = "postgres"
|
||||
engine_version = "15.4"
|
||||
instance_class = var.db_instance_class
|
||||
multi_az = var.environment == "prod" ? true : false
|
||||
depends_on = [module.vpc]
|
||||
}
|
||||
|
||||
# ── Variables ──
|
||||
|
||||
variable "project_name" { type = string }
|
||||
variable "environment" { type = string }
|
||||
variable "aws_region" { type = string; default = "ap-northeast-2" }
|
||||
variable "vpc_cidr" { type = string; default = "10.0.0.0/16" }
|
||||
variable "eks_cluster_version" { type = string; default = "1.29" }
|
||||
variable "node_instance_types" { type = list(string); default = ["t3.medium"] }
|
||||
variable "db_instance_class" { type = string; default = "db.t3.medium" }
|
||||
|
||||
# ── Outputs ──
|
||||
|
||||
output "vpc_id" { value = module.vpc.vpc_id }
|
||||
output "eks_cluster_endpoint" { value = module.eks.cluster_endpoint }
|
||||
output "rds_endpoint" { value = module.rds.endpoint }
|
||||
Reference in new issue
Block a user