Post

쿠버네티스 코어 오브젝트 (Pods, ReplicaSets, Deployments, StatefulSets, Services, Ingress, ConfigMaps, Secrets, PVC, Jobs, DaemonSets)

쿠버네티스 코어 오브젝트 (Pods, ReplicaSets, Deployments, StatefulSets, Services, Ingress, ConfigMaps, Secrets, PVC, Jobs, DaemonSets)

1. Pod: 쿠버네티스의 기본 실행 단위

Pod의 역할

Pod는 쿠버네티스에서 가장 작은 배포 단위다. 하나 이상의 컨테이너를 묶어서 하나의 실행 환경을 만든다.

Pod가 하는 일:

  • 컨테이너들이 같은 IP 주소를 공유하게 함
  • 컨테이너들이 같은 저장공간을 사용할 수 있게 함
  • 컨테이너들의 생명주기를 함께 관리

Pod 내부 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod
spec:
  containers:
    - name: web-server
      image: nginx:1.21
      ports:
        - containerPort: 80
      volumeMounts:
        - name: shared-data
          mountPath: /usr/share/nginx/html
    - name: content-updater
      image: busybox
      command: [ 'sh', '-c' ]
      args:
        - while true; do
          echo "$(date): Hello from sidecar" > /shared/index.html;
          sleep 30;
          done
      volumeMounts:
        - name: shared-data
          mountPath: /shared
  volumes:
    - name: shared-data
      emptyDir: { }

Pod 생명주기 과정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌─────────────────────────────────────────────────────────────┐
│                    Pod Lifecycle                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Pending → Running → Succeeded/Failed                       │
│     │         │           │                                 │
│     ▼         ▼           ▼                                 │
│  ┌─────┐  ┌─────┐     ┌─────────┐                           │
│  │스케줄│  │컨테이│      │파드 완료│                              │
│  │링 중│  │너실행│      │또는실패│                               │
│  └─────┘  └─────┘     └─────────┘                           │
│                                                             │
│  상태 확인 포인트:                                             │
│  • PodScheduled: 노드에 스케줄링 완료                            │
│  • Initialized: 모든 Init 컨테이너 완료                         │
│  • ContainersReady: 모든 컨테이너 준비 완료                       │
│  • Ready: Pod이 트래픽 수신 준비 완료                             │
└─────────────────────────────────────────────────────────────┘

2. ReplicaSet: Pod 복사본 관리자

ReplicaSet의 역할

ReplicaSet은 지정된 수의 Pod가 항상 실행되도록 보장한다. Control Loop 패턴을 사용해 원하는 상태를 계속 유지한다.

ReplicaSet이 하는 일:

  • Pod가 죽으면 새로 만들어서 교체
  • 너무 많은 Pod가 있으면 여분을 제거
  • 라벨 셀렉터로 관리할 Pod들을 찾아냄

ReplicaSet 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-replicaset
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
    matchExpressions:
      - key: tier
        operator: In
        values: [ "frontend" ]
  template:
    metadata:
      labels:
        app: nginx
        tier: frontend
    spec:
      containers:
        - name: nginx
          image: nginx:1.21
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 200m
              memory: 256Mi

ReplicaSet Controller의 Reconciliation 과정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌─────────────────────────────────────────────────────────────┐
│               ReplicaSet Reconciliation                     │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 현재 상태 확인                                         │
│     ├── 실행 중인 파드 수 계산                             │
│     ├── 라벨 셀렉터로 파드 필터링                          │
│     └── 파드 상태 검증 (Running, Pending, Failed)         │
│                                                             │
│  2. 원하는 상태와 비교                                     │
│     ├── Desired Replicas: 3                                │
│     ├── Current Replicas: 2                                │
│     └── Diff: +1 (파드 1개 추가 필요)                     │
│                                                             │
│  3. 조정 작업 수행                                         │
│     ├── 부족한 경우: 새 파드 생성                          │
│     ├── 초과한 경우: 가장 오래된 파드 삭제                 │
│     └── 실패한 파드: 새로운 파드로 교체                    │
│                                                             │
│  4. 상태 업데이트                                          │
│     ├── ReplicaSet Status 업데이트                         │
│     ├── 이벤트 생성 및 로그 기록                           │
│     └── 다음 Reconciliation 주기 대기                     │
└─────────────────────────────────────────────────────────────┘

