본문으로 건너뛰기

Container Host Agent 설치 및 파라미터

K8s/컨테이너 환경의 OS 레벨 메트릭을 수집하는 에이전트이다. oshi-core(pure Java) 라이브러리를 사용하여 네이티브 의존 없이 동작한다.


1. 개요

항목내용
배포 위치K8s Pod 내 (/opt/flowkat/agent.host.container)
프로세스 형태독립 JVM 데몬 프로세스
의존 모듈Collect Server TCP 6100 연결 필요
시스템 라이브러리oshi-core (pure Java, 네이티브 불필요)
로그 위치$AGENT_HOME/logs/

2. 필수 설정 (P0)

파라미터타입기본값conf 키중요도설명
net_collector_ipString127.0.0.1net_collector_ip필수수집 서버 IP. K8s 환경에서는 수집 서버 Service IP 또는 ClusterIP.
net_collector_tcp_portint6100net_collector_tcp_port필수수집 서버 TCP 포트.
obj_nameString""obj_name필수오브젝트 이름. K8s에서는 Pod 이름 기반 자동 생성.
monitoring_group_typeString""monitoring_group_type필수모니터링 그룹 타입.

3. 운영 튜닝 (P1 핵심)

파라미터타입기본값conf 키중요도설명
net_collector_tcp_session_countint1net_collector_tcp_session_count핵심TCP 세션 수.
net_collector_tcp_so_timeout_msint60000net_collector_tcp_so_timeout_ms핵심TCP 소켓 타임아웃(ms).
net_collector_tcp_connection_timeout_msint3000net_collector_tcp_connection_timeout_ms핵심TCP 연결 타임아웃(ms).
disk_warning_pctint70disk_warning_pct핵심디스크 경고 임계치(%).
disk_fatal_pctint90disk_fatal_pct핵심디스크 치명 임계치(%).
disk_ignore_size_gbint9000disk_ignore_size_gb핵심디스크 무시 크기(GB). 대형 스토리지 마운트 제외용.
cpu_warning_pctint70cpu_warning_pct핵심CPU 경고 임계치(%).
cpu_fatal_pctint90cpu_fatal_pct핵심CPU 치명 임계치(%).
mem_warning_pctint80mem_warning_pct핵심메모리 경고 임계치(%).
mem_fatal_pctint90mem_fatal_pct핵심메모리 치명 임계치(%).
log_keep_daysint365log_keep_days핵심로그 보관일.

K8s 전용 설정

파라미터타입기본값conf 키중요도설명
kubeboolean(자동감지)kube고급K8s 환경 여부. 자동 감지되나 수동 설정 가능.
kube_pod_sequence_name_enabledbooleantruekube_pod_sequence_name_enabled고급K8s Pod 순차 이름 사용. 수집 서버의 kube_pod_seq_heartbeat_ttl_ms와 연동.
kube_pod_sequence_name_min_lengthint18kube_pod_sequence_name_min_length고급Pod 이름 최소 길이 기준.

전체 파라미터 목록은 parameter-inventory.md 참조.


4. 설치 절차

사전 요건

  • Java 8 이상
  • Collect Server 기동 및 TCP 6100 포트 개방
  • K8s Pod에서 수집 서버 네트워크 접근 가능

설치 단계

# 1. 에이전트 디렉토리를 컨테이너 이미지에 포함하거나 Pod에 복사
cp -r agent.host.container /opt/flowkat/agent.host.container

# 2. 설정 파일 수정
vi /opt/flowkat/agent.host.container/conf/flowkat.conf

# 3. 기동
sh /opt/flowkat/agent.host.container/host.sh

# 4. 기동 확인
tail -f /opt/flowkat/agent.host.container/logs/flowkat.log

5. 설정 파일 예시

# /opt/flowkat/agent.host.container/conf/flowkat.conf

# P0: 수집 서버
net_collector_ip=10.96.0.100
net_collector_tcp_port=6100

# P0: 식별
monitoring_group_type=K8S-WORKER

# P1: 알림 임계치
cpu_warning_pct=80
mem_warning_pct=85

6. 주의사항

