Workload API vol. 3: DaemonSet, StatefulSet, Job, Cronjob

์„ฑ์œคยท2026๋…„ 2์›” 26์ผ

[โ˜ธ๏ธKubernetes]

๋ชฉ๋ก ๋ณด๊ธฐ
9/13
post-thumbnail

๋“ค์–ด๊ฐ€๋ฉฐ ๐Ÿ‘‹

์ง€๋‚œ ํฌ์ŠคํŒ…์—์„œ๋Š” ๋ฌด์ค‘๋‹จ ์„œ๋น„์Šค์˜ ๋“ ๋“ ํ•œ ๊ธฐ๋ฐ˜์ด ๋˜๋Š” ๋ ˆํ”Œ๋ฆฌ์นด์…‹(ReplicaSet) ๊ณผ ๋””ํ”Œ๋กœ์ด๋จผํŠธ(Deployment) ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด ๋‘˜์€ ์›น ์„œ๋ฒ„๋‚˜ API ์„œ๋ฒ„์ฒ˜๋Ÿผ ์ƒํƒœ๊ฐ€ ์—†๊ณ (Stateless) ๊ณ„์† ์ผœ์ ธ ์žˆ์–ด์•ผ ํ•˜๋Š” ์„œ๋น„์Šค์— ์ตœ์ ํ™”๋˜์–ด ์žˆ์—ˆ์ฃ .

ํ•˜์ง€๋งŒ ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” "๋ชจ๋“  ๋…ธ๋“œ์— ํ•˜๋‚˜์”ฉ๋งŒ ๋– ์•ผ ํ•˜๋Š” ํŒŒ๋“œ", "๋ฐ์ดํ„ฐ๋ฅผ ์˜๊ตฌ์ ์œผ๋กœ ์ €์žฅํ•ด์•ผ ํ•˜๋Š” ํŒŒ๋“œ", "ํ•œ ๋ฒˆ ์ž‘์—…ํ•˜๊ณ  ๊น”๋”ํ•˜๊ฒŒ ๋๋‚˜๋Š” ํŒŒ๋“œ" ๋“ฑ ๋‹ค์–‘ํ•œ ์š”๊ตฌ์‚ฌํ•ญ์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

์˜ค๋Š˜์€ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์—์„œ ์ด๋Ÿฌํ•œ ํŠน์ˆ˜ ๋ชฉ์ ์„ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” 4๊ฐ€์ง€ ํŠน์ˆ˜ ์›Œํฌ๋กœ๋“œ(DaemonSet, StatefulSet, Job, CronJob)์™€, ํด๋Ÿฌ์Šคํ„ฐ ์šด์˜์˜ ํ•„์ˆ˜ ์Šคํ‚ฌ์ธ ๋…ธ๋“œ ๊ด€๋ฆฌ(Cordon, Drain)์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿš€


1. ๋ฐ๋ชฌ์…‹ (DaemonSet): ๋ชจ๋“  ๋…ธ๋“œ์— ํ•˜๋‚˜์”ฉ ๐Ÿ‘ป

๋ฐ๋ชฌ์…‹์€ ๋ ˆํ”Œ๋ฆฌ์นด์…‹์˜ ํŠน์ˆ˜ํ•œ ํ˜•ํƒœ๋กœ, ํด๋Ÿฌ์Šคํ„ฐ ๋‚ด์˜ ๋ชจ๋“  ๋…ธ๋“œ์— ํŒŒ๋“œ๋ฅผ ๋”ฑ ํ•œ ๊ฐœ์”ฉ๋งŒ ์ƒ์„ฑํ•˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ์›Œํฌ๋กœ๋“œ์ž…๋‹ˆ๋‹ค.

๊ฐ€์žฅ ํฐ ํŠน์ง•์€ replicas (ํŒŒ๋“œ ๊ฐœ์ˆ˜)๋ฅผ ์•„์˜ˆ ์ง€์ •ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

