모든 페이지
1 / 3

Loading...

Loading...

Loading...

기동 / 로그 확인 / 종료 / 초기화

Kubernetes 환경에서 SysMasterDB를 기동 / 로그 확인 / 종료 / 초기화하는 방법이다.

1. 기동

클러스터 사전 준비(setup-once.sh)가 완료된 상태에서, 배포 파일이 위치한 디렉터리에서 아래 명령을 수행하면 전체 스택이 배포된다.

kubectl apply -k kubernetes

적용 전에 최종 결과를 확인하려면 아래 명령을 사용한다.

kubectl kustomize kubernetes                       # 병합된 매니페스트 출력
kubectl apply -k kubernetes --dry-run=server       # 클러스터 검증만 수행

1.1. 기동 확인

기동 순서는 별도로 제어할 필요가 없다. 각 모듈이 자신의 의존 대상이 준비될 때까지 대기하므로 아래 순서로 준비된다.

1. metadb, repodb, zookeeper, client-tibero    (의존 대상 없음)
2. broker                                      (zookeeper 필요)
3. sdm                                         (metadb, repodb 필요)
4. analyzer, dbmanager, chatbot                (sdm 필요)
5. collector                                   (sdm, analyzer 필요)
6. client-gateway                              (sdm, dbmanager, collector 필요)

최초 배포는 데이터베이스 초기화로 인해 전체가 준비되기까지 수 분이 소요된다.

kubectl -n sysmasterdb get pods

전 모듈에 헬스 체크가 설정되어 있어 1/1 Running으로 표시되면 실제로 요청을 처리할 수 있는 상태를 의미한다. 별도로 기동 완료 로그를 확인할 필요가 없다.

참고

앞 순서의 모듈을 기다리는 동안 뒤 순서의 파드가 몇 차례 재시작하는 것은 정상이며, 앞 모듈이 준비되면 이어서 정상 상태가 된다. 모듈별 기동 대기 한도는 「Kubernetes 환경」 문서의 매니페스트 구성의 헬스 체크 항목을 참고한다.

파드가 계속 준비되지 않는 경우 아래로 원인을 확인한다.

kubectl -n sysmasterdb describe pod {파드명}       # Events 항목에서 실패 사유 확인
kubectl -n sysmasterdb logs {파드명}
kubectl -n sysmasterdb logs {파드명} --previous    # 재시작 직전 로그

1.2. 접속

kubectl -n sysmasterdb get svc client-gateway

할당된 EXTERNAL-IP로 브라우저에서 https://{EXTERNAL-IP} 로 접속한다. 사이트 인증서를 반입하지 않은 경우 브라우저에 인증서 경고가 표시되는 것은 정상이다.


각 컨테이너의 표준 출력 로그는 아래 명령으로 확인할 수 있다.

다만 각 모듈의 애플리케이션 로그는 표준 출력이 아니라 컨테이너 내 /sysmaster/logs 경로의 로그 파일에 적재되므로, 상세 로그는 아래와 같이 확인한다.

셸 도구가 없는 파드를 조사할 때는 함께 제공되는 유틸리티 이미지를 사용한다. kubectl debug는 파드 이름만 받으므로 디플로이먼트 이름을 전달하면 실패한다.


라이선스는 sdm-license Secret으로만 주입되며, 파드를 재시작하지 않고 교체할 수 있다. 아래 세 단계를 순서대로 수행한다.

Secret을 교체해도 파드 안의 파일이 즉시 바뀌지는 않는다. 아래 명령의 출력이 새 라이선스의 값으로 바뀔 때까지 기다린다(반영에 최대 1분 소요).

정상적으로 갱신되면 아래와 같이 응답한다. expirationDate가 새 라이선스의 만료일과 일치해야 갱신이 완료된 것이다.


변경 대상
반영 방법

특정 모듈만 재시작하는 경우는 다음과 같다.


아래 명령으로 워크로드만 삭제하면 SysMasterDB가 종료된다. 이때 Meta DB와 Repository DB의 데이터 파일은 PVC에 유지되므로, 다시 기동하면 이전에 저장한 데이터를 사용할 수 있다.

다시 기동할 때는 kubectl apply -k kubernetes만 수행한다.


아래 데이터는 PVC 3종에만 존재하며 제품이 생성하는 사본은 없다. 초기화를 수행하기 전에 반드시 백업한다.

PVC
저장 내용

스토리지 계층 백업(CSI VolumeSnapshot 등)을 권장한다. 대상 볼륨은 아래로 확인한다.


아래 명령을 수행하면 네임스페이스를 포함한 모든 오브젝트와 데이터가 삭제되고, 최초 설치 상태와 동일하게 동작한다.

실수로 삭제하더라도 데이터가 보존되도록 하려면, 배포 직후 PVC에 연결된 PV의 reclaim 정책을 Retain으로 변경해 둔다.


증상
원인
조치

sdm-license Secret

위 절차 (재시작 불필요)

meta.conf / repo.conf

데이터베이스 최초 초기화 시에만 사용된다. 이미 초기화된 데이터베이스에는 반영되지 않는다

sdm이 기동하지 않음

라이선스 Secret 없음, 또는 라이선스 version이 1.1이 아님

setup-once.sh 실행 여부 확인

sdm이 데이터베이스에 접속하지 못함

meta.conf / repo.conf의 암호와 Secret 값 불일치

두 값을 동일하게 설정

UI 접속 시 502

NGINX_RESOLVER가 실제 클러스터 DNS 주소와 다름

kubectl get svc kube-dns -n kube-system

sdm이 데이터베이스를 계속 대기

metadb / repodb 서비스에서 7000 포트 누락

서비스 정의 확인

배포가 완료되지 않음

strategy: Recreate 설정을 제거함

원복

파드가 계속 OOMKilled

메모리 limits 부족, 또는 JVM 힙이 limits에 비해 큼

두 값을 함께 상향

Kafka Too many open files

노드의 파일 디스크립터 한계가 낮음

노드에서 nofile 65536 이상으로 설정

대시보드가 비어 있음

TPM Agent가 collector-ingest에 도달하지 못함

EXTERNAL-IP와 Agent 설정 주소 확인

client-gateway만 CrashLoopBackOff

로그 볼륨 마운트를 제거했거나 HTTPS 인증서 파일명이 다름

kubectl logs deploy/client-gateway --previous 로 nginx 오류 메시지 확인

ConfigMap을 변경했는데 반영되지 않음

ConfigMap 이름이 동일해 파드 스펙이 변경되지 않음

kubectl -n sysmasterdb rollout restart deploy

오버레이 추가 후 기존 UI/수집이 중단

kustomization.yml에 resources: / patches: 키를 중복 작성

「Kubernetes 환경」 문서의 매니페스트 구성의 주의 사항 참고

kubectl -n sysmasterdb logs deployment/sdm        # 터미널 출력 로그
kubectl -n sysmasterdb logs deployment/sdm -f     # 실시간 확인
kubectl -n sysmasterdb exec deployment/sdm -- ls /sysmaster/logs
kubectl -n sysmasterdb exec deployment/sdm -- sh -c 'tail -f /sysmaster/logs/sdm.v.{version}.log'
POD=$(kubectl -n sysmasterdb get pod -l app=sdm -o jsonpath='{.items[0].metadata.name}')

kubectl -n sysmasterdb debug -it "$POD" \
  --image={registry}/sysmaster-db-alpine-linux:{version} --target=sdm
kubectl create secret generic sdm-license -n sysmasterdb \
  --from-file=sysmaster-db-license.xml=/path/to/new-license.xml \
  --dry-run=client -o yaml | kubectl apply -f -
kubectl -n sysmasterdb exec deploy/sdm -- grep serial_id /sysmaster/license/sysmaster-db-license.xml
kubectl -n sysmasterdb exec deploy/sdm -- refresh-license
{"message":"License store refresh succeeded.","licenseType":"SUBSCRIPTION","maxMonitoringCores":1000,"expirationDate":"..."}

kustomization.yml (이미지, patch 등)

kubectl apply -k kubernetes

디플로이먼트의 env 항목

kubectl apply -k kubernetes (파드가 자동 교체된다)

smdb-env ConfigMap

