Kubernetes 2026.06.07 10 min read

Node Agent를 Kubernetes에 올리기: DaemonSet, Helm Chart, 그리고 검증 구조

Node Agent를 노드마다 배포할 DaemonSet과 Helm Chart를 정리했다. hostPath, 권한, token, Collector 설정을 나누고 Backend와 Console까지 연결되는 smoke test를 구성했다.

인증 실패 안내 문구가 포함된 HTML 코드를 가까이 촬영한 주제용 사진
Photo by Markus Spiske / Unsplash

Kubernetes Cluster Infra RCA Platform 개발 기록 3편


지난 글에서는 인증, RBAC, webhook 보호, report drilldown을 정리했다.

report를 누가 볼 수 있는지와 어떤 근거까지 보여줄지를 정한 뒤, 실제 노드에서 evidence를 가져올 배포 구조가 필요했다.

이번에는 Node Agent의 Kubernetes 배포를 다룬다.

Backend의 분석에 사용할 노드 evidence를 안정적으로 수집해야 했다.

Node Agent를 Kubernetes 안에 배포할 구조와 Helm Chart, smoke test를 함께 정리했다.


왜 DaemonSet인가

Agent의 관측 대상은 Kubernetes 노드였다.

수집하려던 항목은 다음과 같다.

  • kubelet 상태
  • container runtime 상태
  • CNI 설정
  • DNS 관련 증상
  • disk 사용량
  • inode 사용량
  • kernel log
  • systemd 상태
  • network/conntrack 상태

노드마다 상태가 다르므로 각각 관측해야 했다.

어떤 노드는 DiskPressure, 다른 노드는 MemoryPressure가 발생할 수 있었다. CNI와 container runtime 상태도 노드별로 다를 수 있었다.

각 노드에 Agent를 하나씩 배치하는 방향으로 잡았다.

이 배치에는 DaemonSet이 맞았다.

Kubernetes Node 1
  -> node-agent Pod

Kubernetes Node 2
  -> node-agent Pod

Kubernetes Node 3
  -> node-agent Pod

노드가 추가되면 Agent Pod도 배포할 수 있도록 했다.


Agent가 노드 정보를 읽기 위해 필요한 것

Pod 안에서 호스트의 시스템 정보를 읽을 방법도 필요했다.

다음 경로를 읽기 위한 hostPath mount를 검토했다.

/proc
/etc
/var/log
/run

호스트의 상태를 보기 위한 경로였다.

/var/log에서는 kubelet과 시스템 로그를, /run에서는 container runtime socket 상태를 확인하려고 했다.

mount 범위를 넓히면 노드의 민감한 정보도 컨테이너에 노출될 수 있었다.

필요한 경로를 읽는 역할로 Agent의 범위를 제한했다.

Agent는 노드 상태를 읽고 evidence를 제출하도록 했다.

DaemonSet의 mount와 권한도 이 범위에 맞춰 검토했다.


read-only collector로 시작한 이유

Agent에 자동 복구 기능을 바로 넣지는 않기로 했다.

kubelet이나 containerd 재시작, CNI 설정 변경은 운영 중인 서비스에 영향을 줄 수 있었다.

초기 역할은 다음과 같이 제한했다.

Agent가 하는 일:
노드 상태 읽기
collector 실행
evidence 정리
Backend로 제출

Agent가 하지 않는 일:
노드 직접 수정
서비스 재시작
파일 삭제
CNI 설정 변경
위험 조치 자동 실행

LLM과 rule analyzer가 제안한 조치는 별도의 정책과 승인 흐름에서 검토하도록 했다.

Agent가 이 흐름을 건너뛰어 노드를 수정하지 않게 하려는 구분이었다.


Helm Chart가 필요했던 이유

환경별 설정은 Helm Chart로 분리하기로 했다.

직접 manifest를 수정하는 방식으로는 환경이 늘수록 같은 변경을 반복해야 했다.

달라질 수 있는 값은 다음과 같았다.

  • Backend URL
  • cluster ID
  • agent token
  • image repository
  • image tag
  • resource requests/limits
  • hostPath mount 여부
  • collector 활성화 여부
  • node selector
  • tolerations
  • service account
  • RBAC 설정

