WEBBOOK CHAPTER

Git에서 EKS까지: 28장 upgrade·복구·비용 정리까지 최종 실전을 완주한다

28장 upgrade·복구·비용 정리까지 최종 실전을 완주한다

최종 실전은 새 version 배포가 아니라 운영 cycle 전체다.

  1. PR에서 application·manifest diff와 rollback plan을 review한다.
  2. CI가 test하고 SHA image를 ECR에 한 번 build한다.
  3. scan 결과와 예외를 확인한다.
  4. staging에 같은 digest를 배포해 probe·smoke·metrics를 본다.
  5. production 승인 후 같은 digest를 rollout한다.
  6. release evidence를 남기고 관찰 window를 지킨다.
  7. 실패하면 event·log·revision을 보존한 뒤 rollback한다.

cluster upgrade 전에는 다음을 실행한다.


aws eks list-insights --cluster-name flownote-lab --filter categories=UPGRADE_READINESS
kubectl api-resources
kubectl get --raw /metrics >/dev/null

control plane, managed component, workload를 순서대로 확인하고 한 minor version씩 올린다. data가 있다면 EBS snapshot, database backup, restore drill은 cluster backup과 분리해 검증한다. Kubernetes manifest만 보관해도 database 내용은 돌아오지 않는다.

학습을 마쳤다면 비용 순서대로 삭제한다. Ingress를 먼저 지워 ALB controller가 load balancer를 정리할 시간을 준다.


kubectl delete -f examples/k8s/30-ingress.yaml --ignore-not-found
kubectl delete namespace flownote --ignore-not-found
eksctl delete cluster -f examples/cluster/cluster.yaml --wait
aws ecr delete-repository --repository-name flownote --force 
  --region ap-northeast-2

삭제 명령 성공이 끝이 아니다. 잔존물을 확인한다.


aws eks list-clusters --region ap-northeast-2
aws elbv2 describe-load-balancers --region ap-northeast-2
aws ec2 describe-nat-gateways --filter Name=state,Values=available,pending
aws ec2 describe-addresses
aws logs describe-log-groups --log-group-name-prefix /aws/eks/flownote-lab
aws ecr describe-repositories --region ap-northeast-2

실무 졸업 조건은 “화면이 한 번 열림”이 아니다.

  • 다른 팀원이 빈 계정 또는 test account에서 문서만 보고 재현한다.
  • repository와 pipeline에 장기 AWS key가 없다.
  • build role과 deploy role, 사람 access가 분리되어 있다.
  • image SHA/digest와 runtime version이 일치한다.
  • readiness 실패가 traffic을 막고 liveness가 불필요한 재시작을 만들지 않는다.
  • rollout·smoke 실패가 자동 중단되고 rollback time을 측정했다.
  • audit log와 application signal로 누가 무엇을 언제 바꿨는지 설명한다.
  • monthly cost owner와 budget, tag, cleanup runbook이 있다.

실무 장애 24개 훈련 카드

번호 주입 상황 관찰할 증거 첫 조치
1 잘못된 ECR tag Pod event image URI와 digest 대조
2 ECR pull 권한 없음 AccessDenied event node/workload identity scope 확인
3 process 즉시 종료 previous log exit code·config 확인
4 readiness path 오타 EndpointSlice 없음 probe path와 app route 비교
5 liveness가 DB를 검사 연쇄 restart liveness 의존성 제거
6 request가 지나치게 큼 Pending event quota·allocatable·request 비교
7 memory limit 부족 OOMKilled peak·heap·limit 측정
8 Service selector 오타 endpoint 0개 label set 비교
9 targetPort 오타 ALB unhealthy Service→container port 추적
10 subnet tag 누락 Ingress event public/private discovery tag
11 ALB security group 차단 target timeout SG source와 port 확인
12 DNS가 이전 ALB를 가리킴 dig 결과 alias·TTL·변경 시각 확인
13 certificate domain 불일치 curl -v ACM SAN·listener 확인
14 OIDC audience 불일치 STS AccessDenied token aud와 provider 비교
15 GitHub sub 불일치 assume role 실패 branch/environment claim 확인
16 GitLab project rename trust 실패 stable project_id 조건 검토
17 deploy role이 cluster 미등록 kubectl unauthorized Access Entry 확인
18 RBAC namespace 불일치 forbidden kubectl auth can-i
19 quota가 surge를 막음 rollout timeout old+new request 합산
20 PDB가 drain을 막음 disruptionsAllowed 0 replica·PDB 목적 재평가
21 HPA가 scale하지 않음 metrics unknown metrics·request 확인
22 Auto Mode node가 안 생김 NodePool condition requirement·quota·capacity
23 log 비용 급증 ingestion bytes verbosity·retention 조정
24 cluster 삭제 뒤 ALB 잔존 ELB inventory Ingress 삭제 순서·tag 확인

