복구 기준과 이전 digest
90분 안팎
학습 목표
오류·시간 초과 기준으로 이전 이미지를 복구합니다.
개념
복구는 배포 전에 준비합니다
배포 직후 사용자가 실패를 보고하면 무엇을 어느 버전으로 되돌릴지 바로 설명할 수 있어야 합니다. 이전 이미지를 찾거나 데이터를 지워 실행만 살리는 방식은 복구 시간을 늘립니다. 이번 레슨은 후보로 전환하기 전에 이전 image ID와 설정·데이터 상태를 보관하고 관측 기준을 숫자로 정합니다. 반복 fixture로 정상과 장애를 재현하여 결정이 일관적인지 봅니다. 담당자의 당황한 느낌 대신 관측과 정한 조건으로 판단하고 복구 후 사용자 작업까지 확인하는 것이 목표입니다.
준비 실패와 전환 후 실패는 다릅니다
준비 실패는 사용자 경로를 바꾸지 않았으므로 KEEP입니다. 후보로 전환한 뒤 기준을 넘으면 ROLLBACK입니다. 사용자에게 이미 노출된 후보의 문제를 준비 검사만 다시 실행해서 해결했다고 말할 수 없습니다. 파일 모델에서는 두 결과 모두 최종 active를 이전 값으로 유지하지만 의미는 다릅니다. 미션에서는 실제 이전 Nginx 설정으로 돌아가 요청을 확인합니다. 상태 이름을 나누면 사용자 노출이 언제 시작되었고 어느 검사에서 복구가 필요했는지 기록할 수 있습니다.
관측 창과 분모를 정의합니다
교육용 기준은 준비 성공 후 최소 5개 요청입니다. HTTP 200 이외 또는 elapsed_ms가 1000 이상이면 실패 요청으로 셉니다. 한 요청이 두 조건을 만족해도 하나입니다. 실패율은 실패 요청 수를 전체 요청 수로 나눈 값이며 20% 이상이면 복구합니다. 5개 중 하나는 정확히 20%여서 경계에 포함되고 10개 중 하나는 10%여서 통과합니다. 작은 창과 수치는 이 실습의 정책이며 어느 회사 서비스에도 같은 값이 적절하다고 권하지 않습니다. 분자와 분모를 적어야 기준을 재검토할 수 있습니다.
시간 초과도 실패 표본입니다
서버가 200을 반환해도 정한 시간 안에 사용할 수 없으면 사용자에게 실패입니다. 경계는 1000ms 이상이며 999ms는 이 시간 조건의 실패가 아닙니다. 미션의 지연 fixture는 client timeout 100ms로 실제 시간 초과를 발생시키고 status 504와 elapsed_ms 1000의 실패 표본으로 정규화합니다. 이 값은 실제 소요 시간을 측정한 값이 아닙니다. 연결 실패도 실패 분기에 넣습니다. 응답 없는 요청을 집계에서 빼면 장애가 심할수록 오류율이 낮아지는 잘못된 결과가 됩니다.
정보가 없으면 성공으로 결론내리지 않습니다
samples가 비었거나 5개 미만이면 관측 부족으로 복구합니다. status가 문자열이거나 범위를 벗어나고 시간이 음수인 경우도 복구합니다. 입력 생산자가 손상 자료를 보냈다는 사실과 서비스가 건강하다는 사실은 다릅니다. 실패 표본을 버리고 남은 정상 표본만 세면 결과가 낙관적으로 바뀝니다. 이번 모델은 손상된 창을 통째로 거부합니다. 실제 운영에서는 관측 경로 장애를 알리고 사람이 판단할 수 있지만 자동 성공 승격을 막는 원칙은 유지합니다.
정수 곱으로 경계를 비교합니다
policy.py는 failures 곱하기 100을 samples 길이 곱하기 20과 비교합니다. 소수 반올림으로 경계가 달라지는 문제를 줄이고 분모를 코드에 드러냅니다. 5개 중 하나, 10개 중 하나, 시간 999와 1000을 각각 검사합니다. starter는 준비와 표본 수만 확인한 뒤 ACCEPT여서 정상 사례는 통과하지만 오류와 시간 초과를 놓칩니다. 실패 집계와 경계 비교를 완성합니다. 성공 로그만 출력하거나 경계 fixture를 줄이지 않고 무엇을 실패로 셌는지를 작은 사례로 설명합니다.
이전 대상은 실제 식별자로 남깁니다
모델의 sha256 문자열은 결정 연습용 fixture이며 실제 이미지 존재 증거가 아닙니다. 미션은 이전 CI archive를 검증하고 컨테이너 inspect의 Image가 그 local image ID와 같은지 확인합니다. latest 같은 이름은 다른 이미지로 이동할 수 있어 복구 대상을 고정하지 못합니다. 코드뿐 아니라 비밀 경로·환경 이름·데이터 마운트도 호환하는 조합으로 보관합니다. 비밀 값은 기록하지 않고 주입 경로와 접근 결과만 남깁니다. 이전 컨테이너를 사용해 복구하면 archive 재기동 시간도 피할 수 있습니다.
상태 파일의 교체 범위를 이해합니다
rollback.sh는 JSON fixture로 결정을 내리고 state.json 옆에 임시 파일을 쓴 뒤 os.replace로 교체합니다. active는 ACCEPT에서만 후보가 되고 KEEP과 ROLLBACK에서는 기존 값입니다. previous에는 변경 직전 active를 남기며 데이터 메타데이터를 보존합니다. 같은 파일시스템의 이름 교체 실습이며 전원 장애의 영속성이나 여러 배포자의 동시 갱신까지 해결한 저장소가 아닙니다. 원자적 파일 교체를 전체 배포의 원자성으로 확대하지 않습니다. JSON을 반쯤 쓴 상태가 보이지 않는다는 범위만 설명합니다.
실제 복구에는 대상과 응답이 필요합니다
미션은 이전 설정으로 교체하고 nginx -t와 reload 뒤 backend 헤더를 관측합니다. 이어서 인증한 /notices의 id·title이 변경 전과 같은지 비교합니다. 라우팅이 돌아와도 이전 컨테이너 데이터가 손상되었다면 사용자 복구가 아닙니다. 기존 image ID가 유지되는지도 inspect로 확인합니다. 예외 처리의 finally는 이전 설정 복구를 시도하지만 daemon 자체가 멈췄다면 그것도 실패할 수 있습니다. 자동 복구의 한계와 남은 조치를 관측 증거에 맞춰 설명합니다.
장애 주입 지점을 명시합니다
오류 fixture는 같은 후보 이미지에서 프록시 /notices를 /fixture/error에 연결하고 지연 fixture는 /fixture/slow에 연결합니다. 별도의 나쁜 이미지를 만들었다고 주장하지 않고 사용자 경로 장애 주입으로 기록합니다. 이 방법은 복구 판단과 프록시 복원을 짧은 실험으로 검증합니다. 원본 데이터는 쓰지 않고 후보는 별도 볼륨을 사용합니다. 사고 설명에는 주입과 관측 위치를 적습니다. 코드 결함 재현과 경로 장애 재현을 구분하면 어떤 문제까지 검증했는지 리뷰하기 쉬워집니다.
종료 상태와 정책 결과를 구별합니다
check.sh의 비영 종료에는 case 이름과 decision mismatch 또는 image mismatch를 확인합니다. ROLLBACK은 정책이 복구를 선택했다는 뜻이고 검사 프로그램 자체가 실패했다는 뜻이 아닙니다. 정상 복구 사례도 check.sh는 0으로 끝납니다. 예상 ROLLBACK에 ACCEPT라면 assertion 실패입니다. set -e는 명령 실패를 전파할 뿐 응답 의미나 실패율을 계산하지 않습니다. 제출에는 표본 수·실패 분류·이전 ID·복구 응답·데이터 보존을 적습니다. 링크 교체의 세부 주의점은 더 읽기로 보내고 여기서는 복구가 실제 사용자 작업으로 이어졌는지를 확인합니다.
따라하기
오류율 경계 계산
5개 요청 중 1개 실패의 기준을 정수 비교로 확인합니다. 정확히 20%도 복구 조건에 포함됩니다.
samples=[200,200,200,200,500]
failures=sum(status!=200 for status in samples)
print('requests:',len(samples))
print('failures:',failures)
print('ROLLBACK' if failures*100>=len(samples)*20 else 'ACCEPT')실행 결과
requests: 5 failures: 1 ROLLBACK
시간 경계와 관측 부족 분리
정상 상태 코드여도 1000ms는 실패입니다. 빈 관측은 건강함이 아니라 확인하지 못한 상태입니다.
for elapsed in [999,1000]:
print(elapsed, 'failure' if elapsed>=1000 else 'success')
print('empty:', 'ROLLBACK' if len([])<5 else 'ACCEPT')실행 결과
999 success 1000 failure empty: ROLLBACK
starter의 판단과 상태 기록 검사
starter.zip 루트에서 검사합니다. policy.py의 항상 ACCEPT를 실패 집계와 20% 경계 비교로 바꿉니다. rollback.sh가 JSON fixture로 active·previous를 기록하는지 check.py를 읽고 확인합니다. 모델 식별값은 실제 이미지 ID 증거가 아닙니다.
bash check.sh
cat policy.py
cat check.pysolution 전체 사례 재현
solution.zip 루트에서 같은 검사를 실행합니다. 다음은 작성 환경에서 직접 실행한 출력입니다. 정상·준비 실패·오류율·시간 경계·손상 관측·인증 실패에서 선택한 active와 원본 데이터 보존까지 검사합니다.
bash check.sh실행 결과
PASS healthy PASS not-ready PASS error-boundary PASS below-error-boundary PASS timeout-boundary PASS below-timeout PASS empty PASS small-window PASS bad-status PASS negative-time PASS auth-failure PASS 11 rollback cases; active ID, previous ID, data preserved
확인 문제
실습
policy.py의 decide를 완성합니다. 준비 실패는 KEEP입니다. 준비 성공 후 표본 5개 이상에서 HTTP 200 이외 또는 1000ms 이상 요청을 실패로 세고 실패율 20% 이상은 ROLLBACK, 이외는 ACCEPT입니다. 빈 표본·작은 창·잘못된 자료는 ROLLBACK입니다. 한 요청은 한번만 실패로 셉니다. bash check.sh는 셸 실행과 실제 임시 JSON 상태 교체를 검사합니다. 실제 프록시 복구는 미션의 동일 정책으로 확인합니다.
실행 명령
bash check.sh
기대 결과
11개 사례에서 정책 결과·active 및 previous ID·원본 데이터 보존 검사가 모두 통과합니다.
모범 답안
모범 답안 내려받기더 읽기
면접 질문
- 실패한 배포의 롤백 기준과 검증을 설명합니다.