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·권한을 확인합니다.