팀 실습 워크북: 문서 없이도 복구할 수 있는가

미션 1 현재 실행 identity를 설명한다

aws sts get-caller-identity, kubectl config current-context, kubectl auth can-i --list -n flownote를 저장한다. 세 출력의 identity가 왜 다르게 보이는지 설명한다. “내 노트북에서는 됨” 대신 어떤 federation role이 어떤 Access Entry와 Kubernetes permission을 통과했는지 기록한다.

완료 증거: account ID, assumed role ARN, cluster name, namespace, 허용·거부 verb 표. credential 원문은 포함하지 않는다.

미션 2 network를 손으로 다시 그린다

VPC CIDR, 두 AZ, public/private subnet CIDR, route table, Internet Gateway, NAT Gateway, ALB, Pod를 빈 종이에 그린다. 각 화살표에 source/destination과 port를 적는다. outbound가 필요한 이유와 VPC endpoint로 대체 가능한 traffic을 표시한다.

완료 증거: “public/private”라는 이름 없이 route만 보고 subnet 성격을 판정할 수 있다.

미션 3 image와 source의 양방향 추적을 만든다

running Pod의 imageID digest에서 ECR image detail과 CI run을 찾아 source commit까지 이동한다. 반대로 commit SHA에서 CI run, ECR digest, Deployment revision, Pod를 찾는다.


kubectl -n flownote get pod -l app.kubernetes.io/name=flownote 
  -o jsonpath='{range .items[*]}{.metadata.name}{"t"}{.status.containerStatuses[0].imageID}{"n"}{end}'

완료 증거: 임의 Pod 하나의 source reviewer와 production approver를 10분 안에 찾는다.

미션 4 readiness 실패를 안전하게 관찰한다

test namespace에서만 readiness path가 존재하지 않는 release를 만든다. 새 Pod가 Running이지만 Ready가 되지 않고 Service EndpointSlice에 들어가지 않는지 본다. rollout timeout 뒤 event와 ReplicaSet 상태를 보존하고 undo한다.

완료 증거: 사용자 traffic은 old replica에 남았고, 원인과 rollback 시간이 timeline에 기록됐다.

미션 5 quota와 surge 충돌을 계산한다

replica 3, Pod당 CPU request 500m, maxSurge: 1이면 rollout peak CPU request는 2 vCPU다. namespace quota가 1.5 vCPU라면 네 번째 Pod가 admission에서 거부될 수 있다. 평시 합계만 보지 말고 rollout peak를 표로 계산한다.


peak request = (replicas + maxSurge) × Pod request
headroom = quota - peak request

완료 증거: production의 replica·surge·quota·node 여유를 같은 단위로 비교한 표.

미션 6 OIDC trust를 의도적으로 좁힌다

test role이 main branch 또는 production environment에서만 발급되도록 sub 조건을 제한한다. feature branch job이 role assume에 실패하고 main의 승인된 job은 성공하는지 본다. permission policy를 비워 둔 trust test role을 사용하면 AWS 변경 위험을 줄일 수 있다.

완료 증거: 허용 case와 거부 case의 claim 조건, STS result, CloudTrail event.

