07. SQL Script와 Extension 사용

1. 기능 구분
| 기능 | 역할 |
|---|---|
| SQL Script | 초기 데이터·테이블·권한 SQL 실행 관리 |
| Extension 설정 | DB Pod에 확장 파일 준비 |
| CREATE EXTENSION | Database별 확장 활성화 |
Extension은 파일 준비와 Database 활성화를 구분합니다.
SGCluster에 Extension 추가
↓
DB Pod에 확장 파일 준비
↓
Database에서 CREATE EXTENSION 실행
06번 문서의 appdb·appuser·app Schema를 사용합니다.
2. 변수 설정
export K8S_CONTEXT="$(kubectl config current-context)"
export DB_NAMESPACE="postgres"
export DB_CLUSTER="demo-db-yaml"
export SQL_SCRIPT="${DB_CLUSTER}-app-init"
UI 클러스터는 DB_CLUSTER를 실제 이름으로 바꿉니다.
kubectl --context "$K8S_CONTEXT" get sgcluster "$DB_CLUSTER" \
--namespace "$DB_NAMESPACE"
3. SQL Script 등록
3.1. 실행 방식
SGScript는 순서가 있는 SQL 목록이며 SGCluster에서 참조합니다.
| 항목 | 실행 기준 |
|---|---|
| 사용자 | postgres |
| Database | 항목별 지정, 생략 시 postgres |
| 실행 방식 | Auto-commit |
| 변경 관리 | 버전이 있는 스크립트 |
전체 스크립트가 단일 트랜잭션은 아닙니다. 일부 SQL만 성공할 수 있으므로 재실행 영향을 고려합니다.
3.2. SGScript 작성
테이블·초기 데이터·권한을 설정합니다.
cat > 03-app-script.yaml <<EOF
apiVersion: stackgres.io/v1
kind: SGScript
metadata:
name: ${SQL_SCRIPT}
namespace: ${DB_NAMESPACE}
spec:
scripts:
- name: initialize-app-settings
database: appdb
script: |
CREATE TABLE IF NOT EXISTS app.settings (
key text PRIMARY KEY,
value text NOT NULL
);
INSERT INTO app.settings (key, value)
VALUES ('service_name', 'StackGres demo')
ON CONFLICT (key) DO NOTHING;
GRANT SELECT, INSERT, UPDATE, DELETE
ON TABLE app.settings TO appuser;
EOF
postgres로 실행되므로 appuser 권한을 별도로 부여합니다.
kubectl --context "$K8S_CONTEXT" apply \
-f 03-app-script.yaml
3.3. 클러스터에 연결
SGCluster YAML의 spec에 추가합니다.
spec:
managedSql:
scripts:
- sgScript: demo-db-yaml-app-init
기존 managedSql.scripts는 유지하고 실제 SGScript 이름을 추가합니다.
자동 생성된 <클러스터 이름>-default 스크립트와 참조는 임의로 삭제하지 않습니다.
kubectl --context "$K8S_CONTEXT" apply \
-f 02-cluster.yaml
SGScript 생성만으로 실행되지 않습니다. SGCluster 참조까지 확인합니다.
3.4. Web UI 사용
- SQL Script 관리 화면을 엽니다.
- Namespace·이름을 지정합니다.
- Database를
appdb로 지정합니다. - SQL을 등록합니다.
- 클러스터의 Managed SQL에 연결합니다.
화면 구성은 버전에 따라 다릅니다. 적용 후 YAML·실행 상태를 확인합니다.
4. SQL 실행 결과 확인
관리 SQL 상태를 조회합니다.
kubectl --context "$K8S_CONTEXT" get sgcluster "$DB_CLUSTER" \
--namespace "$DB_NAMESPACE" \
-o jsonpath='{.status.managedSql}{"\n"}'
전체 상태는 YAML로 확인합니다.
kubectl --context "$K8S_CONTEXT" get sgcluster "$DB_CLUSTER" \
--namespace "$DB_NAMESPACE" \
-o yaml
애플리케이션 계정으로 접속합니다.
kubectl --context "$K8S_CONTEXT" exec -it \
--namespace "$DB_NAMESPACE" \
"${DB_CLUSTER}-0" \
--container postgres-util \
-- psql \
-h "${DB_CLUSTER}.${DB_NAMESPACE}" \
-U appuser \
-d appdb \
-W
SELECT * FROM app.settings;
예상 결과입니다.
key | value
--------------+----------------
service_name | StackGres demo
\q
변경 시 버전·재실행 대상을 확인합니다. 실행 완료된 SQL을 단순 덮어쓰지 않습니다.
5. Extension 추가
5.1. 호환성 확인
계층 경로를 다루는 ltree를 사용합니다. 설치 전 다음을 확인합니다.
- PostgreSQL 버전에 맞는 패키지
- StackGres 버전의 지원 여부
- 추가 설정·사전 로딩 필요 여부
- 패키지 다운로드 가능 여부
확장별 요구사항을 확인하고 이름만으로 사용 가능하다고 가정하지 않습니다.
5.2. SGCluster 설정
기존 postgres 설정에 확장을 추가합니다.
spec:
postgres:
version: "<기존 PostgreSQL 버전>"
extensions:
- name: ltree
기존 PostgreSQL 버전·Extension 목록은 유지합니다.
kubectl --context "$K8S_CONTEXT" apply \
-f 02-cluster.yaml
Web UI에서는 클러스터 편집 화면의 Extension 항목에 추가합니다.
변경 후 Pod 상태를 확인합니다.
kubectl --context "$K8S_CONTEXT" get pods \
--namespace "$DB_NAMESPACE"
6. Database에서 Extension 활성화
6.1. 관리자 접속
postgres로 appdb에 접속합니다.
kubectl --context "$K8S_CONTEXT" exec -it \
--namespace "$DB_NAMESPACE" \
"${DB_CLUSTER}-0" \
--container postgres-util \
-- psql \
-h "${DB_CLUSTER}.${DB_NAMESPACE}" \
-U postgres \
-d appdb \
-W
확장 파일 준비 여부를 확인합니다.
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE name = 'ltree';
목록에 있으면 활성화합니다.
CREATE EXTENSION IF NOT EXISTS ltree WITH SCHEMA public;
설치 버전·Schema를 확인합니다.
SELECT e.extname, e.extversion, n.nspname
FROM pg_extension e
JOIN pg_namespace n ON n.oid = e.extnamespace
WHERE e.extname = 'ltree';
6.2. 동작 확인
SELECT 'company.platform.database'::public.ltree;
SELECT
'company.platform.database'::public.ltree
OPERATOR(public.<@)
'company.platform'::public.ltree
AS is_descendant;
is_descendant가 true인지 확인합니다.
public에 설치했으므로 타입·연산자에 Schema를 명시합니다.
\q
활성화는 Database별 작업입니다. 다른 Database에서도 별도로 실행합니다.
7. SGScript로 Extension 활성화
수동 검증 후 기존 SGScript에 추가할 수 있습니다.
spec:
scripts:
# 기존 SQL 항목 유지
- name: enable-ltree
database: appdb
script: |
CREATE EXTENSION IF NOT EXISTS ltree WITH SCHEMA public;
진행 순서입니다.
- SGCluster에 Extension 선언
- 확장 파일 준비 확인
- SGScript로 CREATE EXTENSION 실행
- Database에서 결과 확인
SGScript는 확장 파일을 다운로드·설치하지 않습니다.
8. 오류 확인
| 증상 | 확인 항목 |
|---|---|
| SQL 미실행 | SGCluster 참조·Namespace·실행 상태 |
| Database 없음 | 실행 Database·생성 여부 |
| SQL 일부만 반영 | Auto-commit·실패 지점 |
| appuser 권한 오류 | 테이블 소유자·GRANT |
| Extension 목록에 없음 | 지원 패키지·파일 준비 |
| CREATE EXTENSION 실패 | 권한·의존성·추가 설정 |
| Extension 변경 후 Pod 오류 | 패키지 다운로드·컨테이너 로그 |
Event를 확인합니다.
kubectl --context "$K8S_CONTEXT" get events \
--namespace "$DB_NAMESPACE" \
--sort-by=.metadata.creationTimestamp
- *재실행을 위해 테이블·기본 스크립트를 임의로 삭제하면 안됩니다