phonebill/develop/database/plan/db-plan-bill-inquiry-dev.md
2025-09-09 01:12:14 +09:00

17 KiB

Bill-Inquiry 서비스 개발환경 데이터베이스 설치 계획서

1. 개요

1.1 설치 목적

  • Bill-Inquiry 서비스 전용 PostgreSQL 14 데이터베이스 개발환경 구축
  • 요금조회 기능을 위한 독립적인 데이터베이스 환경 제공
  • Kubernetes StatefulSet을 통한 안정적인 데이터 지속성 보장

1.2 설치 환경

  • 플랫폼: Azure Kubernetes Service (AKS)
  • 환경: 개발환경 (Development)
  • 네임스페이스: phonebill-dev
  • 클러스터: phonebill-dev-aks (2 노드, Standard_B2s)

1.3 참조 문서

  • 물리아키텍처 설계서: design/backend/physical/physical-architecture-dev.md
  • 데이터 설계 종합: design/backend/database/data-design-summary.md
  • Bill-Inquiry 데이터 설계서: design/backend/database/bill-inquiry.md
  • 스키마 파일: design/backend/database/bill-inquiry-schema.psql

2. 데이터베이스 구성 정보

2.1 기본 정보

항목 설명
데이터베이스명 bill_inquiry_db Bill-Inquiry 서비스 전용 DB
DBMS PostgreSQL 14 안정화된 PostgreSQL 14 버전
컨테이너 이미지 bitnami/postgresql:14 Bitnami 공식 이미지
문자셋 UTF8 한글 지원을 위한 UTF8
타임존 Asia/Seoul 한국 표준시
초기 사용자 postgres 관리자 계정
초기 비밀번호 Hi5Jessica! 개발환경용 고정 비밀번호

2.2 스키마 구성

스키마 용도 테이블 수
public 비즈니스 테이블 5개
cache 캐시 데이터 (Redis 보조용) 포함됨
audit 감사 및 이력 포함됨

2.3 주요 테이블

테이블명 용도 예상 데이터량
customer_info 고객정보 임시 캐시 소규모
bill_inquiry_history 요금조회 요청 이력 중간규모
kos_inquiry_history KOS 연동 이력 중간규모
bill_info_cache 요금정보 캐시 소규모
system_config 시스템 설정 소규모

3. 리소스 할당 계획

3.1 컴퓨팅 리소스

리소스 유형 요청량 제한량 설명
CPU 500m 1000m 개발환경 최적화
Memory 1Gi 2Gi 기본 워크로드 대응
Storage 20Gi - 개발 데이터 충분 용량

3.2 스토리지 구성

설정 항목 설명
스토리지 클래스 managed-standard Azure Disk Standard HDD
볼륨 타입 PersistentVolumeClaim 데이터 지속성 보장
마운트 경로 /bitnami/postgresql 표준 데이터 디렉토리
백업 방식 Azure Disk Snapshot 일일 자동 백업

3.3 네트워크 구성

설정 항목 설명
Service 타입 ClusterIP 클러스터 내부 접근
내부 포트 5432 PostgreSQL 표준 포트
Service 이름 postgresql-bill-inquiry 서비스 디스커버리용
DNS 주소 postgresql-bill-inquiry.phonebill-dev.svc.cluster.local 내부 접근 주소

4. PostgreSQL 설정

4.1 성능 최적화 설정

설정 항목 설명
max_connections 100 개발환경 충분한 연결 수
shared_buffers 256MB 메모리의 25% 할당
effective_cache_size 1GB 총 메모리의 75%
work_mem 4MB 작업 메모리
maintenance_work_mem 64MB 유지보수 작업 메모리

4.2 로그 설정

설정 항목 설명
log_destination stderr 표준 에러로 로그 출력
log_min_duration_statement 1000ms 1초 이상 쿼리 로그
log_statement none 개발환경용 최소 로깅
log_connections on 연결 로그 활성화

4.3 보안 설정

설정 항목 설명
비밀번호 암호화 BCrypt 안전한 비밀번호 저장
SSL 모드 require TLS 암호화 통신
접근 제어 md5 비밀번호 기반 인증
외부 접근 제한 클러스터 내부만 허용

5. Kubernetes 매니페스트

5.1 ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgresql-bill-inquiry-config
  namespace: phonebill-dev