3. Deployment: 애플리케이션 배포 관리자

Deployment의 역할

Deployment는 애플리케이션의 배포와 업데이트를 관리한다. ReplicaSet을 관리하는 상위 개념으로, 무중단 배포와 롤백 기능을 제공한다.

Deployment가 하는 일:

  • 새 버전 배포 시 무중단 업데이트 (롤링 업데이트)
  • 배포 이력 관리 및 롤백 기능 제공
  • 배포 과정에서 문제 발생 시 자동 중단

Deployment 계층 구조

1
2
3
4
5
Deployment
    ↓ (관리)
ReplicaSet (v1)     ReplicaSet (v2)
    ↓                    ↓
Pod Pod Pod         Pod Pod Pod

Deployment 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1      # 동시에 중단 가능한 파드 수
      maxSurge: 2           # 동시에 추가 생성 가능한 파드 수
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.21
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 5

롤링 업데이트 과정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌─────────────────────────────────────────────────────────────┐
│                 Rolling Update Process                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  초기 상태: nginx:1.20 (5개 파드)                         │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐                 │
│  │ v20 │ │ v20 │ │ v20 │ │ v20 │ │ v20 │                 │
│  └─────┘ └─────┘ └─────┘ └─────┘ └─────┘                 │
│                                                             │
│  1단계: 새 ReplicaSet 생성 및 파드 2개 추가 (maxSurge=2)  │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│  │ v20 │ │ v20 │ │ v20 │ │ v20 │ │ v20 │ │ v21 │ │ v21 │ │
│  └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
│                                                             │
│  2단계: 새 파드 Ready 확인 후 기존 파드 1개 제거          │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐         │
│  │ v20 │ │ v20 │ │ v20 │ │ v20 │ │ v21 │ │ v21 │         │
│  └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘         │
│                                                             │
│  3단계: 과정 반복하여 모든 파드 교체 완료                 │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐                 │
│  │ v21 │ │ v21 │ │ v21 │ │ v21 │ │ v21 │                 │
│  └─────┘ └─────┘ └─────┘ └─────┘ └─────┘                 │
└─────────────────────────────────────────────────────────────┘

4. StatefulSet: 상태가 있는 애플리케이션 관리자

StatefulSet의 역할

StatefulSet은 데이터베이스나 분산 시스템 같은 상태가 있는 애플리케이션을 관리한다. 각 Pod가 고유한 신원을 가져야 하는 경우에 사용한다.

StatefulSet이 Deployment와 다른 점:

  • Pod에 고정된 이름 부여 (web-0, web-1, web-2)
  • Pod마다 전용 저장공간 제공 (PVC 자동 생성)
  • 순서대로 생성/삭제/업데이트
  • 안정적인 네트워크 식별자 제공

StatefulSet vs Deployment 비교

특성DeploymentStatefulSet
파드 이름무작위순차적 (web-0, web-1, web-2)
네트워크 ID임시적안정적 (web-0.service.ns.svc.cluster.local)
스토리지공유 가능파드별 전용 PVC
배포 순서병렬순차적
업데이트롤링 (무작위)순차적 (역순)

StatefulSet 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-cluster
spec:
  serviceName: mysql
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: root-password
          volumeMounts:
            - name: mysql-storage
              mountPath: /var/lib/mysql
  volumeClaimTemplates:
    - metadata:
        name: mysql-storage
      spec:
        accessModes: [ "ReadWriteOnce" ]
        storageClassName: fast-ssd
        resources:
          requests:
            storage: 100Gi

StatefulSet 배포 과정

1
2
3
4
5
6
7
8
9
10
순차적 배포:
mysql-0 → Ready → mysql-1 → Ready → mysql-2

역순 업데이트:
mysql-2 업데이트 → mysql-1 업데이트 → mysql-0 업데이트

안정적 네트워크 식별자:
mysql-0.mysql.default.svc.cluster.local
mysql-1.mysql.default.svc.cluster.local
mysql-2.mysql.default.svc.cluster.local

5. Service: 네트워크 연결 관리자

Service의 역할

Service는 Pod들에 대한 안정적인 네트워크 접근 방법을 제공한다. Pod의 IP가 계속 바뀌는 문제를 해결하고, 로드밸런싱 기능도 제공한다.

