장애 전환과 검증 범위
실습의 프라이머리 파드 삭제 후 역할 전환, 데이터 대조, 재접속 기록과 단일 노드, 비동기 복제의 검증 한계
#핵심 요약
실습에서는 현재 프라이머리를 확인하고 해당 파드를 삭제한 뒤 기존 레플리카의 프라이머리 전환과 삭제한 파드의 재생성을 관찰했음
약 1.6초는 승격 대상 선정까지, 약 17초는 삭제 후 healthy 확인까지 걸린 시간임
실제 쓰기 재개 시간은 기재 없음
구성은 단일 VM, 단일 노드, 로컬 PV, 비동기 복제로, 파드 장애 사례와 노드 전체 장애 대응, 모든 장애의 무손실 보장은 구분함
#개념과 동작 원리
| 장애 전환 단계 | 데이터 대조와 복구 관찰 기록 |
|---|---|
| 이행 후 기준 | 소스, 타깃 고객 수, 주문 수, 주문 금액 합계를 비교하고 레플리카의 복구 상태, 주문 건수 조회 |
| 장애 주입 | 현재 프라이머리 파드를 조회해 삭제, 노드, VM 전체 중단은 아님 |
| 역할 전환 | 관찰 시작 시 이미 기존 레플리카가 PRIMARY로 표시됨, Failing over 중간 상태는 미포착 |
| 준비된 인스턴스 수 회복 | 준비된 인스턴스 수 1에서 2로 회복하며 삭제한 파드는 같은 이름, 기존 PVC를 이용해 레플리카로 재합류 |
| 데이터 확인 | 새 프라이머리의 복구 상태 f, 기존 프라이머리에서 재생성된 레플리카의 복구 상태 t 확인 |
| 외부 재접속 | 기존 port-forward 오류 후 다시 실행하고 같은 읽기, 쓰기 Service를 경유해 업무 호출 |
웹 Deployment의 새 이름 파드 생성과 DB 오퍼레이터의 역할 전환, 기존 이름/PVC 복구를 같은 과정으로 합치지 않음
#실습 데이터 비교
| 확인 구간 | 실습 값 | 주의사항 |
|---|---|---|
| 이행 후 소스, 타깃 | 고객 100,000건, 주문 1,000,000건, 주문 금액 합계 250444357921.73으로 일치 | 세 집계값만 비교했으며 개별 행과 컬럼의 일치 여부는 확인 불가 |
| 레플리카 | 복구 상태 t, 주문 1,000,000건 |
조회 시점의 복제 결과이며 동기 복제, 무손실 보장이 아님 |
| 장애 후 새 프라이머리 | 복구 상태 f, 주문 1,000,000건, 합계 250444357921.73 |
수업 자료에 기록된 파드 삭제 사례의 집계값 유지 |
| 업무 호출 후 | 호출 성공, 등급별 33,333, 33,334, 33,333건 | 실습에서는 기준 금액 초과 고객 부재로 등급 변경이 없었다고 설명, 실제 데이터 변경 성공과 구분 |
수업 자료의 명령 일부는 대상 주소가 출력과 다르고 장애 후 조회문의 스키마도 명령, 출력이 서로 달라, 위 표는 출력에 기록된 집계, 역할 기준임
#단계별 소요 시간
| 실습의 관찰값 | 의미 |
|---|---|
| 삭제 후 약 1.6초 | 로그의 승격 대상 선정 시각 기준이며 승격 완료, 쓰기 재개 시각은 아님 |
| 삭제 후 약 17초 | Cluster in healthy state를 확인한 시각까지의 기록 |
| watch의 최초 PRIMARY | 삭제 명령 반환 후 관찰을 시작하여 이미 역할 전환 대상이 표시된 상태 |
| Timeline, 이벤트 반복, 파드 AGE | 실습 작성 중 추가 페일오버 이력이 포함된 결과이며 최초 1회 실행 결과로 합칠 수 없음 |
서비스 복구 시간을 재려면 승격 대상 선정, 승격 완료, healthy, 실제 업무 재개 시각을 각각 확인해야 함
#필수 명령어 또는 SQL
kubectl get cluster <CLUSTER_NAME>
date; kubectl delete pod <현재 PRIMARY 파드>
kubectl get cluster <CLUSTER_NAME> -w
kubectl get pods
kubectl exec -it <새 PRIMARY 파드> -- psql <TARGET_DB_NAME> -c "SELECT pg_is_in_recovery(), COUNT(*), SUM(amount) FROM <스키마>.orders;"
kubectl exec -it <재생성된 파드> -- psql <TARGET_DB_NAME> -c "SELECT pg_is_in_recovery();"kubectl port-forward --address 0.0.0.0 svc/<CLUSTER_NAME>-rw 5432:5432
PGPASSWORD="$K8S_PW" psql -h <K8S_VM_IP> -U <USERNAME> -d <TARGET_DB_NAME> -c "CALL mig.p_upgrade_grade(5000000);"
PGPASSWORD="$K8S_PW" psql -h <K8S_VM_IP> -U <USERNAME> -d <TARGET_DB_NAME> -c "SELECT grade_cd, COUNT(*) FROM mig.cust GROUP BY 1 ORDER BY 1;"결과 해석: 실습에서는 이전 레플리카로 PRIMARY가 바뀌고 준비된 인스턴스 수 1→2, healthy로 회복하는 출력을 기록했음
삭제된 파드는 재생성 후 레플리카로 확인됐으며 모든 단계가 watch에 포착된 것은 아님
kubectl logs -n cnpg-system deploy/cnpg-controller-manager | grep -i -E "failover|promot" | tail
kubectl describe cluster <CLUSTER_NAME> | tail -30결과 해석: 실습 로그에는 승격 요청, 대상 프라이머리 정보, 이벤트에는 FailingOver, FailoverTarget이 있음
로그와 이벤트는 일부가 생략됐고 반복 테스트도 포함되어 전체 처리 이력은 확인 불가
#사용 조건과 주의사항
실습에서는 Service를 대상으로 port-forward했어도 기존 파드 연결이 끊겨 첫 외부 접속이 실패하고 lost connection to pod 후 재실행한 사례임
같은 Service 이름을 유지한 사실과 기존 연결의 무중단 유지는 구분함
프로시저의 호출 성공과 실제 고객 등급 변경은 구분하며 수업 자료에는 등급 분포 유지 이유가 별도로 적혀 있음
파드 재생성의 데이터 유지와 Cluster, PVC 삭제는 다른 작업이며, 정리 절차(kubectl delete -f)는 장애 복구 절차가 아님