data:
  POSTGRES_DB: "bill_inquiry_db"
  POSTGRES_USER: "postgres"
  POSTGRESQL_MAX_CONNECTIONS: "100"
  POSTGRESQL_SHARED_BUFFERS: "256MB"
  POSTGRESQL_EFFECTIVE_CACHE_SIZE: "1GB"
  POSTGRESQL_WORK_MEM: "4MB"
  POSTGRESQL_MAINTENANCE_WORK_MEM: "64MB"
  POSTGRESQL_LOG_MIN_DURATION_STATEMENT: "1000"

5.2 Secret

apiVersion: v1
kind: Secret
metadata:
  name: postgresql-bill-inquiry-secret
  namespace: phonebill-dev
type: Opaque
data:
  postgres-password: SGk1SmVzc2ljYSE= # Hi5Jessica!

5.3 PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgresql-bill-inquiry-pvc
  namespace: phonebill-dev
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: managed-standard
  resources:
    requests:
      storage: 20Gi

5.4 StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgresql-bill-inquiry
  namespace: phonebill-dev
  labels:
    app: postgresql-bill-inquiry
    tier: database
spec:
  serviceName: postgresql-bill-inquiry
  replicas: 1
  selector:
    matchLabels:
      app: postgresql-bill-inquiry
  template:
    metadata:
      labels:
        app: postgresql-bill-inquiry
        tier: database
    spec:
      containers:
      - name: postgresql
        image: bitnami/postgresql:14
        imagePullPolicy: IfNotPresent
        env:
        - name: POSTGRES_DB
          valueFrom:
            configMapKeyRef:
              name: postgresql-bill-inquiry-config
              key: POSTGRES_DB
        - name: POSTGRES_USER
          valueFrom:
            configMapKeyRef:
              name: postgresql-bill-inquiry-config
              key: POSTGRES_USER
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: postgresql-bill-inquiry-secret
              key: postgres-password
        - name: POSTGRESQL_MAX_CONNECTIONS
          valueFrom:
            configMapKeyRef:
              name: postgresql-bill-inquiry-config
              key: POSTGRESQL_MAX_CONNECTIONS
        - name: POSTGRESQL_SHARED_BUFFERS
          valueFrom:
            configMapKeyRef:
              name: postgresql-bill-inquiry-config
              key: POSTGRESQL_SHARED_BUFFERS
        - name: POSTGRESQL_EFFECTIVE_CACHE_SIZE
          valueFrom:
            configMapKeyRef:
              name: postgresql-bill-inquiry-config
              key: POSTGRESQL_EFFECTIVE_CACHE_SIZE
        - name: POSTGRESQL_WORK_MEM
          valueFrom:
            configMapKeyRef:
              name: postgresql-bill-inquiry-config
              key: POSTGRESQL_WORK_MEM
        - name: POSTGRESQL_MAINTENANCE_WORK_MEM
          valueFrom:
            configMapKeyRef:
              name: postgresql-bill-inquiry-config
              key: POSTGRESQL_MAINTENANCE_WORK_MEM
        - name: POSTGRESQL_LOG_MIN_DURATION_STATEMENT
          valueFrom:
            configMapKeyRef:
              name: postgresql-bill-inquiry-config
              key: POSTGRESQL_LOG_MIN_DURATION_STATEMENT
        ports:
        - name: postgresql
          containerPort: 5432
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
          limits:
            cpu: 1000m
            memory: 2Gi
        volumeMounts:
        - name: postgresql-data
          mountPath: /bitnami/postgresql
        livenessProbe:
          exec:
            command:
            - /bin/sh
            - -c
            - exec pg_isready -U postgres -h 127.0.0.1 -p 5432
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 6
        readinessProbe:
          exec:
            command:
            - /bin/sh
            - -c
            - exec pg_isready -U postgres -h 127.0.0.1 -p 5432
          initialDelaySeconds: 5
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 6
      volumes:
      - name: postgresql-data
        persistentVolumeClaim:
          claimName: postgresql-bill-inquiry-pvc

5.5 Service

apiVersion: v1
kind: Service
metadata:
  name: postgresql-bill-inquiry
  namespace: phonebill-dev
  labels:
    app: postgresql-bill-inquiry
    tier: database
spec:
  type: ClusterIP
  ports:
  - name: postgresql
    port: 5432
    targetPort: 5432
    protocol: TCP
  selector:
    app: postgresql-bill-inquiry

6. 스키마 초기화

6.1 초기화 Job

apiVersion: batch/v1
kind: Job
metadata:
  name: bill-inquiry-db-init
  namespace: phonebill-dev