상황주의 내용
Host Agent와 구분물리/VM 서버에는 agent.host(sigar JNI), K8s 환경에는 agent.host.container(oshi-core pure Java)를 사용한다.
netstat 부하counter_netstat_enabled=true(기본). 대규모 클러스터에서 부하 발생 시 false 설정 검토.
Pod 순차 번호kube_pod_sequence_name_enabled=true 시 수집 서버가 Pod별 순차 번호를 부여. TTL은 수집 서버의 kube_pod_seq_heartbeat_ttl_ms(기본 120초)로 관리.
log_rotation 하위 호환log_rotation_enabled(정식 키) + log_rotation_enalbed(Host Agent 오타 폴백) 양쪽 지원. 신규 설정 시 log_rotation_enabled 사용 권장.

7. 관련 문서


8. Container 에이전트 사양

Container 에이전트는 oshi-core(pure Java)를 사용하므로 네이티브 JNI 라이브러리가 없다. K8s Pod 내에서 독립 JVM 데몬으로 동작한다.

리소스항목추정값비고
메모리JVM 힙 (기본)256~512 MB (JVM 자동 결정)-Xmx 미지정. K8s resources.limits.memory 설정으로 상한 제어 권장
메모리oshi-core 객체 캐시+10~20 MBOS 정보 캐싱
메모리실제 RSS (정상 동작 시)~120~180 MBMetaspace + Heap + oshi 객체 합산
CPUK8s API 호출 없음 (cgroups 직접 읽기)< 0.1%/sys/fs/cgroup 파일 직접 파싱. K8s API 호출 없음
CPUoshi-core 수집 주기< 0.2%CPU·메모리·디스크·네트워크 주기 수집
Pod 리소스requests.memory128 Mi정상 가동 최소 기준
Pod 리소스limits.memory256 MiOOMKill 방지 상한
Pod 리소스requests.cpu50 m평상시 점유율 기준
Pod 리소스limits.cpu200 m버스트 허용 상한
디스크로그 위치$AGENT_HOME/logs/컨테이너 에이전트/conf/flowkat.conflog_dir로 변경 가능
디스크emptyDir 사용량 (PodSeqManager 데이터)< 1 MBK8s Pod 순차 번호(kube_pod_sequence_name_enabled=true) 관리 데이터. Pod 재시작 시 초기화됨
네트워크Counter 전송 대역폭< 1 KB/초Collect Server TCP 6100 연결

9. Kubernetes 환경 트러블슈팅

K8s 환경별 알려진 이슈

#증상원인해결
K-1CNI 호환성 문제 (Calico, Cilium)CNI 네트워크 정책이 에이전트 TCP 통신 차단NetworkPolicy 예외 추가
K-2istio sidecar 환경에서 에이전트 연결 실패initContainer가 istio proxy 초기화 전에 연결 시도holdApplicationUntilProxyStarts 설정
K-3Pod 재시작 시 에이전트 식별 변경PodSeqManager 순차 번호 재할당PodSeqManager 동작 원리 참조
K-4emptyDir 용량 초과에이전트 로컬 버퍼 누적로그 로테이션 단축, 볼륨 분리
K-5CrashLoopBackOff에서 에이전트 데이터 유실Pod 비정상 종료 시 미전송 데이터 손실graceful shutdown 설정

K-1: CNI 호환성 문제 (Calico, Cilium)

증상: FlowKat 대시보드에서 Container Host Agent가 "연결 끊김" 상태로 표시된다. 에이전트 로그에 Connection refused 또는 Connection timed out이 반복 출력된다.

원인: Calico, Cilium 등 CNI 플러그인의 NetworkPolicy가 기본적으로 Pod 간 TCP 통신을 차단한다. 에이전트가 Collect Server(TCP 6100)에 연결을 시도하지만 정책에 의해 드롭된다.

확인 방법:

# 에이전트 Pod 로그에서 연결 오류 확인
kubectl logs <agent-pod-name> -n <namespace> | grep -E "Connection|refused|timeout"

# NetworkPolicy 목록 확인
kubectl get networkpolicy -n <namespace>

# Pod에서 직접 연결 테스트
kubectl exec -it <agent-pod-name> -n <namespace> -- \
nc -zv <collect-server-service-ip> 6100

