Add platform infrastructure configuration
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
# Phase 2 Keycloak·MinIO AIStor 수동 배포 진입점
|
||||
|
||||
상세 설계는 중앙 문서 `/home/donghyeon/workspace/docs/platform`에서 관리한다.
|
||||
이 파일은 선언의 의존 순서와 검증 진입점만 기록한다.
|
||||
|
||||
## 상태
|
||||
|
||||
2026-07-23 기준 Keycloak-only 경로는 DB Secret 두 사본, DatabaseRole·Database,
|
||||
additive NetworkPolicy, Operator·Server `26.7.0`, Ingress, `hyeonworks` realm,
|
||||
confidential `gitea` client와 OIDC Secret까지 실제 적용했다. Traefik 최소 trust도
|
||||
완료했다. Host Nginx의 `id.learn.hyeonworks.com` proxy와 Gitea OIDC·브랜딩 live
|
||||
적용도 완료했고 OAuth source·정책·redirect·브랜딩 자동 검증을 통과했다. 실제
|
||||
realm 사용자의 브라우저 login/callback/logout, 비상 관리자 로그인과 재시작
|
||||
지속성 검증은 남아 있다. MinIO AIStor는 NetworkPolicy, namespace, AIStor 전용
|
||||
두 Secret, 900Gi Retain Local PV, 공식 Operator와 단일 ObjectStore까지 실제
|
||||
적용했다. `Initialized/green`, PVC Bound, ClusterIP-only와 인증된 S3
|
||||
put/get/delete checksum 검증을 통과했다.
|
||||
|
||||
## 적용 전 렌더 검증
|
||||
|
||||
Helm `3.19.4`가 `PATH`에 없다면 검증된 실행 파일의 절대 경로를 지정한다.
|
||||
|
||||
```sh
|
||||
cd /home/donghyeon/workspace/platform
|
||||
PLATFORM_HELM_BIN=/absolute/path/to/helm \
|
||||
bash scripts/validate/render-phase2.sh
|
||||
```
|
||||
|
||||
이 명령은 Phase 1 검증을 먼저 수행한 뒤 Phase 2 전체를 로컬 렌더한다. 실제
|
||||
클러스터의 ObjectStore CRD 설치 여부와 무관하며 어떤 리소스도 적용하지 않는다.
|
||||
|
||||
## Keycloak-only 적용 진입점
|
||||
|
||||
AIStor license와 ObjectStore 준비를 기다리지 않고 Keycloak만 먼저 배포할 때는
|
||||
다음 전용 스크립트를 사용한다. Helm과 AIStor Secret은 요구하지 않는다.
|
||||
|
||||
```sh
|
||||
cd /home/donghyeon/workspace/platform
|
||||
bash scripts/bootstrap/apply-keycloak.sh --execute
|
||||
```
|
||||
|
||||
스크립트는 Keycloak namespace, Keycloak DB Secret 두 개, 공용 PostgreSQL의
|
||||
`DatabaseRole`·`Database`·`NetworkPolicy`, Keycloak Operator, Keycloak CR과
|
||||
Ingress를 순서대로 렌더·검증·적용하고 각 readiness를 기다린다. 먼저 현재
|
||||
Kubernetes context와 API server를 출력한 뒤 `APPLY`를 정확히 입력해야 한다.
|
||||
두 DB Secret이 모두 없으면 비밀번호를 화면에 표시하지 않고 두 번 입력받은 뒤
|
||||
`APPLY KEYCLOAK SECRETS`를 한 번 더 확인한다. 두 Secret이 이미 있으면 값을
|
||||
바꾸지 않고 계약만 검증해 재사용한다.
|
||||
|
||||
자동 적용 전에 두 Secret을 안전하게 미리 생성하려면 다음 명시적 비대화형 모드를
|
||||
사용할 수 있다.
|
||||
|
||||
```sh
|
||||
kubectl apply --filename=infrastructure/namespaces/phase2/keycloak.yaml
|
||||
bash scripts/bootstrap/create-keycloak-secrets.sh --generate --execute
|
||||
bash scripts/bootstrap/apply-keycloak.sh --execute
|
||||
```
|
||||
|
||||
`--generate --execute`는 OpenSSL CSPRNG로 32바이트 난수를 생성해 mode `0600`
|
||||
임시 파일에만 기록한다. 생성값은 argv나 화면에 출력하지 않으며 두 플래그 자체를
|
||||
자동 생성 승인으로 취급한다. 두 Secret이 이미 있으면 새 값을 만들거나 회전하지
|
||||
않고 기존 계약을 검증해 그대로 재사용한다.
|
||||
독립 실행하는 Secret 생성기는 `platform-data`와 `keycloak` namespace가 먼저
|
||||
존재해야 하므로 위 첫 명령을 생략하지 않는다.
|
||||
|
||||
위 Keycloak-only 명령은 실제 완료됐으며 재실행 시 기존 Secret을 회전하지 않고
|
||||
계약과 readiness를 다시 검증한다. 실제 결과는 중앙
|
||||
`runbooks/2026-07-23-keycloak-gitea-oidc-cutover.md`에 기록한다.
|
||||
|
||||
|
||||
중간 단계가 실패해도 namespace, Secret, DB 리소스, Operator 또는 Keycloak
|
||||
리소스를 자동 삭제하지 않는다. DB reclaim policy는 `Retain`으로 유지하며 원인을
|
||||
해결한 뒤 같은 명령을 다시 실행하는 것이 복구 경로다. Host Nginx의 Keycloak
|
||||
정적 hold 제거와 Gitea OIDC 인증 소스 등록은 이 스크립트 범위가 아니다.
|
||||
|
||||
## AIStor 실제 적용 및 재검증
|
||||
|
||||
실제 적용에는 다음 진입점을 사용했다.
|
||||
|
||||
```sh
|
||||
cd /home/donghyeon/workspace/platform
|
||||
PLATFORM_HELM_BIN=/home/donghyeon/.local/bin/helm \
|
||||
bash scripts/bootstrap/apply-aistor.sh \
|
||||
--license-file /home/donghyeon/.secrets/aistor/minio.license \
|
||||
--root-config-file /home/donghyeon/.secrets/aistor/root.env \
|
||||
--execute
|
||||
|
||||
bash scripts/validate/aistor-s3-smoke.sh --execute
|
||||
```
|
||||
|
||||
첫 스크립트가 수행하고 검증한 순서는 다음과 같다.
|
||||
|
||||
1. Phase 1과 Keycloak-only 리소스가 정상이며 Host Nginx·Gitea OIDC 작업과 AIStor
|
||||
작업이 서로 독립임을 확인한다.
|
||||
2. AIStor Operator·ObjectStore용 저장소 소유 NetworkPolicy를 먼저 렌더하고
|
||||
k3s CNI의 승인 흐름과 차단 흐름을 검증한다. webhook,
|
||||
Kubernetes API, license 확인, DNS, ObjectStore 내부 통신과 승인된 S3 소비자를
|
||||
빠뜨리지 않는다.
|
||||
|
||||
- `infrastructure/controllers/aistor-operator`
|
||||
- `services/minio-aistor`
|
||||
|
||||
3. 정확히 `aistor`, `object-storage` namespace만 검토·적용한다.
|
||||
4. `/srv/k3s/aistor`의 XFS mount·권한과 예상 밖 StorageClass 소비자가 없음을
|
||||
확인한 뒤 `infrastructure/storage/aistor-local-pv`를 적용한다.
|
||||
5. AIStor 두 Secret만 two-or-none으로 관리하는 전용 helper를 실행한다.
|
||||
기존 four-or-none `create-phase2-secrets.sh`는 현재 Keycloak-only 상태에서
|
||||
실행하지 않는다.
|
||||
6. NetworkPolicy gate 통과 후 `infrastructure/controllers/aistor-operator`와 해당
|
||||
정책을 적용하고 CRD, 두 Operator, admission webhook이 준비될 때까지 기다린다.
|
||||
7. `services/minio-aistor`와 해당 정책을 적용하고 하나의 서버·하나의 900Gi 볼륨,
|
||||
`ClusterIP` S3/Console, 예상 PVC·PV binding을 확인한다. 실제 workload에서도
|
||||
승인·차단 흐름을 다시 시험한다.
|
||||
8. S3 put/get/delete와 checksum, 관리 포트 비노출을 확인한다.
|
||||
|
||||
1~8의 자동 검증은 완료했다. ObjectStore Pod 재생성 뒤 기존 영구 객체가 유지되는지
|
||||
보는 별도 지속성 시험은 운영 데이터와 구분된 시험 버킷·승인 창을 정한 뒤 수행한다.
|
||||
|
||||
Argo CD 인계와 Host Nginx 변경은 이 Phase 2 수동 적용 범위에 포함하지 않는다.
|
||||
Istio와 sidecar injection도 적용하지 않는다.
|
||||
|
||||
## Secret 안전 조건
|
||||
|
||||
- Keycloak-only 경로의 두 DB Secret 중 일부만 존재하면
|
||||
`create-keycloak-secrets.sh`가 생성·회전을 거부한다. 두 Secret은
|
||||
`platform-data`와 `keycloak` namespace에 동일한 `keycloak` 사용자와 동일한
|
||||
비밀번호로 존재해야 한다.
|
||||
- Keycloak-only 스크립트는 AIStor license와 ObjectStore root Secret을 읽거나
|
||||
요구하거나 수정하지 않는다.
|
||||
- Keycloak DB Secret과 AIStor 두 Secret은 모두 존재하지만 서로 독립 계약이다.
|
||||
- 기존 four-or-none helper는 이 상태에서 중단하는 것이 정상이며 우회하거나
|
||||
Keycloak Secret을 삭제하지 않는다.
|
||||
- AIStor 전용 helper는 AIStor 두 Secret이 모두 없거나 모두 존재할 때만
|
||||
진행하고 one-of-two 상태에서는 자동 삭제·덮어쓰기 없이 중단한다.
|
||||
- 두 AIStor Secret이 모두 존재하면 타입·정확한 키, license file 동일성, root
|
||||
configuration 형식만 검증하고 값을 바꾸지 않는다.
|
||||
- license payload, root 사용자·비밀번호, DB 비밀번호는 Git, argv, 표준 출력에
|
||||
기록하지 않는다.
|
||||
- bootstrap helper는 credential 또는 license 회전을 수행하지 않는다.
|
||||
Reference in New Issue
Block a user