spec:
  template:
    spec:
      containers:
      - name: db-init
        image: bitnami/postgresql:14
        env:
        - name: PGPASSWORD
          valueFrom:
            secretKeyRef:
              name: postgresql-bill-inquiry-secret
              key: postgres-password
        command: ["/bin/bash"]
        args:
        - -c
        - |
          echo "스키마 초기화 시작..."
          
          # 연결 대기
          until pg_isready -h postgresql-bill-inquiry -p 5432 -U postgres; do
            echo "PostgreSQL 서버 대기 중..."
            sleep 2
          done
          
          echo "스키마 생성 중..."
          psql -h postgresql-bill-inquiry -U postgres -d bill_inquiry_db << 'EOF'
          
          -- 타임존 설정
          SET timezone = 'Asia/Seoul';
          
          -- 확장 모듈 활성화
          CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
          CREATE EXTENSION IF NOT EXISTS "pg_stat_statements";
          
          -- 테이블 생성 (bill-inquiry-schema.psql 내용)
          -- 고객정보 테이블 생성
          CREATE TABLE IF NOT EXISTS customer_info (
              customer_id VARCHAR(50) NOT NULL,
              line_number VARCHAR(20) NOT NULL,
              customer_name VARCHAR(100),
              status VARCHAR(10) NOT NULL DEFAULT 'ACTIVE',
              operator_code VARCHAR(10) NOT NULL,
              cached_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
              expires_at TIMESTAMP NOT NULL,
              created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
              updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
              CONSTRAINT pk_customer_info PRIMARY KEY (customer_id),
              CONSTRAINT uk_customer_info_line UNIQUE (line_number),
              CONSTRAINT ck_customer_info_status CHECK (status IN ('ACTIVE', 'INACTIVE'))
          );
          
          -- 기타 테이블들은 전체 스키마 파일에서 가져와 적용
          
          -- 기본 시스템 설정 데이터 삽입
          INSERT INTO system_config (config_key, config_value, description, config_type) VALUES
          ('bill.cache.ttl.hours', '4', '요금정보 캐시 TTL (시간)', 'INTEGER'),
          ('kos.connection.timeout.ms', '30000', 'KOS 연결 타임아웃 (밀리초)', 'INTEGER'),
          ('kos.retry.max.attempts', '3', 'KOS 최대 재시도 횟수', 'INTEGER')
          ON CONFLICT (config_key) DO NOTHING;
          
          SELECT 'Bill-Inquiry Database 초기화 완료' AS result;
          
          EOF
          
          echo "스키마 초기화 완료"
        volumeMounts:
        - name: schema-script
          mountPath: /scripts
      volumes:
      - name: schema-script
        configMap:
          name: bill-inquiry-schema-script
      restartPolicy: OnFailure

6.2 스키마 스크립트 ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: bill-inquiry-schema-script
  namespace: phonebill-dev
data:
  init-schema.sql: |
    -- bill-inquiry-schema.psql 파일의 전체 내용을 여기에 포함

7. 설치 절차

7.1 사전 준비

  1. AKS 클러스터 확인

    kubectl config current-context
    kubectl get nodes
    
  2. 네임스페이스 생성

    kubectl create namespace phonebill-dev
    kubectl config set-context --current --namespace=phonebill-dev
    
  3. 스토리지 클래스 확인

    kubectl get storageclass
    

7.2 설치 순서

  1. ConfigMap 및 Secret 생성

    kubectl apply -f postgresql-bill-inquiry-config.yaml
    kubectl apply -f postgresql-bill-inquiry-secret.yaml
    
  2. PersistentVolumeClaim 생성

    kubectl apply -f postgresql-bill-inquiry-pvc.yaml
    kubectl get pvc
    
  3. StatefulSet 배포

    kubectl apply -f postgresql-bill-inquiry-statefulset.yaml
    kubectl get statefulset
    kubectl get pods -w
    
  4. Service 생성

    kubectl apply -f postgresql-bill-inquiry-service.yaml
    kubectl get service
    
  5. 스키마 초기화

    kubectl apply -f bill-inquiry-schema-configmap.yaml
    kubectl apply -f bill-inquiry-db-init-job.yaml
    kubectl logs -f job/bill-inquiry-db-init
    

7.3 설치 검증

  1. Pod 상태 확인

    kubectl get pods -l app=postgresql-bill-inquiry
    kubectl describe pod postgresql-bill-inquiry-0
    
  2. 데이터베이스 접속 테스트

    kubectl exec -it postgresql-bill-inquiry-0 -- psql -U postgres -d bill_inquiry_db
    
  3. 테이블 생성 확인

    \dt
    SELECT COUNT(*) FROM system_config;
    SELECT config_key, config_value FROM system_config LIMIT 5;
    
  4. 서비스 연결 테스트

    kubectl run test-client --rm -it --image=postgres:14 --restart=Never -- psql -h postgresql-bill-inquiry.phonebill-dev.svc.cluster.local -U postgres -d bill_inquiry_db
    

