refactor: 폴더 구조 변경

This commit is contained in:
donghyeon-ka
2026-08-02 00:22:19 +09:00
parent f9c463f87a
commit be2f8e4863
1869 changed files with 4565 additions and 295591 deletions
@@ -96,41 +96,38 @@ spec:
## 좋은 예시 2: multi-region prod overlay 디렉터리 (kr-main + kr-dr)
```text
k8s/
base/
app/
units/
identity/
auth/
gitops/
apps/
identity-auth/
base/
kustomization.yaml
deployment.yaml
service.yaml
servicemonitor.yaml
pdb.yaml
hpa.yaml
overlays/
dev/
staging/
prod/
kr-main/
kustomization.yaml
deployment.yaml
service.yaml
servicemonitor.yaml
pdb.yaml
hpa.yaml
plugins/
ingress-nginx/
cert-manager/
external-secrets/
managing/
flyway-migrate-identity/
overlays/
dev/
kustomization.yaml
staging/
kustomization.yaml
prod/
kr-main/
kustomization.yaml
patches/
auth-replicas.yaml
auth-resources.yaml
auth-topology-spread.yaml
kr-dr/
kustomization.yaml
patches/
auth-replicas.yaml
auth-image-pull-mirror.yaml
patches/
kr-dr/
kustomization.yaml
patches/
flyway-migrate-identity/
base/
overlays/
platform/
ingress-nginx/
cert-manager/
secret-delivery/
clusters/
dev/main/
staging/main/
prod/kr-main/
prod/kr-dr/
```
**왜 좋은가:**
@@ -375,7 +372,7 @@ spec:
image: registry.example.com/auth:1.24.3
```
**문제:** `selector.matchLabels`는 Deployment/StatefulSet에서 **immutable**이다. `version`은 배포마다 바뀌고 `environment`는 overlay가 주입한다 → 첫 배포 이후 재apply 시 `field is immutable` 에러로 영구 차단. selector에는 불변 3종(`name`/`instance`/`component`)만.
**문제:** `selector.matchLabels`는 Deployment/StatefulSet에서 **immutable**이다. `version`은 배포마다 바뀌고 `environment`는 overlay가 주입한다 → 첫 배포 이후 재apply 시 `field is immutable` 에러로 영구 차단. selector에는 불변 2종(`name`/`instance`)만.
---
+1 -1
View File
@@ -600,7 +600,7 @@ resources:
- aescbc:
keys:
- name: fallback-2026-q1
secret: c2VjcmV0LTMyLWJ5dGUtZmFsbGJhY2sta2V5LTIwMjZxMS1leGFtcGxl
secret: <kms-fallback-key-base64>
- identity: {}
```
+2 -1
View File
@@ -1,6 +1,7 @@
# db / migration 예시
모든 YAML은 `kubectl apply` 가능하다. 상세 Flyway Job 예시는 `examples/infra/flyway.md` 참조.
모든 YAML은 `kubectl apply` 가능하다. 상세 Flyway Job 예시는
`docs/examples/infra/flyway.md` 참조.
---
+1 -1
View File
@@ -105,7 +105,7 @@ metadata:
app.kubernetes.io/managed-by: keycloak-operator
spec:
instances: 3
image: registry.example.com/platform/keycloak:26.0.7-optimized
image: registry.example.com/platform/keycloak:26.0.7-optimized # gitleaks:allow
startOptimized: true
db:
vendor: postgres
+46 -42
View File
@@ -8,35 +8,39 @@ kubectl kustomize <dir> | kubectl apply --server-side --field-manager=ci --dry-r
---
## 좋은 예시 1: base / components / overlays 전체 구조 + 실제 base `kustomization.yaml`
## 좋은 예시 1: catalog unit의 base / components / overlays 구조
```text
k8s/
base/
app/units/identity/auth/
kustomization.yaml
deployment.yaml
service.yaml
servicemonitor.yaml
pdb.yaml
hpa.yaml
components/
with-topology-spread-zone/
kustomization.yaml
patch.yaml
with-pdb-tier1/
kustomization.yaml
patch.yaml
overlays/
gitops/
apps/
identity-auth/
base/
kustomization.yaml
deployment.yaml
service.yaml
servicemonitor.yaml
pdb.yaml
hpa.yaml
components/
with-topology-spread-zone/
kustomization.yaml
patch.yaml
with-pdb-tier1/
kustomization.yaml
patch.yaml
overlays/
prod/kr-main/
kustomization.yaml
patches/
auth-resources.yaml
auth-ingress-host.yaml
clusters/
prod/kr-main/
kustomization.yaml
patches/
auth-resources.yaml
auth-ingress-host.yaml
```
```yaml
# k8s/base/app/units/identity/auth/kustomization.yaml
# gitops/apps/identity-auth/base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
@@ -66,7 +70,7 @@ labels:
## 좋은 예시 2: base Deployment (완전 apply-ready)
```yaml
# k8s/base/app/units/identity/auth/deployment.yaml
# gitops/apps/identity-auth/base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -206,12 +210,12 @@ spec:
## 좋은 예시 3: overlay prod/kr-main — 환경 차이만
```yaml
# k8s/overlays/prod/kr-main/kustomization.yaml
# gitops/apps/identity-auth/overlays/prod/kr-main/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: prod-identity-auth
resources:
- ../../../base/app/units/identity/auth
- ../../../base
components:
- ../../../components/with-topology-spread-zone
- ../../../components/with-pdb-tier1
@@ -246,7 +250,7 @@ patches:
```
```yaml
# k8s/overlays/prod/kr-main/patches/auth-resources.yaml
# gitops/apps/identity-auth/overlays/prod/kr-main/patches/auth-resources.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -302,7 +306,7 @@ spec:
## 좋은 예시 4: Kustomize Component — `with-pdb-tier1`
```yaml
# k8s/components/with-pdb-tier1/kustomization.yaml
# gitops/apps/identity-auth/components/with-pdb-tier1/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
@@ -310,7 +314,7 @@ resources:
```
```yaml
# k8s/components/with-pdb-tier1/pdb.yaml
# gitops/apps/identity-auth/components/with-pdb-tier1/pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
@@ -343,7 +347,7 @@ spec:
## 좋은 예시 5: ConfigMap generator + hash suffix를 활용한 자동 rollout
```yaml
# k8s/base/app/units/identity/auth/kustomization.yaml (with generator)
# gitops/apps/identity-auth/base/kustomization.yaml (with generator)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
@@ -373,7 +377,7 @@ generatorOptions:
## 좋은 예시 6: HPA v2 + behavior (base 리소스)
```yaml
# k8s/base/app/units/identity/auth/hpa.yaml
# gitops/apps/identity-auth/base/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
@@ -433,12 +437,12 @@ spec:
## 나쁜 예시 1: `commonLabels`로 environment 주입 → selector immutable 에러
```yaml
# k8s/overlays/prod/kustomization.yaml (BAD)
# gitops/apps/identity-auth/overlays/prod/kustomization.yaml (BAD)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: prod-identity-auth
resources:
- ../../base/app/units/identity/auth
- ../../base
commonLabels:
example.com/environment: prod
```
@@ -450,10 +454,10 @@ commonLabels:
## 나쁜 예시 2: overlay가 base를 거의 재작성
```text
k8s/base/app/units/identity/auth/deployment.yaml (150 lines)
k8s/overlays/prod/deployment.yaml (140 lines, 95% identical)
k8s/overlays/staging/deployment.yaml (140 lines)
k8s/overlays/dev/deployment.yaml (135 lines)
gitops/apps/identity-auth/base/deployment.yaml (150 lines)
gitops/apps/identity-auth/overlays/prod/deployment.yaml (140 lines, 95% identical)
gitops/apps/identity-auth/overlays/staging/deployment.yaml (140 lines)
gitops/apps/identity-auth/overlays/dev/deployment.yaml (135 lines)
```
**문제:** overlay가 base의 95%를 복붙 + 몇 줄 수정. drift 발생 시점부터 base가 의미 없어진다. 해결: overlay는 `patches:` + `images:` + `replicas:` + `labels:`만 쓰고 전체 리소스는 base에서 가져온다.
@@ -463,7 +467,7 @@ k8s/overlays/dev/deployment.yaml (135 lines)
## 나쁜 예시 3: 운영 secret을 `secretGenerator`로 plaintext Git 커밋
```yaml
# k8s/overlays/prod/kustomization.yaml (BAD)
# gitops/apps/identity-auth/overlays/prod/kustomization.yaml (BAD)
secretGenerator:
- name: auth-secrets
literals:
@@ -478,7 +482,7 @@ secretGenerator:
## 나쁜 예시 4: `patchesStrategicMerge` / `patchesJson6902` (deprecated)
```yaml
# k8s/overlays/prod/kustomization.yaml (BAD, v5 deprecated)
# gitops/apps/identity-auth/overlays/prod/kustomization.yaml (BAD, v5 deprecated)
patchesStrategicMerge:
- patches/auth-resources.yaml
patchesJson6902:
@@ -497,7 +501,7 @@ patchesJson6902:
## 나쁜 예시 5: base에 환경 host / domain 고정
```yaml
# k8s/base/app/units/identity/auth/ingress.yaml (BAD)
# gitops/apps/identity-auth/base/ingress.yaml (BAD)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
@@ -523,11 +527,11 @@ spec:
## 나쁜 예시 6: `bases:` 사용 (v2.1에서 `resources:`로 통합됨)
```yaml
# k8s/overlays/prod/kustomization.yaml (BAD)
# gitops/apps/identity-auth/overlays/prod/kustomization.yaml (BAD)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../base/app/units/identity/auth
- ../../base
```
**문제:** `bases:`는 v2.1에서 `resources:`에 흡수됨. 신규 코드에서 사용 금지. 해결: `resources:` 사용.
@@ -537,7 +541,7 @@ bases:
## 나쁜 예시 7: HPA가 있는 Deployment에 overlay `replicas:`로 고정값 주입
```yaml
# k8s/overlays/prod/kustomization.yaml (BAD — conflicts with HPA)
# gitops/apps/identity-auth/overlays/prod/kustomization.yaml (BAD — conflicts with HPA)
replicas:
- name: auth
count: 3
+26 -48
View File
@@ -581,7 +581,7 @@ metadata:
namespace: minio-prod
type: Opaque
stringData:
token: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9..."
token: "<minio-prometheus-token>"
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
@@ -636,42 +636,31 @@ data:
#!/bin/sh
set -eu
mc alias set minio https://minio.minio-prod.svc.cluster.local "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" --api S3v4
mc --config-dir /tmp/mc alias import minio <<EOF
{
"url": "https://minio.minio-prod.svc.cluster.local",
"accessKey": "$MINIO_ROOT_USER",
"secretKey": "$MINIO_ROOT_PASSWORD",
"api": "s3v4",
"path": "auto"
}
EOF
# Object Lock은 bucket 생성 시점에만 활성화 가능
mc mb --with-lock minio/critical-audit || true
mc retention set --default COMPLIANCE 2555d minio/critical-audit # 7년 보관
mc --config-dir /tmp/mc mb --with-lock minio/critical-audit || true
mc --config-dir /tmp/mc retention set --default COMPLIANCE 2555d minio/critical-audit
# Versioning + lifecycle
mc mb minio/app-data || true
mc version enable minio/app-data
mc ilm add --expire-noncurrent-days 90 minio/app-data
mc ilm add --expire-incomplete-upload-days 7 minio/app-data
mc --config-dir /tmp/mc mb minio/app-data || true
mc --config-dir /tmp/mc version enable minio/app-data
mc --config-dir /tmp/mc ilm add --expire-noncurrent-days 90 minio/app-data
mc --config-dir /tmp/mc ilm add --expire-incomplete-upload-days 7 minio/app-data
# SSE-KMS 기본 적용
mc encrypt set sse-kms minio-app-key minio/app-data
mc encrypt set sse-kms minio-critical-key minio/critical-audit
# Service account 발급 (앱 전용, 최소 권한 policy)
mc admin policy create minio auth-server-rw /policies/auth-server-rw.json
mc admin user svcacct add minio "$MINIO_ROOT_USER" \
--access-key "$AUTH_SERVER_ACCESS_KEY" \
--secret-key "$AUTH_SERVER_SECRET_KEY" \
--policy /policies/auth-server-rw.json || true
mc --config-dir /tmp/mc encrypt set sse-kms minio-app-key minio/app-data
mc --config-dir /tmp/mc encrypt set sse-kms minio-critical-key minio/critical-audit
echo "bootstrap complete"
auth-server-rw.json: |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:ListBucket"],
"Resource": ["arn:aws:s3:::app-data/*", "arn:aws:s3:::app-data"]
}
]
}
---
apiVersion: batch/v1
kind: Job
@@ -703,21 +692,11 @@ spec:
secretKeyRef:
name: minio-root-creds
key: password
- name: AUTH_SERVER_ACCESS_KEY
valueFrom:
secretKeyRef:
name: auth-server-minio-svcacct
key: access_key
- name: AUTH_SERVER_SECRET_KEY
valueFrom:
secretKeyRef:
name: auth-server-minio-svcacct
key: secret_key
volumeMounts:
- name: scripts
mountPath: /scripts
- name: policies
mountPath: /policies
- name: tmp
mountPath: /tmp
securityContext:
runAsNonRoot: true
runAsUser: 1000
@@ -734,12 +713,10 @@ spec:
items:
- key: init.sh
path: init.sh
- name: policies
configMap:
name: minio-bootstrap
items:
- key: auth-server-rw.json
path: auth-server-rw.json
- name: tmp
emptyDir:
medium: Memory
sizeLimit: 64Mi
```
**왜 좋은가:**
@@ -747,7 +724,8 @@ spec:
- `mc mb --with-lock`은 bucket 생성 시점에만 Object Lock 활성화 가능 — Job이 그 타이밍을 보장
- COMPLIANCE 모드 7년 retention = 감사/규제 요구 충족 (root도 bypass 불가)
- `app-data` bucket은 versioning + lifecycle (90일 noncurrent expire + 7일 incomplete abort)
- service account는 특정 bucket prefix만 접근 가능한 policy로 제한
- 애플리케이션 access key 발급은 별도 bootstrap에서 inline 최소 권한 policy
함께 수행하고, 생성 secret은 Vault로 직접 전달
- `backoffLimit: 3` + idempotent 명령 (`|| true`) → 재실행 안전
---
@@ -6,13 +6,13 @@
```bash
# 1) render
kubectl kustomize k8s/overlays/prod > /tmp/render.yaml
kubectl kustomize gitops/clusters/prod/main/stages/50-apps > /tmp/render.yaml
# 2) diff
kubectl diff -k k8s/overlays/prod
kubectl diff -k gitops/clusters/prod/main/stages/50-apps
# 3) apply
kubectl apply -k k8s/overlays/prod
kubectl apply -k gitops/clusters/prod/main/stages/50-apps
# 4) rollout status with timeout
kubectl rollout status deployment/auth-server -n auth-prod --timeout=10m
@@ -607,10 +607,10 @@ kubectl get pods -A -o wide --field-selector spec.nodeName="${NODE}"
git checkout v1.24.0
# 2) diff
kubectl diff -k k8s/overlays/prod
kubectl diff -k gitops/clusters/prod/main/stages/50-apps
# 3) apply
kubectl apply -k k8s/overlays/prod
kubectl apply -k gitops/clusters/prod/main/stages/50-apps
# 4) rollout status
kubectl rollout status deployment/auth-server -n auth-prod --timeout=10m
@@ -627,7 +627,7 @@ kubectl rollout status deployment/auth-server -n auth-prod --timeout=10m
## 나쁜 예시 1: diff 없이 apply
```bash
kubectl apply -k k8s/overlays/prod
kubectl apply -k gitops/clusters/prod/main/stages/50-apps
```
**문제:**
+2 -2
View File
@@ -106,8 +106,8 @@ Environment:
CONFIRM=yes non-interactive confirmation (alternative to --yes)
Examples:
render-diff-apply --overlay k8s/overlays/prod --context prod-eu
CONFIRM=yes render-diff-apply --overlay k8s/overlays/prod --context prod-eu --timeout 15m
render-diff-apply --overlay gitops/clusters/prod/main/stages/50-apps --context prod-eu
CONFIRM=yes render-diff-apply --overlay gitops/clusters/prod/main/stages/50-apps --context prod-eu --timeout 15m
EOF
}
+1 -1
View File
@@ -216,7 +216,7 @@ spec:
- stateless 장기 실행 → Deployment 정답
- PDB + HPA + topologySpread (zone+hostname) 모두 tier-1에 맞게 동반
- digest pinning, restricted PodSecurity 호환, preStop sleep으로 graceful drain
- selector에는 불변 3종만 (version/environment 없음)
- selector에는 불변 2종만 (`name`/`instance`; version/environment 없음)
---