Markdown Preview
Kubernetes DaemonSet을 활용한 클러스터 모니터링 및 메트릭 수집 완벽 가이드
Frontmatter
Kubernetes DaemonSet은 클러스터의 모든 노드에 파드 하나씩 배포하는 컨트롤러로, 모니터링 에이전트·로그 수집·네트워크·스토리지 등 노드별 작업에 적합하다. 예시로 Node Exporter DaemonSet을 monitoring 네임스페이스에 배포하고, Prometheus와 Grafana를 연동해 시스템 메트릭을 수집·시각화하는 전체 흐름을 단계별 YAML 파일과 명령어로 제공한다. 또한 DaemonSet과 ReplicaSet의 차이점과 배포 순서를 정리한다.
DaemonSet이란?
DaemonSet은 Kubernetes에서 클러스터의 모든 노드(또는 특정 노드들)에 파드를 하나씩 배포하는 컨트롤러입니다. 레플리카셋이 지정된 수의 파드 복제본을 유지하는 것과 달리, DaemonSet은 각 노드마다 정확히 하나의 파드를 실행합니다.
주로 다음과 같은 용도로 사용됩니다:
- 모니터링 에이전트: 각 노드의 시스템 메트릭 수집
- 로그 수집기: 노드별 로그 수집 및 중앙 집중화
- 네트워크 플러그인: CNI(Container Network Interface) 데몬
- 스토리지 데몬: Ceph, GlusterFS 등의 분산 스토리지 클라이언트
구성 요소
이번 실습에서는 Node Exporter DaemonSet을 배포하고, Prometheus와 Grafana를 통해 모니터링 환경을 구축합니다.
- Namespace:
monitoring네임스페이스 생성하여 모니터링 관련 리소스를 격리합니다.
- ServiceAccount:
node-exporter와prometheus서비스 어카운트를 생성하여 파드에 적절한 권한을 부여합니다.
- RBAC: Prometheus가 Kubernetes 리소스를 탐색할 수 있도록 ClusterRole과 ClusterRoleBinding을 통해 권한을 부여합니다.
- Node Exporter DaemonSet: 각 노드에 시스템 메트릭 수집기를 배포합니다.
- Services:
- Node Exporter 서비스 (ClusterIP, NodePort)
- Prometheus 서비스 (ClusterIP, LoadBalancer)
- Grafana 서비스 (ClusterIP, LoadBalancer)
- Prometheus: 메트릭을 수집하고 저장하는 시계열 데이터베이스입니다.
- Grafana: Prometheus에서 수집한 메트릭 데이터를 시각화하는 대시보드 도구입니다.
1️⃣ Namespace 생성
모니터링 관련 리소스를 격리하기 위한 네임스페이스를 먼저 생성합니다.
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: monitoring2️⃣ ServiceAccount & RBAC 설정
Node Exporter와 Prometheus가 적절한 권한으로 동작할 수 있도록 ServiceAccount와 RBAC를 설정합니다.
# 서비스 어카운트 생성 - node-exporter
apiVersion: v1
kind: ServiceAccount
metadata:
name: node-exporter
namespace: monitoring
---
# 서비스 어카운트 생성 - prometheus
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: monitoring
---
# 클러스터롤 생성 - prometheus-discovery for Service Discovery
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus-discovery
rules:
- apiGroups: [""]
resources: ["nodes", "pods", "endpoints", "services", "namespaces"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps", "extensions"]
resources: ["replicasets"]
verbs: ["get", "list", "watch"]
---
# 클러스터롤바인딩 - prometheus-discovery
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-discovery
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus-discovery
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitoringRBAC 설명
- ClusterRole: Prometheus가 Kubernetes API를 통해 서비스 디스커버리를 수행하기 위한 권한 정의
- ClusterRoleBinding: prometheus 서비스 어카운트에 ClusterRole 권한을 바인딩
- 이를 통해 Prometheus는
monitoring네임스페이스의 Pod들을 자동으로 탐색 가능
3️⃣ Node Exporter DaemonSet
Node Exporter는 시스템 메트릭(CPU, 메모리, 디스크, 네트워크 등)을 수집하여 Prometheus가 스크래핑할 수 있도록 HTTP 엔드포인트로 노출하는 도구입니다. DaemonSet으로 배포되어 클러스터의 각 노드에서 실행됩니다.
주요 특징
prom/node-exporter:v1.8.1이미지 사용
- hostNetwork 모드: 노드의 네트워크 네임스페이스를 직접 사용하여 실제 네트워크 메트릭 수집
- tolerations 설정: control-plane/master 노드의 taint를 무시하고 배포 가능
- rootfs 마운트: 호스트의 루트 파일시스템을 읽기 전용으로 마운트하여 시스템 정보 수집
- securityContext: nobody 사용자로 실행, 권한 상승 방지, 읽기 전용 루트 파일시스템
DaemonSet 매니페스트
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitoring
labels:
app: node-exporter
spec:
selector:
matchLabels:
app: node-exporter
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
app: node-exporter
spec:
# 서비스 어카운트 지정
serviceAccountName: node-exporter
# control-plane 노드에도 배포하려면 taint 허용
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
# 모든 워커 노드에 배포. 특정 라벨만 대상으로 하려면 아래에 nodeSelector 추가
# nodeSelector:
# node-role: worker
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: node-exporter
image: prom/node-exporter:v1.8.1
imagePullPolicy: IfNotPresent
args:
# 보안상 기본값 유지, 필요한 경우 커스텀 플래그 추가
- --path.rootfs=/host
ports:
- name: metrics
containerPort: 9100
hostPort: 9100
protocol: TCP
resources:
requests:
cpu: "50m"
memory: "64Mi"
limits:
cpu: "200m"
memory: "256Mi"
securityContext:
runAsUser: 65534 # nobody
runAsGroup: 65534 # nogroup
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
seccompProfile:
type: RuntimeDefault
volumeMounts:
- name: rootfs
mountPath: /host
readOnly: true
volumes:
- name: rootfs
hostPath:
path: /
type: Directory
DaemonSet 주요 설정 설명
- tolerations: Master/Control-plane 노드의 taint를 허용하여 모든 노드에 배포
- hostNetwork: true: 호스트 네트워크 사용으로 실제 노드 네트워크 메트릭 수집
- hostPort: 9100: 각 노드의 9100 포트로 직접 접근 가능
- readOnlyRootFilesystem: 보안 강화를 위한 읽기 전용 루트 파일시스템
배포 명령어
# 네임스페이스 생성
kubectl apply -f namespace.yaml
# 서비스 어카운트 및 RBAC 생성
kubectl apply -f serviceaccount-rbac.yaml
# Node Exporter DaemonSet 배포
kubectl apply -f node-exporter-daemonset.yaml
# 서비스 생성
kubectl apply -f node-exporter-service.yaml확인 방법
배포 후 다음 명령어로 상태를 확인할 수 있습니다:
# DaemonSet 상태 확인
kubectl get daemonset -n monitoring
# Pod 상태 확인 (각 노드마다 하나씩 실행됨)
kubectl get pods -n monitoring -l app=node-exporter
# 서비스 확인
kubectl get svc -n monitoring
# 특정 파드의 로그 확인
kubectl logs -n monitoring -l app=node-exporter --tail=50정상적으로 배포되면, 클러스터의 노드 수만큼 Node Exporter 파드가 실행됩니다. 예를 들어 3개의 노드가 있다면 3개의 파드가 생성됩니다.
Node Exporter Service
Node Exporter에 접근하기 위한 서비스를 생성합니다. ClusterIP와 NodePort 두 가지 타입을 제공합니다.
# 서비스 생성
apiVersion: v1
kind: Service
metadata:
name: node-exporter
namespace: monitoring
labels:
app: node-exporter
spec:
type: ClusterIP
ports:
- name: metrics
port: 9100
targetPort: 9100
protocol: TCP
selector:
app: node-exporter
---
# node-exporter 서비스 (Prometheus가 접근)
apiVersion: v1
kind: Service
metadata:
name: node-exporter-nodeport
namespace: monitoring
labels:
app: node-exporter
spec:
type: NodePort
ports:
- name: metrics
port: 9100
targetPort: 9100
protocol: TCP
nodePort: 30100
selector:
app: node-exporter4️⃣ Prometheus 설정 및 배포
Prometheus ConfigMap
Prometheus의 설정 파일을 ConfigMap으로 관리합니다. Kubernetes Service Discovery를 통해 Node Exporter Pod를 자동으로 탐색합니다.
# prometheus-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitoring
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'node-exporter-pods'
kubernetes_sd_configs:
- role: pod
kubeconfig_file: ""
relabel_configs:
- source_labels: [__meta_kubernetes_namespace]
action: keep
regex: monitoring
- source_labels: [__meta_kubernetes_pod_label_app]
action: keep
regex: node-exporter
- source_labels: [__meta_kubernetes_pod_container_port_number]
action: keep
regex: 9100
- source_labels: [__meta_kubernetes_pod_ip, __meta_kubernetes_pod_container_port_number]
separator: ':'
target_label: __address__
action: replaceKubernetes Service Discovery 설명
- kubernetes_sd_configs: Kubernetes API를 통해 타겟을 자동 탐색
- role: pod: Pod 단위로 스크래핑 타겟 탐색
- relabel_configs: 메타데이터 기반 필터링
monitoring네임스페이스의 Pod만 선택
app=node-exporter라벨을 가진 Pod만 선택
- 9100 포트를 사용하는 컨테이너만 선택
Prometheus Deployment
# prometheus-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: monitoring
labels:
app: prometheus
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
serviceAccountName: prometheus
containers:
- name: prometheus
image: prom/prometheus:v2.55.0
args:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
- --web.enable-admin-api
ports:
- name: web
containerPort: 9090
volumeMounts:
- name: config
mountPath: /etc/prometheus
- name: data
mountPath: /prometheus
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "1"
memory: "1Gi"
volumes:
- name: config
configMap:
name: prometheus-config
- name: data
emptyDir: {}Prometheus Service
# prometheus-service.yaml
# Prometheus 서비스 (ClusterIP - Grafana가 접근)
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: monitoring
labels:
app: prometheus
spec:
type: ClusterIP
ports:
- name: web
port: 9090
targetPort: 9090
protocol: TCP
selector:
app: prometheus
---
# Prometheus LoadBalancer 서비스 (외부 접근용)
apiVersion: v1
kind: Service
metadata:
name: prometheus-lb
namespace: monitoring
labels:
app: prometheus-lb
spec:
type: LoadBalancer
ports:
- name: web
port: 9090
targetPort: 9090
protocol: TCP
selector:
app: prometheus5️⃣ Grafana 설정 및 배포
Grafana ConfigMap
Grafana의 데이터소스와 대시보드 프로비저닝 설정을 ConfigMap으로 관리합니다.
# grafana-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-config
namespace: monitoring
data:
datasources.yml: |
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus.monitoring.svc.cluster.local:9090
isDefault: true
dashboards.yml: |
apiVersion: 1
providers:
- name: 'default'
orgId: 1
folder: 'Node Exporter'
type: file
disableDeletion: false
updateIntervalSeconds: 30
options:
path: /var/lib/grafana/dashboardsGrafana Deployment
# grafana-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: monitoring
labels:
app: grafana
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana:12.4.0-19274378403
ports:
- name: web
containerPort: 3000
env:
- name: GF_SECURITY_ADMIN_USER
value: admin
- name: GF_SECURITY_ADMIN_PASSWORD
value: admin
- name: GF_PATHS_PROVISIONING
value: /etc/grafana/provisioning
volumeMounts:
- name: grafana-config
mountPath: /etc/grafana/provisioning/datasources/datasources.yml
subPath: datasources.yml
- name: grafana-config-dash
mountPath: /etc/grafana/provisioning/dashboards/dashboards.yml
subPath: dashboards.yml
- name: grafana-dash-jsons
mountPath: /var/lib/grafana/dashboards/node_exporter_full.json
subPath: node_exporter_full.json
- name: grafana-storage
mountPath: /var/lib/grafana
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
volumes:
- name: grafana-config
configMap:
name: grafana-config
- name: grafana-config-dash
configMap:
name: grafana-config
- name: grafana-dash-jsons
configMap:
name: grafana-config
- name: grafana-storage
emptyDir: {}Grafana Service
# grafana-service.yaml
# Grafana 서비스 (ClusterIP - 클러스터 내부 접근용)
apiVersion: v1
kind: Service
metadata:
name: grafana
namespace: monitoring
labels:
app: grafana
spec:
type: ClusterIP
ports:
- name: web
port: 3000
targetPort: 3000
protocol: TCP
selector:
app: grafana
---
# Grafana LoadBalancer 서비스 (외부 접근용)
apiVersion: v1
kind: Service
metadata:
name: grafana-lb
namespace: monitoring
labels:
app: grafana-lb
spec:
type: LoadBalancer
ports:
- name: web
port: 3000
targetPort: 3000
protocol: TCP
selector:
app: grafana6️⃣ 전체 배포 순서
모든 리소스를 순서대로 배포하는 방법입니다.
# 1. 네임스페이스 생성
kubectl apply -f namespace.yaml
# 2. ServiceAccount 및 RBAC 설정
kubectl apply -f serviceaccount-rbac.yaml
# 3. Node Exporter DaemonSet 및 서비스 배포
kubectl apply -f node-exporter-daemonset.yaml
kubectl apply -f node-exporter-service.yaml
# 4. Prometheus 설정 및 배포
kubectl apply -f prometheus-config.yaml
kubectl apply -f prometheus-deployment.yaml
kubectl apply -f prometheus-service.yaml
# 5. Grafana 설정 및 배포
kubectl apply -f grafana-config.yaml
kubectl apply -f grafana-deployment.yaml
kubectl apply -f grafana-service.yamlOne-liner 배포
모든 YAML 파일을 하나의 디렉토리에 저장했다면, 다음 명령어로 한 번에 배포할 수 있습니다:
kubectl apply -f ./monitoring/Prometheus & Grafana 상세 설명
Prometheus는 메트릭을 수집하고 저장하는 오픈소스 모니터링 시스템입니다. 시계열 데이터베이스를 내장하고 있어 메트릭을 효율적으로 저장하고 쿼리할 수 있습니다.
Grafana는 Prometheus에서 수집한 데이터를 시각화하는 대시보드 도구로, 다양한 그래프와 차트를 통해 시스템 상태를 직관적으로 파악할 수 있습니다.
배포 방법
다음 명령어로 Prometheus와 Grafana를 배포합니다:
# Prometheus 설정 및 배포
kubectl apply -f prometheus.yaml
# Prometheus 서비스 생성
kubectl apply -f prometheus-service.yaml
# Grafana 배포 및 서비스 생성
kubectl apply -f grafana.yaml
kubectl apply -f grafana-service.yaml확인 방법
배포 후 다음 명령어로 상태를 확인합니다:
# Prometheus 상태 확인
kubectl get pods -n monitoring -l app=prometheus
# Grafana 상태 확인
kubectl get pods -n monitoring -l app=grafana
# 서비스 확인
kubectl get svc -n monitoring
# Prometheus가 타겟을 수집하고 있는지 확인
kubectl logs -n monitoring -l app=prometheus --tail=50접근 정보
서비스가 정상적으로 실행되면 다음 주소로 접근할 수 있습니다:
- Prometheus:
http://<MASTER_NODE_IP>:9090Prometheus UI에서 수집된 메트릭을 확인하고 PromQL 쿼리를 실행할 수 있습니다.
- Grafana:
http://<MASTER_NODE_IP>:3000기본 계정 정보:admin/admin(최초 로그인 시 비밀번호 변경 권장)
Grafana 대시보드 설정
Grafana에 접속한 후 다음 단계를 통해 대시보드를 구성할 수 있습니다:
- Data Source 추가: Configuration → Data Sources → Add data source → Prometheus 선택
- Prometheus URL 입력:
http://prometheus:9090
- 대시보드 가져오기: Dashboards → Import → 대시보드 ID 입력 (예: 1860 - Node Exporter Full)
DaemonSet vs ReplicaSet
DaemonSet과 ReplicaSet의 주요 차이점을 정리하면 다음과 같습니다:
구분 | ReplicaSet | DaemonSet |
파드 수 | 사용자가 지정한 replicas 수 | 노드 수와 동일 (노드당 1개) |
배포 위치 | 스케줄러가 적절한 노드 선택 | 모든 노드 (또는 selector로 지정한 노드) |
주요 용도 | 애플리케이션 서버, API 서버 | 모니터링 에이전트, 로그 수집기, 네트워크 데몬 |
스케일링 | replicas 값으로 조정 가능 | 노드 추가/제거 시 자동 조정 |
핵심 정리
이 문서에서는 Kubernetes의 DaemonSet 개념과 실습 방법에 대해 알아보았습니다. DaemonSet은 각 노드마다 하나의 파드를 실행하는 컨트롤러로, 모니터링이나 로그 수집 같은 노드별 작업에 최적화되어 있습니다.
✅ DaemonSet: 클러스터의 모든 노드(또는 특정 노드)에 파드를 하나씩 배포하는 Kubernetes 컨트롤러
✅ 주요 용도: 모니터링 에이전트, 로그 수집기, 네트워크 플러그인, 스토리지 데몬
✅ Node Exporter: 각 노드의 시스템 메트릭(CPU, 메모리, 디스크 등)을 수집하는 DaemonSet
✅ Prometheus: 메트릭 수집 및 저장을 담당하는 시계열 데이터베이스
✅ Grafana: Prometheus 데이터를 시각화하는 대시보드 도구
✅ 주요 특징: hostNetwork 모드, tolerations로 master 노드 배포 가능, 노드 추가 시 자동 배포
✅ ReplicaSet과의 차이: ReplicaSet은 지정된 수의 복제본 유지, DaemonSet은 노드당 1개 파드 실행