쿠버네티스의 대표적인 워크로드 리소스인 Daemonset(데몬셋)을 살펴보는 섹션입니다 :)
Daemonset - 데몬셋
먼저 쿠버네티스의 공식문서를 통해서 Daemonset의 정의를 살펴보겠습니다.
"데몬셋 은 모든(또는 일부) 노드가 파드의 사본을 실행하도록 한다. 노드가 클러스터에 추가되면 파드도 추가된다. 노드가 클러스터에서 제거되면 해당 파드는 가비지(garbage)로 수집된다. 데몬셋을 삭제하면 데몬셋이 생성한 파드들이 정리된다."
해당 내용을 살펴보면, 디플로이먼트(Deployment)와 스테이트풀셋(Statefulset)과 달리 노드별로 하나씩 동일한 파드를 구성하게 해주는 워크로드 리소스로 해석됩니다.
데몬셋(Daemonset)은 노드별로 하나의 파드가 배치되기 때문에 replicas를 설정하는 부분이 없으며, 만약 특정 노드가 삭제된다면 배포된 Pod가 다른 노드로 이동하는 것이 아닌 가비지(Garbage)로 수집됩니다.
데몬셋 사용
쿠버네티스 공식 문서에 따르면 일부 대표적인 용도로 다음과 같습니다.
- 모든 노드에서 클러스터 스토리지 데몬 실행
- 모든 노드에서 로그 수집 데몬 실행
- 모든 노드에서 노드 모니터링 데몬 실행
데몬셋(Daemonset)은 주로 노드의 리소스 모니터링 어플리케이션, 로그 수집을 위한 어플리케이션 배포에 사용됩니다.
데몬셋 생성하기
쿠버네티스 공식 문서를 참고하여 yaml 파일을 생성합니다.
(https://kubernetes.io/ko/docs/concepts/workloads/controllers/daemonset/)
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: journalctl
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
tolerations:
# 이 톨러레이션(toleration)은 데몬셋이 컨트롤 플레인 노드에서 실행될 수 있도록 만든다.
# 컨트롤 플레인 노드가 이 파드를 실행해서는 안 되는 경우, 이 톨러레이션을 제거한다.
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- kind : DaemonSet 으로 설정해주세요 ! (대소문자 주의)
- spec.template : Deployment, Statefulset과 마찬가지로 배포할 파드에 대해서 정의하는 부분입니다.
- spec.template.spec.tolerations : 만약 특정 조건을 가진 노드에 DaemonSet Pod를 배포하고 싶을때 사용하는 부분입니다.
- spec.template.spec.nodeSelector : 만약 특정 레이블을 가진 노드에 배포하고 싶을때 사용하는 항목입니다. 해당 yaml 설정에는 없지만 해당 위치에 추가하여 Node Label의 Key-Value에 맞춰서 선언하면 됩니다 !
spec.tolerations을 살펴보면 컨트롤 플레인(Control Plane) 노드에서 해당 파드를 실행하고 싶지 않을 경우 제거한다고 써져있습니다.
( 필자는 Control Plane(Master) 노드에서 실행하기를 원치 않기 때문에 해당 부분은 삭제하였습니다 ! )
metadata.namespace가 기본적으로 kube-system으로 설정되어 있는데 필자는 journalctl 네임스페이스에 배포하기 위해서 위와 같이 설정하였습니다 !
데몬셋 배포하기
$ kubectl apply -f daemonset.yaml -n journalctl
daemonset.apps/fluentd-elasticsearch created
데몬셋 상태 확인하기
$ kubectl get pod -n journalctl
NAME READY STATUS RESTARTS AGE
fluentd-elasticsearch-2x7g9 1/1 Running 0 5m33s
fluentd-elasticsearch-h9fw4 1/1 Running 0 5m33s
fluentd-elasticsearch-mck94 1/1 Running 0 5m33s
$ kubectl get ds -n journalctl
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
fluentd-elasticsearch 3 3 3 3 3 <none> 5m39s
$ kubectl describr ds/fluentd-elasticsearch -n journalctl
Name: fluentd-elasticsearch
Selector: name=fluentd-elasticsearch
Node-Selector: <none>
Labels: k8s-app=fluentd-logging
Annotations: deprecated.daemonset.template.generation: 1
Desired Number of Nodes Scheduled: 3
Current Number of Nodes Scheduled: 3
Number of Nodes Scheduled with Up-to-date Pods: 3
Number of Nodes Scheduled with Available Pods: 3
Number of Nodes Misscheduled: 0
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: name=fluentd-elasticsearch
Containers:
fluentd-elasticsearch:
Image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
Port: <none>
Host Port: <none>
Limits:
memory: 200Mi
Requests:
cpu: 100m
memory: 200Mi
Environment: <none>
Mounts:
/var/log from varlog (rw)
Volumes:
varlog:
Type: HostPath (bare host directory volume)
Path: /var/log
HostPathType:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 5m51s daemonset-controller Created pod: fluentd-elasticsearch-mck94
Normal SuccessfulCreate 5m51s daemonset-controller Created pod: fluentd-elasticsearch-h9fw4
Normal SuccessfulCreate 5m51s daemonset-controller Created pod: fluentd-elasticsearch-2x7g9
배포된 Pod 명을 확인해보면 <daemonset-name>-<random-value> 값으로 설정됩니다. Deployment와 동일하게 네이밍 규칙을 가지는 것으로 확인되며 Deployment도 Pod를 배포할때 "deployment-coontroller"를 통해서 배포한다면 Daemonset은 "damonset-controller"를 통해서 배포되는것을 확인할 수 있습니다.
Daemonset의 특징으로 각 노드에 Pod가 배포된다고 언급하였습니다. 해당 내용을 확인하기 위해서 먼저 Node를 확인하고, 각 Pod가 Node별로 배포되었는지 확인해보겠습니다.
노드 확인하기
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
190.ap-northeast-2.compute.internal Ready <none> 12d v1.26.10-eks-e71965b
112.ap-northeast-2.compute.internal Ready <none> 12d v1.26.10-eks-e71965b
177.ap-northeast-2.compute.internal Ready <none> 12d v1.26.10-eks-e71965b
현재 구성되어 있는 Worker Node는 총 3대로 구성되어 있습니다.
- 112.ap-northeast-2.compute.internal
- 190.ap-northeast-2.compute.internal
- 177.ap-northeast-2.compute.internal
각 노드별로 Pod에 배포되었는지 확인하기 위해서 wide 옵션을 추가하여 확인해보겠습니다.
데몬셋 상태 확인하기
$ kubectl get pod -n journalctl -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
fluentd-elasticsearch-2x7g9 1/1 Running 0 17m 192.168.3.35 177.ap-northeast-2.compute.internal <none> <none>
fluentd-elasticsearch-h9fw4 1/1 Running 0 17m 192.168.1.107 190.ap-northeast-2.compute.internal <none> <none>
fluentd-elasticsearch-mck94 1/1 Running 0 17m 192.168.2.85 112.ap-northeast-2.compute.internal <none> <none>
NODE 필드를 확인해보면 앞서 확인했던 Worker Node 별로 Pod 1개씩 배포되었음을 확인할 수 있습니다 !
다음으로 특정 노드에만 배포하도록 설정할 수 있는 방법 중 Node Label을 설정하여 배포해보겠습니다.
노드 레이블 설정하기
먼저 Node에 설정되어 있는 Label를 확인하는 명령어를 살펴보겠습니다. 노드 확인하기 섹션에서 사용한 명령어에서 "--show-labels" 옵션을 추가하면 Node에 설정되어 있는 Label을 확인할 수 있습니다.
$ kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
190.ap-northeast-2.compute.internal Ready <none> 12d v1.26.10-eks-e71965b kubernetes.io/arch=amd64,kubernetes.io/hostname=190.ap-northeast-2.compute.internal,kubernetes.io/os=linux
112.ap-northeast-2.compute.internal Ready <none> 12d v1.26.10-eks-e71965b kubernetes.io/arch=amd64,kubernetes.io/hostname=112.ap-northeast-2.compute.internal,kubernetes.io/os=linux
177.ap-northeast-2.compute.internal Ready <none> 12d v1.26.10-eks-e71965b kubernetes.io/arch=amd64,kubernetes.io/hostname=177.ap-northeast-2.compute.internal,kubernetes.io/os=linux
다음으로 Node에 Label을 설정하겠습니다.
"kubectl label nodes <your-node-name> <Label-Key>=<Label-Value>" 명령어를 사용하여 설정하겠습니다.
( 데몬셋 실습을 위해서 2개의 노드에 대해서만 설정하겠습니다. )
$ kubectl label nodes 190.ap-northeast-2.compute.internal ns=journalctl
node/190.ap-northeast-2.compute.internal labeled
$ kubectl label nodes 112.ap-northeast-2.compute.internal ns=journalctl
node/112.ap-northeast-2.compute.internal labeled
$ kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
190.ap-northeast-2.compute.internal Ready <none> 12d v1.26.10-eks-e71965b kubernetes.io/arch=amd64,kubernetes.io/hostname=190.ap-northeast-2.compute.internal,kubernetes.io/os=linux, ns=journalctl
112.ap-northeast-2.compute.internal Ready <none> 12d v1.26.10-eks-e71965b kubernetes.io/arch=amd64,kubernetes.io/hostname=112.ap-northeast-2.compute.internal,kubernetes.io/os=linux, ns=journalctl
177.ap-northeast-2.compute.internal Ready <none> 12d v1.26.10-eks-e71965b kubernetes.io/arch=amd64,kubernetes.io/hostname=177.ap-northeast-2.compute.internal,kubernetes.io/os=linux
데몬셋 생성하기 (NodeSelector)
앞서 데몬셋 생성하기에서 사용한 yaml 파일에서 spec.template.spec.nodeSelector를 추가하여 생성해보겠습니다.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: journalctl
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
nodeSelector:
ns: journalctl
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
앞서 Node에 지정한 Label의 Key-Value로 nodeSelector에 설정해주었습니다. 다시 배포를 진행합니다.
$ kubectl apply -f daemonset.yaml -n journalctl
daemonset.apps/fluentd-elasticsearch configured
데몬셋 상태 확인하기 (NodeSelector)
앞서 확인했던 명렁어를 사용하여 상태를 확인해보겠습니다.
$ kubectl get pod -n journalctl -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
fluentd-elasticsearch-cktn5 1/1 Running 0 55s 192.168.2.93 112.ap-northeast-2.compute.internal <none> <none>
fluentd-elasticsearch-k7tlp 1/1 Running 0 52s 192.168.1.114 190.ap-northeast-2.compute.internal <none> <none>
$ kubectl get ds -n journalctl
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
fluentd-elasticsearch 2 2 2 2 2 ns=journalctl 37m
$ kubectl describe ds/fluentd-elasticsearch -n journalctl
Name: fluentd-elasticsearch
Selector: name=fluentd-elasticsearch
Node-Selector: ns=journalctl
Labels: k8s-app=fluentd-logging
Annotations: deprecated.daemonset.template.generation: 2
Desired Number of Nodes Scheduled: 2
Current Number of Nodes Scheduled: 2
Number of Nodes Scheduled with Up-to-date Pods: 2
Number of Nodes Scheduled with Available Pods: 2
Number of Nodes Misscheduled: 0
Pods Status: 2 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: name=fluentd-elasticsearch
Containers:
fluentd-elasticsearch:
Image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
Port: <none>
Host Port: <none>
Limits:
memory: 200Mi
Requests:
cpu: 100m
memory: 200Mi
Environment: <none>
Mounts:
/var/log from varlog (rw)
Volumes:
varlog:
Type: HostPath (bare host directory volume)
Path: /var/log
HostPathType:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 38m daemonset-controller Created pod: fluentd-elasticsearch-mck94
Normal SuccessfulCreate 38m daemonset-controller Created pod: fluentd-elasticsearch-h9fw4
Normal SuccessfulCreate 38m daemonset-controller Created pod: fluentd-elasticsearch-2x7g9
Normal SuccessfulDelete 77s daemonset-controller Deleted pod: fluentd-elasticsearch-2x7g9
Normal SuccessfulDelete 75s daemonset-controller Deleted pod: fluentd-elasticsearch-mck94
Normal SuccessfulCreate 73s daemonset-controller Created pod: fluentd-elasticsearch-cktn5
Normal SuccessfulDelete 72s daemonset-controller Deleted pod: fluentd-elasticsearch-h9fw4
Normal SuccessfulCreate 69s daemonset-controller Created pod: fluentd-elasticsearch-k7tlp
먼저 배포된 Pod를 살펴보면 앞서 설정했던 2개의 노드에 대해서만 배포가 수행되었습니다.
Daemonset을 살펴보면 "NODE SELECTOR" 부분에 yaml 파일로 설정하였던 spec.template.spec.nodeSelector 값이 설정되어 있는것을 확인할 수 있습니다.
Daemonset의 "Events"를 살펴보면 앞서 배포되었던 3개의 파드는 모두 삭제되고 새로운 2개의 파드가 재배포 되었음을 확인할 수 있습니다.

다음 섹션은 REST 오브젝트인 Service에 대해서 살펴보겠습니다 :)
'Kubernetes' 카테고리의 다른 글
인증서를 무료로 관리해보자(Cert-manager + Let’s Encrypt) (0) | 2025.01.12 |
---|---|
VKE - Vultr Kubernetes Engine (0) | 2025.01.12 |
kind(Kubernetes in Docker) (0) | 2025.01.12 |
Kubernetes Workload Resources(Statefulset) (61) | 2023.12.03 |
Kubernetes Workload Resources(Deployment, Replicaset) (4) | 2023.11.27 |