Service가 필요한 이유:

  • Pod는 죽었다 살아나면서 IP가 계속 바뀜
  • 여러 Pod 중 어느 것에 요청을 보내야 할지 모름
  • Service가 이런 문제를 해결하고 로드밸런싱도 제공

Service 타입별 역할과 설정

1. ClusterIP (기본값) - 클러스터 내부 전용

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: ClusterIP
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080

2. NodePort - 외부 접근 가능

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
  name: web-nodeport
spec:
  type: NodePort
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 31000  # 30000-32767 범위

3. LoadBalancer - 클라우드 로드밸런서 자동 생성

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Service
metadata:
  name: web-loadbalancer
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080

6. Ingress: HTTP/HTTPS 라우팅 관리자

Ingress의 역할

Ingress는 클러스터 외부에서 HTTP/HTTPS로 들어오는 트래픽을 관리한다. 하나의 진입점에서 여러 서비스로 라우팅하는 역할을 한다.

Ingress가 하는 일:

  • 도메인별로 다른 서비스로 라우팅
  • URL 경로별로 다른 서비스로 분기
  • SSL/TLS 인증서 관리
  • 로드밸런싱과 트래픽 제어

Ingress 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
  tls:
    - hosts:
        - api.example.com
        - web.example.com
      secretName: example-tls
  rules:
    - host: web.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-service
                port:
                  number: 80
    - host: api.example.com
      http:
        paths:
          - path: /v1
            pathType: Prefix
            backend:
              service:
                name: api-v1-service
                port:
                  number: 80
          - path: /v2
            pathType: Prefix
            backend:
              service:
                name: api-v2-service
                port:
                  number: 80

Ingress 라우팅 과정

1
2
3
4
5
외부 요청 → Ingress Controller → Service → Pod

web.example.com/     → web-service     → web Pod
api.example.com/v1/  → api-v1-service  → API v1 Pod
api.example.com/v2/  → api-v2-service  → API v2 Pod

7. ConfigMap: 설정 데이터 관리자

ConfigMap의 역할

ConfigMap은 애플리케이션의 설정 정보를 코드와 분리하여 저장한다. 환경에 따라 다른 설정을 적용할 때 유용하다.

ConfigMap이 하는 일:

  • 환경변수로 설정값 전달
  • 설정 파일을 볼륨으로 마운트
  • 코드 수정 없이 설정 변경 가능

ConfigMap 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  # 키-값 쌍
  database_url: "postgres://db:5432/myapp"
  log_level: "info"
  feature_flags: "feature1=true,feature2=false"

  # 파일 형태
  nginx.conf: |
    server {
        listen 80;
        server_name localhost;
        location / {
            proxy_pass http://backend:8080;
            proxy_set_header Host $host;
        }
    }

ConfigMap 사용 방법

환경변수로 주입:

1
2
3
4
5
6
7
8
9
10
11
12
spec:
  containers:
    - name: app
      env:
        - name: DATABASE_URL
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: database_url
      envFrom:
        - configMapRef:
            name: app-config

볼륨 마운트:

1
2
3
4
5
6
7
8
9
10
spec:
  containers:
    - name: app
      volumeMounts:
        - name: config-volume
          mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: app-config

8. Secret: 민감한 정보 관리자

Secret의 역할

Secret은 비밀번호, API 키, 인증서 같은 민감한 정보를 안전하게 저장한다. ConfigMap과 유사하지만 보안이 강화된 버전이다.

Secret과 ConfigMap의 차이:

  • Secret: 민감한 정보 (Base64 인코딩, 암호화 가능)
  • ConfigMap: 일반 설정 정보 (평문)

Secret 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
data:
  # Base64로 인코딩된 값
  database-password: cGFzc3dvcmQxMjM=
  api-key: YWJjZGVmZ2hpams=
stringData:
  # 평문으로 입력 (자동으로 Base64 인코딩됨)
  smtp-password: "my-secret-password"
---
# Docker Registry 인증용 Secret
apiVersion: v1
kind: Secret
metadata:
  name: docker-registry-secret
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: |
    {
      "auths": {
        "registry.example.com": {
          "username": "user",
          "password": "pass",
          "auth": "dXNlcjpwYXNz"
        }
      }
    }

