Kubernetes의 배포 전략과 컨트롤러 이해하기
Deployment
Deployment는 쿠버네티스에서 애플리케이션의 배포와 업데이트를 관리하는 핵심 컨트롤러다. 이를 통해 ReplicaSet의 생성 및 관리부터 애플리케이션 업데이트와 롤백까지 선언적으로 수행할 수 있다. Deployment를 사용하면 Pod 및 ReplicaSet을 명시적으로 생성할 수 있으며, 쿠버네티스 컨트롤 플레인은 현재 상태를 지속적으로 모니터링하여 원하는 상태로 유지한다.
Deployment의 주요 기능은 다음과 같다.
- Pod와 ReplicaSet의 생명주기를 자동으로 관리한다.
- 다양한 애플리케이션 배포 전략을 지원한다.
- 문제가 발생했을 때 이전 버전으로 롤백하는 기능을 제공한다.
- 애플리케이션의 확장성과 스케일링을 자동화한다.
Deployment 사용을 위한 기본적인 YAML 파일 구조는 다음과 같다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:1.0
ports:
- containerPort: 8080
ReCreate 배포 전략
ReCreate 배포 전략은 애플리케이션을 업데이트할 때 이전 버전의 모든 파드를 한 번에 종료하고 새 버전의 파드로 교체하는 가장 단순한 방식이다.
특징
- 작동 방식: 기존 버전의 모든 파드를 동시에 삭제한 후, 새 버전의 파드를 생성하여 배포를 완료한다.
- 다운타임: 이전 버전의 파드가 모두 중지되고 새 버전의 파드가 완전히 시작될 때까지 서비스 중단 시간이 발생한다.
- 자원 사용: 파드를 교체하는 과정에서 일시적으로 필요한 컴퓨팅 리소스가 줄어든다는 장점이 있다.
- 적합한 환경: 주로 개발 환경이나 짧은 다운타임이 허용되는 서비스 환경에서 사용된다.
ReCreate 전략을 설정하는 YAML 예시는 다음과 같다.
spec:
strategy:
type: Recreate
Rolling Update 배포 전략
Rolling Update는 쿠버네티스의 기본 배포 전략으로, 파드를 점진적으로 교체하여 서비스 중단 없이 애플리케이션을 안전하게 업데이트한다.
특징
- 작동 방식: 새 버전의 파드를 순차적으로 배포하면서 동시에 이전 버전의 파드를 점진적으로 제거하여 서비스 연속성을 보장한다.
- 다운타임: 제로 다운타임(Zero downtime) 배포를 목표로 하므로, 서비스 중단 없이 업데이트를 진행할 수 있다.
- 자원 사용: 업데이트 과정에서 새 버전과 이전 버전의 파드가 동시에 실행되는 구간이 있어 일시적으로 추가적인 컴퓨팅 자원이 필요하다.
- 점진적 배포: 한 번에 하나의 파드만 교체하거나, 미리 설정된 비율에 따라 여러 파드를 동시에 업데이트할 수 있다.
속도 제어 옵션
Rolling Update의 속도를 조절하기 위해 다음 두 가지 옵션을 사용할 수 있다.
- maxSurge: 업데이트 중 최대로 허용할 추가 파드의 수를 지정한다. 절대 개수(예: 1) 또는 replicas 대비 비율(예: 25%)로 설정할 수 있다. 예를 들어, replicas가 10이고 maxSurge가 25%라면, 업데이트 중 최대 3개의 추가 파드가 생성될 수 있으며, 총 파드 수는 13개를 넘지 않는다.
- maxUnavailable: 업데이트 중 사용 불가능 상태가 되어도 괜찮은 최대 파드의 수를 지정한다. 절대 개수(예: 1) 또는 replicas 대비 비율(예: 25%)로 설정할 수 있다. 예를 들어, replicas가 10이고 maxUnavailable이 25%라면, 업데이트 중 최대 3개의 파드가 비활성화될 수 있으며, 항상 최소 7개의 파드가 가용한 상태를 유지한다.
Rolling Update 전략을 설정하는 YAML은 다음과 같다.
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
변형된 Rolling Update 전략
Ramped Slow Rollout (점진적 느린 롤아웃):
- 새 버전의 배포 속도를 매우 세밀하게 제어할 때 사용한다.
maxSurge: 1
,maxUnavailable: 0
으로 설정하여 한 번에 단 하나의 파드만 교체하며, 항상 최소 요구 파드 수를 유지한다.
Best-effort Controlled Rollout (최선 노력 제어 롤아웃):
- 더 빠른 롤아웃을 위해 일정 비율의 파드 비활성화를 허용하는 방식이다.
maxUnavailable
을 특정 비율(예: 50%)로 설정하고maxSurge
를 0으로 설정하여, 가용 파드 수를 줄이면서 업데이트 속도를 높인다.
Blue/Green 배포 전략
Blue/Green 배포 전략은 쿠버네티스에서 기본 기능으로 제공되지는 않지만, Service 객체와 두 개의 Deployment 객체를 활용하여 효과적으로 구현할 수 있다.
특징
- 작동 방식: 현재 운영 중인 환경(Blue)과 동일한 구성으로 새로운 버전의 환경(Green)을 별도로 완전히 구축한 후, 쿠버네티스 Service의 라벨 셀렉터를 변경하여 트래픽을 한 번에 Green 환경으로 전환한다.
- 다운타임: 트래픽 전환이 라벨 변경을 통해 즉시 이루어지므로, 사용자 입장에서는 다운타임이 거의 발생하지 않는다.
- 버전 공존 방지: Blue 환경과 Green 환경이 동시에 사용자 트래픽을 처리하는 시간이 없으므로, 버전 간 호환성 문제를 원천적으로 방지할 수 있다.
- 신속한 롤백: Green 환경에서 문제가 발견될 경우, Service의 라벨 셀렉터를 다시 Blue 환경으로 변경하여 매우 빠르게 이전 버전으로 롤백할 수 있다.
- 자원 사용: 업데이트 기간 동안 두 개의 동일한 환경을 유지해야 하므로, 일시적으로 두 배의 컴퓨팅 리소스가 필요하다.
구현 방법은 다음과 같다.
- 현재 운영 중인 Blue 환경(Deployment)을 가리키는 Service를 설정한다.
- 새 버전을 배포할 Green 환경(Deployment)을 Blue 환경과 동일하게 구성한다.
- Green 환경에 대한 충분한 테스트를 수행한다.
- Service의 Selector 설정을 변경하여 트래픽이 Green 환경을 가리키도록 전환한다.
- Green 환경이 안정적으로 운영되는 것을 확인한 후, 더 이상 필요 없는 Blue 환경을 삭제한다.
Blue/Green 배포 시 서비스 트래픽 전환을 위한 YAML 예시는 다음과 같다.
apiVersion: v1
kind: Service
metadata:
name: blue-green-service
spec:
ports:
- name: "80"
port: 80
protocol: TCP
targetPort: 80
selector:
app: my-app
version: blue # 트래픽 전환 시 'version: green'으로 변경
type: NodePort
Canary 배포 전략
Canary 배포는 새 버전을 전체 사용자 중 극히 일부에게만 먼저 공개하여 실제 운영 환경에서의 안정성을 검증하고, 위험을 최소화하면서 점진적으로 배포를 확대하는 전략이다.
특징
- 작동 방식: 새 버전의 애플리케이션을 소수의 파드로 배포하고, Service나 Ingress를 통해 전체 트래픽의 일부(예: 5%)만을 새 버전으로 라우팅하여 실제 사용자 환경에서 테스트한다.
- 점진적 전환: 새 버전에서 문제가 발견되지 않으면, 새 버전으로 향하는 트래픽 비율을 점진적으로 늘려가며(예: 5% -> 20% -> 50% -> 100%), 최종적으로 모든 트래픽이 새 버전을 사용하도록 전환한다.
- 위험 감소: 만약 새 버전에서 예상치 못한 문제가 발생하더라도, 영향을 받는 사용자가 전체 중 일부에 불과하므로 서비스 전체 장애로 이어질 위험을 크게 줄일 수 있다.
- 타겟팅: 특정 HTTP 헤더, 쿠키, 사용자 지역 등을 기준으로 트래픽을 라우팅하여 특정 사용자 그룹만을 대상으로 새 버전을 테스트하는 것도 가능하다.
구현 방법은 다음과 같다.
- 기존 버전(예: v1)의 Deployment와 새 버전(예: v2)의 Deployment를 모두 생성한다. 두 Deployment는 동일한 라벨(예:
app: my-app
)을 가지지만, 버전 구분을 위한 별도 라벨(예:version: v1
,version: v2
)을 추가한다. - 두 Deployment를 모두 포괄하는 하나의 Service를 생성한다 (Service의 selector는
app: my-app
). - 초기에는 v2 Deployment의 replicas 수를 매우 작게 설정하여(예: 전체 파드의 5%), 적은 비율의 트래픽만 v2로 가도록 한다.
- 모니터링을 통해 v2 버전의 안정성을 확인하면서, 점진적으로 v2 Deployment의 replicas 수를 늘리고 v1 Deployment의 replicas 수를 줄여나간다.
- 또는, Istio와 같은 서비스 메시나 Ingress 컨트롤러의 고급 라우팅 규칙(가중치 기반 라우팅)을 사용하여 트래픽 비율을 세밀하게 제어한다.
DaemonSet, Job, CronJob
DaemonSet
DaemonSet은 쿠버네티스 클러스터 내의 모든 노드 또는 특정 조건을 만족하는 노드 그룹 각각에 지정된 파드의 복제본이 하나씩 실행되도록 보장하는 컨트롤러다.
특징
- 작동 방식: 각 노드마다 지정된 파드를 정확히 하나씩 배포하고, 해당 파드가 항상 실행 상태를 유지하도록 관리한다.
- 노드 추가 대응: 새로운 노드가 클러스터에 추가되면, DaemonSet 컨트롤러는 자동으로 해당 노드에도 지정된 파드를 배포한다.
- 노드 삭제 대응: 노드가 클러스터에서 제거되면, 해당 노드에서 실행되던 DaemonSet 파드는 자동으로 가비지 컬렉션(삭제)된다.
주요 사용 사례는 다음과 같다.
- 시스템 모니터링 에이전트 배포: 모든 노드의 성능 지표 수집을 위해 Prometheus Node Exporter와 같은 에이전트를 각 노드에 배포한다.
- 로그 수집기 배포: 모든 노드의 컨테이너 로그를 중앙 집중식 로깅 시스템으로 전송하기 위해 fluentd나 Filebeat 같은 로그 수집기를 각 노드에 배포한다.
- 클러스터 스토리지 데몬 실행: Ceph나 GlusterFS와 같은 분산 스토리지 시스템의 데몬을 각 노드에서 실행한다.
- 네트워크 플러그인 관리: Calico나 Cilium 같은 CNI(Container Network Interface) 플러그인의 에이전트를 각 노드에 배포하여 클러스터 네트워킹을 구성한다.
DaemonSet을 정의하는 YAML 예시는 다음과 같다.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitoring
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
# 마스터 노드에도 배포되도록 설정 (필요시)
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
containers:
- name: node-exporter
image: prom/node-exporter:latest
ports:
- containerPort: 9100
protocol: TCP
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
Job
Job은 하나 이상의 파드를 실행하여 특정 작업을 성공적으로 완료시키는 것을 목적으로 하는 컨트롤러다. 배치(Batch)성 작업이나 일회성 태스크를 수행하는 데 사용된다.
특징
- 작동 방식: 지정된 수의 파드가 성공적으로 완료될 때까지 파드를 생성하고 실행한다. 하나 이상의 파드가 실패하면, Job 컨트롤러는 설정된 재시도 정책에 따라 파드를 다시 시작할 수 있다.
- 파드 상태: Job에 의해 생성된 파드는 해당 작업(프로세스)이 성공적으로 종료되면 'Completed' 상태가 되며, 삭제되지 않고 남아 있는다. 이는 작업 결과나 로그를 확인할 수 있도록 하기 위함이다.
- 재시도 메커니즘: 파드가 실행 중인 노드에 장애가 발생하거나 파드 자체에서 오류가 발생하여 비정상 종료되면, Job 컨트롤러는 다른 노드에서 파드를 다시 생성하여 작업을 계속 수행한다.
restartPolicy
는 주로OnFailure
또는Never
로 설정한다.
주요 옵션은 다음과 같다.
- completions: Job이 성공적으로 완료되었다고 간주하기 위해 필요한 총 성공 파드 수를 지정한다. 예를 들어,
completions: 5
로 설정하면 5개의 파드가 성공적으로 종료되어야 Job이 완료된다. - parallelism: 동시에 실행될 수 있는 최대 파드의 수를 지정한다. 예를 들어,
parallelism: 2
로 설정하면, Job은 한 번에 최대 2개의 파드만 병렬로 실행한다.completions
수에 도달할 때까지 파드를 순차적으로 또는 병렬로 생성하며 관리한다. - activeDeadlineSeconds: Job이 시작된 후 최대로 실행될 수 있는 시간을 초 단위로 지정한다. 이 시간 내에 Job이 완료되지 못하면, 시스템은 실행 중인 모든 파드를 강제 종료시키고 Job 상태를 'DeadlineExceeded' 실패로 표시한다.
- backoffLimit: Job이 실패로 간주되기 전에 재시도할 최대 횟수를 지정한다.
Job을 정의하는 YAML 예시는 다음과 같다.
apiVersion: batch/v1
kind: Job
metadata:
name: data-processing-job
spec:
# 5개의 파드가 성공적으로 완료되어야 함
completions: 5
# 동시에 최대 2개의 파드만 실행
parallelism: 2
# 10분(600초) 내에 완료되지 않으면 실패 처리
activeDeadlineSeconds: 600
# 최대 3번까지 재시도
backoffLimit: 3
template:
spec:
containers:
- name: data-processor
image: data-processor:latest
command: ["python", "process_data.py"]
# 파드가 실패했을 경우에만 재시작
restartPolicy: OnFailure
CronJob
CronJob은 지정된 일정(schedule)에 따라 주기적으로 Job을 생성하고 실행하는 컨트롤러다. 리눅스의 cron
유틸리티와 유사한 방식으로 동작한다.
특징
- 작동 방식: 사용자가 정의한 cron 표현식 형식의 스케줄에 맞춰 Job 객체를 자동으로 생성한다. 생성된 각 Job은 해당 시점의 작업을 수행한다.
- 사용 사례: 데이터베이스 백업, 주기적인 리포트 생성, 배치성 이메일 발송, 시스템 상태 점검 등 정기적으로 실행되어야 하는 작업에 매우 유용하다.
주요 옵션은 다음과 같다.
- schedule: Job을 생성할 주기를 cron 표현식으로 정의한다. 예를 들어,
"0 2 * * *"
는 매일 새벽 2시에 Job을 실행하라는 의미다. (분 시 일 월 요일
) - concurrencyPolicy: 동시에 실행될 수 있는 Job 인스턴스를 어떻게 처리할지 정책을 지정한다.
- Allow(기본값): 이전 Job 실행이 완료되지 않았더라도, 예약된 시간이 되면 새로운 Job 생성을 허용한다. 여러 Job이 동시에 실행될 수 있다.
- Forbid: 이전 Job 실행이 아직 진행 중이라면, 다음 예약된 시간에는 새로운 Job 생성을 건너뛴다(skip). 이전 작업이 반드시 완료되어야 하는 경우 사용한다.
- Replace: 이전 Job 실행이 아직 진행 중이라면, 해당 Job을 먼저 취소(삭제)하고 새로운 Job을 생성하여 실행한다. 항상 최신 스케줄의 Job만 실행되도록 보장한다.
- startingDeadlineSeconds: 예약된 시간보다 늦게 Job 생성이 시작될 경우, 얼마나 지연될 때까지 Job 실행을 시도할지 최대 시간을 초 단위로 지정한다. 이 시간을 초과하면 해당 스케줄의 Job 실행은 실패로 간주된다.
- successfulJobsHistoryLimit: 성공적으로 완료된 Job의 기록(Job 객체와 관련 파드)을 몇 개까지 보존할지 지정한다. 기본값은 3이다.
- failedJobsHistoryLimit: 실패한 Job의 기록을 몇 개까지 보존할지 지정한다. 기본값은 1이다.
CronJob을 정의하는 YAML 예시는 다음과 같다.
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-report-generator
spec:
# 매일 오전 9시에 실행
schedule: "0 9 * * *"
# 이전 작업이 실행 중이면 다음 작업은 건너뜀
concurrencyPolicy: Forbid
# 스케줄 시간에서 100초 이상 지연되면 실행하지 않음
startingDeadlineSeconds: 100
# 성공한 Job 기록은 최근 5개까지 유지
successfulJobsHistoryLimit: 5
# 실패한 Job 기록은 최근 3개까지 유지
failedJobsHistoryLimit: 3
# 생성될 Job의 템플릿 정의
jobTemplate:
spec:
template:
spec:
containers:
- name: report-generator
image: report-generator:v1.2
command: ["/app/generate_report.sh"]
restartPolicy: OnFailure
추가 CronJob 정책 설명
- concurrencyPolicy: Allow: 이 정책은 주기적으로 실행해야 하는 간단한 작업에 적합하다. 이전 작업의 완료 여부와 관계없이 예약된 시간에 새 작업을 시작한다. 각 작업이 독립적일 때 유용하다.
- concurrencyPolicy: Forbid: 이전 작업이 완료되어야만 다음 작업을 실행할 수 있는 상황에 적합하며, 데이터 충돌이나 리소스 경쟁 가능성이 있는 작업에 유용하다. 예를 들어, 특정 리소스를 독점적으로 사용하는 백업 작업 등에 사용될 수 있다.
- concurrencyPolicy: Replace: 항상 가장 최신 상태의 작업 실행이 중요한 경우에 적합하다. 이전 작업이 아직 실행 중이라면 해당 작업을 중단시키고 새로운 작업을 시작한다. 상태 동기화나 최신 데이터 반영 작업 등에 활용될 수 있다.
'Tech > Kubenetes' 카테고리의 다른 글
Kubernetes (6) (0) | 2025.04.16 |
---|---|
Kubernetes (5) (1) | 2025.04.15 |
Kubernetes (3) (0) | 2025.04.11 |
Kubernetes (2) (0) | 2025.04.10 |
Kubernetes (1) (0) | 2025.04.08 |