콘텐츠로 이동






09. 트러블슈팅과 정리

1. 기본 확인 순서

오류는 다음 순서로 확인합니다.

설정 → Event → Pod·PVC → 컨테이너 로그 → Service·접속

Web UI 오류와 DB 장애는 구분합니다. UI가 느려도 SQL 접속은 정상일 수 있습니다.

실제 환경에 맞춰 변수를 설정합니다.

export K8S_CONTEXT="$(kubectl config current-context)"
export SG_NAMESPACE="stackgres"
export SG_RELEASE="stackgres-operator"

export DB_NAMESPACE="postgres"
export DB_CLUSTER="demo-db-yaml"
export DB_SERVICE="$DB_CLUSTER"

2. 기본 진단 명령

2.1. 리소스와 Event

kubectl --context "$K8S_CONTEXT" get sgclusters \
  --namespace "$DB_NAMESPACE"

kubectl --context "$K8S_CONTEXT" get pods,pvc,svc \
  --namespace "$DB_NAMESPACE" \
  -o wide

kubectl --context "$K8S_CONTEXT" get events \
  --namespace "$DB_NAMESPACE" \
  --sort-by=.metadata.creationTimestamp

2.2. Pod와 컨테이너

kubectl --context "$K8S_CONTEXT" describe pod "${DB_CLUSTER}-0" \
  --namespace "$DB_NAMESPACE"

컨테이너 이름을 확인합니다.

kubectl --context "$K8S_CONTEXT" get pod "${DB_CLUSTER}-0" \
  --namespace "$DB_NAMESPACE" \
  -o jsonpath='{.spec.initContainers[*].name}{"\n"}{.spec.containers[*].name}{"\n"}'

문제 컨테이너의 로그를 조회합니다.

kubectl --context "$K8S_CONTEXT" logs "${DB_CLUSTER}-0" \
  --namespace "$DB_NAMESPACE" \
  --container <CONTAINER_NAME> \
  --tail=200

재시작 전 로그는 --previous로 확인합니다.

kubectl --context "$K8S_CONTEXT" logs "${DB_CLUSTER}-0" \
  --namespace "$DB_NAMESPACE" \
  --container <CONTAINER_NAME> \
  --previous \
  --tail=200

3. Operator 설치 오류

helm status "$SG_RELEASE" \
  --namespace "$SG_NAMESPACE" \
  --kube-context "$K8S_CONTEXT"

kubectl --context "$K8S_CONTEXT" get deployments,pods,jobs \
  --namespace "$SG_NAMESPACE"

kubectl --context "$K8S_CONTEXT" get events \
  --namespace "$SG_NAMESPACE" \
  --sort-by=.metadata.creationTimestamp
증상 확인 항목
Forbidden 설치 계정 RBAC
기존 리소스 충돌 Release·리소스 소유 관계
Job 실패 설치 Job Pod 로그
Deployment 미준비 배치·이미지·Readiness
Webhook 오류 Operator·Service·인증서·통신

원인 확인 전 CRD 삭제·설치 반복을 하지 않습니다.

4. Web UI 접속 오류

4.1. 접속 경로

루트 주소에서 오류가 나면 /admin/을 확인합니다.

https://<관리 주소>/admin/

4.2. HTTP·HTTPS 불일치

다음 오류는 요청 프로토콜·대상 포트를 확인합니다.

The plain HTTP request was sent to HTTPS port
구성 확인 항목
HTTP 백엔드 HTTP 활성화·Ingress 대상 포트
HTTPS 백엔드 Controller의 HTTPS 백엔드 설정
외부 TLS 종료 백엔드 구간 프로토콜
kubectl --context "$K8S_CONTEXT" get svc stackgres-restapi \
  --namespace "$SG_NAMESPACE" \
  -o yaml

kubectl --context "$K8S_CONTEXT" get ingress \
  --namespace "$SG_NAMESPACE" \
  -o yaml

4.3. 반복 타임아웃

브라우저 개발자 도구의 Network에서 실패한 API 요청을 확인합니다.

  • Request URL
  • Status Code
  • Duration
  • Response