Secret 사용 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
spec:
  containers:
    - name: app
      env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: database-password
      volumeMounts:
        - name: secret-volume
          mountPath: /etc/secrets
          readOnly: true
  volumes:
    - name: secret-volume
      secret:
        secretName: app-secrets
        defaultMode: 0400  # 읽기 전용

9. PersistentVolumeClaim: 저장공간 요청서

PVC의 역할

PVC는 Pod가 사용할 영구 저장공간을 요청한다. Pod가 재시작되거나 다른 노드로 이동해도 데이터가 보존된다.

PVC가 하는 일:

  • 필요한 저장공간 크기와 성능 특성을 명시
  • 스토리지 클래스에 따라 적절한 볼륨 할당
  • Pod 생명주기와 독립적으로 데이터 보존

PVC 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 고성능 SSD 스토리지
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: database-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast-ssd
  resources:
    requests:
      storage: 100Gi
---
# 대용량 표준 스토리지
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: logs-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: standard
  resources:
    requests:
      storage: 1Ti

Volume Access Modes

Mode설명적합한 용도
ReadWriteOnce (RWO)단일 노드에서 읽기/쓰기데이터베이스, 단일 인스턴스 앱
ReadOnlyMany (ROX)여러 노드에서 읽기 전용정적 컨텐츠, 공유 설정
ReadWriteMany (RWX)여러 노드에서 읽기/쓰기공유 파일 시스템, 로그 수집

10. Job: 일회성 작업 관리자

Job의 역할

Job은 한 번 실행하고 끝나는 작업을 관리한다. 웹 서버처럼 계속 실행되는 서비스와 달리, 특정 작업을 완료하면 종료한다.

Job이 하는 일:

  • 작업 완료까지 Pod 실행 유지
  • 실패 시 자동 재시도
  • 여러 작업을 병렬로 실행 가능
  • 작업 완료 후 Pod 정리

Job 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: batch/v1
kind: Job
metadata:
  name: data-migration
spec:
  # 완료할 작업 수
  completions: 5
  # 동시 실행할 파드 수
  parallelism: 2
  # 재시도 횟수
  backoffLimit: 3
  # 작업 완료 후 파드 유지 시간
  ttlSecondsAfterFinished: 3600
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: migrator
          image: migration:latest
          command:
            - /bin/sh
            - -c
            - |
              echo "Starting migration batch ${JOB_COMPLETION_INDEX}"
              migrate --batch=${JOB_COMPLETION_INDEX}

Job 실행 과정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌─────────────────────────────────────────────────────────────┐
│                    Job Execution Process                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  목표: 5개 작업 완료, 최대 2개 병렬 실행                  │
│                                                             │
│  1단계: Pod 2개 동시 시작                                  │
│  ┌───────────┐ ┌───────────┐                               │
│  │ Task 1    │ │ Task 2    │                               │
│  │ Running   │ │ Running   │                               │
│  └───────────┘ └───────────┘                               │
│                                                             │
│  2단계: Task 1 완료, Task 3 시작                          │
│  ┌───────────┐ ┌───────────┐ ┌───────────┐                │
│  │ Task 1    │ │ Task 2    │ │ Task 3    │                │
│  │Completed  │ │ Running   │ │ Running   │                │
│  └───────────┘ └───────────┘ └───────────┘                │
│                                                             │
│  3단계: 모든 작업 완료까지 반복                           │
│  ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│  │ Task 1-5  │ │   All     │ │ Complete  │ │    Job    │ │ Finished  │ │
│  │Completed  │ │Completed  │ │   Tasks   │ │  Status   │ │   Clean   │ │
│  └───────────┘ └───────────┘ └───────────┘ └───────────┘ └───────────┘ │
└─────────────────────────────────────────────────────────────┘

11. CronJob: 정기 작업 관리자

CronJob의 역할

CronJob은 정해진 시간에 반복적으로 실행되는 작업을 관리한다. 리눅스의 cron과 같은 기능을 제공한다.

CronJob이 하는 일:

  • 정해진 스케줄에 따라 Job 자동 생성
  • 백업, 로그 정리, 리포트 생성 등에 활용
  • 작업 이력 관리 및 실패 시 알림

CronJob 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
apiVersion: batch/v1
kind: CronJob
metadata:
  name: database-backup