ํด๋Ÿฌ์Šคํ„ฐ์— ๋…ธ๋“œ๊ฐ€ ์ƒˆ๋กœ ์ถ”๊ฐ€๋˜๋ฉด ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๊ฐ€ ์•Œ์•„์„œ ์ƒˆ ๋…ธ๋“œ์— ๋ฐ๋ชฌ์…‹ ํŒŒ๋“œ๋ฅผ ํ•˜๋‚˜ ๋„์›Œ์ฃผ๊ณ , ๋…ธ๋“œ๊ฐ€ ์‚ญ์ œ๋˜๋ฉด ํŒŒ๋“œ๋„ ํ•จ๊ป˜ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค. (ํŠน์ • ๋…ธ๋“œ์— ๋„์šฐ๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด nodeSelector๋‚˜ Anti-Affinity๋กœ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

๐Ÿ’ก ์–ธ์ œ ์‚ฌ์šฉํ• ๊นŒ?

์ฃผ๋กœ ๊ฐ ๋…ธ๋“œ์˜ ๋ฆฌ์†Œ์Šค ์ƒํƒœ๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ๋ชจ๋‹ˆํ„ฐ๋ง ์—์ด์ „ํŠธ(Datadog, Prometheus Node Exporter)๋‚˜ ๋…ธ๋“œ๋ณ„ ๋กœ๊ทธ๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ๋กœ๊ทธ ์ˆ˜์ง‘๊ธฐ(Fluentd) ๋“ฑ ๋ชจ๋“  ๋…ธ๋“œ์—์„œ ๋ฐ˜๋“œ์‹œ ๋Œ์•„๊ฐ€์•ผ ํ•˜๋Š” ๋ฐฑ๊ทธ๋ผ์šด๋“œ ํ”„๋กœ์„ธ์Šค์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.


โ‘  ๋ฐ๋ชฌ์…‹ ๋ฐฐํฌ ์‹ค์Šต (Prometheus-exporter)

์ •ํ™•ํ•œ ์ดํ•ด๋ฅผ ์œ„ํ•ด ๋ชจ๋‹ˆํ„ฐ๋ง์„ ์œ„ํ•œ ํ”„๋กœ๋ฉ”ํ…Œ์šฐ์Šค ์ต์Šคํฌํ„ฐ๋ฅผ ๋ฐ๋ชฌ์…‹์œผ๋กœ ๋„์›Œ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

# daemonset.yaml
apiVersion: apps/v1  # ๋ฐ๋ชฌ์…‹๋„ apps/v1์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค
kind: DaemonSet
metadata:
  name: prometheus-daemonset
spec:
  selector:
    matchLabels:
      tier: monitoring # ๊ธฐ๋Šฅ๊ตฌ๋ณ„์„ ์œ„ํ•œ ์ด๋ฆ„ํ‘œ
      name: prometheus-exporter
  template:
    metadata:
      labels:
        tier: monitoring
        name: prometheus-exporter
    spec:
      containers:
      - name: prometheus
        image: prom/node-exporter
        ports:
        - containerPort: 80
# ์ƒ์„ฑ ๋ฐ ํ™•์ธ
$ kubectl apply -f daemonset.yaml
$ kubectl get pods -o wide  # ํŒŒ๋“œ๊ฐ€ ๊ฐ ๋…ธ๋“œ๋งˆ๋‹ค ํ•˜๋‚˜์”ฉ ๊ท ๋“ฑํ•˜๊ฒŒ ๋ฐฐ์น˜๋œ ๊ฒƒ์„ ํ™•์ธ!

NAME                         READY   STATUS    RESTARTS   AGE     IP             NODE      NOMINATED NODE   READINESS GATES
prometheus-daemonset-2plvc   1/1     Running   0          4m17s   10.244.1.134   worker2   <none>           <none>
prometheus-daemonset-8g9bn   1/1     Running   0          4m17s   10.244.2.100   worker1   <none>           <none>

์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์‹œ๋ฉด ๊ฐ ์›Œ์ปค ๋…ธ๋“œ์— 1๊ฐœ์”ฉ ๋ฐ๋ชฌ์…‹์ด ์ƒ์„ฑ๋˜์–ด ๋Œ์•„๊ฐ€๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


โ‘ก ๋ฐ๋ชฌ์…‹์˜ ์—…๋ฐ์ดํŠธ ์ „๋žต

๋ฐ๋ชฌ์…‹์˜ ์—…๋ฐ์ดํŠธ ์ „๋žต์€ ๋””ํ”Œ๋กœ์ด๋จผํŠธ์™€๋Š” ์กฐ๊ธˆ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

  • OnDelete: ๋งค๋‹ˆํŽ˜์ŠคํŠธ(YAML)๋ฅผ ์ˆ˜์ •ํ•ด ์ด๋ฏธ์ง€๋ฅผ ๋ณ€๊ฒฝํ•ด๋„ ๊ธฐ์กด ํŒŒ๋“œ๊ฐ€ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ด€๋ฆฌ์ž๊ฐ€ kubectl delete pod ๋ช…๋ น์œผ๋กœ ์ˆ˜๋™ ์‚ญ์ œํ•ด์•ผ๋งŒ ์ƒˆ ๋ฒ„์ „์˜ ํŒŒ๋“œ๊ฐ€ ๋œน๋‹ˆ๋‹ค. ๋ฐ๋ชฌ์…‹์€ ํ•œ ๋ฒˆ ๋„์šฐ๋ฉด ์žฅ๊ธฐ๊ฐ„ ์ผœ๋‘๋Š” ๋ชจ๋‹ˆํ„ฐ๋ง ์šฉ๋„๊ฐ€ ๋งŽ์•„ ๊ณผ๊ฑฐ์— ์ฃผ๋กœ ์“ฐ๋˜ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

  • RollingUpdate: ์ตœ์‹  ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์—์„œ ์ง€์›ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๋‹จ, ํ•˜๋‚˜์˜ ๋…ธ๋“œ์— ํŒŒ๋“œ๋ฅผ 2๊ฐœ ๋„์šธ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ maxUnavailable(๋™์‹œ์— ์‚ญ์ œ ๊ฐ€๋Šฅํ•œ ํŒŒ๋“œ ์ˆ˜)๋งŒ ์ง€์ •ํ•ด์„œ ๋กค๋ง ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.


2. ์Šคํ…Œ์ดํŠธํ’€์…‹ (StatefulSet): ์˜์›ํ•œ ๋ฐ์ดํ„ฐ์™€ ์ด๋ฆ„ ๐Ÿ’พ

์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ์ƒํƒœ(State)๋ฅผ ์œ ์ง€(ful) ํ•ด์•ผ ํ•˜๋Š” ์›Œํฌ๋กœ๋“œ๋ฅผ ์œ„ํ•œ ๋ฆฌ์†Œ์Šค์ž…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(MySQL, MongoDB ๋“ฑ)์ฒ˜๋Ÿผ ํŒŒ๋“œ๊ฐ€ ์žฌ์‹œ์ž‘๋˜๋”๋ผ๋„ ์ด์ „์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.


๋””ํ”Œ๋กœ์ด๋จผํŠธ(๋ ˆํ”Œ๋ฆฌ์นด์…‹)์™€ ๋น„๊ตํ•˜๋ฉด ํฐ ์ฐจ์ด์ ์ด ๋‘ ๊ฐ€์ง€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์ด๋ฆ„: ํŒŒ๋“œ ์ด๋ฆ„ ๋’ค์— ๋ฌด์ž‘์œ„ ๋ฌธ์ž์—ด์ด ๋ถ™๋Š” ๋””ํ”Œ๋กœ์ด๋จผํŠธ์™€ ๋‹ฌ๋ฆฌ, sample-statefulset-0, sample-statefulset-1์ฒ˜๋Ÿผ ์ˆœ์ฐจ์ ์ธ ์ˆซ์ž ์ธ๋ฑ์Šค๊ฐ€ ๋ถ™์Šต๋‹ˆ๋‹ค. ์‚ญ์ œ๋  ๋•Œ๋Š” ๋ฒˆํ˜ธ๊ฐ€ ํฐ ๊ฒƒ๋ถ€ํ„ฐ ์—ญ์ˆœ์œผ๋กœ ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค.

  2. ๋…๋ฆฝ์ ์ธ ์˜๊ตฌ ๋ณผ๋ฅจ: spec.volumeClaimTemplates ์„ค์ •์„ ํ†ตํ•ด ํŒŒ๋“œ๋งˆ๋‹ค ๊ณ ์œ ํ•œ ์˜๊ตฌ ๋ณผ๋ฅจ(Persistent Volume)์„ ๋ถ™์—ฌ์ค๋‹ˆ๋‹ค. ํŒŒ๋“œ๊ฐ€ ์ฃฝ๊ณ  ๋‹ค๋ฅธ ๋…ธ๋“œ์—์„œ ๋‹ค์‹œ ์‚ด์•„๋‚˜๋„, ์ด๋ฆ„์ด ๋˜‘๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด์— ์“ฐ๋˜ ๋ณผ๋ฅจ์„ ๊ทธ๋Œ€๋กœ ๋‹ค์‹œ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์กดํ•ฉ๋‹ˆ๋‹ค.


โ‘  ์Šคํ…Œ์ดํŠธํ’€์…‹ ์ƒ์„ฑ ์‹ค์Šต

์‹ค์Šต์„ ํ†ตํ•ด์„œ ์•Œ์•„๋ด…์‹œ๋‹ค.

# sample-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sample-statefulset
spec:
  # ์Šคํ…Œ์ดํŠธํ’€์…‹์€ ํŒŒ๋“œ์˜ ๊ณ ์œ ํ•œ ๋„คํŠธ์›Œํฌ ID๋ฅผ ์œ„ํ•ด ๋ฐ˜๋“œ์‹œ ์ „์šฉ Service๊ฐ€ ํ•„์š”ํ•จ
  serviceName: sample-statefulset
  # ์ƒ์„ฑ๋  ํŒŒ๋“œ์˜ ๊ฐœ์ˆ˜ (0๋ฒˆ, 1๋ฒˆ, 2๋ฒˆ ์ˆœ์„œ๋Œ€๋กœ ์ƒ์„ฑ๋จ)
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - name: nginx-container
        image: nginx
        volumeMounts:
        # ํ•˜๋‹จ์˜ volumeClaimTemplates์—์„œ ์ •์˜ํ•œ ์ด๋ฆ„์„ ์—ฌ๊ธฐ์— ์—ฐ๊ฒฐ
        - name: www
          # ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋  ๊ฒฝ๋กœ
          mountPath: /usr/share/nginx/html

  # ์Šคํ…Œ์ดํŠธํ’€์…‹์˜ ํ•ต์‹ฌ: ๊ฐ ํŒŒ๋“œ๋งˆ๋‹ค '๊ฐœ๋ณ„' ๋ณผ๋ฅจ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋Š” ํ…œํ”Œ๋ฆฟ
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      # ํ•œ ๋…ธ๋“œ์—์„œ๋งŒ ์ฝ๊ธฐ/์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค์ •
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          # ๊ฐ ํŒŒ๋“œ๋ณ„๋กœ ํ• ๋‹น๋  ์ €์žฅ ๊ณต๊ฐ„ ํฌ๊ธฐ
          storage: 1G
$ kubectl apply -f sample-statefulset.yaml

# ํŒŒ๋“œ ํ™•์ธ (0, 1, 2 ์ˆœ์„œ๋Œ€๋กœ ์ƒ์„ฑ๋จ)
$ kubectl get pods
# ๋ณผ๋ฅจ ๋ฐ ํด๋ ˆ์ž„ ํ™•์ธ
$ kubectl get pvc
$ kubectl get pv

ํ˜„ ์‹œ์ ์—์„œ๋Š” ํ•ด๋‹น ๋ช…๋ น์–ด๊ฐ€ ์•ˆ๋ ํ…๋ฐ StatefulSet์€ volumeClaimTemplates๋ฅผ ํ†ตํ•ด ๊ฐ ํŒŒ๋“œ๋งˆ๋‹ค 1GB์งœ๋ฆฌ ์ „์šฉ ๋””์Šคํฌ (PVC)๋ฅผ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ๊ตฌ์ถ•ํ•œ ๋กœ์ปฌ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค ํ™˜๊ฒฝ์—๋Š” ๋””์Šคํฌ๋ฅผ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์‹œ์Šคํ…œ(StorageClass) ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ๋””์Šคํฌ๋ฅผ ๋ฐ›์ง€ ๋ชปํ•ด ์‹คํ–‰์ด ์•ˆ๋˜๋Š” ๊ฒ๋‹ˆ๋‹ค.

๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด, ์กฐ๊ฑด์— ๋งž๋Š” PV(Persistent Volume) 3๊ฐœ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ง์ ‘ ๋งŒ๋“ค๋ฉด ๋ฉ๋‹ˆ๋‹ค.


3. ์žก (Job): ๋ชฉํ‘œ ๋‹ฌ์„ฑ ํ›„ ๊น”๋”ํ•˜๊ฒŒ ์‚ฌ๋ผ์ง ๐Ÿƒโ€โ™‚๏ธ

์•ž์„œ ๋ณธ ๋ฆฌ์†Œ์Šค๋“ค์ด ์›น์„œ๋ฒ„์ฒ˜๋Ÿผ ๊ณ„์† ์ผœ์ ธ ์žˆ์–ด์•ผ ํ•˜๋Š” ๋ฆฌ์†Œ์Šค๋ผ๋ฉด, ์žก(Job) ์€ ํ•œ ๋ฒˆ(๋˜๋Š” ์ง€์ •๋œ ํšŸ์ˆ˜๋งŒํผ)๋งŒ ์‹คํ–‰๋˜๊ณ  ๋ชฉ์ ์„ ๋‹ฌ์„ฑํ•˜๋ฉด ์Šค์Šค๋กœ ์ข…๋ฃŒ(Completed)๋˜๋Š” ์›Œํฌ๋กœ๋“œ์ž…๋‹ˆ๋‹ค.

์ฃผ๊ธฐ์ ์ธ ๋ฐฑ์—…, ๋Œ€๊ทœ๋ชจ ์—ฐ์‚ฐ, ๋ฐฐ์น˜(Batch) ์ž‘์—… ๋“ฑ์— ์“ฐ์ž…๋‹ˆ๋‹ค.


โ‘  ์›์ฃผ์œจ(Pi) ๊ณ„์‚ฐ Job ์‹ค์Šต

๋ฐ”๋กœ ์‹ค์Šต ๋จผ์ € ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

# sample-job.yaml
apiVersion: batch/v1  # Job์€ batch/v1์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4  # ์‹คํŒจ๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ์ตœ๋Œ€ ํšŸ์ˆ˜
$ kubectl apply -f sample-job.yaml
$ kubectl logs pi-์ผ๋ จ๋ฒˆํ˜ธ  # ์™„๋ฃŒ๋œ ํŒŒ๋“œ์˜ ๋กœ๊ทธ๋ฅผ ์ฐ์–ด๋ณด๋ฉด ํŒŒ์ด 2์ฒœ ์ž๋ฆฌ๊ฐ€ ์ถœ๋ ฅ๋จ!

ํ•ด๋‹น ํŒŒ๋“œ๋Š” ์—ฐ์‚ฐ์ด ๋๋‚˜๋ฉด Running ์ƒํƒœ์—์„œ Completed(์™„๋ฃŒ) ์ƒํƒœ๋กœ ๋ณ€๊ฒฝ๋˜์–ด ์ž‘์—…์„ ๋ฉˆ์ถฅ๋‹ˆ๋‹ค.

(์ดํ›„ ํ•˜๋‹จ์— ์„ค๋ช…ํ•  ttlSecondsAfterFinished ์˜ต์…˜์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด ๋กœ๊ทธ ํ™•์ธ์„ ์œ„ํ•ด ํŒŒ๋“œ ์ž์ฒด๋Š” ์‚ญ์ œ๋˜์ง€ ์•Š๊ณ  ๋‚จ์•„์žˆ์Šต๋‹ˆ๋‹ค.)


โ‘ก ํ•ต์‹ฌ ํŒŒ๋ผ๋ฏธํ„ฐ ์•Œ์•„๋ณด๊ธฐ

  • restartPolicy (์‹คํŒจ ์‹œ ๋Œ€์ฒ˜๋ฒ•)

  • Never: ์žฅ์• ๊ฐ€ ๋‚˜๋ฉด ์•„์˜ˆ ์ƒˆ๋กœ์šด ์ด๋ฆ„์˜ ํŒŒ๋“œ๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด์„œ ๋‹ค์‹œ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.

  • OnFailure: ํŒŒ๋“œ๋Š” ์ƒˆ๋กœ ๋งŒ๋“ค์ง€ ์•Š๊ณ , ๊ธฐ์กด ํŒŒ๋“œ ์•ˆ์˜ ์ปจํ…Œ์ด๋„ˆ ๋ช…๋ น์–ด๋งŒ ๋‹ค์‹œ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • ttlSecondsAfterFinished: ์žก์ด '์„ฑ๊ณต'ํ•˜๊ณ  ๋‚˜์„œ ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด ํŒŒ๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์‚ญ์ œ(์ฒญ์†Œ)ํ•ด์ฃผ๋Š” ์œ ์šฉํ•œ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

  • ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์˜ต์…˜

    ๋ชฉ์ ์— ๋”ฐ๋ผ ์žก์„ ๋ณ‘๋ ฌ๋กœ ํ์ž‰ํ•˜์—ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์ž‘์—… ์œ ํ˜•completions (์„ฑ๊ณต ํšŸ์ˆ˜)parallelism (๋ณ‘๋ ฌ ์‹คํ–‰ ์ˆ˜)
    ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๋Š” ๋‹จ์ผ ํƒœ์Šคํฌ1 (๊ธฐ๋ณธ๊ฐ’)1 (๊ธฐ๋ณธ๊ฐ’)
    ์ง€์ •๋œ ํšŸ์ˆ˜(N๋ฒˆ)๋ฅผ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰N์ž„์˜์˜ ์ˆซ์ž
    ์ˆœ์„œ๋Œ€๋กœ ํ•˜๋‚˜์”ฉ ์‹คํ–‰ํ•˜๋Š” ํ์„ค์ • ์•ˆ ํ•จ1
    N๊ฐœ๋ฅผ ๋ณ‘๋ ฌ๋กœ ๋ฝ‘์•„ ์“ฐ๋Š” ํ์„ค์ • ์•ˆ ํ•จ์ž„์˜์˜ ์ˆซ์ž (N)

4. ํฌ๋ก ์žก (CronJob): ์ฃผ๊ธฐ์ ์ธ ์Šค์ผ€์ค„๋ง โฐ

์žก(Job)์ด ์ˆ˜๋™์œผ๋กœ ํ•œ ๋ฒˆ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋ผ๋ฉด, ํฌ๋ก ์žก(CronJob) ์€ ๋ฆฌ๋ˆ…์Šค์˜ crontab์ฒ˜๋Ÿผ ํŠน์ • ์ฃผ๊ธฐ๋งˆ๋‹ค Job์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด ์ฃผ๋Š” ์›Œํฌ๋กœ๋“œ์ž…๋‹ˆ๋‹ค.

๋งค์ผ ์ž์ • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐฑ์—…, ๋งค์‹œ๊ฐ„ ๋กœ๊ทธ ์•„์นด์ด๋น™ ๋“ฑ์— ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.

# cronjob.yaml
apiVersion: batch/v1
kind: CronJob 
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"  # 1๋ถ„๋งˆ๋‹ค ์‹คํ–‰ (๋ถ„ ์‹œ ์ผ ์›” ์š”์ผ)
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent 
            command:
            - /bin/sh
            - -c
            - date; echo Hello from Kubernetes cluster
          restartPolicy: OnFailure

ํฌ๋ก ์žก์€ ์ง€์ •๋œ ์‹œ๊ฐ„๋งˆ๋‹ค ํŒŒ๋“œ๋ฅผ ๊ณ„์† ์žฌ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ณผ๊ฑฐ์˜ ์ด๋ ฅ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ 3๊ฐœ๊นŒ์ง€๋งŒ ๋‚จ๊ธฐ๊ณ  ์˜ค๋ž˜๋œ ํŒŒ๋“œ๋Š” ์•Œ์•„์„œ ์ง€์›Œ์ค๋‹ˆ๋‹ค.


โ‘  ๋™์‹œ ์‹คํ–‰ ์ œ์–ด (spec.concurrencyPolicy)

์‹คํ–‰ ์ฃผ๊ธฐ๊ฐ€ ์งง๊ฑฐ๋‚˜ ์ž‘์—…์ด ์˜ค๋ž˜ ๊ฑธ๋ ค ์ด์ „ ์ž‘์—…์ด ๋œ ๋๋‚ฌ๋Š”๋ฐ ๋‹ค์Œ ์ฃผ๊ธฐ ์‹œ๊ฐ„์ด ๋˜์—ˆ์„ ๋•Œ์˜ ๋™์ž‘์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

  • Allow (๊ธฐ๋ณธ๊ฐ’): ์ œํ•œ ์—†์ด ๋ฌด์กฐ๊ฑด ์ƒˆ ์žก์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • Forbid: ์ด์ „ ์žก์ด ์•ˆ ๋๋‚ฌ์œผ๋ฉด ์ด๋ฒˆ ์ฃผ๊ธฐ๋Š” ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค.

  • Replace: ์ด์ „ ์žก์„ ๊ฐ•์ œ๋กœ ์ทจ์†Œํ•˜๊ณ  ์ƒˆ๋กœ์šด ์žก์œผ๋กœ ๋ฎ์–ด์”Œ์›๋‹ˆ๋‹ค.


๐Ÿ’ก [ํ•ต์‹ฌ] ์‹ค๋ฌด ๊ฐ•์‚ฌ๋‹˜ ๊ฟ€ํŒ: ๋กœ๊ทธ๋Š” ๋ฐ˜๋“œ์‹œ ์™ธ๋ถ€(External)๋กœ!

ํฌ๋ก ์žก์ด๋‚˜ ํŒŒ๋“œ์˜ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•  ๋•Œ ๋งค๋ฒˆ ํ„ฐ๋ฏธ๋„์—์„œ kubectl logs๋ฅผ ์น˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ๋น„ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค. ์‹ค๋ฌด(์šด์˜ ๋‹จ๊ณ„)์—์„œ๋Š” ์™ธ๋ถ€ ๋กœ๊ทธ ์‹œ์Šคํ…œ(Elasticsearch, Datadog ๋“ฑ)์œผ๋กœ ๋กœ๊ทธ๋ฅผ ๋ฆฌ๋‹ค์ด๋ ‰์…˜ํ•˜์—ฌ ์ค‘์•™ ์ง‘์ค‘ํ™”ํ•˜๋Š” ๊ฒƒ์„ ๊ฐ•๋ ฅํžˆ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

  1. ๋กœ๊ทธ ํŒŒํŽธํ™” ํ•ด๊ฒฐ: ์›Œ์ปค ๋…ธ๋“œ์— ๋ฟ”๋ฟ”์ด ํฉ์–ด์ง„ ๋กœ๊ทธ๋ฅผ ํ•œ ๊ณณ์—์„œ ๊ฒ€์ƒ‰/๋ถ„์„

  2. ๊ณ ๊ฐ€์šฉ์„ฑ(HA): K8s ํด๋Ÿฌ์Šคํ„ฐ๋‚˜ ๋…ธ๋“œ๊ฐ€ ์ฃฝ์–ด๋„ ๋กœ๊ทธ๋Š” ์•ˆ์ „ํ•˜๊ฒŒ ๋ณด์กด

  3. ์ฐธ๊ณ : ๊ณผ๊ฑฐ์—๋Š” HostPath๋ฅผ ์จ์„œ ๋…ธ๋“œ์— ์ง์ ‘ ๋‚จ๊ธฐ๊ธฐ๋„ ํ–ˆ์œผ๋‚˜ ์š”์ฆ˜์€ ์•ˆ ์“ฐ๋Š” ์ถ”์„ธ์ž…๋‹ˆ๋‹ค.


5. ๋…ธ๋“œ ์ž์› ๋ณดํ˜ธํ•˜๊ธฐ (Cordon & Drain) ๐Ÿšง

์ง€๊ธˆ๊นŒ์ง€ ํŒŒ๋“œ๋ฅผ ๋„์šฐ๋Š” ๋ฒ•์„ ๋ฐฐ์› ๋‹ค๋ฉด, ์ด๋ฒˆ์—” "๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๋…ธ๋“œ(์„œ๋ฒ„)์—์„œ ํŒŒ๋“œ๋ฅผ ๋Œ€ํ”ผ์‹œํ‚ค๊ฑฐ๋‚˜ ๋„์šฐ์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰๋Š” ๋ฐฉ๋ฒ•" ์„ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ•˜๋“œ์›จ์–ด ์ ๊ฒ€์ด๋‚˜ ์ปค๋„ ์—…๋ฐ์ดํŠธ ์‹œ ํ•„์ˆ˜์ ์ธ ํด๋Ÿฌ์Šคํ„ฐ ์šด์˜ ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค.


โ‘  Cordon: "์—ฌ๊ธฐ์—” ๋” ์ด์ƒ ํŒŒ๋“œ ๋ฐฐ์ • ๊ธˆ์ง€!"

ํŠน์ • ๋…ธ๋“œ์— ๋ฌธ์ œ๊ฐ€ ๊ฐ์ง€๋˜์–ด ํ˜„ ์ƒํƒœ๋Š” ์œ ์ง€ํ•˜๋˜, ์ƒˆ๋กœ์šด ํŒŒ๋“œ๊ฐ€ ์Šค์ผ€์ค„๋ง(๋ฐฐ์น˜)๋˜๋Š” ๊ฒƒ๋งŒ ๋ง‰๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

# worker1 ๋…ธ๋“œ๋ฅผ ์Šค์ผ€์ค„๋ง ๋ถˆ๊ฐ€๋Šฅ ์ƒํƒœ๋กœ ๋ณ€๊ฒฝ
$ kubectl cordon worker1

# ๋””ํ”Œ๋กœ์ด๋จผํŠธ๋ฅผ 4๊ฐœ๋กœ ์Šค์ผ€์ผ ์•„์›ƒ ํ•ด๋ณด๋ฉด?
$ kubectl scale deployment sample-deployment --replicas=4

๐Ÿ‘‰ ํ™•์ธํ•ด ๋ณด๋ฉด ๊ธฐ์กด์— worker1์— ์žˆ๋˜ ํŒŒ๋“œ๋Š” ๊ทธ๋Œ€๋กœ ์‚ด์•„์žˆ์ง€๋งŒ, ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ํŒŒ๋“œ๋“ค์€ ๋ชจ๋‘ worker2์—๋งŒ ๋ชฐ๋ ค์„œ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.


โ‘ก Drain: "๋ฐฉ๋นผ์„ธ์š”. ๋…ธ๋“œ ๋น„์šฐ๊ธฐ"

๋…ธ๋“œ๋ฅผ ์™„์ „ํžˆ ์žฌ๋ถ€ํŒ…ํ•˜๊ฑฐ๋‚˜ ๊ต์ฒดํ•ด์•ผ ํ•ด์„œ, ํ•ด๋‹น ๋…ธ๋“œ์— ๋Œ๊ณ  ์žˆ๋Š” ๋ชจ๋“  ํŒŒ๋“œ๋ฅผ ๋‹ค๋ฅธ ๊ฑด๊ฐ•ํ•œ ๋…ธ๋“œ๋กœ ๊ฐ•์ œ ๋Œ€ํ”ผ(Eviction) ์‹œํ‚ฌ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. drain์„ ์‹คํ–‰ํ•˜๋ฉด ํ•ด๋‹น ๋…ธ๋“œ๋Š” ์ž๋™์œผ๋กœ cordon ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

# worker1์˜ ๋ชจ๋“  ํŒŒ๋“œ๋ฅผ ๋Œ€ํ”ผ์‹œํ‚ด
$ kubectl drain worker1 --ignore-daemonsets

๐Ÿ‘‰ ์ฃผ์˜: ๊ฐ ๋…ธ๋“œ๋งˆ๋‹ค ๋ฐ˜๋“œ์‹œ ํ•˜๋‚˜์”ฉ ๋– ์žˆ์–ด์•ผ ํ•˜๋Š” ๋ฐ๋ชฌ์…‹(DaemonSet) ํŒŒ๋“œ๋Š” ๋Œ€ํ”ผ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ์—๋Ÿฌ๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์œ„ ๋ช…๋ น์–ด์ฒ˜๋Ÿผ --ignore-daemonsets ์˜ต์…˜์„ ์ฃผ์–ด ๋ฐ๋ชฌ์…‹์€ ๋ฌด์‹œํ•˜๊ณ  ๋‚˜๋จธ์ง€ ํŒŒ๋“œ๋“ค๋งŒ ๋Œ€ํ”ผ์‹œ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค.


๋งˆ์น˜๋ฉฐ โœ๏ธ

์˜ค๋Š˜์€ ๊ฐ ๋…ธ๋“œ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ๋ชฌ์…‹๋ถ€ํ„ฐ, ๋ฐ์ดํ„ฐ๋ฅผ ์ง€ํ‚ค๋Š” ์Šคํ…Œ์ดํŠธํ’€์…‹, ์ผํšŒ์„ฑ ์ž‘์—…์„ ์œ„ํ•œ ์žก/ํฌ๋ก ์žก, ๊ทธ๋ฆฌ๊ณ  ๋…ธ๋“œ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋น„์šฐ๋Š” ์šด์˜ ์Šคํ‚ฌ๊นŒ์ง€ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์˜ ์‹ฌํ™” ์›Œํฌ๋กœ๋“œ๋“ค์„ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ํŠน์ˆ˜ ์›Œํฌ๋กœ๋“œ๋“ค์„ ๋ชฉ์ ์— ๋งž๊ฒŒ ์ ์žฌ์ ์†Œ์— ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ์ด ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋ฅผ ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค๋‹ต๊ฒŒ ์“ฐ๋Š” ์ง€๋ฆ„๊ธธ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ๋Š” ์™ธ๋ถ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์šฐ๋ฆฌ ์„œ๋น„์Šค๋ฅผ ์˜คํ”ˆํ•˜๋Š” ๊ด€๋ฌธ, ์„œ๋น„์Šค(Service)์™€ ์ธ๊ทธ๋ ˆ์Šค(Ingress) ์— ๋Œ€ํ•ด ๋‹ค๋ฃจ์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€