Kubernetes 모드 설치
모든 핵심 문서를 확인했습니다. 이제 상세한 답변을 작성합니다.
exemONE Kubernetes 모드 신규 설치 가이드
참고 문서:
1. 시스템 요구사항
1-1. 서버 사양
| 구분 | CPU | Memory | SSD - Storage(월) |
|---|---|---|---|
| 최소 | 8 core | 16 GB | 0.5 TB |
| 권장 | 16 core | 32 GB | 1 TB |
인스턴스 개수별 사양:
| 인스턴스 | CPU | Memory | Storage(월) |
|---|---|---|---|
| 5개 | 2 core | 4 GB | 125GB |
| 10개 | 4 core | 8 GB | 250GB |
| 20개 | 8 core | 16 GB | 0.5 TB |
| 40개 | 16 core | 32 GB | 1 TB |
- HDD의 경우 성능이 심하게 떨어지기 때문에 SSD 권장
- 디스크 사용량은 모니터링 대상과 수집 양에 따라 다를 수 있으므로, 구축 후 일별 사용량을 체크하여 필요 시 디스크 증설 또는 보관 주기 수정 필요
1-2. 지원 환경
| 항목 | 내용 |
|---|---|
| 실행 환경 | Kubernetes 클러스터 (docker 또는 containerd 런타임) |
| 설치 파일 | exemone-kubernetes-pkg-{version}.tar.gz |
| 설치 명령어 | sh generate.sh → sh apply.sh |
| 관리 도구 | kubectl 명령어 |
2. 포트 정보
| Target | 출발지 | 도착지 | Type | Port | 포트 사용 내용 |
|---|---|---|---|---|---|
| exem-host-agent | unix 장비 | Receiver | TCP | 9010 | 범용 TCP 요청 및 응답 |
| exem-host-agent | linux, windows 장비 | Receiver | gRPC | 9009 | 범용 gRPC 요청 및 응답 |
| exem-k8s-agent | 모니터링 대상 장비 | Receiver | gRPC | 9009 | 범용 gRPC 요청 및 응답 |
| exem-container-agent | 모니터링 대상 장비 | Receiver | gRPC | 9009 | 범용 gRPC 요청 및 응답 |
| exem-db-agent | 수집 서버 | Target DB | TCP | DB Listener Port | DB 지표 수집 |
| exem-java-agent | 모니터링 대상 장비 | Receiver | TCP | 9010 | 범용 TCP 요청 및 응답 |
| Cloud | - | Receiver | TCP | 443 | 클라우드 데이터 수집 |
| 모니터링 사용자 PC | 사용자 PC | Gateway | HTTPS | 8443 | WEB UI 접속 포트 |
| HTTP | 8080 | WEB UI 접속 포트 | |||
| ClickHouse | TCP | 8123 | 수집 데이터 저장 | ||
| PostgreSQL | TCP | 5432 | 메타 데이터 저장 |
3. 수집 서버 모듈 구성 (총 16개)

설치 후 kubectl get pods로 확인 시, 모든 Pod가 Running 상태여야 합니다.
4. 핵심 제약조건
exemone-api와 exemone-receiver Pod는 반드시 동일한 Node에서 실행되어야 합니다.
이를 위해 Worker Node에 라벨을 설정하고, Deployment의 nodeSelector로 제어합니다.
라벨 설정:
kubectl label nodes worker-node1 workload=exemone-k8s
Deployment nodeSelector 설정 (파일: {SET_NAME}/deployment.yaml):
...
spec:
selector:
matchLabels:
app: exemone-receiver
replicas: 1
template:
...
spec:
nodeSelector:
workload: exemone-k8s # 또는 kubernetes.io/hostname: worker-node1
...
5. Kubernetes 모드 신규 설치 절차 (단계별)
[Phase 1] 사전 설정
단계 1. Storage Class 생성
exemONE 서비스 데이터를 저장할 Storage Class가 미리 생성되어 있어야 합니다.
StorageClass 매니페스트 예시:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage-exemone-k8s
provisioner: rancher.io/local-path
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
kubectl apply -f storageclass.yaml
단계 2. Namespace 생성
exemONE 서비스를 실행할 Namespace를 생성합니다.
kubectl create namespace exemone-k8s
단계 3. Worker Node 라벨 설정 (제약조건 적용)
api와 receiver가 동일 노드에서 실행되도록 라벨을 설정합니다.
kubectl label nodes worker-node1 workload=exemone-k8s
[Phase 2] 패키지 압축 해제
단계 1. 패키지 파일 압축 해제
tar xvzf exemone-kubernetes-pkg-v3.0.1.0.tar.gz