배포 템플릿과 값을 나누면 환경마다 YAML 전체를 수정할 필요가 줄어든다.

다음 구조로 정리했다.

values.yaml
  -> 환경별 설정

templates/daemonset.yaml
  -> Node Agent 배포 구조

templates/serviceaccount.yaml
  -> Agent 실행 계정

templates/clusterrole.yaml
  -> 필요한 Kubernetes 조회 권한

templates/secret.yaml
  -> Agent token 또는 민감 설정

배포 명령은 다음처럼 사용할 수 있었다.

helm install rca-agent ./charts/rca-agent \
  --set backend.url=https://example.com \
  --set clusterId=my-cluster

운영자가 values.yaml에서 필요한 값을 바꾸고 같은 템플릿을 재사용할 수 있도록 했다.


Agent token을 어떻게 다룰 것인가

Agent가 Backend에 evidence를 제출할 때 인증하도록 했다.

등록되지 않은 Pod의 임의 제출을 막으려는 목적이다.

등록 과정에서 node token을 발급하고, Agent가 이 token으로 통신하는 구조를 잡았다.

흐름은 다음과 같다.

cluster 등록
  -> agent install command 생성
  -> node-agent 배포
  -> node token으로 Backend 인증
  -> evidence request polling
  -> evidence submit

token 전달 방식도 검토했다.

manifest나 install command에 값이 그대로 드러날 수 있었기 때문이다.

운영에서는 Secret으로 분리하는 방향을 생각했다.

문제:
Agent token이 manifest나 command에 그대로 노출될 수 있음

수정 방향:
Kubernetes Secret으로 분리
환경 변수 또는 mounted file로 Agent에 전달
Backend API 접근 시 token 검증

개발 단계에서는 간단한 방식으로 시작할 수 있었다.

다만 이후 Secret 기반으로 옮길 수 있도록 구조를 열어 두기로 했다.


collector 설정을 values.yaml로 분리하기

Collector는 환경별로 켜고 끌 수 있어야 했다.

systemd나 kernel log 접근 권한이 제한된 환경도 있었다.

클러스터에 따라 containerd 외의 runtime을 사용할 수도 있었다.

이 차이를 values.yaml에서 조정하도록 하는 방향을 잡았다.

설정 예시는 다음과 같다.

collectors:
  systemd:
    enabled: true
  kernel:
    enabled: true
  runtime:
    enabled: true
  cni:
    enabled: true
  dns:
    enabled: true
  disk:
    enabled: true
  network:
    enabled: true

환경에 맞춰 수집 범위를 정할 수 있도록 했다.

초기에는 모든 항목의 자동 탐지보다 운영자가 활성화 여부를 지정하는 방식을 우선했다.


권한은 최소한으로 시작해야 한다

수집에 필요한 권한은 항목별로 검토했다.

Kubernetes API 권한과 호스트 접근 권한을 나눠 봤다.

API 권한은 Node, Pod, Event, Endpoint 등의 조회에 필요했다.

호스트 파일시스템과 시스템 정보 접근은 hostPath mount와 securityContext를 확인해야 했다.

필요한 권한만 주고, 읽지 못한 항목은 수집 결과에 남기기로 했다.

권한을 모두 열어서 성공시키기보다 접근이 제한된 상태를 기록하도록 했다.

containerd socket에 접근하지 못했을 때도 runtime 장애인지 permission 문제인지 구분해야 했다.

containerd socket 접근 실패
  -> permission denied
  -> runtime 장애가 아니라 collector 권한 문제로 기록

앞 글에서 정리한 permission denied 처리와 같은 기준이다.


로컬 검증이 필요했던 이유

배포 파일을 만든 뒤에는 컴포넌트 연결을 검증할 방법이 필요했다.

Backend, Web Console, Node Agent, DB, migration, API 인증이 서로 연결돼 있었다.

하나씩 실행하는 시험만으로는 이 연결을 확인하기 어려웠다.

그래서 로컬 smoke test를 구성했다.

각 기능의 상세 시험과 별도로 최소 실행 흐름을 빠르게 확인하려고 했다.

대상은 다음과 같았다.

Backend가 실행되는가
/health/ready가 정상 응답하는가
DB migration이 적용되는가
Web Console이 Backend와 통신하는가
cluster 등록이 가능한가
agent manifest 또는 install command를 받을 수 있는가
RCA report API가 깨지지 않는가

