콘텐츠로 이동






06. PostgreSQL 접속과 초기 구성

1. 접속 구성

DB Service로 접속하고 애플리케이션용 Database·Role을 생성합니다.

항목 설정 값
Namespace postgres
클러스터 이름 demo-db-yaml
초기 관리 사용자 postgres
애플리케이션 Database appdb
애플리케이션 Role appuser
내부 접속 Service 이름·5432
외부 접속 NodePort 또는 임시 port-forward

Web UI와 DB 접속 주소는 다릅니다.

Web UI: 브라우저 → 관리 Service → /admin/
DB:     psql / DBeaver / 애플리케이션 → DB Service

2. 변수와 Service 확인

export K8S_CONTEXT="$(kubectl config current-context)"
export DB_NAMESPACE="postgres"
export DB_CLUSTER="demo-db-yaml"

UI 클러스터를 사용하면 이름을 변경합니다.

export DB_CLUSTER="demo-db"

Service·Pod를 확인합니다.

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

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

기본 Primary Service는 클러스터 이름과 같습니다. 실제 이름·포트를 확인하고 지정합니다.

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

쓰기 작업은 Primary Service를 사용합니다.

3. 관리자 비밀번호 확인

기본 인증 정보는 클러스터와 같은 이름의 Secret에 저장됩니다.

kubectl --context "$K8S_CONTEXT" get secret "$DB_CLUSTER" \
  --namespace "$DB_NAMESPACE" \
  -o jsonpath='{.data.superuser-password}' | base64 --decode

printf '\n'

초기 접속은 postgres와 조회한 비밀번호를 사용합니다.

사용자 정의 인증은 SGCluster의 credentials 설정·참조 Secret을 확인합니다. 비밀번호와 Secret 전체 YAML은 공개하지 않습니다.

4. Kubernetes 내부 접속

4.1. Service 주소

실행 위치 접속 주소
같은 Namespace demo-db-yaml:5432
다른 Namespace demo-db-yaml.postgres:5432
전체 DNS 이름 demo-db-yaml.postgres.svc.<클러스터 도메인>:5432

클러스터 도메인은 실제 값을 사용합니다. k8s-k8s-test인 경우 다음과 같습니다.

demo-db-yaml.postgres.svc.k8s-k8s-test:5432

4.2. Service 경유 접속

DB Pod의 관리 컨테이너에서 Service로 접속합니다.

kubectl --context "$K8S_CONTEXT" exec -it \
  --namespace "$DB_NAMESPACE" \
  "${DB_CLUSTER}-0" \
  --container postgres-util \
  -- psql \
     -h "${DB_SERVICE}.${DB_NAMESPACE}" \
     -p 5432 \
     -U postgres \
     -d postgres \
     -W

조회한 비밀번호를 입력하고 실행합니다.

SELECT current_database(), current_user;
SELECT pg_is_in_recovery();
SELECT 1;

Primary에서는 pg_is_in_recovery()가 false인지 확인합니다.

\q

이 단계는 Service 경유 검증입니다. 실제 애플리케이션 Pod에서도 통신 정책·DNS를 확인합니다.

5. 외부 접속

5.1. 임시 port-forward

관리 PC에서 실행합니다.

kubectl --context "$K8S_CONTEXT" port-forward \
  --namespace "$DB_NAMESPACE" \
  service/"$DB_SERVICE" \
  15432:5432 \
  --address 127.0.0.1

같은 PC의 다른 터미널에서 접속합니다.

psql \
  -h 127.0.0.1 \
  -p 15432 \
  -U postgres \
  -d postgres \
  -W

port-forward는 임시 검증용이며 운영용 고정 경로로 사용하지 않습니다.

5.2. NodePort 설정

관리 중인 SGCluster YAML에 추가합니다.

spec:
  postgresServices:
    primary:
      type: NodePort

기존 버전·프로파일·스토리지 설정은 유지합니다.

kubectl --context "$K8S_CONTEXT" apply \
  -f 02-cluster.yaml

UI 클러스터는 임시 patch로 변경할 수 있습니다.

kubectl --context "$K8S_CONTEXT" patch sgcluster "$DB_CLUSTER" \
  --namespace "$DB_NAMESPACE" \
  --type merge \
  -p '{"spec":{"postgresServices":{"primary":{"type":"NodePort"}}}}'