8. 모니터링 및 관리

8.1 모니터링 메트릭

메트릭 임계값 설명
CPU 사용률 < 80% 정상 동작 범위
Memory 사용률 < 85% 메모리 부족 방지
Disk 사용률 < 80% 스토리지 여유공간
Connection 수 < 80 최대 연결 수 100의 80%
평균 응답시간 < 100ms 쿼리 성능 모니터링

8.2 로그 관리

# PostgreSQL 로그 확인
kubectl logs postgresql-bill-inquiry-0

# 실시간 로그 모니터링
kubectl logs -f postgresql-bill-inquiry-0

# 로그 검색
kubectl logs postgresql-bill-inquiry-0 | grep ERROR

8.3 백업 및 복구

  1. 수동 백업

    kubectl exec postgresql-bill-inquiry-0 -- pg_dump -U postgres bill_inquiry_db > bill_inquiry_backup_$(date +%Y%m%d).sql
    
  2. Azure Disk Snapshot

    # PVC에 바인딩된 Disk 확인
    kubectl get pv
    
    # Azure CLI로 스냅샷 생성
    az snapshot create \
      --resource-group phonebill-dev-rg \
      --name bill-inquiry-db-snapshot-$(date +%Y%m%d) \
      --source {DISK_ID}
    

9. 트러블슈팅

9.1 일반적인 문제

문제 원인 해결방안
Pod Pending 리소스 부족 노드 리소스 확인, requests 조정
Connection Failed Service 설정 오류 Service 및 Endpoint 확인
Init 실패 스키마 오류 스키마 파일 문법 검사
성능 저하 설정 부적절 PostgreSQL 튜닝 적용

9.2 문제 해결 절차

# 1. Pod 상태 확인
kubectl get pods -l app=postgresql-bill-inquiry
kubectl describe pod postgresql-bill-inquiry-0

# 2. 로그 확인
kubectl logs postgresql-bill-inquiry-0 --tail=100

# 3. 서비스 확인
kubectl get service postgresql-bill-inquiry
kubectl get endpoints postgresql-bill-inquiry

# 4. PVC 상태 확인
kubectl get pvc postgresql-bill-inquiry-pvc
kubectl describe pvc postgresql-bill-inquiry-pvc

# 5. ConfigMap/Secret 확인
kubectl get configmap postgresql-bill-inquiry-config -o yaml
kubectl get secret postgresql-bill-inquiry-secret -o yaml

10. 보안 고려사항

10.1 접근 제어

  • Network Policy: 클러스터 내부 접근만 허용
  • RBAC: 최소 권한 원칙 적용
  • Secret 관리: 비밀번호 암호화 저장

10.2 데이터 보호

  • 암호화: 전송 구간 TLS 적용
  • 백업 암호화: 백업 데이터 암호화
  • 접근 로그: 모든 접근 기록 유지

11. 운영 가이드

11.1 정기 작업

  • 주간: 백업 상태 확인 및 복구 테스트
  • 월간: 성능 메트릭 분석 및 튜닝
  • 분기: 보안 패치 및 업그레이드 검토

11.2 비상 대응

  1. 서비스 중단 시

    • Pod 재시작: kubectl rollout restart statefulset/postgresql-bill-inquiry
    • 백업으로부터 복구
    • 새로운 PVC 생성 후 데이터 이전
  2. 성능 문제 시

    • 리소스 확장: CPU/Memory limits 증가
    • 설정 튜닝: PostgreSQL 파라미터 최적화
    • 인덱스 재구성: 슬로우 쿼리 최적화

12. 비용 최적화

12.1 리소스 최적화

  • Storage: Standard HDD 사용으로 비용 절약
  • CPU/Memory: 개발환경 최적화된 사이징
  • 백업: Azure Disk Snapshot 활용으로 저비용

12.2 예상 비용 (월간)

항목 비용 (USD) 설명
Storage (20GB Standard) $2 Azure Disk Standard HDD
컴퓨팅 리소스 $0 AKS 노드 내 리소스 활용
백업 스토리지 $1 Snapshot 저장 비용
총 비용 $3 월간 예상 비용

작성일: 2025-09-08
작성자: 백엔더 (이개발)
검토자: 아키텍트 (김기획), 데옵스 (최운영)
승인자: 기획자 (김기획)