미션 7 build role로 deploy가 안 되는지 증명한다

build role로 ECR push는 허용하되 EKS 변경을 시도하면 거부되어야 한다. deploy role은 기존 digest를 적용할 수 있지만 ECR repository 삭제와 IAM 변경은 거부되어야 한다.

완료 증거: allow test만큼 deny test가 포함된 permission matrix.

미션 8 Service selector를 고장 내고 역추적한다

test 환경에서 Service selector를 존재하지 않는 label로 바꾼다. Pod는 Ready지만 EndpointSlice endpoint가 0개가 되고 ALB target이 unhealthy해지는 순서를 기록한다. 진단은 ALB에서 Pod로 무작정 뛰지 않고 Ingress→Service→EndpointSlice→label을 따른다.

완료 증거: 각 경계의 정상/비정상 명령 출력과 수정 diff.

미션 9 PDB가 보호하는 실패와 못 막는 실패를 비교한다

kubectl drain 같은 voluntary eviction에서 PDB가 동시 중단을 제한하는지 test cluster에서 확인한다. node hard failure는 PDB가 막지 못한다는 가정을 tabletop으로 분석한다. replica가 서로 다른 AZ에 배치되는지 topology spread 또는 anti-affinity 필요성도 검토한다.

완료 증거: maintenance scenario와 AZ failure scenario의 예상 available replica 수.

미션 10 HPA와 node scaling의 시간차를 측정한다

허가된 load test 환경에서 요청을 늘려 HPA desired replica가 변하는 시각, 새 Pod Pending 시각, node provisioning 시각, Pod Ready 시각을 기록한다. 이 합이 scale-out latency다. traffic spike가 그보다 빠르면 minimum replica·scheduled scaling·queue 같은 완충이 필요하다.

완료 증거: T0 traffic → T1 HPA → T2 node → T3 Ready timeline과 p95 latency.

미션 11 log retention을 비용과 incident 요구에 맞춘다

control plane과 application log의 일일 ingestion, retention, query 빈도를 구한다. audit log는 보안 보존 요구를 확인하고, debug verbosity를 상시 켜는 대신 incident 시 임시로 올리는 절차를 만든다.

완료 증거: log group별 owner·retention·예상 비용·삭제 금지 사유.

미션 12 RTO와 RPO를 숫자로 검증한다

RTO(Recovery Time Objective)는 허용 가능한 복구 시간, RPO(Recovery Point Objective)는 허용 가능한 data 손실 시점이다. “고가용성”이라는 말 대신 FlowNote의 목표를 숫자로 적는다.


Application rollback RTO: 10분
Cluster 재생성 RTO: 90분
Configuration RPO: Git에 merge된 마지막 commit
Database RPO: 15분

새 cluster에 manifest를 apply하는 것만으로 data RPO가 검증되지는 않는다. backup을 실제 restore하고 application이 읽을 수 있는지 확인한다.

완료 증거: stopwatch로 측정한 restore drill 결과와 목표 차이.

미션 13 minor version upgrade rehearsal을 한다

EKS upgrade insight와 deprecated API scanner 결과를 읽고 add-on·client·manifest compatibility 표를 만든다. test cluster에서 control plane과 workload를 upgrade하고 rollout·PDB·node replacement를 관찰한다.

완료 증거: go/no-go 기준, rollback 가능 조건, upgrade 뒤 smoke와 24시간 관찰 항목.

미션 14 비용 잔존물 game day를 연다

cluster를 삭제한 뒤 일부 resource가 남았다고 가정한다. ALB, target group, NAT Gateway, Elastic IP, EBS volume, snapshot, log group, ECR image를 tag와 생성 시각으로 찾는다. 자동 삭제된다고 믿지 말고 inventory가 비었거나 보존 이유와 owner가 있는지 확인한다.

완료 증거: 생성 resource 수와 삭제 후 resource 수를 비교한 reconciliation 표.

미션 15 새 팀원이 runbook만 보고 배포한다