kubectl -n sysmasterdb rollout restart deploy/sdm
kubectl -n sysmasterdb rollout status  deploy/sdm
kubectl -n sysmasterdb delete deploy,svc --all
kubectl -n sysmasterdb get pvc                 # 3개가 Bound 상태로 남아 있어야 한다

metadb-data

설정, 계정, 관제 대상 목록

repodb-data

수집된 메트릭 전체

sdm-reports

kubectl -n sysmasterdb get pvc -o custom-columns=PVC:.metadata.name,PV:.spec.volumeName
kubectl delete -k kubernetes
kubectl get ns sysmasterdb             # NotFound 가 될 때까지 대기한다
kubectl get pv | grep sysmasterdb      # 남아 있으면 스토리지 정책에 따라 처리한다
for pvc in metadb-data repodb-data sdm-reports; do
  pv=$(kubectl -n sysmasterdb get pvc "$pvc" -o jsonpath='{.spec.volumeName}')
  kubectl patch pv "$pv" -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
done

전체 파드 ImagePullBackOff

레지스트리 주소 미수정, 또는 인증 필요

kustomization.yml의 newName 확인 / 사설 레지스트리 인증 구성 추가

전체 파드 Pending

PVC가 Pending (default StorageClass 없음)

kubectl -n sysmasterdb get events --sort-by=.lastTimestamp | tail -30

2. 로그 확인

주의

로그는 기본적으로 파드 내부 임시 볼륨에 기록된다. 컨테이너가 재시작해도 로그는 유지되지만 파드가 교체되면(배포, 노드 drain, eviction) 사라진다. 장애 조사를 위해 로그를 보존해야 하는 환경에서는 「설치 및 파라미터 설정」 문서의 9. 선택 구성의 로그 영속화를 적용한다.

client-tibero는 정적 파일 서버로 파일 로그를 기록하지 않고 표준 출력으로만 내보낸다. /sysmaster/logs가 비어 있는 것이 정상이며, 로그는 kubectl logs로 확인한다.

2.1. 문제 분석용 디버그 컨테이너

3. 라이선스 갱신

3.1. Secret을 새 라이선스로 교체

3.2. 파드 내부 파일에 반영되었는지 확인

3.3. sdm에 리로드 지시

주의 — 3.2 단계(반영 확인)를 생략하지 않는다.

Secret을 적용한 직후에는 파드 내부 파일이 아직 이전 내용이다. 그 상태에서 3.3의 refresh-license를 수행하면 이전 라이선스를 다시 읽고 성공으로 응답하므로, 갱신된 것처럼 보이지만 실제로는 갱신되지 않는다.

반영 여부는 serial_id나 signature처럼 라이선스마다 값이 다른 항목으로 판정한다. start_date / end_date는 갱신 전 라이선스의 만료일과 갱신 후 라이선스의 시작일이 동일한 경우가 많아, 아직 교체되지 않은 파일에도 일치할 수 있다.

참고

  • 갱신이 실패하면 HTTP 500과 함께 사유가 응답된다. 이 경우에도 파드는 재시작하지 않고 서비스는 계속 동작하며, 기존 라이선스가 유지된다.

  • 라이선스의 identified_by_host 항목은 기록용이며 실행 중 파드의 호스트명과 대조하지 않는다. 파드 이름이 배포마다 변경되어도 라이선스에는 영향이 없다.

  • setup-once.sh를 새 라이선스 파일로 다시 실행하는 방법도 가능하다. 이때 크리덴셜 환경변수를 지정하지 않으면 기존 크리덴셜 Secret은 그대로 유지된다.

4. 설정 변경과 재시작

주의

전 모듈이 단일 인스턴스로 구성되어 있어 재시작 중에는 해당 기능이 일시 중단된다. 특히 client-gateway를 재시작하면 사용자 UI 접속이 끊긴다.

5. 종료

6. 백업

주의

논리 백업(pg_dump)을 사용하는 경우, Meta DB와 Repository DB가 모두 TimescaleDB 확장을 사용한다는 점을 고려해야 한다. 일반적인 pg_dump / pg_restore 절차만으로는 복원 결과가 정상적이지 않을 수 있으므로, TimescaleDB의 timescaledb_pre_restore() / timescaledb_post_restore()를 함께 사용해야 하며 복원까지 성공하는 것을 실제 환경에서 확인한 후에만 백업 수단으로 채택한다.

7. 초기화

주의 — 이 명령은 데이터까지 삭제한다.

kubernetes/base/foundation.yml에 네임스페이스와 PVC 3종이 함께 정의되어 있어 삭제 대상에 포함된다. PVC가 삭제되면 StorageClass의 reclaimPolicy가 Delete(동적 프로비저닝 기본값)인 경우 볼륨 데이터도 함께 삭제되며, setup-once.sh가 생성한 Secret 2종도 네임스페이스와 함께 사라진다.

데이터를 유지해야 하는 경우 위 5. 종료를 사용한다. 재설치하려면 setup-once.sh 실행부터 다시 수행해야 한다.

8. 문제 해결

kubectl apply -k kubernetes 후 kubectl -n sysmasterdb rollout restart deploy

생성된 리포트 파일

kubectl -n sysmasterdb get pvc

3. 라이선스 갱신

설치 및 파라미터 설정

Kubernetes 환경에서 SysMasterDB를 설치하는 과정이다.

SysMasterDB 8.4의 Kubernetes 배포 파일은 kustomize 기반 매니페스트로 제공된다. 배포 파일의 kubernetes 디렉터리에 전체 스택 매니페스트(base)와 클러스터 1회 부트스트랩 스크립트(setup-once.sh)가 포함되어 있으며, kubectl apply -k 명령 한 번으로 전체 스택이 배포된다.

각 매니페스트 파일의 구성과 설정값의 의미는 「Kubernetes 환경」 문서의 매니페스트 구성 항목을, 환경에 따라 선택적으로 적용하는 구성은 아래 9. 선택 구성 항목을 참고한다.

1. 도커(Docker) 이미지 로드

설치 파일이 준비된 디렉터리에서 아래의 명령을 수행하여 도커 이미지를 로드한다.

docker load -i sysmaster-db-{version}.tar

이때 로드된 도커 이미지 중 Kubernetes 배포에 사용하는 이미지는 다음과 같다.

  • sysmaster-db-client:{version}

  • sysmaster-db-client-tibero:{version}

  • sysmaster-db-sdm:{version}

  • sysmaster-db-dbmanager:{version}

  • sysmaster-db-collector:{version}

  • sysmaster-db-analyzer:{version}

  • sysmaster-db-chatbot:{version}

  • sysmaster-db-tiberoopensql-postgres:{version}

  • sysmaster-db-kafka-loggable:{version}

  • sysmaster-db-zookeeper-loggable:{version}

  • sysmaster-db-alpine-linux:{version}


로드한 도커 이미지들을 해당 환경에서 사용 중인 이미지 레지스트리로 태그를 변경하여 푸시한다.

푸시가 완료되면 kubernetes/kustomization.yml 파일의 images 항목에서 각 이미지의 newName을 해당 레지스트리 주소로 수정한다. 이미지 태그는 base 매니페스트에 릴리스 버전으로 이미 지정되어 있으므로, 릴리스 버전과 다른 태그로 푸시한 경우에만 newTag를 추가로 지정한다.


kubernetes/base 디렉터리의 매니페스트가 전체 스택(11개 디플로이먼트)을 정의한다. 모든 오브젝트는 sysmasterdb 네임스페이스에 생성되며, 컴포넌트 간 통신은 서비스(Service) 이름으로 이루어진다. 각 디플로이먼트에 대한 설명은 다음과 같다.

디플로이먼트
설명
포트

배포 전에 반드시 kubernetes/setup-once.sh를 클러스터당 1회 실행해야 한다. 실행하지 않으면 파드가 기동하지 못한다.

스크립트가 수행하는 내용은 다음과 같다.

  1. sdm-license Secret 생성 — 발급받은 라이선스 파일을 Secret으로 등록하며, sdm 파드가 이를 /sysmaster/license 경로로 마운트한다. SysMasterDB 8.4는 license version="1.1"만 허용하며, 다른 버전의 라이선스를 전달하면 스크립트가 실패한다.

  2. smdb-credentials Secret 생성 — Admin 계정과 Meta DB/Repository DB 접속 암호를 Secret으로 등록한다. 매니페스트에는 암호가 평문으로 존재하지 않으며, 암호를 사용하는 파드(sdm/analyzer/chatbot)만 Secret을 주입받는다.

  3. CoreDNS rewrite 등록 — client-gateway가 sdm 이름을 해석할 수 있도록 rewrite name sdm sdm.sysmasterdb.svc.cluster.local