spec:
  # 매일 새벽 2시에 실행
  schedule: "0 2 * * *"
  # 동시 실행 정책
  concurrencyPolicy: Forbid
  # 실패한 작업 보관 수
  failedJobsHistoryLimit: 3
  # 성공한 작업 보관 수
  successfulJobsHistoryLimit: 1
  # 시작 기한 (초)
  startingDeadlineSeconds: 300
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: backup
              image: postgres:13
              command:
                - /bin/bash
                - -c
                - |
                  BACKUP_FILE="/backup/db_$(date +%Y%m%d_%H%M%S).sql"
                  pg_dump $DATABASE_URL > $BACKUP_FILE
                  aws s3 cp $BACKUP_FILE s3://backup-bucket/database/
                  rm $BACKUP_FILE

CronJob 스케줄 예시

1
2
3
4
5
"0 2 * * *"     # 매일 새벽 2시
"0 */6 * * *"   # 6시간마다
"0 0 * * 0"     # 매주 일요일 자정
"0 0 1 * *"     # 매월 1일 자정
"0 9-17 * * 1-5" # 평일 오전 9시부터 오후 5시까지 매시간

12. DaemonSet: 노드별 필수 서비스 관리자

DaemonSet의 역할

DaemonSet은 모든 노드(또는 특정 노드)에서 반드시 실행되어야 하는 시스템 레벨 서비스를 관리한다.

DaemonSet이 하는 일:

  • 새 노드가 클러스터에 추가되면 자동으로 Pod 배치
  • 노드가 제거되면 해당 Pod도 함께 제거
  • 시스템 모니터링, 로그 수집, 네트워킹 등에 주로 사용
  • 각 노드마다 정확히 하나의 Pod만 실행

DaemonSet 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-collector
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: log-collector
  template:
    metadata:
      labels:
        name: log-collector
    spec:
      # 시스템 권한 필요
      serviceAccountName: log-collector
      hostNetwork: true
      hostPID: true
      containers:
        - name: fluentd
          image: fluentd:v1.14
          resources:
            limits:
              memory: 512Mi
              cpu: 100m
          volumeMounts:
            # 호스트의 로그 디렉토리 마운트
            - name: varlog
              mountPath: /var/log
              readOnly: true
            - name: containers
              mountPath: /var/lib/docker/containers
              readOnly: true
            # Fluentd 설정
            - name: config
              mountPath: /fluentd/etc
          env:
            - name: ELASTICSEARCH_HOST
              value: "elasticsearch.logging.svc.cluster.local"
      volumes:
        - name: varlog
          hostPath:
            path: /var/log
        - name: containers
          hostPath:
            path: /var/lib/docker/containers
        - name: config
          configMap:
            name: fluentd-config
      # 특정 노드에만 배포 (선택사항)
      nodeSelector:
        node-type: worker
      # 노드 장애 시 빠른 재배포
      tolerations:
        - key: node.kubernetes.io/not-ready
          operator: Exists
          effect: NoExecute
          tolerationSeconds: 30

DaemonSet 배포 과정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
┌─────────────────────────────────────────────────────────────┐
│                DaemonSet Deployment Process                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  클러스터 상태: 3개 노드                                   │
│                                                             │
│  ┌─────────┐    ┌─────────┐    ┌─────────┐                 │
│  │ Node-1  │    │ Node-2  │    │ Node-3  │                 │
│  │         │    │         │    │         │                 │
│  │ ┌─────┐ │    │ ┌─────┐ │    │ ┌─────┐ │                 │
│  │ │ Log │ │    │ │ Log │ │    │ │ Log │ │                 │
│  │ │ Pod │ │    │ │ Pod │ │    │ │ Pod │ │                 │
│  │ └─────┘ │    │ └─────┘ │    │ └─────┘ │                 │
│  └─────────┘    └─────────┘    └─────────┘                 │
│                                                             │
│  새 노드 추가 시:                                         │
│  ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐ │
│  │ Node-1  │    │ Node-2  │    │ Node-3  │    │ Node-4  │ │
│  │ ┌─────┐ │    │ ┌─────┐ │    │ ┌─────┐ │    │ ┌─────┐ │ │
│  │ │ Log │ │    │ │ Log │ │    │ │ Log │ │    │ │ Log │ │ │
│  │ │ Pod │ │    │ │ Pod │ │    │ │ Pod │ │    │ │ Pod │ │ │
│  │ └─────┘ │    │ └─────┘ │    │ └─────┘ │    │ └─────┘ │ │
│  └─────────┘    └─────────┘    └─────────┘    └─────────┘ │
│                                              ↑             │
│                                        자동으로 Pod 생성    │
└─────────────────────────────────────────────────────────────┘