단계 2. installer 폴더로 이동 후 내부 패키지 압축 해제
cd exemone-kubernetes/installer
tar xvzf exemone-kubernetes.tar.gz
단계 3. exemone-kubernetes 폴더로 이동
cd exemone-kubernetes
[Phase 3] 이미지 로드
exemONE 서비스를 사용할 모든 Node에 이미지를 로드해야 합니다.
- 이미지 폴더 위치:
exemone-kubernetes/image/
Docker 사용 시:
docker load -i <이미지>.tar.gz
# 예시) docker load -i bitnami-kafka-3.3.2-debian-11-r5.tar.gz
# 이미지 로드 검증
docker images | grep exemone
containerd 사용 시:
namespace의 경우,
k8s.io가 일반적이나 환경에 따라 다를 수 있습니다.
ctr -n k8s.io images import <이미지>.tar.gz
# 예시) ctr -n k8s.io images import bitnami-kafka-3.3.2-debian-11-r5.tar.gz
# 이미지 로드 검증
ctr -n k8s.io images ls | grep exemone
containerd에서 invalid tar header 에러 발생 시:
gunzip -k <이미지>.tar.gz # gzip 압축 해제
ctr -n k8s.io images import <이미지>.tar
# 예시
gunzip -k bitnami-kafka-3.3.2-debian-11-r5.tar.gz
ctr -n k8s.io images import bitnami-kafka-3.3.2-debian-11-r5.tar
[Phase 4] 수집 모듈 설치
스크립트 실행 위치: exemone-kubernetes/installer/exemone-kubernetes
단계 1. generate.sh 실행 (yaml 파일 생성)
generate.sh는 templates 폴더 내 yaml 파일을 사용하여 exemONE 수집 모듈 생성을 위한 yaml 파일을 신규 생성합니다.
sh generate.sh
실행 시 입력하는 설정 옵션:
Please enter set name: exemone
Please enter namespace: exemone-k8s
Please enter cluster domain: cluster.local
Please enter storage class name: local-storage-exemone-k8s
create yaml files
Directory exemone created
Files copied
replace variables in yaml files
done!
| 설정 옵션 | 설명 |
|---|---|
| SET NAME | 희망하는 폴더 이름 (해당 폴더에 yaml 파일이 생성됨) |
| NAMESPACE | 설치할 네임스페이스 |
| CLUSTER_DOMAIN | 클러스터 도메인 (일반적으로 cluster.local) |
| STORAGE_CLASS_NAME | PV 생성에 사용할 Storage Class (사전 설정 필요) |
generate.sh실행 후 SET_NAME으로 지정한 폴더 안에 다음과 같은 yaml 파일들이 생성됩니다:deployment.yaml,statefulset.yaml,pvc.yaml,service.yaml,configmap.yaml등
단계 2. apply.sh 실행 (설치)
SET_NAME 폴더에 있는 yaml 파일들을 Kubernetes 클러스터에 apply합니다.
sh apply.sh
Please enter set name: exemone
persistentvolumeclaim/exemone-db-agent-configs created
persistentvolumeclaim/exemone-db-agent-logs created
persistentvolumeclaim/exemone-db-agent-queries created
persistentvolumeclaim/exemone-cloud-agent-configs created
persistentvolumeclaim/exemone-cloud-agent-logs created
persistentvolumeclaim/exemone-cloud-agent-queries created
persistentvolumeclaim/exemone-receiver-logs created
persistentvolumeclaim/exemone-core-logs created
persistentvolumeclaim/exemone-core-db created
persistentvolumeclaim/exemone-alerter-logs created
persistentvolumeclaim/exemone-ingester-logs created
[Phase 5] 설치 확인
단계 1. Pod 및 PVC 배포 확인
kubectl get pods -n exemone-k8s
kubectl get pvc -n exemone-k8s
예상 결과:
[root@localhost ~]# kubectl get pods -n exemone-k8s
NAME READY STATUS RESTARTS AGE
exem-container-agent-2hktr 1/1 Running 0 119m
exem-container-agent-72948 1/1 Running 0 119m
...
[root@localhost ~]# kubectl get pvc -n exemone-k8s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
exemone-alerter-logs Bound pvc-92108ca2-ddc3-4d8c-b54c-6ec352b7abb8 512Mi RWO local-storage-exemone-k8s 4h1m
exemone-api-class Bound pvc-c54d63b2-79d6-48b0-a661-e4959366a59a 512Mi RWO
...
단계 2. exemone-api와 exemone-receiver 동일 노드 배포 검증
kubectl get pods -n exemone-k8s -o wide | grep -E 'exemone-api|exemone-receiver'
예상 결과 (동일 Node 확인):
exemone-api-6d66444566-trzdp 1/1 Running 0 4h2m 10.244.2.22 worker-node1 <none> <none>
exemone-receiver-95d99f5bb-g9wfz 1/1 Running 0 4h2m 10.244.2.18 worker-node1 <none> <none>
두 Pod가 동일한 worker-node1에서 실행되고 있으면 정상입니다.
6. 매니페스트(YAML) 설정 상세
6-1. 생성되는 주요 YAML 파일
generate.sh 실행 시 templates 폴더의 yaml 파일을 기반으로, 입력한 변수값이 치환되어 {SET_NAME} 폴더에 yaml 파일이 생성됩니다.
치환되는 변수 목록:
| 변수 | 설명 |
|---|---|
${namespace} | Namespace |
${clusterDomain} | 클러스터 도메인 |
${storageClassName} | Storage Class 이름 |
${dbAgentVersion} | exemone-db-agent 이미지 버전 |
${receiverVersion} | exemone-receiver 이미지 버전 |
${coreVersion} | exemone-core 이미지 버전 |
${alerterVersion} | exemone-alerter 이미지 버전 |
${ingesterVersion} | exemone-ingester 이미지 버전 |
${gatewayVersion} | exemone-gateway 이미지 버전 |
${apiVersion} | exemone-api 이미지 버전 |
${frontVersion} | exemone-front 이미지 버전 |
${nginxVersion} | exemone-nginx 이미지 버전 |
${postgresqlVersion} | exemone-postgresql 이미지 버전 |
${clickhouseVersion} | exemone-clickhouse 이미지 버전 |
${redisVersion} | exemone-redis 이미지 버전 |
${kafkaVersion} | exemone-kafka 이미지 버전 |
6-2. StorageClass 매니페스트 예시
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage-exemone-k8s
provisioner: rancher.io/local-path
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
6-3. StatefulSet 매니페스트 예시 (PostgreSQL)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: exemone-postgresql
namespace: ${namespace}
labels:
io.exem: "true"
io.exem.prod: exemone
io.exem.one.type: middleware
io.exem.one.app: postgresql
spec:
selector:
matchLabels:
app: exemone-postgresql
serviceName: "exemone-postgresql"
replicas: 1
template:
metadata:
labels:
app: exemone-postgresql
spec:
volumes:
- name: exemone-postgresql-initdbd
configMap:
name: exemone-postgresql-initdbd
defaultMode: 420
- name: exemone-postgresql-data
persistentVolumeClaim:
claimName: exemone-postgresql-data
containers:
- name: exemone-postgresql
image: maxgauge/exemone-postgres:${postgresqlVersion}
ports:
- name: postgres
containerPort: 5432
protocol: TCP
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: exemone-postgresql-password
key: password
volumeMounts:
- name: exemone-postgresql-initdbd
mountPath: /docker-entrypoint-initdb.d
- name: exemone-postgresql-data
mountPath: /var/lib/postgresql/data/pgdata
resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "4"
memory: "10Gi"
imagePullSecrets:
- name: regcred
6-4. Deployment nodeSelector 설정 (api/receiver 동일 노드 배포)
spec:
selector:
matchLabels:
app: exemone-receiver
replicas: 1
template:
spec:
nodeSelector:
workload: exemone-k8s # 또는 kubernetes.io/hostname: worker-node1
6-5. .env 파일 (모듈 버전 관리)
파일 위치: exemone-kubernetes/installer/exemone-kubernetes/.env