스크립트는 kubectl과 python3를 사용하며, 두 명령이 PATH에 없으면 즉시 중단된다. 실행 메시지는 영문으로 출력된다.


kubernetes/base/foundation.yml 파일을 열어 smdb-env ConfigMap에서 전 모듈이 공통으로 사용하는 파라미터 값을 설정한다.

파라미터 이름
설명
초기값
Compose 환경의 이름
Kubernetes 배포에서 실제 설정 위치

예를 들어 수집 정보 보관 주기를 7일에서 14일로 변경하는 경우, kubernetes/base/sysmaster/sdm.yml에서 metric_retention_day 값을 직접 수정한다.

변경 후 kubectl apply -k kubernetes를 수행하면 sdm 파드가 자동으로 교체된다. 반영 여부는 아래로 확인한다.

kubernetes/base/sysmaster/sdm.yml 파일을 열어 env 항목에서 계정, 세션, 접속 IP 제한, 이벤트 로그 보관에 필요한 파라미터 값을 설정한다.

해당 과정에서 설정하는 파라미터에 대한 설명은 다음과 같다.

파라미터 이름
설명
초기값

변경 후 kubectl apply -k kubernetes를 수행하면 sdm 파드가 자동으로 교체된다.


kubernetes/base/meta.conf, kubernetes/base/repo.conf 파일이 Meta DB와 Repository DB의 초기화(사용자·데이터베이스·확장 생성)에 사용된다. 다음은 Meta DB에 대한 파라미터 설정 예시이다.

운영 환경에서는 pg_superuser_password(기본 postgres)와 pg_users 계정의 암호(기본 sysmaster)를 반드시 교체한다. 그 외 conf 파일은 기본적으로 제공되는 설정값을 사용하되, 다음에서 설명하는 파라미터는 필요 시 구동 환경에 맞게 사용자가 직접 설정해준다.

파라미터 이름
설명

외부 노출이 필요한 서비스는 LoadBalancer 타입으로 구성되어 있다.

서비스
포트
용도

배포 후 아래 명령으로 할당된 주소를 확인한다.

collector-ingest에 할당된 EXTERNAL-IP의 8292 포트를 관제 데이터베이스의 TPM Agent에 수집 서버 주소로 등록한다. 이 주소에 Agent가 도달하지 못하면 수집 정보가 유입되지 않아 대시보드가 비어 있게 된다.


항목
요건
확인 방법
  • default StorageClass가 없거나 특정 StorageClass를 사용해야 하는 경우 kubernetes/base/foundation.yml의 PVC 3종에 storageClassName을 지정한다. 지정하지 않은 상태에서 default도 없으면 PVC가 Pending에 머물고 파드가 기동하지 못한다.

  • 클러스터 DNS 주소가 다른 경우 kubernetes/base/client/client-gateway.yml의 NGINX_RESOLVER 값을 수정한다. 값이 틀리면 UI 접속 시 502 오류가 발생한다.

  • 파일 디스크립터는 Kubernetes에서 파드 단위로 설정할 수단이 없다.


기본 배포에는 포함되지 않으며, 환경에 따라 필요한 것만 kubernetes/kustomization.yml에 추가한다.

아래 예시에서 [기존]이 표시된 줄은 이미 파일에 있는 줄이고, <- 추가가 표시된 줄만 새로 작성하는 것이다. resources: patches: 키를 새로 작성하면 기존 항목이 무효화된다(매니페스트 구성 문서의 주의 사항 참고).

파일
사용 환경

레지스트리가 익명 pull을 허용하지 않는 환경에서 필요하다. 적용하지 않으면 전체 파드가 ImagePullBackOff 상태가 된다.


기본값 imagePullPolicy: Always는 파드가 기동될 때마다(노드 재부팅, 재스케줄 포함) 레지스트리를 조회한다. 릴리스 이미지는 태그가 버전으로 고정되어 내용이 변하지 않으므로, 운영 환경에서는 레지스트리가 점검·장애로 중단된 경우 이미지가 노드에 캐시되어 있어도 파드가 기동하지 못하는(ErrImagePull) 위험만 남는다. 이 구성은 정책을 IfNotPresent로 완화한다.


기본 상태에서 client-gateway는 이미지에 내장된 self-signed 인증서를 사용한다. 서비스는 정상 동작하지만 브라우저에 인증서 경고가 표시되므로, 사이트 도메인 인증서를 반입한다.

https-cert.yml의 내용은 다음과 같다.


기본 구성에서 로그는 파드 내부 임시 볼륨에 기록되므로, 파드가 교체되면(배포, 노드 drain, eviction) 로그가 사라진다. 장애 조사를 위해 로그를 보존해야 하는 환경에서는 전 모듈이 공유하는 영구 볼륨으로 전환한다.

두 파일은 한 쌍이다. logs-pvc.yml만 추가하면 파드는 여전히 임시 볼륨을 사용하고, patch만 추가하면 참조할 PVC가 없어 전체 파드가 기동하지 못한다.

  • ReadWriteMany를 지원하는 StorageClass가 필요하다(NFS, CephFS 등). 지원하지 않는 스토리지에 적용하면 PVC가 Pending에 머물고 전체 파드가 기동하지 못한다.

  • smdb-logs PVC는 storageClassName을 지정하지 않은 상태로 제공된다. 즉 클러스터의 default StorageClass로 생성되므로, default가 ReadWriteMany를 지원하지 않으면 그대로는 Pending이 된다. Kubernetes는 접근 모드를 보고 StorageClass를 선택해 주지 않으므로, ReadWriteMany를 제공하는 StorageClass가 default가 아니면 직접 지정해야 한다.

  • 용량 기본값은 50Gi이다. 수집 규모와 보관 주기에 맞춰 조정한다. 가득 차면 로그 기록이 실패한다.

  • 볼륨 안에서 각 모듈은 자기 이름의 하위 디렉터리에 기록한다(sdm/, analyzer/ 등). 모듈별로 디렉터리를 분리하지 않으면 압축 보관되는 오류 로그 파일명이 모듈 간에 겹쳐 서로 덮어쓰게 된다.

  • 이 구성에는 로그 확인 전용 파드가 함께 포함된다. 공유 볼륨을 읽기 전용으로 마운트하고 대기만 하므로, 애플리케이션 파드가 기동하지 못하는 상태에서도 전체 모듈의 로그를 확인할 수 있다.


Kubernetes는 기본적으로 동일 네임스페이스의 모든 파드가 서로 자유롭게 통신할 수 있으며, 클러스터 내의 다른 워크로드에서도 파드 IP로 직접 접근할 수 있다. 클러스터를 다른 서비스와 공유하거나 내부망 격리 요건이 있는 환경에서는 이 구성으로 실제로 필요한 통신 경로만 허용한다.

허용되는 통신 경로는 다음과 같다. 구성이나 포트를 변경한 경우 이 규칙도 함께 갱신해야 한다.

대상
허용 출처
포트

적용 후 검증

CNI가 NetworkPolicy를 지원해야 한다. calico, cilium 등은 정상 동작하지만, 지원하지 않는 CNI는 정책을 오류 없이 무시한다. 적용된 것으로 오인하지 않도록 반드시 실제 차단 여부를 확인한다.

애플리케이션 이미지에는 nc 등의 네트워크 도구가 없으므로 python으로 확인한다. chatbot 파드에서 sdm 파드로 두 포트를 시도하며, 허용 경로인 8090은 OPEN, 차단 대상인 8080은 BLOCKED 여야 정상이다(8080은 client-gateway만 접근할 수 있는 포트이다).

  • 8090이 OPEN이어야 이 판정이 유효하다. 두 포트 모두 BLOCKED로 표시되면 정책이 아니라 확인 절차 자체가 실패한 것이다(파드 IP 오기재, sdm 미기동 등). 이 경우 차단되었다고 판단하지 않는다.

  • 8080이 OPEN이면 CNI가 정책을 무시하고 있는 것이다. 클러스터의 CNI 종류를 확인한다.