DaemonSet 주요 용도

  • 로그 수집기: Fluentd, Filebeat, Logstash
  • 모니터링 에이전트: Prometheus Node Exporter, Datadog Agent
  • 네트워크 플러그인: Calico, Flannel, Weave
  • 보안 에이전트: Falco, Twistlock
  • 스토리지 드라이버: Ceph, GlusterFS

오브젝트 간의 관계와 전체 구조

계층적 관리 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌─────────────────────────────────────────────────────────────┐
│                  Kubernetes Object Hierarchy                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  외부 접근 계층:                                           │
│  Ingress → Service → Pod                                    │
│                                                             │
│  워크로드 관리 계층:                                       │
│  Deployment → ReplicaSet → Pod                              │
│  StatefulSet → Pod (+ PVC)                                  │
│  DaemonSet → Pod (각 노드마다)                             │
│  Job/CronJob → Pod (임시)                                   │
│                                                             │
│  설정 및 데이터 계층:                                     │
│  Pod ← ConfigMap (설정)                                     │
│  Pod ← Secret (민감정보)                                    │
│  Pod ← PVC (영구저장소)                                     │
└─────────────────────────────────────────────────────────────┘

실제 애플리케이션 예시

웹 애플리케이션 전체 구성:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# 1. 네임스페이스
apiVersion: v1
kind: Namespace
metadata:
  name: webapp

---
# 2. 설정 관리
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: webapp
data:
  database_host: "mysql-service"
  redis_host: "redis-service"

---
# 3. 민감정보 관리
apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
  namespace: webapp
stringData:
  db_password: "secret123"
  api_key: "abcd1234"

---
# 4. 데이터베이스 (StatefulSet)
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  namespace: webapp
spec:
  serviceName: mysql-service
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: db_password
          volumeMounts:
            - name: mysql-data
              mountPath: /var/lib/mysql
  volumeClaimTemplates:
    - metadata:
        name: mysql-data
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 20Gi

---
# 5. 데이터베이스 서비스
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
  namespace: webapp
spec:
  clusterIP: None  # Headless Service
  selector:
    app: mysql
  ports:
    - port: 3306

---
# 6. 웹 애플리케이션 (Deployment)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
  namespace: webapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
        - name: webapp
          image: webapp:latest
          ports:
            - containerPort: 8080
          env:
            - name: DATABASE_HOST
              valueFrom:
                configMapKeyRef:
                  name: app-config
                  key: database_host
            - name: DATABASE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: db_password
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 30
            periodSeconds: 5

---
# 7. 웹 애플리케이션 서비스
apiVersion: v1
kind: Service
metadata:
  name: webapp-service
  namespace: webapp
spec:
  selector:
    app: webapp
  ports:
    - port: 80
      targetPort: 8080

---
# 8. 외부 접근 (Ingress)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapp-ingress
  namespace: webapp
spec:
  rules:
    - host: myapp.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: webapp-service
                port:
                  number: 80

---
# 9. 정기 백업 작업 (CronJob)
apiVersion: batch/v1
kind: CronJob
metadata:
  name: db-backup
  namespace: webapp
spec:
  schedule: "0 2 * * *"  # 매일 새벽 2시
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: backup
              image: mysql:8.0
              command:
                - /bin/bash
                - -c
                - mysqldump -h mysql-service -u root -p$MYSQL_ROOT_PASSWORD mydb > /backup/backup_$(date +%Y%m%d).sql
              env:
                - name: MYSQL_ROOT_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      name: app-secrets
                      key: db_password

주요 Best Practices

1. 리소스 관리:

1
2
3
4
5
6
7
resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 512Mi

2. 헬스 체크:

1
2
3
4
5
6
7
8
9
10
11
12
13
livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5

3. 보안 설정:

1
2
3
4
5
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false

4. 라벨링 전략:

1
2
3
4
5
6
metadata:
  labels:
    app: webapp
    version: v1.2.0
    environment: production
    component: frontend
This post is licensed under CC BY 4.0 by the author.