기능 수정 후 전체 흐름이 깨졌는지 확인하는 데 사용하려는 시험이었다.


smoke test에서 확인하고 싶었던 흐름

프로세스 실행 상태에 더해 실제 API 흐름을 확인하려고 했다.

Backend start
  -> readiness check
  -> Web Console start
  -> cluster create
  -> agent install info 조회
  -> evidence/report 관련 API 확인

환경 변수, API 경로, migration 누락 같은 연결 문제를 이 단계에서 확인할 수 있었다.

예를 들어 Console이 변경 전 환경 변수나 API 경로를 사용하면 호출이 실패할 수 있고, migration이 빠지면 DB 접근에서 문제가 생길 수 있었다.

새 기능을 추가한 뒤에도 같은 smoke test로 연결을 확인하도록 했다.


Codex를 어떻게 활용했는가

배포 구조와 권한 범위는 직접 정했다.

DaemonSet 선택, hostPath 범위, Helm values 구분, API 조회 권한을 검토했다.

Helm template, 반복 YAML, smoke test 코드, 문서 초안에는 Codex를 활용했다.

다음 작업이 해당했다.

  • DaemonSet template 초안 작성
  • values.yaml 옵션 정리
  • ServiceAccount / RBAC manifest 구성
  • Dockerfile과 배포 파일 정리
  • smoke test 스크립트 보강
  • README 배포 방법 정리
  • 반복적인 설정 검증 코드 작성

생성된 코드에서 mount 경로와 권한, 금지한 동작이 의도대로 적용됐는지는 직접 확인했다.

작업 범위는 다음과 같았다.

사람:
DaemonSet이 필요한 이유 판단
Agent 권한 범위 결정
hostPath 위험성 검토
운영 환경에서의 배포 흐름 설계
최종 구조 검토

Codex:
Helm template 반복 작성
values.yaml 정리
smoke test 스크립트 보강
문서 초안 정리
반복 코드 작성

이렇게 반복 작성 시간을 줄이고 배포와 권한 검토에 시간을 쓸 수 있었다.


이 단계에서 가장 중요했던 점

노드에서 필요한 정보를 읽을 수 있는지와 접근 범위가 과하지 않은지를 함께 봤다.

작업 기준은 다음과 같았다.

  1. Agent는 노드마다 하나씩 떠야 하므로 DaemonSet으로 배포한다
  2. Agent는 read-only collector로 시작한다
  3. hostPath mount는 필요한 경로만 사용한다
  4. token은 Secret으로 분리할 수 있는 구조를 고려한다
  5. collector 설정은 values.yaml에서 조절 가능하게 한다
  6. 권한 부족은 실패가 아니라 evidence로 남긴다
  7. Helm Chart로 환경별 배포 설정을 분리한다
  8. smoke test로 Backend, Console, Agent 관련 흐름을 검증한다
  9. Codex는 반복 구현에 활용하되, 권한과 보안 판단은 사람이 한다

특히 2번과 6번을 함께 확인했다.

Agent의 역할은 수집으로 제한했다.

권한 때문에 읽지 못한 정보를 실제 서비스 장애로 분류하지 않도록 했다.


마무리

Node Agent의 Kubernetes 배포 구조를 정리했다.

DaemonSet으로 노드마다 배치하고 Helm Chart로 환경별 설정을 나눴다. hostPath와 권한은 필요한 범위부터 검토했다.

Backend, Console, Agent 관련 API 흐름을 확인할 smoke test도 함께 구성했다.

로컬 API 검증에서 실제 클러스터 배포를 준비하는 단계로 넘어간 작업이었다.

당시 완성된 상태는 아니었지만 배포와 권한을 다룰 기준은 정리했다.

이후에도 읽기 전용 수집과 실패 상태의 구분을 유지하려고 했다.

다음 글에서는 Web Console에서 RCA report를 확인하고 cluster와 report를 관리하는 흐름을 다룬다.

SEARCH JOURNAL

기록 검색

글 제목, 요약, 태그에서 찾습니다.

검색을 준비하고 있어요.

검색어를 입력해 주세요.

    Ctrl/⌘ K 검색 Esc 닫기 결과 이동