sdm

수집 정보를 조회하고 클라이언트와 통신하는 API 서버

8080(사용자), 8090(내부)

dbmanager

관제 데이터베이스에 대한 상태 확인과 Admin 기능을 수행하는 서버

8082

collector

관제 데이터베이스로부터 데이터를 수집하는 서버

8292(수집), 8083(내부)

analyzer

수집한 정보를 가공해 분석 및 저장하는 서버

8081

chatbot

AI 챗봇 서버

8089

metadb

UI 관련 설정 정보를 저장하는 DB 서버

5432, 7000(헬스)

repodb

관제 데이터베이스 수집 데이터를 저장하는 DB 서버

5432, 7000(헬스)

broker

Kafka 브로커

9092

zookeeper

Kafka 코디네이터

2181

규칙을 CoreDNS에 추가한다.

DONT_CHECK_HTTP_HEALTH

컨테이너 내부 헬스 체크 스크립트 비활성화 여부

false

HEALTH_LOG_RETENTION_DAY

헬스 체크 로그 보관 주기

30

KAFKA_MESSAGE_MAX_BYTES

카프카 메시지 사이즈 설정, 1MB ~ 2GB 범위로 설정 가능 smdb-env 값은 broker에만 반영된다. collector가 보내는 메시지의 최대 크기는 collector 디플로이먼트의 broker_message-max-size이므로 함께 변경한다.

20971520 Byte

METADB_USER

chatbot 모듈의 Meta DB 접속 사용자 이름

sysmaster

REPODB_USER

chatbot 모듈의 Repository DB 접속 사용자 이름

sysmaster

각 디플로이먼트의 logging_file_max-size / logging_file_total-size-cap

LOG_LEVEL

각 디플로이먼트의 logging_level_root

CONTAINER_LOG_PATH

각 디플로이먼트의 logging_file_path 및 볼륨 마운트 경로

ADMIN_USERNAME

sdm 디플로이먼트의 application_admin_username

SQL_FLUSH_THRESHOLD / SQL_RS_FETCH_SIZE

collector 디플로이먼트의 sql-loading_flush-threshold / sql-loading_fetch-size

LIMIT_SQL_HASH_COUNT

collector 디플로이먼트의 sql-loading_limit-sql-hash-count

PERFORMANCE_LOGGING

sdm / analyzer / collector / dbmanager 각 디플로이먼트의 동일 이름 env 항목

ACCOUNT_INACTIVE_LOCK_DAYS

sdm 디플로이먼트의 account_inactive-lock-days

ACCOUNT_REFRESH_TOKEN_EXPIRE_DAYS

sdm 디플로이먼트의 account_refresh-token-expire-days

ACCOUNT_PASSWORD_HISTORY_COUNT

sdm 디플로이먼트의 account_password-history-count

ACCOUNT_PASSWORD_CHANGE_DAYS

sdm 디플로이먼트의 account_password-change-days

SESSION_MAX_CONCURRENT_SESSIONS

sdm 디플로이먼트의 security_session_max-concurrent-sessions

SESSION_IDLE_TIMEOUT_MINUTES

sdm 디플로이먼트의 security_session_idle-timeout-minutes (배포 파일에 기본 포함되지 않으며, 필요 시 env에 추가한다)

IP_RESTRICTION_TARGET

sdm 디플로이먼트의 security_ip-restriction_target

IP_RESTRICTION_SUPER_ADMIN_IP

sdm 디플로이먼트의 security_ip-restriction_super-admin-ip

IP_RESTRICTION_TRUSTED_PROXIES

sdm 디플로이먼트의 security_ip-restriction_trusted-proxies

ACCESS_LOG_RETENTION_DAY

sdm 디플로이먼트의 access-log_retention_day

account_password-history-count

이전 비밀번호 재사용 금지 비밀번호를 바꿀 때 직전 N개와 같은 값으로는 바꿀 수 없다. 1~24로 설정 가능하다.

1

account_password-change-days

비밀번호 주기적 변경 안내 마지막으로 비밀번호를 바꾼 뒤(값이 없으면 계정을 만든 뒤) 이 기간이 지나면 로그인 응답으로 변경을 안내한다. 0 이하면 기능을 끈다.

0

security_session_max-concurrent-sessions

계정당 동시 세션 수

  • 0이면 제한하지 않는다(기본).

  • 1 이상이면, 이 수를 넘는 로그인이 성공할 때 가장 먼저 로그인한 세션부터 끊는다.

0

security_session_idle-timeout-minutes

유휴 세션 자동 로그오프(분) 0 이하면 기능을 끈다. [참고] sdm.yml에 기본 포함되지 않으며, 필요 시 env에 추가한다.

30

security_ip-restriction_target

허용IP 외 접속차단서비스

  • NONE: 비활성화.

  • ADMIN: super admin과, 어느 그룹에서든 ADMIN 이상 역할이 있는 사용자에게만 적용한다.

  • ALL: 모든 사용자에게 적용한다.

NONE

security_ip-restriction_super-admin-ip

super admin의 허용 IP super admin의 허용 IP는 이 값으로만 정한다.

빈값

security_ip-restriction_trusted-proxies

프록시 대역

Kubernetes 환경에서는 client-gateway 파드가 속한 Pod 대역을 넣어야 한다.

사내 PC 대역(10.0.0.0/8, 192.168.0.0/16 등)은 넣으면 안 된다. 그 대역의 PC가 헤더를 위조해 IP 제한을 피할 수 있다.

127.0.0.0/8, ::1, 172.16.0.0/12, 10.88.0.0/15

access-log_retention_day

이벤트 로그 보관 기간(일) ACCESS_LOG ( 로그인/ 로그아웃 로그) 보관 기간을 설정한다.

0 이하면 기록, 보관, 삭제 정책이 모두 멈춘다. 이미 쌓인 데이터는 그대로 둔다.

365

노드 여유 자원

메모리 16GB 이상, CPU 4코어 이상 권장

kubectl describe node

파일 디스크립터

nofile 65536 이상

배포 후 kubectl -n sysmasterdb exec deploy/repodb -- sh -c 'ulimit -n'

컨테이너 런타임의 기본값을 상속하므로 노드 측에서 보장해야 한다(containerd의
LimitNOFILE
). 값이 낮으면 Kafka가
Too many open files
오류로 종료되거나 PostgreSQL 접속이 실패한다.

logs-pvc.yml + logs-pvc-patch.yml

파드가 교체되어도 로그를 보존 (ReadWriteMany 스토리지 필요)

network-policy.yml

파드 간 통신 제한 (CNI 지원 필요)

collector

sdm

8083

sdm

client-gateway

8080, 8090

sdm

analyzer, collector, dbmanager, chatbot

8090

metadb, repodb

sdm, analyzer, chatbot, dbmanager

5432, 7000

broker

collector, analyzer, broker

9092

zookeeper

broker

2181

client-tibero

client-gateway

80

chatbot

sdm

8089

dbmanager

sdm

8082

analyzer

sdm

8081

client-gateway

사용자가 브라우저를 통해 접속하게 될 웹 진입점(리버스 프록시)

443

client-tibero

UI 정적 자원을 제공하는 웹 서버

TZ

SysMasterDB 서버 Time-Zone 설정

Asia/Seoul

USE_SENTRY

외부 오류 리포팅 사용 여부. 운영 환경에서는 false로 둔다

RETENTION_DAY (수집 정보 보관 주기)

sdm 디플로이먼트의 metric_retention_day

LOG_RETENTION_DAY

각 디플로이먼트의 logging_file_max-history

account_inactive-lock-days

장기 미사용 계정 잠금 마지막으로 사용한 뒤 이 기간(일)이 지나면 로그인, 토큰 재발급, 역할 변경을 막는다. 0 이하면 기능을 끈다.

0

account_refresh-token-expire-days

Refresh Token 유효기간 0 이하면 따로 정하지 않은 것으로 본다. 이때 유효기간은 장기 미사용 잠금이 켜져 있으면 잠금 기간과 상한이 같다.

pg_max_connections

Meta DB(또는 Repository DB)의 최대 커넥션 수

log_timezone

Meta DB(또는 Repository DB)의 로그 시간 Time-Zone

client-gateway

443

사용자 UI/API 접속(https)

collector-ingest

8292

default StorageClass