같은 시각의 REST API 로그와 비교합니다.

kubectl --context "$K8S_CONTEXT" logs \
  --namespace "$SG_NAMESPACE" \
  deployment/stackgres-restapi \
  --all-containers=true \
  --tail=200

프록시·REST API·브라우저 중 실패 구간을 확인하고 타임아웃을 조정합니다.

5. PVC·Pod Pending

5.1. PVC 확인

kubectl --context "$K8S_CONTEXT" get pvc \
  --namespace "$DB_NAMESPACE"

kubectl --context "$K8S_CONTEXT" describe pvc <PVC_NAME> \
  --namespace "$DB_NAMESPACE"

kubectl --context "$K8S_CONTEXT" get storageclass
kubectl --context "$K8S_CONTEXT" get pv
상태 확인 항목
PVC Pending StorageClass·Provisioner·용량·배치
PVC Bound, Pod Pending 노드 배치·볼륨 연결·마운트
WaitForFirstConsumer Pod 배치·볼륨 생성 조건
로컬 볼륨 볼륨의 노드 제약

5.2. VolumeBinding 충돌

다음 메시지는 PVC의 동시 변경 충돌일 수 있습니다.

the object has been modified;
please apply your changes to the latest version and try again

단일 메시지로 최종 실패를 판단하지 않습니다. 재시도 후 PVC·Pod 상태가 진행되는지 확인합니다.

PVC 삭제·resourceVersion 수정으로 해결하려 하지 않습니다.

6. 이미지·초기화 오류

6.1. ImagePullBackOff

Pod Event에서 다운로드 오류를 확인합니다.

오류 유형 확인 항목
이미지 없음 저장소 경로·태그
인증 실패 imagePullSecrets
인증서 오류 노드 런타임의 인증서 신뢰
연결 실패 노드 DNS·방화벽·프록시

관리 PC의 다운로드 성공이 노드의 성공을 보장하지는 않습니다.

6.2. Init Container 지연

상태·로그를 확인합니다.

kubectl --context "$K8S_CONTEXT" describe pod "${DB_CLUSTER}-0" \
  --namespace "$DB_NAMESPACE"

kubectl --context "$K8S_CONTEXT" logs "${DB_CLUSTER}-0" \
  --namespace "$DB_NAMESPACE" \
  --container <INIT_CONTAINER_NAME> \
  --tail=200

스토리지·파일 초기화·확장 패키지 중 지연 단계를 구분합니다.

7. 클러스터 생성 지연

총시간보다 단계별 지연을 확인합니다.

단계 확인 대상
리소스 생성 SGCluster·Operator 로그
볼륨 준비 PVC·스토리지 Event
Pod 배치 스케줄링 Event
이미지 다운로드 Pulling·Pulled Event
초기화 Init Container
DB 준비 Patroni·PostgreSQL·Readiness
UI 표시 REST API·브라우저 요청

UI 표시와 SQL 실행 가능 시점은 따로 기록합니다.

이미지 캐시·인스턴스 수·스토리지 조건이 다른 결과를 단순 비교하지 않습니다.

8. DB 접속 오류

8.1. Service 연결 대상

kubectl --context "$K8S_CONTEXT" get svc "$DB_SERVICE" \
  --namespace "$DB_NAMESPACE" \
  -o yaml

kubectl --context "$K8S_CONTEXT" get endpointslices \
  --namespace "$DB_NAMESPACE" \
  --selector "kubernetes.io/service-name=${DB_SERVICE}"
증상 확인 항목
DNS 실패 Service 이름·Namespace·도메인
Timeout 방화벽·NetworkPolicy·접속 주소
Connection refused 포트·Service 연결 대상
인증 실패 Role·비밀번호·인증 설정
권한 오류 Database·Schema·테이블 권한
쓰기 실패 Primary 접속 여부
TLS 오류 DB TLS·클라이언트 설정

내부는 Service 포트, 외부 NodePort는 할당 포트를 사용합니다.

8.2. 역할 확인

