# 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: ""`), 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 # render 2. kubectl diff -k # preview 3. kubectl apply -k # 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/ --timeout=10m`: 타임아웃 필수. - `kubectl rollout history deployment/`: revision 확인. - `kubectl rollout undo deployment/ --to-revision=`: 이전 revision으로 되돌림. - `kubectl rollout pause deployment/`: 롤아웃 중단 (부분 적용 뒤 관찰용). - `kubectl rollout resume deployment/`: 재개. - `kubectl rollout restart deployment/`: 이미지 변경 없이 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: auth-server namespace: flux-system spec: interval: 5m path: ./k8s/overlays/prod prune: true sourceRef: kind: GitRepository name: platform dependsOn: - name: cert-manager - name: postgres-operator ``` ### 11. node 작업 (drain / cordon) 은 PDB 존중 흐름 ``` 1. kubectl cordon 2. kubectl drain \ --ignore-daemonsets \ --delete-emptydir-data \ --grace-period=30 \ --timeout=10m 3. 작업 수행 4. kubectl uncordon ``` 옵션 의미: - `--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 ` → 렌더 검증 3. `kubectl diff -k ` → 변경 확인 4. `kubectl apply -k ` 5. `kubectl rollout status deployment/ --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 ` 2. `kubectl drain --ignore-daemonsets --delete-emptydir-data --grace-period=30 --timeout=10m` 3. 작업 수행 4. `kubectl uncordon ` 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.