해결 방법: Collect Server로의 이그레스(egress)를 허용하는 NetworkPolicy를 추가한다.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-flowkat-agent-egress
namespace: <namespace>
spec:
podSelector:
matchLabels:
app: flowkat-agent-container
policyTypes:
- Egress
egress:
- ports:
- protocol: TCP
port: 6100

관련 문서: 17.network-ports.md — 포트 목록 및 방화벽 설정


K-2: istio sidecar 환경에서 에이전트 연결 실패

증상: istio가 활성화된 네임스페이스에서 에이전트 Pod가 기동 직후 ECONNREFUSED 오류를 반복하다가 결국 정상 연결된다. 또는 초기화 중 완전히 연결 실패로 종료된다.

원인: 에이전트 JVM이 istio sidecar(istio-proxy) 컨테이너보다 먼저 기동되어 TCP 아웃바운드 연결을 시도한다. istio proxy가 준비되기 전에는 모든 이그레스 트래픽이 차단된다.

확인 방법:

# Pod 이벤트에서 컨테이너 기동 순서 확인
kubectl describe pod <agent-pod-name> -n <namespace>

# istio-proxy 준비 상태 확인
kubectl get pod <agent-pod-name> -n <namespace> \
-o jsonpath='{.status.containerStatuses[*].name} {.status.containerStatuses[*].ready}'

# istio sidecar 로그에서 초기화 타이밍 확인
kubectl logs <agent-pod-name> -n <namespace> -c istio-proxy | head -30

해결 방법: holdApplicationUntilProxyStarts 옵션을 활성화하여 istio proxy가 준비된 이후에 애플리케이션 컨테이너가 기동되도록 한다.

ConfigMap 전역 설정:

apiVersion: v1
kind: ConfigMap
metadata:
name: istio
namespace: istio-system
data:
mesh: |
defaultConfig:
holdApplicationUntilProxyStarts: true

Pod 단위 annotation 적용:

apiVersion: v1
kind: Pod
metadata:
annotations:
proxy.istio.io/config: |
holdApplicationUntilProxyStarts: true

K-3: Pod 재시작 시 에이전트 식별 변경 (PodSeqManager 동작 원리)

증상: FlowKat 대시보드에서 같은 Deployment의 Pod가 재시작될 때마다 새로운 오브젝트로 등록된다. myapp-pod_0, myapp-pod_rnd123456 형태가 혼재한다.

원인 — PodSeqManager 동작 원리: kube_pod_sequence_name_enabled=true(기본값) 상태에서 에이전트는 수집 서버로부터 순차 번호(seqNoForKube)를 받아 오브젝트 이름을 {podName}_{seq} 형태로 구성한다.

수집 서버로부터 순차 번호를 받기 전 초기화 구간에는 {podName}_rnd{randomNo} 임시 이름을 사용한다(설정 파일). 순차 번호 할당 흐름:

  1. 에이전트 기동 → seqNoForKube = -1 (미할당 상태, 설정 파일)
  2. 에이전트가 수집 서버에 heartbeat 전송
  3. 수집 서버가 kube_pod_seq_heartbeat_ttl_ms(기본 120초) 내에 응답하면 순차 번호 반환
  4. Configure.setSeqNoForKube(seq) 호출 → obj_name{podName}_{seq}로 확정 (설정 파일)
  5. counter_object_registry_path(/tmp/flowkat) 에 {seq}.flowkatkubeseq 파일 기록 (에이전트 하트비트 로직)

Pod 재시작 시 /tmp/flowkat(emptyDir)이 초기화되면 기존 seq 파일이 소실되고, 수집 서버가 TTL 만료 전까지 동일 번호를 재할당하지 않으면 새 번호가 부여된다.

확인 방법:

# 에이전트 내부 seq 파일 확인
kubectl exec -it <agent-pod-name> -n <namespace> -- \
ls -la /tmp/flowkat/

# 에이전트 로그에서 obj_name 확인
kubectl logs <agent-pod-name> -n <namespace> | grep -E "obj_name|seqNo|podName|_rnd"

해결 방법: 수집 서버의 TTL을 Pod 재시작 주기보다 길게 설정하거나, counter_object_registry_path를 emptyDir 대신 영속 볼륨으로 마운트한다.