.env 파일에서 각 모듈의 이미지 버전을 관리하며, 모듈 패치 시 이 파일의 버전을 변경한 후 apply.sh를 재실행합니다.
7. bash 스크립트를 실행할 수 없는 환경
generate.sh / apply.sh를 실행할 수 없는 경우, templates/ 폴더 아래 yaml 파일에서 위 변수 문자열을 수동으로 치환하여 각 오브젝트를 kubectl apply -f로 직접 적용할 수 있습니다.
8. 수집 모듈 삭제
스크립트 실행 위치: exemone-kubernetes/installer/exemone-kubernetes
sh delete.sh
apply.sh에서 적용한 모든 exemONE 서비스 모듈 및 데이터가 삭제됩니다.- SET_NAME으로 생성한 폴더 내의 YAML 파일도 함께 삭제됩니다.
데이터(PVC) 유지가 필요한 경우
delete.sh 파일에서 아래 라인을 주석 처리해야 합니다:
# kubectl delete -f ./$SET_NAME/pvc.yaml
9. 모듈 패치 방법
9-1. 개별 모듈 패치
- 이미지 로드: 모든 Node에 신규 이미지 로드
- .env 파일 수정: 패치할 모듈의 버전 정보를 변경
vi exemone-kubernetes/installer/exemone-kubernetes/.env
- apply.sh 실행:
sh apply.sh
- 정상 구동 확인:
kubectl get pods -n exemone-k8s
상세 가이드: Kubernetes 모듈 패치 가이드
9-2. 패키지 패치 (template/script 변경 포함)
신규 패치 버전에서 template이나 script 파일이 변경된 경우 아래 절차를 따릅니다:
- 기존 홈 디렉토리 백업:
mv exemone-kubernetes exemone-kubernetes.bak
- 신규 패키지 압축 해제:
tar -xzvf exemone-kubernetes-pkg-v3.0.508.21.tar.gz
- 모든 Node에 이미지 로드
- 기존 디렉토리에서 StorageClass 확인:
cd exemone-kubernetes.bak/installer/exemone-kubernetes
cat exemone/pvc.yaml | grep -m 1 storageClassName
- 기존 YAML에서 사용자가 수정한 부분(NodeSelector, 리소스 제한 등)을 신규 templates에 반영
generate.sh실행 →apply.sh실행
상세 가이드: Kubernetes 패키지 패치 가이드
10. PostgreSQL 13→17 업데이트 (선택사항)
exemONE의 PostgreSQL을 13에서 17로 업데이트하는 경우 아래 절차를 따릅니다.
주의사항:
delete.sh실행 시 기존 데이터가 삭제되므로 권장하지 않습니다- Pod 재생성 시 기존 PVC와 동일한 Node에서 실행되어야 합니다
- 수집 모듈 패치와 함께 진행 시, 수집 모듈 패치 후 PostgreSQL 업데이트 진행
- 반드시 최신 패키지 파일에서 진행 필요
업데이트 절차 요약:
- exemone-postgresql의 Pod, StatefulSet 이름 확인
- exemone-api의 Pod, Deployment 이름 확인
- exemone-api Pod 정지 (replicas 0):
kubectl -n <namespace> scale deploy <deploy 이름> --replicas 0
- PostgreSQL 데이터 백업:
kubectl -n <namespace> exec <postgres 파드> -- pg_dumpall -U postgres > pg13_dump.sql
- PG 기존 PVC 유지 (제거하지 않음)
- exemone-postgresql StatefulSet 제거:
kubectl -n <namespace> delete statefulset <statefulset 이름>
- PVC 이름 변경하여 추가 (
exemone-postgresql-data-17) - StatefulSet 수정 (volume, volumeMounts 이름 변경)
generate.sh→ PVC 생성 → StatefulSet 생성- 데이터 복원:
kubectl cp ./pg13_dump.sql <namespace>/<postgres 파드>:/tmp/pg13_dump.sql
kubectl -n <namespace> exec -it <postgres 파드> -- psql -U postgres -f /tmp/pg13_dump.sql
- exemone-api 재시작:
kubectl -n <namespace> scale deploy exemone-api --replicas 1
11. 설치 후 정상 작동 확인 리스트
11-1. Pod 상태 확인
kubectl get pods -n exemone-k8s
- 모든 Pod가 Running 상태인지 확인
- RESTARTS 횟수가 계속 증가하지 않는지 확인
11-2. api/receiver 동일 노드 확인
kubectl get pods -n exemone-k8s -o wide | grep -E 'exemone-api|exemone-receiver'
11-3. 비정상 Pod 로그 확인
Pod가 CrashLoopBackOff 등 비정상 상태인 경우:
kubectl logs -n exemone-k8s <Pod 이름>
11-4. 웹 화면 접속 확인
- 브라우저에서
https://[Gateway 서비스 IP]:8443또는http://[Gateway 서비스 IP]:8080으로 접속 - 로그인이 정상적으로 되는지 확인
- 로그인 실패 시
exemone-apiPod 로그 확인 필요
11-5. 에이전트 상태 확인
- HOST 기본 뷰: Active / Inactive 상태 확인