PVC 3종(metadb 10Gi / repodb 20Gi / sdm-reports 10Gi, ReadWriteOnce)이 이를 통해 생성된다

kubectl get sc

클러스터 DNS 주소

client-gateway의 NGINX_RESOLVER(기본 10.96.0.10)가 실제 값과 일치해야 한다

image-pull-secret.yml

레지스트리가 인증을 요구하는 경우

image-pull-policy.yml

폐쇄망 — 레지스트리 장애 시에도 노드 캐시로 파드가 기동되도록

https-cert.yml

client-gateway

제한 없음(브라우저)

443

collector

제한 없음(TPM Agent)

참고

sysmaster-db-alpine-linux는 셸 도구가 포함된 유틸리티 이미지로, 평상시 배포에는 기동되지 않는다. 다음 두 경우에 사용되므로 다른 이미지와 함께 레지스트리에 push해 두는 것을 권장한다.

  • 9. 선택 구성의 로그 영속화를 적용할 때 생성되는 로그 확인 전용 파드

  • 셸 도구가 없는 파드를 조사할 때 사용하는 임시 디버그 컨테이너

로드된 전체 목록은 docker images | grep sysmaster-db 명령으로 확인할 수 있다.

2. 도커(Docker) 이미지 푸시

참고

레지스트리가 인증을 요구하는 환경에서는 9. 선택 구성의 사설 레지스트리 인증을 함께 적용한다. 적용하지 않으면 전체 파드가 ImagePullBackOff 상태가 된다.

3. 쿠버네티스(Kubernetes) 오브젝트 구성

4. 클러스터 사전 준비 (setup-once.sh)

주의

크리덴셜 3종(ADMIN_PASSWORD, METADB_PASSWORD, REPODB_PASSWORD)은 반드시 모두 환경변수로 전달해야 하며, 미지정 시 스크립트가 실패한다(평가/테스트 목적에 한해 ALLOW_DEV_DEFAULTS=1 설정으로 기본값 사용 가능).

이때 METADB_PASSWORD와 REPODB_PASSWORD는 아래 6. Meta DB 및 Repository DB 파라미터 설정의 meta.conf, repo.conf에 설정한 pg_users의 pass 값과 반드시 일치해야 한다(DB 초기화 계정 = 앱 접속 계정). 불일치 시 setup-once.sh가 실패한다.

참고

