Files
project-infra/docs/standards/infra/operations-runbook-upgrade-rollback.md
T

301 lines
12 KiB
Markdown

# operations / runbook / upgrade / rollback 기준
## 목적
이 문서는 1000+ 서비스를 운영하는 플랫폼에서 모든 변경이 거쳐야 하는 **runbook 규칙**을 고정한다. GitOps 원본, rolling update 파라미터 튜닝, 진보된 배포 전략 (Argo Rollouts, canary, blue/green), K3s 자동 업그레이드, node 작업(drain/cordon), rollback 의미와 경계가 대상이다.
## 공식 / 업계 근거
- Kubernetes `Deployment.spec.strategy`: `RollingUpdate` (default, maxSurge/maxUnavailable 25%/25%) 또는 `Recreate` (singleton).
- `kubectl rollout`: `status --timeout`, `history`, `undo --to-revision`, `pause`, `resume`, `restart`.
- **Argo Rollouts** (https://argoproj.github.io/argo-rollouts/): `Rollout` CRD가 Deployment의 대체제로 canary / blueGreen 지원. `AnalysisTemplate` + Prometheus metric으로 자동 승격/롤백.
- **Flagger**: Argo Rollouts의 대안, service-mesh 친화적 (Istio/Linkerd/App Mesh).
- **ArgoCD**: sync wave (`argocd.argoproj.io/sync-wave: "<int>"`), sync phase hook (`PreSync`, `Sync`, `PostSync`, `SyncFail`, `PostDelete`).
- **Flux**: `Kustomization.spec.dependsOn` 으로 순서 명시.
- `kubectl drain --ignore-daemonsets --delete-emptydir-data --grace-period=30` 가 node maintenance 표준. PDB를 존중하므로 PDB 설계가 전제.
- **K3s System Upgrade Controller** (https://docs.k3s.io/upgrades/automated): `Plan` CRD로 server-plan / agent-plan 분리, concurrency 제어, nodeSelector로 대상 제한.
- Flyway `validate`, `info`, `migrate` — application rollout 과 분리.
## 기본 규칙
### 1. Source of truth = Git 의 Kustomize / Helm overlay
운영 변경은 Git에 있는 선언형 원본에서만 시작한다.
기본 금지:
- 운영 노드에서 manifest 파일 직접 편집.
- `kubectl edit` 로 live object 수정 후 문서 없음.
- `/var/lib/rancher/k3s/server/manifests` 를 1차 원본처럼 사용.
### 2. 변경 절차는 render → diff → apply → status → post-check 로 고정
```
1. kubectl kustomize <overlay> # render
2. kubectl diff -k <overlay> # preview
3. kubectl apply -k <overlay> # apply
4. kubectl rollout status ... --timeout=10m
5. post-check (smoke test, SLO check)
```
`diff` 없는 `apply` 는 프로덕션 금지.
### 3. `rollingUpdate.maxSurge` / `maxUnavailable` 는 워크로드별 튜닝
기본값 `25% / 25%`**replica 수에 따라 틀릴 수 있다**.
- **replica 2**: default는 maxUnavailable 0, maxSurge 1 추천 → 항상 최소 2 유지 + 1 추가.
- **replica 3**: `maxSurge: 1, maxUnavailable: 0` → 가용성 우선.
- **replica 10+**: `maxSurge: 25%, maxUnavailable: 10%` → 속도와 가용성 균형.
- **latency-sensitive**: `maxUnavailable: 0` 고정.
- **cost-sensitive large fleet**: `maxSurge: 10%, maxUnavailable: 10%`.
### 4. `Recreate` 전략은 singleton / 동시성 금지 워크로드에만
- PVC ReadWriteOnce + 단일 pod 가 전제인 app (legacy MySQL single instance 등).
- Old/New 동시 실행 시 데이터 부정합이 나는 앱.
- 짧은 downtime이 허용되는 경우.
일반 stateless app은 절대 Recreate 쓰지 않는다.
### 5. `kubectl rollout` 명령 계열
- `kubectl rollout status deployment/<name> --timeout=10m`: 타임아웃 필수.
- `kubectl rollout history deployment/<name>`: revision 확인.
- `kubectl rollout undo deployment/<name> --to-revision=<N>`: 이전 revision으로 되돌림.
- `kubectl rollout pause deployment/<name>`: 롤아웃 중단 (부분 적용 뒤 관찰용).
- `kubectl rollout resume deployment/<name>`: 재개.
- `kubectl rollout restart deployment/<name>`: 이미지 변경 없이 Pod 재생성 (secret 갱신 후 등).
### 6. 진보된 배포 전략: Argo Rollouts (canary / blueGreen)
표준 `Deployment` 로는 부족한 경우 (자동화된 canary, metric-based 승격) 에는 Argo Rollouts 의 `Rollout` CRD 를 쓴다.
- **canary**: `steps:` 로 traffic %, pause, analysis 순서 기술.
- **blueGreen**: `activeService` / `previewService` 로 서비스 두 개 전환.
- **AnalysisTemplate**: Prometheus query로 success rate / p99 latency 측정 → 자동 promote or abort.
- **대안 Flagger**: Istio / Linkerd / App Mesh + Flagger `Canary` CRD. service mesh 있는 플랫폼에서 선택.
### 7. Argo Rollouts 기본 canary 스텝
```
steps:
- setWeight: 10
- pause: { duration: 2m }
- analysis: { templates: [{ templateName: success-rate }] }
- setWeight: 25
- pause: { duration: 5m }
- analysis: { templates: [...] }
- setWeight: 50
- pause: { duration: 10m }
- setWeight: 100
```
각 setWeight 사이에 pause + analysis 로 자동 abort gate.
### 8. blueGreen 은 traffic cutover 가 필요한 경우만
blueGreen은:
- schema 변경이 양립 불가해서 instant cutover가 필요.
- 외부 system 과 coordination 필요 (rollback도 instant).
일반 변경은 canary 가 우선. blueGreen 은 trade-off (리소스 2배, warm-up 부담) 때문에 default 가 아니다.
### 9. ArgoCD sync wave / hook
배포 순서는 sync wave annotation 으로 명시한다.
- `argocd.argoproj.io/sync-wave: "-2"` → CRD.
- `argocd.argoproj.io/sync-wave: "-1"` → namespace, secret store, operator.
- `argocd.argoproj.io/sync-wave: "0"` → 본 리소스 (기본).
- `argocd.argoproj.io/sync-wave: "1"` → Ingress, post-deploy job.
hook:
- `PreSync`: schema migration job.
- `Sync`: 본 리소스 (default).
- `PostSync`: smoke test Job, cache warm.
- `SyncFail`: 실패 시 알림 Job.
- `PostDelete`: 삭제 후 cleanup.
### 10. Flux Kustomization dependsOn
Flux 플랫폼에서는 `Kustomization.spec.dependsOn` 으로 순서를 명시한다.
```yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: prod-50-apps
namespace: flux-system
spec:
interval: 5m
path: ./gitops/clusters/prod/main/stages/50-apps
prune: true
sourceRef:
kind: GitRepository
name: platform
dependsOn:
- name: prod-40-operations
```
### 11. node 작업 (drain / cordon) 은 PDB 존중 흐름
```
1. kubectl cordon <node>
2. kubectl drain <node> \
--ignore-daemonsets \
--delete-emptydir-data \
--grace-period=30 \
--timeout=10m
3. 작업 수행
4. kubectl uncordon <node>
```
옵션 의미:
- `--ignore-daemonsets`: DaemonSet pod는 evict 대상이 아님.
- `--delete-emptydir-data`: ephemeral 데이터 수용.
- `--grace-period=30`: preStop + terminationGracePeriod 존중.
- `--timeout=10m`: PDB 로 인한 무한 대기 차단.
**PDB 없는 critical workload** 는 drain 실패 또는 downtime 유발. PDB 설계가 선결 조건.
### 12. K3s System Upgrade Controller
K3s 자동 업그레이드는 `system-upgrade-controller``Plan` CRD 를 쓴다.
구성:
- **server-plan**: control-plane 먼저 업그레이드. `concurrency: 1`, nodeSelector: `node-role.kubernetes.io/control-plane=true`.
- **agent-plan**: agent 노드. `concurrency: 1~N` (small cluster는 1), server-plan 완료 후.
- `cordon: true`, `drain.force: true, deleteEmptydirData: true, ignoreDaemonsets: true` 표준.
- `version:` 또는 `channel:` 로 target K3s version.
- `upgrade.image: rancher/k3s-upgrade` + 버전 tag.
### 13. blue/green via two Services (수동 패턴)
Argo Rollouts 없이 간단 blue/green 이 필요하면:
- Deployment A (blue), Deployment B (green) 각각.
- Service selector 의 `version` label 만 전환 (blue → green).
- rollback = selector 를 다시 blue 로.
- canary 는 이 방식으로 구현하지 않는다 (Argo Rollouts 사용).
### 14. Rollback 은 DB rollback 이 아니다
**가장 자주 오해되는 규칙**. 반드시 내재화한다.
- `kubectl rollout undo` 는 Deployment workload 만 되돌린다.
- **DB schema 변경 / migration 은 되돌아가지 않는다**.
- rollback 설계는 **schema-forward-compatible** 로 한다:
- Expand (schema 추가 → 이전 코드도 호환) → Migrate (데이터 이전) → Contract (이전 코드용 schema 제거). Expand/Contract를 별도 릴리스로 분리.
- 긴급 상황에서도 rollout undo 로 DB 를 되돌릴 수 없다. DB 는 별도 restore 절차 (PITR, snapshot).
### 15. Flyway validate → migrate 를 application rollout 과 분리
```
1. flyway validate # checksum / 순서 확인
2. flyway info # 대기 migration 확인
3. flyway migrate # 실제 적용
4. kubectl apply -k ... # app rollout (별도 단계)
5. kubectl rollout status # 앱 기동 확인
```
application startup 안에 migration 을 숨기지 않는다 (rollout 실패와 migration 실패 섞임).
### 16. restore 와 rollout 구분
**rollout** (workload 변경 되돌리기):
- `kubectl rollout undo` 또는 이전 Git revision apply.
- Deployment / StatefulSet / DaemonSet 대상.
**restore** (상태 복구):
- K3s control plane → etcd snapshot restore.
- PostgreSQL → PITR / base backup + WAL.
- Vault → raft snapshot restore.
- MinIO → replication resync 또는 DR site cutover.
서로 다른 runbook 이다. "rollback" 이라는 한 단어로 뭉치지 않는다.
### 17. 긴급 변경도 runbook 을 벗어나지 않음
장애 대응 hot-fix 라도:
- 어떤 overlay 를 바꿨는지 commit / PR.
- 어떤 명령을 실행했는지 기록 (shell history / runbook log).
- 사후 Git 반영 (live-cluster drift 제거).
- 임시 조치의 만료 / 정리 시점 기록.
### 18. destructive 작업은 명시 승인 + 증거 보존
요구 작업:
- namespace 삭제.
- PVC 삭제.
- StatefulSet 삭제 + PVC 정리.
- K3s snapshot restore.
- Vault raft snapshot restore.
- DB restore overwrite.
- MinIO bucket purge / replication cutover.
규칙:
- 2-person approval.
- 작업 전 full snapshot 확보.
- dry-run / diff 선행.
- post-mortem 작성.
## 권장 절차 템플릿
### 일반 app 변경
1. PR 생성 + review
2. `kubectl kustomize <overlay>` → 렌더 검증
3. `kubectl diff -k <overlay>` → 변경 확인
4. `kubectl apply -k <overlay>`
5. `kubectl rollout status deployment/<name> --timeout=10m`
6. smoke test + SLO dashboard 확인
7. 결과 PR comment
### DB migration 포함 변경
1. migration SQL review
2. `flyway validate``flyway info``flyway migrate`
3. app overlay apply
4. `kubectl rollout status`
5. post-check
6. 실패 시 DB runbook 과 app rollback runbook 분리 적용
### K3s control plane upgrade
1. 해당 버전 release notes / caveat 확인
2. etcd snapshot 확보
3. `Plan` CRD apply (server-plan)
4. control-plane 업그레이드 완료 확인
5. `Plan` CRD apply (agent-plan)
6. agent 업그레이드 완료 확인
7. packaged component 영향 확인
8. 실패 시 etcd restore runbook
### node maintenance
1. `kubectl cordon <node>`
2. `kubectl drain <node> --ignore-daemonsets --delete-emptydir-data --grace-period=30 --timeout=10m`
3. 작업 수행
4. `kubectl uncordon <node>`
5. `kubectl get pods -o wide` 로 재배치 확인
## 프로젝트 기준 요약
- source of truth = Git Kustomize/Helm overlay, live-cluster 수정 금지.
- render → diff → apply → rollout status → post-check 순서 고정.
- rollingUpdate 파라미터는 워크로드별 튜닝, default 25%/25% 맹신 금지.
- Argo Rollouts 로 canary + AnalysisTemplate 자동 gate, Flagger 는 mesh 환경 대안.
- ArgoCD sync wave / hook, Flux dependsOn 으로 순서 명시.
- node 작업은 PDB 존중 drain 흐름, PDB 설계가 선결.
- K3s 업그레이드는 System Upgrade Controller `Plan` CRD (server → agent).
- blue/green 은 cutover 필요 시, canary 가 default.
- **rollback 은 DB rollback 이 아니다** — schema-forward-compatible 로 설계.
- Flyway validate/migrate 는 application rollout 과 분리.
- restore 와 rollout 은 다른 runbook.
- destructive 작업은 2-person approval + snapshot.