- Database 기본 뷰: Active / No Signal 상태 확인

- Kubernetes Pod 뷰: Running 상태 확인

- WAS 기본 뷰: Active 상태 확인

inactive 또는 nosignal인 경우, 수집서버 ↔ 타겟 서버 간 네트워크 및 포트(9009/9010) 방화벽 확인이 필요합니다.
12. Helm Chart 관련
참고 문서에서 확인한 바에 따르면, exemONE Kubernetes 설치는 Helm Chart 방식이 아닌 자체 스크립트 기반(generate.sh + apply.sh)으로 YAML 매니페스트를 생성·배포하는 방식을 사용합니다. generate.sh가 templates 폴더의 YAML 파일에 변수를 치환하여 배포용 YAML을 생성하는 역할을 하므로, Helm의 템플릿 렌더링과 유사한 기능을 수행합니다.
13. 주의사항
- 제약조건 필수: exemone-api와 exemone-receiver Pod는 반드시 동일 Node에 배포해야 합니다. nodeSelector 또는
kubernetes.io/hostname라벨로 제어하세요. - SSD 필수: HDD 사용 시 심각한 성능 저하가 발생합니다.
- 모든 Node에 이미지 로드: 이미지는 서비스를 사용할 모든 Worker Node에 로드해야 합니다.
- Storage Class 사전 생성:
generate.sh실행 전에 Storage Class가 반드시 존재해야 합니다. - Namespace 사전 생성:
apply.sh실행 전에 Namespace가 반드시 존재해야 합니다. - 패키지 파일 준비: 설치 파일(
exemone-kubernetes-pkg-{version}.tar.gz)은 제품기술팀에 문의하여 준비합니다. - delete.sh 사용 주의: PVC 데이터를 유지하려면 반드시
kubectl delete -f ./$SET_NAME/pvc.yaml라인을 주석 처리한 후 실행하세요. - PostgreSQL 업데이트 순서: 수집 모듈 패치와 함께 진행 시, 수집 모듈 패치를 먼저 진행한 후 PostgreSQL 업데이트를 진행해야 합니다.
- containerd 환경: containerd 사용 시 이미지 import에
ctr -n k8s.io images import명령어를 사용하되,invalid tar header에러 발생 시gunzip으로 압축 해제 후.tar파일로 import하세요.