# flowkat.conf — seq 파일을 영속 경로에 저장
counter_object_registry_path=/data/flowkat
# Pod spec — /data/flowkat를 PersistentVolumeClaim으로 마운트
volumes:
- name: flowkat-seq
persistentVolumeClaim:
claimName: flowkat-agent-seq-pvc
containers:
- name: flowkat-agent
volumeMounts:
- name: flowkat-seq
mountPath: /data/flowkat

관련 문서: 23.support-agent-connection.md — 에이전트-수집 서버 연결 상태 진단


K-4: emptyDir 용량 초과

증상: 에이전트 Pod가 반복 재시작되거나 OOMKilled 오류가 발생한다. kubectl describe pod에서 emptyDir size limit exceeded 이벤트가 확인된다.

원인: 에이전트 로그 디렉토리(logs/)가 emptyDir에 위치하고 log_keep_days=365(기본값)가 적용된 경우, 오래된 로그가 삭제되지 않고 누적된다. emptyDir에 sizeLimit이 지정된 경우 초과 시 Pod가 퇴출(Eviction)된다.

확인 방법:

# 에이전트 로그 디렉토리 사용량 확인
kubectl exec -it <agent-pod-name> -n <namespace> -- \
du -sh /opt/flowkat/agent.host.container/logs/

# Pod 이벤트 확인
kubectl describe pod <agent-pod-name> -n <namespace> | grep -A 5 "Events:"

# emptyDir 볼륨 정의 확인
kubectl get pod <agent-pod-name> -n <namespace> -o jsonpath='{.spec.volumes}'

해결 방법: 로그 보관 기간을 단축하고 에이전트 로그를 emptyDir 외부 볼륨으로 분리한다.

# flowkat.conf — 로그 보관 기간 단축
log_keep_days=7
log_dir=/opt/flowkat/agent.host.container/logs

emptyDir에 sizeLimit을 명시하여 초과 시 조기 감지한다:

volumes:
- name: agent-logs
emptyDir:
sizeLimit: 500Mi
containers:
- name: flowkat-agent
volumeMounts:
- name: agent-logs
mountPath: /opt/flowkat/agent.host.container/logs

K-5: CrashLoopBackOff에서 에이전트 데이터 유실

증상: Pod가 CrashLoopBackOff 상태에서 반복 재시작될 때 FlowKat 대시보드에서 해당 Pod의 메트릭 데이터에 빈 구간(gap)이 발생한다.

원인: 에이전트 JVM이 비정상 종료되면 메모리 버퍼에 있는 미전송 카운터/퍼포먼스 데이터가 소실된다. 수집 서버와의 TCP 세션이 즉시 끊기므로 수집 서버 측에서도 플러시가 발생하지 않는다.

확인 방법:

# Pod 재시작 횟수 및 종료 코드 확인
kubectl get pod <agent-pod-name> -n <namespace> \
-o jsonpath='{.status.containerStatuses[0].restartCount} {.status.containerStatuses[0].lastState.terminated.exitCode}'

# 이전 컨테이너 로그 확인
kubectl logs <agent-pod-name> -n <namespace> --previous | tail -50

# CrashLoop 원인 이벤트 확인
kubectl describe pod <agent-pod-name> -n <namespace> | grep -E "Reason|Exit Code|OOM"

해결 방법: Pod 종료 시 JVM에 SIGTERM이 전달되도록 terminationGracePeriodSeconds를 설정하여 에이전트가 진행 중인 전송을 완료할 시간을 확보한다.

spec:
terminationGracePeriodSeconds: 30
containers:
- name: flowkat-agent
lifecycle:
preStop:
exec:
# SIGTERM 전달 전 잠시 대기하여 진행 중인 전송 완료
command: ["/bin/sh", "-c", "sleep 5"]

TCP 세션 수를 늘려 전송 실패 시 재시도 가능성을 높인다:

# flowkat.conf — TCP 세션 증가로 전송 안정성 향상
net_collector_tcp_session_count=2
net_collector_tcp_so_timeout_ms=30000

관련 문서: 23.support-agent-connection.md — 연결 끊김 진단 및 재연결 패턴