kubectl --context "$K8S_CONTEXT" exec \
  --namespace "$DB_NAMESPACE" \
  "${DB_CLUSTER}-0" \
  --container patroni \
  -- patronictl list

SQL로도 확인합니다.

SELECT pg_is_in_recovery();

Replica에 연결됐다면 쓰기 대상 Service·현재 Primary를 확인합니다.

9. SQL Script·Extension 오류

증상 확인 항목
SQL 미실행 managedSql 참조·Namespace·실행 상태
SQL 일부만 반영 실패 지점·Auto-commit
앱 계정 권한 오류 객체 소유자·GRANT
Extension 없음 지원 패키지·파일 준비
활성화 실패 Database·권한·의존성
확장 기능 조회 실패 설치 Schema·search_path

SQL 상태를 조회합니다.

kubectl --context "$K8S_CONTEXT" get sgcluster "$DB_CLUSTER" \
  --namespace "$DB_NAMESPACE" \
  -o jsonpath='{.status.managedSql}{"\n"}'

대상 Database에서 확장을 확인합니다.

SELECT name, default_version, installed_version
FROM pg_available_extensions;

SELECT extname, extversion
FROM pg_extension;

파일 준비와 CREATE EXTENSION 실행은 구분합니다.

10. 진단 결과 보관

작업 디렉터리를 생성합니다.

mkdir -p diagnostics

설정·리소스 상태·Event를 저장합니다.

kubectl --context "$K8S_CONTEXT" get sgcluster "$DB_CLUSTER" \
  --namespace "$DB_NAMESPACE" \
  -o yaml \
  > diagnostics/sgcluster.yaml

kubectl --context "$K8S_CONTEXT" get pods,pvc,svc \
  --namespace "$DB_NAMESPACE" \
  -o wide \
  > diagnostics/resources.txt

kubectl --context "$K8S_CONTEXT" get events \
  --namespace "$DB_NAMESPACE" \
  --sort-by=.metadata.creationTimestamp \
  > diagnostics/events.txt

공개 전 내부 주소·SQL·인증 정보를 제거합니다. Secret 전체는 수집하지 않습니다.

11. 테스트 리소스 정리

11.1. 삭제 전 확인

  • Context·클러스터 이름
  • 데이터 보존 필요성
  • SGCluster·PVC·PV 관계와 reclaimPolicy
  • 공유 설정·다른 클러스터의 참조

SGCluster 삭제는 PVC·데이터 삭제로 이어질 수 있습니다. 설정 파일은 백업이 아닙니다.

11.2. 클러스터 삭제

데이터가 필요 없는 테스트 클러스터만 삭제합니다.

kubectl --context "$K8S_CONTEXT" delete sgcluster "$DB_CLUSTER" \
  --namespace "$DB_NAMESPACE"

남은 리소스를 확인합니다.

kubectl --context "$K8S_CONTEXT" get pods,pvc,svc \
  --namespace "$DB_NAMESPACE"

kubectl --context "$K8S_CONTEXT" get pv

남은 PVC는 대상·보존 필요성을 확인한 뒤 삭제 여부를 판단합니다.

11.3. 관련 설정 삭제

다른 클러스터가 참조하지 않는 리소스만 삭제합니다.

kubectl --context "$K8S_CONTEXT" delete sgscript \
  "${DB_CLUSTER}-app-init" \
  --namespace "$DB_NAMESPACE"

kubectl --context "$K8S_CONTEXT" delete sginstanceprofile \
  demo-profile \
  --namespace "$DB_NAMESPACE"

실제 이름을 사용합니다. UI가 생성한 추가 리소스도 참조를 확인합니다.

11.4. Operator 제거

모든 StackGres DB의 사용 종료·정리를 확인한 뒤 진행합니다.

kubectl --context "$K8S_CONTEXT" get sgclusters \
  --all-namespaces
helm uninstall "$SG_RELEASE" \
  --namespace "$SG_NAMESPACE" \
  --kube-context "$K8S_CONTEXT"

Operator 제거는 DB·데이터 정리를 대신하지 않습니다. 잔여 CRD·RBAC·Secret은 따로 확인하고 일괄 삭제하지 않습니다.