YAML 관리 클러스터는 변경 사항을 파일에도 반영합니다.

5.3. 할당 포트 확인

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

출력 예시입니다.

NAME           TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)
demo-db-yaml   NodePort   10.96.20.30   <none>        5432:32700/TCP

예제의 NodePort는 32700입니다.

외부 접속: <접근 가능한 노드 IP>:32700
내부 접속: demo-db-yaml.postgres:5432

실제 할당 포트와 접근 가능한 노드 IP로 접속합니다.

psql \
  -h <NODE_IP> \
  -p <NODE_PORT> \
  -U postgres \
  -d postgres \
  -W

NodePort는 DB TLS를 활성화하지 않습니다. 접근 제한·TLS는 별도로 구성합니다.

6. Database와 Role 생성

6.1. 관리자 접속

4절 또는 5절의 방법으로 postgres에 접속하고 Role을 생성합니다.

CREATE ROLE appuser LOGIN;

psql 명령으로 비밀번호를 설정합니다.

\password appuser

비밀번호를 두 번 입력합니다. 실제 비밀번호는 SQL·셸 명령에 기록하지 않습니다.

Database를 생성합니다.

CREATE DATABASE appdb OWNER appuser;

6.2. 애플리케이션 Schema

Database를 전환합니다.

\connect appdb

전용 Schema와 기본 검색 경로를 설정합니다.

CREATE SCHEMA app AUTHORIZATION appuser;

ALTER ROLE appuser IN DATABASE appdb
SET search_path TO app;

appuser가 Database·Schema를 소유하는 구성입니다. 운영에서는 필요에 따라 소유자·배포·실행 Role을 분리합니다.

\q

7. 애플리케이션 계정 검증

내부 Service로 appuser 접속을 확인합니다.

kubectl --context "$K8S_CONTEXT" exec -it \
  --namespace "$DB_NAMESPACE" \
  "${DB_CLUSTER}-0" \
  --container postgres-util \
  -- psql \
     -h "${DB_SERVICE}.${DB_NAMESPACE}" \
     -p 5432 \
     -U appuser \
     -d appdb \
     -W

설정한 비밀번호를 입력하고 계정·검색 경로·읽기·쓰기를 확인합니다.

SELECT current_database(), current_user;
SHOW search_path;

CREATE TABLE app.connection_check (
    id integer PRIMARY KEY,
    message text
);

INSERT INTO app.connection_check
VALUES (1, 'Application connection OK');

SELECT * FROM app.connection_check;

테스트 테이블을 삭제하고 종료합니다.

DROP TABLE app.connection_check;
\q

애플리케이션은 postgres 대신 appuser로 접속합니다.

8. DBeaver와 애플리케이션 설정

8.1. DBeaver

새 PostgreSQL 연결에 입력합니다.

항목 port-forward NodePort
Host 127.0.0.1 접근 가능한 노드 IP
Port 15432 실제 할당 포트
Database appdb appdb
Username appuser appuser
Password 설정한 비밀번호 설정한 비밀번호

SSL은 실제 DB TLS 구성에 맞춥니다. 인증서 오류를 피하려고 검증을 무조건 끄지 않습니다.

8.2. 애플리케이션 연결

Kubernetes 내부 JDBC 예시입니다.

jdbc:postgresql://demo-db-yaml.postgres:5432/appdb
항목 값
사용자 appuser
비밀번호 애플리케이션 Secret에서 전달
Schema app
접속 대상 Primary Service

PgBouncer 설정과 애플리케이션의 세션 기능·커넥션 풀 설정도 확인합니다.

9. 접속 오류 확인

증상 확인 항목
이름 해석 실패 Service 이름·Namespace·DNS 도메인
연결 시간 초과 노드 IP·방화벽·NetworkPolicy
연결 거부 포트·Service 연결 대상·Pod 상태
인증 실패 Role·비밀번호·인증 설정
Database 없음 이름·생성 여부
권한 오류 Database·Schema·객체 권한
TLS 오류 DB SSL·인증서·클라이언트 설정

Service 연결 대상·Event를 확인합니다.

kubectl --context "$K8S_CONTEXT" get endpointslices \
  --namespace "$DB_NAMESPACE" \
  --selector "kubernetes.io/service-name=${DB_SERVICE}"

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

관리자만 접속되면 애플리케이션 Role·권한을 확인합니다.