저자가 옆에서 구두로 도와주지 않는다. 새 팀원은 account·region·cost warning을 확인하고 staging 배포, smoke, rollback, cleanup을 수행한다. 막힌 문장은 사람 탓으로 돌리지 않고 runbook 결함으로 기록한다.

완료 증거: 소요 시간, 잘못 이해한 용어, 위험했던 명령, 문서 수정 PR.

출간용 실습 채점표

영역 0점 1점 2점
재현 저자만 가능 도움을 받아 가능 새 계정·새 팀원이 문서만으로 가능
identity admin 한 개 role 분리는 했으나 deny 미검증 사람·build·deploy 분리와 deny 증거
artifact latest SHA tag digest·SBOM·source 양방향 추적
availability replica만 여러 개 probe 또는 PDB probe·surge·quota·PDB·AZ 시나리오
rollback 명령만 존재 test 성공 data compatibility와 RTO 측정
observability log 열람 dashboard release marker·SLO·incident query
cost 월말 확인 budget alert resource owner·ceiling·삭제 reconciliation
문서 command 모음 설명 포함 타인이 완주하고 수정 PR 제출

총 16점 중 13점 이상이면서 identity·rollback·cost가 각각 2점이어야 production 후보로 본다. 자동 test 통과는 출발점이며 실제 account의 cloud architect·security·FinOps review를 대체하지 않는다.

부록 A 45분 로컬 무비용 실습

AWS account 없이도 application과 image contract, manifest structure, readiness gate를 검증한다.


cd /Users/honi/WithAI/books/git-to-eks-cloud-infra
npm run qa
npm start
# http://127.0.0.1:4196/dist/lab/index.html

npm run qa는 unit test, FlowNote image build, non-root container smoke, 28장 원고 build, 실제 실습 화면 capture, 필수 주제·asset 검증을 실행한다. cloud resource는 만들지 않는다.

부록 B production 변경 요청서


서비스/환경:
변경 이유와 범위:
source commit SHA:
image URI와 digest:
manifest diff:
DB migration 호환성:
예상 replica·node·ALB·log 비용 변화:
배포 전 SLO와 baseline:
rollout 중단 조건:
smoke scenario:
rollback image와 명령:
관찰 담당자와 시간:
승인자:
release evidence URL:

부록 C 명령을 안전하게 읽는 법

  • create, apply, set, associate, update는 state를 바꾼다. 대상 account·region·namespace를 먼저 출력한다.
  • delete --force, wildcard IAM, public CIDR, secret 출력은 예제를 그대로 실행하지 않는다.
  • pipe 앞 명령이 실패해도 뒤 명령이 실행될 수 있다. script에는 set -Eeuo pipefail과 명시적 검사 단계를 둔다.
  • kubectl apply 전에 diff; deploy 뒤 rollout status; 삭제 뒤 inventory 조회를 한 세트로 둔다.
  • CI log에는 token, credential, kubeconfig, Secret data를 출력하지 않는다.

부록 D 공식 자료와 시점

자료는 2026년 8월 12일에 확인했다. 당시 EKS standard support version은 1.36~1.33이었지만 살아 있는 문서의 값은 바뀐다. 생성 당일 aws eks describe-cluster-versions와 각 제품 release note를 다시 확인한다.

부록 E 저작권·상표·보안

본문, FlowNote code, pipeline fixture, Kubernetes manifest, SVG와 실습 화면은 이 책을 위해 독자적으로 작성했다. AWS, Amazon EKS, Amazon ECR, GitHub, GitLab, Kubernetes, Docker, Node.js는 각 권리자의 명칭 또는 상표이며 제품 식별을 위해 사용했다. 제휴나 보증을 뜻하지 않는다.

공식 console 화면·logo·타 도서의 표·긴 문장을 포함하지 않았다. 예제 domain은 .invalid, account ID는 문서용 placeholder다. 실제 credential, customer data, internal host, production log를 이 원고나 외부 AI 서비스에 넣지 않는다. 공개 전 cloud architect·security·FinOps 담당자의 현재 환경 검수를 거친다.