CoreDNS 구성을 자동으로 변경할 수 없는 환경(다른 DNS 제공자를 사용하거나 kube-system 권한이 없는 경우)에서는 스크립트가 수동 적용 방법을 안내하며 중단된다. 이때는 클러스터 DNS 설정의 .:53 { 블록에 아래 한 줄을 직접 추가하고 DNS 파드를 재기동한다. 이 설정이 없으면 client-gateway가 sdm 이름을 해석하지 못해 UI 접속 시 502 오류가 발생한다.

5. 설치 파라미터 설정

주의 — 아래 파라미터는 smdb-env에서 변경해도 반영되지 않는다.

smdb-env에는 Docker Compose 환경과 같은 이름의 파라미터(아래 표의 왼쪽)도 들어 있지만, Kubernetes 배포에서는 사용되지 않는다. 각 모듈이 실제로 읽는 설정은 해당 디플로이먼트의 env 항목에 직접 지정되어 있으며, ConfigMap 쪽만 변경하면 오류 없이 무시된다. 아래 표의 오른쪽 값을 변경해야 한다.

참고

  • 계정 암호(ADMIN_PASSWORD, METADB_PASSWORD, REPODB_PASSWORD)는 ConfigMap이 아니라 위 4. 클러스터 사전 준비의 setup-once.sh가 생성하는 smdb-credentials Secret으로 관리된다.

  • smdb-env의 값을 직접 변경한 경우에는 파드가 자동으로 교체되지 않는다. kubectl -n sysmasterdb rollout restart deploy 명령을 함께 수행해야 반영된다.

  • 수집 정보 보관 주기를 늘리면 Repository DB 사용량도 비례해 증가하므로, repodb-data 볼륨 크기를 함께 검토한다.

계정 및 보안 파라미터 설정

6. Meta DB 및 Repository DB 파라미터 설정

주의

이 파일들은 데이터베이스 최초 초기화 시에만 사용된다. 이미 초기화된 데이터베이스에는 값을 변경하고 파드를 재기동해도 반영되지 않으므로, 배포 전에 값을 확정해야 한다.

또한 pg_log 경로는 Meta DB / Repository DB의 로그 볼륨 마운트 경로(/sysmaster/logs)와 일치해야 한다. 다른 경로로 변경하면 DB 로그가 볼륨 외부에 기록되어 파드가 교체될 때마다 사라진다.

참고

Meta DB 및 Repository DB 파라미터 변경이 필요한 경우, 관련 파라미터 설정은 OpenSQL 사용 가이드를 참조할 수 있다. 그러나 관련 파라미터 설정을 임의 수정하는 경우, SysMasterDB 서버의 정상 동작이 보장되지 않는다. 따라서 위 표에 명시된 파라미터 외 다른 파라미터는, 기본 제공 설정값을 그대로 사용하는 것을 권장한다.

7. 외부 노출 포트 설정

참고

EXTERNAL-IP가 계속 <pending> 상태로 표시되는 경우 클러스터에 LoadBalancer 구현체가 없는 것이다. 이때는 kubernetes/gateway-lb.yml, kubernetes/collector-lb.yml의 type을 NodePort로 수정하거나 Ingress를 앞에 구성한다.

8. 기타 배포 전제

9. 선택 구성

사설 레지스트리 인증 — image-pull-secret.yml

주의

target을 좁혀 일부 디플로이먼트에만 적용하면, 적용되지 않은 파드만 ImagePullBackOff 상태로 남는다. 전체 디플로이먼트에 적용해야 한다.

폐쇄망 이미지 정책 — image-pull-policy.yml

참고

적용 후에는 동일한 태그로 이미지를 다시 push해도 노드가 새 이미지를 가져오지 않는다. 이미지를 교체할 때는 새 태그를 사용하고 kustomization.yml의 images 항목에 newTag를 지정한다.

HTTPS 인증서 — https-cert.yml

주의

Secret의 키 이름(= 마운트될 파일명)은 sysmaster-db-server.crt, sysmaster-db-server.key여야 한다. 다른 이름을 사용하면 nginx가 인증서를 읽지 못해 client-gateway 파드가 CrashLoopBackOff 상태가 되고, 사용자 UI 접속이 중단된다.

로그 영속화 — logs-pvc.yml + logs-pvc-patch.yml

참고

로그 확인 전용 파드는 유틸리티 이미지(sysmaster-db-alpine-linux)를 사용한다. 이 구성을 사용하려면 해당 이미지도 레지스트리에 push되어 있어야 한다.

파드 간 통신 제한 — network-policy.yml

주의 — 파일 전체를 그대로 적용한다.

첫 규칙이 모든 수신을 차단하고 나머지 규칙이 필요한 경로만 다시 허용하는 구조이다. 일부만 선택해 적용하거나 라벨·포트를 수정하면 해당 경로가 차단되어 파드가 기동하지 못하거나, 수집 파이프라인(collector → broker → analyzer)이 오류 없이 중단된다.

80

false

LOG_FILE_SIZE / LOG_TOTAL_SIZE

0

관제 데이터베이스의 TPM Agent가 수집 정보를 push하는 포트

kubectl get svc kube-dns -n kube-system

사이트 HTTPS 인증서로 교체

8292

docker tag sysmaster-db-sdm:{version} {registry}/sysmaster-db-sdm:{version}
docker push {registry}/sysmaster-db-sdm:{version}
# 나머지 이미지들도 동일하게 수행한다.
ADMIN_PASSWORD=... METADB_PASSWORD=... REPODB_PASSWORD=... \
  ./setup-once.sh /path/to/sysmaster-db-license.xml
apiVersion: v1
kind: ConfigMap
metadata:
  name: smdb-env
  namespace: sysmasterdb
data:
  TZ: "Asia/Seoul"
  USE_SENTRY: "false"
  DONT_CHECK_HTTP_HEALTH: "false"
  HEALTH_LOG_RETENTION_DAY: "30"
  KAFKA_MESSAGE_MAX_BYTES: "20971520"
  METADB_USER: "sysmaster"
  REPODB_USER: "sysmaster"
# kubernetes/base/sysmaster/sdm.yml
          env:
            ...
            - { name: metric_retention_day, value: "14" }    # 기본값 "7"
kubectl -n sysmasterdb exec deploy/sdm -- printenv metric_retention_day
# kubernetes/base/sysmaster/sdm.yml
          env:
            ...
            - { name: "account_inactive-lock-days", value: "0" }
            - { name: "account_refresh-token-expire-days", value: "0" }
            - { name: "account_password-history-count", value: "1" }
            - { name: "account_password-change-days", value: "0" }
            - { name: "security_session_max-concurrent-sessions", value: "0" }
            - { name: "security_ip-restriction_target", value: "NONE" }
            - { name: "security_ip-restriction_super-admin-ip", value: "" }
            - { name: "security_ip-restriction_trusted-proxies", value: "127.0.0.0/8,::1,172.16.0.0/12,10.88.0.0/15" }
            - { name: "access-log_retention_day", value: "365" }
pg_superuser: "postgres"
pg_superuser_password: "postgres"
pg_data: "/pgdata"
pg_log: "/sysmaster/logs"        # 로그 볼륨 마운트 경로와 일치해야 한다
pg_users:
  - name: "sysmaster"
    pass: "sysmaster"            # setup-once.sh 의 METADB_PASSWORD 와 같은 값이어야 한다
    role_attr_flags: LOGIN
pg_databases:
  - name: metadb
    owner: sysmaster
pg_extensions:
  - name: "timescaledb"
    database: "metadb"
    state: present
  - name: "vector"
    database: "metadb"
    state: present
pg_max_connections: 100
pg_owner_id: 1000
pg_group_id: 1000

pg_multi_params:
  - name: "shared_preload_libraries"
    value: "pg_stat_statements,timescaledb"
    state: present

pg_postgres_conf_params:
  - name: "shared_buffers"
    value: "256MB"
  - name: "effective_cache_size"
    value: "768MB"
  - name: "maintenance_work_mem"
    value: "64MB"
  - name: "work_mem"
    value: "3276kB"
  - name: "log_filename"
    value: "metadb-%H%M.log"
  - name: "log_timezone"
    value: "Asia/Seoul"
  - name: "log_min_duration_statement"
    value: "2000"
  - name: "log_min_messages"
    value: "INFO"
  - name: "log_parameter_max_length"
    value: "0"
  - name: "log_rotation_age"
    value: "60"
  - name: "log_rotation_size"
    value: "100MB"
  - name: "log_truncate_on_rotation"
    value: "on"
kubectl -n sysmasterdb get svc client-gateway collector-ingest
kubectl -n sysmasterdb create secret docker-registry smdb-registry \
  --docker-server={registry} --docker-username={계정} --docker-password={암호}
patches:
  - path: gateway-lb.yml                 # [기존] 삭제하지 않는다
    target: { kind: Service, name: client-gateway }
  - path: image-pull-secret.yml          # <- 추가
    target: { kind: Deployment }
patches:
  - path: gateway-lb.yml                 # [기존] 삭제하지 않는다
    target: { kind: Service, name: client-gateway }
  - path: image-pull-policy.yml          # <- 추가
    target: { kind: Deployment }
kubectl -n sysmasterdb create secret generic smdb-https-cert \
  --from-file=sysmaster-db-server.crt={인증서 파일} \
  --from-file=sysmaster-db-server.key={개인키 파일}
patches:
  - path: gateway-lb.yml                 # [기존] 삭제하지 않는다
    target: { kind: Service, name: client-gateway }
  - path: https-cert.yml                 # <- 추가
    target: { kind: Deployment, name: client-gateway }
apiVersion: apps/v1
kind: Deployment
metadata:
  name: client-gateway
  namespace: sysmasterdb
spec:
  template:
    spec:
      volumes:
        - name: ssl
          # base의 emptyDir를 지우지 않으면 볼륨 소스가 2개가 되어 API 서버가 거부한다.
          emptyDir: null
          secret:
            secretName: smdb-https-cert
resources:
  - base                                 # [기존]
  - collector-lb.yml                     # [기존] 삭제하면 수집 진입점이 사라진다
  - logs-pvc.yml                         # <- 추가

patches:
  - path: gateway-lb.yml                 # [기존] 삭제하지 않는다
    target: { kind: Service, name: client-gateway }
  - path: logs-pvc-patch.yml             # <- 추가
    target: { kind: Deployment }
kubectl get sc            # default 표시와 ReadWriteMany 제공 StorageClass 확인
# kubernetes/logs-pvc.yml
spec:
  storageClassName: {RWX-StorageClass}     # <- 추가
  accessModes: ["ReadWriteMany"]
kubectl -n sysmasterdb exec -it deploy/smdb-logs-viewer -- sh
kubectl -n sysmasterdb exec deploy/smdb-logs-viewer -- sh -c 'tail -f /sysmaster/logs/sdm/sdm.v.*.log'
resources:
  - base                                 # [기존]
  - collector-lb.yml                     # [기존]
  - network-policy.yml                   # <- 추가
SDM_IP=$(kubectl -n sysmasterdb get pod -l app=sdm -o jsonpath='{.items[0].status.podIP}')
kubectl -n sysmasterdb exec deploy/chatbot -- python -c 'import socket,sys
ip=sys.argv[1]
for p in (8090, 8080):
    try:
        socket.create_connection((ip, p), 5).close(); print(p, "OPEN")
    except Exception as e:
        print(p, "BLOCKED", type(e).__name__)' "$SDM_IP"
rewrite name sdm sdm.sysmasterdb.svc.cluster.local

Kubernetes 환경

SysMasterDB 8.4는 Kubernetes 환경에 kustomize 기반 매니페스트로 배포된다. 배포 파일의 kubernetes 디렉터리에 전체 스택 매니페스트와 클러스터 부트스트랩 스크립트가 포함되어 있으며, kubectl apply -k 명령 한 번으로 11개 모듈이 배포된다.

구성

배포 절차

  1. 이미지 로드 및 push — 배포 파일의 이미지를 사이트 레지스트리에 등록한다.

  2. 파라미터 설정 — 레지스트리 주소, 계정 암호, 데이터베이스 초기화 설정을 지정한다.

  3. 클러스터 사전 준비 — setup-once.sh로 라이선스 Secret, 크리덴셜 Secret, DNS 설정을 등록한다.

  4. 배포 — kubectl apply -k kubernetes

  5. 접속 — LoadBalancer에 할당된 주소로 접속한다.

항목
요건

배포 파일의 kubernetes 디렉터리 구성은 다음과 같다.

각 모듈 파일은 디플로이먼트(Deployment) 1개 + 서비스(Service) 1개로 구성된다.


배포 파일은 제공된 파일 구성 그대로 사용한다. 새 파일을 만들거나 제공된 파일을 삭제·이름 변경하지 않고, 제공된 파일 안에서 파라미터 값만 수정한다. 사이트별로 달라지는 값과 그 수정 위치는 아래 표와 같다.

base 디렉터리의 파일도 아래 표에 지정된 값은 직접 수정하되, 리소스(디플로이먼트·서비스·볼륨 등)를 추가하거나 삭제하지 않는다. 별도의 patch 파일은 만들지 않으며, 선택 구성 파일(image-pull-secret.yml 등)은 이미 제공된 파일이므로 kustomization.yml에 등록만 한다. 다음 버전으로 업그레이드할 때는 새 배포 파일에 변경했던 값을 다시 반영한다.

변경 대상
수정 위치

배포는 이 파일 하나에서 시작한다. 배포 파일에 포함된 상태는 다음과 같다.


영구 볼륨 3종

PVC
크기
저장 내용
유실 시

전체 모듈이 동일한 구조를 가진다. 다음은 base/sysmaster/sdm.yml의 예시이다.


전 모듈에 3종의 헬스 체크가 설정되어 있어, kubectl get pods에서 1/1 Running으로 표시되면 실제로 요청을 처리할 수 있는 상태를 의미한다.

종류
역할
실패 시

기동 대기 한도는 periodSeconds × failureThreshold이며 모듈마다 다르다.

모듈
기동 대기 한도
확인 방식

기동이 지속적으로 실패하는 환경에서는 failureThreshold 값을 늘린다. periodSeconds는 장애 감지 속도에 영향을 주므로 변경하지 않는 것을 권장한다.


모듈
requests (메모리/CPU)
limits (메모리)
JVM 힙
  • requests 합계는 파드가 스케줄링되기 위해 노드에 남아 있어야 하는 최소 여유이다. 부족하면 파드가 Pending 상태에 머문다.

  • limits는 상한이며, 메모리가 이를 초과하면 컨테이너가 강제 종료(OOMKilled)된다.

  • CPU에는 상한을 두지 않았다. 수집이 몰리는 순간이나 기동 시 불필요하게 지연되는 것을 방지하기 위함이다.


전 모듈이 replicas: 1로 구성되어 있으며 이는 의도된 값이다.

모듈
사유

같은 이유로 위 모듈에는 strategy: Recreate가 적용되어 있다. 이 설정을 제거하면 배포가 완료되지 않거나, zookeeper의 경우 오류 없이 Kafka 메타데이터가 초기화될 수 있다. 또한 자동 확장(HPA)은 사용할 수 없다.


파일 디스크립터

nofile 65536 이상 (노드 측 설정)

라이선스

SysMasterDB 8.4용 라이선스 파일 (version="1.1")

외부 노출

LoadBalancer 또는 NodePort / Ingress

전 모듈 공통 설정

base/foundation.yml의 smdb-env

DB 초기화 계정·암호

base/meta.conf, base/repo.conf

20Gi

수집된 메트릭 전체

관제 이력이 사라진다

sdm-reports

10Gi

생성된 TPR/ASH 리포트 파일

목록에는 남지만 리포트를 열 수 없다

livenessProbe

살아 있는가

컨테이너 재시작

collector, analyzer, dbmanager, chatbot, client-gateway

20분

HTTP 또는 포트 접속

zookeeper, broker, client-tibero

2분

포트 접속(client-tibero는 HTTP /)

1Gi / 200m

6Gi

4g

sdm

1Gi / 200m

3Gi

2g

collector

1Gi / 200m

3Gi

2g

metadb

512Mi / 100m

2Gi

–

broker

1Gi / 100m

2Gi

–

dbmanager

512Mi / 100m

1Gi

640m

chatbot

256Mi / 50m

1Gi

–

zookeeper

256Mi / 50m

512Mi

–

client-gateway

64Mi / 20m

256Mi

–

client-tibero

64Mi / 20m

256Mi

–

합계

약 7.6Gi / 1.2코어

35Gi

Meta DB / Repository DB의 공유 메모리(/dev/shm, 각 1Gi / 8Gi)는 메모리 limits에 포함된다. 공유 메모리를 늘리는 경우 limits도 함께 상향해야 한다.

analyzer, collector, dbmanager, chatbot

단일 인스턴스를 전제로 sdm에 등록·동작한다

Kubernetes

이미지 pull이 가능한 컨테이너 레지스트리

StorageClass

default StorageClass (ReadWriteOnce 영구 볼륨 3종, 총 40Gi)

노드 자원

kubernetes/
├── kustomization.yml      배포 진입점. 레지스트리 주소와 외부 노출 방식을 지정한다
├── setup-once.sh          클러스터 1회 부트스트랩 (라이선스·크리덴셜 Secret, CoreDNS)
├── base/                  전체 스택 매니페스트. 파일은 추가·삭제하지 않고 값만 수정한다
│   ├── kustomization.yml    base 파일 목록
│   ├── foundation.yml       Namespace + 공통 환경변수(ConfigMap) + PVC 3개
│   ├── meta.conf            Meta DB 초기화 설정
│   ├── repo.conf            Repository DB 초기화 설정
│   ├── db/metadb.yml, db/repodb.yml
│   ├── kafka/zookeeper.yml, kafka/broker.yml
│   ├── sysmaster/sdm.yml, collector.yml, analyzer.yml, dbmanager.yml, chatbot.yml
│   └── client/client-gateway.yml, client/client-tibero.yml
├── gateway-lb.yml         사용자 UI/API를 LoadBalancer로 노출 (기본 적용)
├── collector-lb.yml       수집 포트 8292를 LoadBalancer로 노출 (기본 적용)
├── image-pull-secret.yml  [선택] 사설 레지스트리 인증
├── image-pull-policy.yml  [선택] 폐쇄망 환경의 이미지 pull 정책
├── https-cert.yml         [선택] 사이트 HTTPS 인증서 반입
├── logs-pvc.yml           [선택] 로그 영속화
├── logs-pvc-patch.yml     [선택] 위와 한 쌍
└── network-policy.yml     [선택] 파드 간 통신 제한

이미지 레지스트리 주소

kustomization.yml의 images[].newName

외부 노출 방식(LoadBalancer 등)

gateway-lb.yml, collector-lb.yml의 type

메모리·CPU 상한, 개별 환경변수

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - base                  # 전체 스택 매니페스트
  - collector-lb.yml      # 수집 포트(8292) 외부 노출

images:                   # 각 이미지의 레지스트리 주소를 사이트 값으로 교체한다
  - { name: sysmaster-db-sdm,                    newName: {registry}/sysmaster-db-sdm }
  - { name: sysmaster-db-dbmanager,              newName: {registry}/sysmaster-db-dbmanager }
  - { name: sysmaster-db-collector,              newName: {registry}/sysmaster-db-collector }
  - { name: sysmaster-db-analyzer,               newName: {registry}/sysmaster-db-analyzer }
  - { name: sysmaster-db-tiberoopensql-postgres, newName: {registry}/sysmaster-db-tiberoopensql-postgres }
  - { name: sysmaster-db-zookeeper-loggable,     newName: {registry}/sysmaster-db-zookeeper-loggable }
  - { name: sysmaster-db-kafka-loggable,         newName: {registry}/sysmaster-db-kafka-loggable }
  - { name: sysmaster-db-client,                 newName: {registry}/sysmaster-db-client }
  - { name: sysmaster-db-client-tibero,          newName: {registry}/sysmaster-db-client-tibero }
  - { name: sysmaster-db-chatbot,                newName: {registry}/sysmaster-db-chatbot }
  - { name: sysmaster-db-alpine-linux,           newName: {registry}/sysmaster-db-alpine-linux }

patches:
  - path: gateway-lb.yml                              # 사용자 UI/API 외부 노출
    target: { kind: Service, name: client-gateway }
apiVersion: v1
kind: Namespace
metadata:
  name: sysmasterdb
---
# 전 모듈이 공통으로 주입받는 환경변수.
# 값을 변경한 뒤에는 파드를 교체해야 반영된다.
#   kubectl -n sysmasterdb rollout restart deploy
# 계정 암호는 여기 두지 않는다 - setup-once.sh가 생성하는 smdb-credentials Secret이 담당한다.
apiVersion: v1
kind: ConfigMap
metadata:
  name: smdb-env
  namespace: sysmasterdb
data:
  TZ: "Asia/Seoul"
  USE_SENTRY: "false"
  DONT_CHECK_HTTP_HEALTH: "false"
  HEALTH_LOG_RETENTION_DAY: "30"
  ...
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: metadb-data
  namespace: sysmasterdb
spec:
  # storageClassName 미지정 -> 클러스터 default StorageClass로 프로비저닝된다.
  # default가 없거나 특정 StorageClass를 써야 하면 이 위치에 storageClassName: {StorageClass} 를 추가한다.
  # 미지정 상태에서 default도 없으면 PVC가 Pending에 머물고 파드가 기동하지 못한다.
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: repodb-data
  namespace: sysmasterdb
spec:
  # 수집 메트릭 저장소. 관제 대상 수와 보관 주기에 비례해 커진다.
  # 배포 후 확장은 StorageClass가 볼륨 확장을 지원할 때만 가능하므로 최초에 넉넉히 잡는다.
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 20Gi
---
# sdm이 생성하는 TPR/ASH 리포트 파일 저장소(/sysmaster/reports).
# 리포트 목록은 Meta DB에 남으므로, 파일이 사라지면 목록에는 보이는데 열리지 않는 상태가 된다.
# 반드시 영구 볼륨이어야 한다.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sdm-reports
  namespace: sysmasterdb
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 10Gi

metadb-data

10Gi

설정, 계정, 관제 대상 목록

초기 설치 상태로 돌아간다

apiVersion: apps/v1
kind: Deployment
metadata: { name: sdm, namespace: sysmasterdb }
spec:
  replicas: 1
  # 새 파드를 먼저 띄우지 않고 기존 파드를 내린 뒤 교체한다.
  # 기본값(RollingUpdate)이면 배포 중 두 파드가 잠시 공존하는데,
  # reports PVC가 ReadWriteOnce라 두 번째 파드가 볼륨을 붙지 못해 배포가 끝나지 않는다.
  strategy: { type: Recreate }
  selector: { matchLabels: { app: sdm } }
  template:
    metadata: { labels: { app: sdm } }
    spec:
      containers:
        - name: sdm
          image: sysmaster-db-sdm:{version}
          imagePullPolicy: Always
          envFrom: [{ configMapRef: { name: smdb-env } }]   # 공통 설정 일괄 주입
          env:
            # JVM 힙. 아래 메모리 limits의 약 2/3이며, limits를 조정하면 함께 변경한다.
            - { name: java_heap_size_max, value: "2g" }
            - { name: java_heap_size_min, value: "512m" }
            - { name: spring_datasource_hikari_jdbc-url, value: "jdbc:postgresql://metadb:5432/metadb" }
            - { name: spring_datasource_hikari_username, value: "sysmaster" }
            # 암호는 매니페스트에 두지 않고 Secret에서 참조한다.
            - { name: spring_datasource_hikari_password,
                valueFrom: { secretKeyRef: { name: smdb-credentials, key: METADB_PASSWORD } } }
            - { name: metric_retention_day, value: "7" }    # 수집 메트릭 보관 주기(일)
            - { name: logging_file_max-history, value: "30" }  # 로그 보관 일수
            - { name: logging_file_max-size, value: "20MB" }
            - { name: logging_file_total-size-cap, value: "1GB" }
            # 업그레이드 시 수행되는 데이터 마이그레이션 패치 제어.
            # 문제가 발생하면 해당 패치만 즉시 비활성화할 수 있다.
            #   kubectl -n sysmasterdb set env deploy/sdm patch_v8-2-1-to-v8-3-0-migration_skip=true
            - { name: "patch_v8-2-1-to-v8-3-0-migration_skip", value: "false" }
          ports:
            - { containerPort: 8090 }   # 내부 통신용
            - { containerPort: 8080 }   # 사용자 API용
          # 기동이 완료될 때까지 readiness/liveness를 유예한다(기동 중 재시작 방지).
          # 8080이 아니라 8090을 확인하는 이유: 8080에는 라이선스 상태 필터가 있어
          # 라이선스 만료·코어 초과 시 401을 반환하며, 이 경우 정상 동작 중인 파드가
          # 재시작되고 재기동도 실패해 복구가 불가능해진다.
          startupProbe:
            httpGet:
              path: /actuator/health
              port: 8090
              httpHeaders: [{ name: Authorization, value: smdb-internal }]
            periodSeconds: 5
            failureThreshold: 180       # 대기 한도 15분 (5초 x 180)
          readinessProbe:               # 실패 시 트래픽만 차단, 재시작하지 않는다
            httpGet:
              path: /actuator/health
              port: 8090
              httpHeaders: [{ name: Authorization, value: smdb-internal }]
            periodSeconds: 10
            failureThreshold: 3
          livenessProbe:                # 실패 시 컨테이너를 재시작한다
            httpGet:
              path: /actuator/health
              port: 8090
              httpHeaders: [{ name: Authorization, value: smdb-internal }]
            periodSeconds: 20
            failureThreshold: 6
          resources:
            requests: { memory: 1Gi, cpu: 200m }   # 스케줄링에 필요한 예약량
            limits:   { memory: 3Gi }              # 초과 시 컨테이너가 강제 종료(OOMKilled)된다
          volumeMounts:
            - { name: license, mountPath: /sysmaster/license }
            - { name: reports, mountPath: /sysmaster/reports }
            # subPath로 모듈별 하위 디렉터리에 기록한다. 로그 영속화(선택 구성) 시
            # 모듈 간 로그 파일명이 겹치는 것을 방지한다.
            - { name: logs, mountPath: /sysmaster/logs, subPath: sdm }
      volumes:
        # setup-once.sh가 생성한 라이선스 Secret. 없으면 sdm이 기동하지 못한다.
        - { name: license, secret: { secretName: sdm-license } }
        - { name: reports, persistentVolumeClaim: { claimName: sdm-reports } }
        # 로그는 파드 내부 임시 볼륨. 컨테이너가 재시작해도 남지만 파드가 교체되면 사라진다.
        - { name: logs, emptyDir: {} }
---
apiVersion: v1
kind: Service
metadata: { name: sdm, namespace: sysmasterdb }
spec:
  selector: { app: sdm }
  ports:
    - { name: master, port: 8090, targetPort: 8090 }
    - { name: http,   port: 8080, targetPort: 8080 }

startupProbe

기동이 완료되었는가

한도 초과 시 컨테이너 재시작

readinessProbe

지금 요청을 받을 수 있는가

metadb, repodb

10분

헬스 응답 본문 확인(최초 기동은 DB 생성으로 수 분)

sdm

15분

repodb

2Gi / 200m

16Gi

–

sdm, metadb, repodb

영구 볼륨이 ReadWriteOnce — 두 번째 파드가 볼륨을 붙지 못한다

broker

브로커 ID가 고정되어 있어 두 파드가 동일 ID로 등록할 수 없다

zookeeper

사전 요구사항

매니페스트 구성

참고

매니페스트 파일에는 주석이 없다. 배포 환경의 터미널에서 문자가 정상적으로 표시되지 않는 경우가 있어, 설정값에 대한 설명은 모두 이 매뉴얼에 수록하였다. 아래 예시의 주석은 설명을 위해 추가한 것이다.

1. 수정 위치 원칙

2. kustomization.yml

주의 — resources: patches: images:는 파일에 한 번씩만 작성한다.

선택 구성의 예시를 파일 끝에 그대로 덧붙이면 같은 키가 두 번 생기고, kustomize는 오류나 경고 없이 마지막 것만 적용한다. 앞에 있던 항목은 조용히 사라진다.

  • patches:를 새로 작성하면 → gateway-lb.yml이 무효화되어 UI가 외부에 노출되지 않는다.

  • resources:를 새로 작성하면 → collector-lb.yml이 무효화되어 수집 경로가 사라진다.

  • images:를 새로 작성하면 → 나머지 이미지의 레지스트리 주소가 사라져 전체 파드가

항상 기존 키의 목록 아래에 항목만 추가한다. 수정 후에는 아래로 확인한다.

3. foundation.yml — 네임스페이스 · 공통 설정 · 영구 볼륨

4. 모듈 매니페스트 읽는 법

주의

Kubernetes에서는 서비스(Service)에 정의된 포트로만 다른 파드에 접근할 수 있다. 컨테이너가 열어둔 포트라도 서비스에 없으면 다른 모듈이 접근하지 못한다. Meta DB / Repository DB 서비스에 헬스 확인용 7000 포트가 함께 정의되어 있는 것도 같은 이유이며, 이 포트를 제거하면 sdm이 DB 준비 상태를 확인하지 못해 계속 대기한다.

5. 헬스 체크(probe)

6. 자원 할당

주의

JVM을 사용하는 모듈(sdm, analyzer, collector, dbmanager)은 메모리 limits와 java_heap_size_max를 함께 조정해야 한다. limits만 낮추면 JVM이 힙을 확장하다 컨테이너 한도를 넘어 강제 종료된다.

7. 모듈을 2개 이상으로 늘릴 수 없는 이유

SysMasterDB 8.4 Kubernetes 구성도

메모리 16GB 이상, CPU 4코어 이상 권장

각 모듈 매니페스트(base/sysmaster/sdm.yml 등)의 resources, env

repodb-data

서비스에서 트래픽만 차단 (재시작 없음)

HTTP /actuator/health (8090)

analyzer

단일 노드 구성 — 두 파드가 동시에 기동하면 broker의 접속 대상이 불확정해진다

ImagePullBackOff
상태가 된다.
kubectl kustomize kubernetes | grep -c 'type: LoadBalancer'       # 2
kubectl kustomize kubernetes | grep -c 'name: collector-ingest'   # 1