쿠버네티스 컨트롤러 종류
Deployment란?
Deployment는 ReplicaSet의 상위 개념으로, Pod와 ReplicaSet에 대한 배포를 관리합니다. 운영 중에 어플리케이션의 새 버전을 배포해야하거나 부하가 증가하면서 Pod를 추가하는 등 여러 가지 동작을 Deployment로 관리할 수 있습니다.
또한 Deployment는 배포에 대한 이력을 관리하는데 만약 배포한 새버전의 문제가 생긴 경우 Deployment를 통해 쉽게 이전 버전으로 롤백할 수 있습니다. 쿠버네티스로 서비스를 운영하는 상황이라면 ReplicaSet만으로 운영하기 보다는 대부분 Deployment단위로 Pod와 ReplicaSet을 관리하여 운영합니다.
Deployment 구성
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-deployment
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: demo-container
image: nginx:latest
- .spec.replicas
- 생성할 Pod의 수를 지정해줍니다.
- .spec.selector
- 식별할 Pod를 지정해줍니다.
- .spec.selector.matchLables를 통해 식별할 Pod의 라벨을 지정해줍니다.
- .spec.template
- Pod의 구성을 정의합니다.
Deployment 업데이트
두 가지의 전략- RollingUpdate, Recreate
RollingUpdate
RollingUpdate 배포 전략은 무중단 배포 전략으로 기존 버전의 Pod를 하나씩 삭제하고 새 버전의 Pod를 생성하면서 순차적으로 교체하는 방법입니다. Pod가 순차적으로 교체되기 때문에 다운타임이 발생하지 않는다는 장점이 있지만, 이전 버전의 Pod와 새 버전의 Pod가 공존하는 시간이 발생하게됩니다.
RollingUpdate 사용 예시)
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-deployment
spec:
replicas: 10
selector:
matchLabels:
app: nginx
strategy:
type: RollingUpdate # .spec.strategy.type을 RollingUpdate로 지정 생략시 기본값으로 RollingUpdate로 지정됨
rollingUpdate:
maxSurge: 3
maxUnavailable: 2
minReadySeconds: 10 # Pod의 Status가 Ready가 될때까지의 최소대기시간, Pod의 변화를 관찰하기위해 지정해줌
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: demo-container
image: nginx:latest
RollingUpdate 방식을 사용할 때 maxSurge와 maxUnavailable을 명시하여 Rolling Update의 프로세스를 제어할 수 있습니다.
- maxSurge
- Rolling Update 시 동시에 생성할 수 있는 Pod의 최대 개수 지정, 개수 혹은 비율(%)로 지정 가능, 기본값 25%
- 개수로 지정하게 되는 경우 백분율로 올림하여 계산합니다.
- maxUnavailable이 0일 경우 0이될 수 없습니다.
- 만약 maxSurge의 값이 30% 라면 업데이트하는 동안 항상 실행(Running) 중인 파드의 수가 최대 replicas의 130%가 되도록 보장합니다.
- maxUnavailable
- Rolling Update 시 동시에 삭제할 수 있는 Pod의 최대 개수 지정, 개수 혹은 비율(%)로 지정 가능, 기본값 25%
- 개수로 지정하게 되는 경우 백분율로 내림하여 계산합니다.
- maxSurge가 0일 경우 0이될 수 없습니다.
- 만약 maxUnavailable의 값이 30% 라면 업데이트 하는 동안 항상 사용가능(Available)한 파드의 수가 최소 replicas의 70% 이상이 되도록 보장합니다.
Recreate
Recreate 배포 전략은 가장 단순한 배포 전략으로, 기존 버전의 Pod를 모두 삭제한 후 새 버전의 Pod를 생성하는 방법입니다. Recreate 배포 전략은 단순하지만 위 그림처럼 새 버전의 ReplicaSet이 생성되기 전까지 다운타임이 발생할 수 있다는 단점이 있습니다.
DaemonSet이란?
DaemonSet은 쿠버네티스 클러스터의 모든 노드(또는 선택한 특정 노드)에 동일한 파드(Pod)를 자동으로 배포하고 관리하는 리소스입니다. 주로 각 노드마다 반드시 실행되어야 하는 작업들을 수행할 때 사용됩니다.
주요 특징
- 전체 노드 배포:
클러스터 내 모든 노드에 특정 파드를 실행하여, 각 노드에서 동일한 기능(예: 로깅, 모니터링, 네트워크 플러그인 등)을 수행할 수 있게 합니다. - 자동 동기화:
새로운 노드가 클러스터에 추가되면 자동으로 DaemonSet에 정의된 파드가 해당 노드에도 생성됩니다. 반대로, 노드가 클러스터에서 제거되면 해당 노드의 파드도 함께 정리됩니다. - 선택적 배포:
노드 셀렉터나 토인트/톨러레이션(Taints/Tolerations)을 활용해 특정 노드 그룹에만 파드를 배포할 수도 있습니다. 이를 통해 클러스터의 특정 영역에서만 데몬을 실행할 수 있습니다. - 자체 치유:
실행 중인 파드가 비정상적으로 종료되면, 쿠버네티스가 자동으로 새 파드를 생성해 클러스터의 원하는 상태를 유지합니다.
사용 사례
- 모니터링 에이전트:
Prometheus Node Exporter와 같은 모니터링 도구를 각 노드에서 실행해, 노드별 시스템 메트릭을 수집합니다. - 로그 수집기:
Fluentd나 Logstash와 같이 각 노드의 로그를 중앙 로그 시스템으로 전달하는 에이전트를 배포합니다.
동작 방식
- 배포:
DaemonSet을 생성하면 쿠버네티스 컨트롤 플레인이 현재 클러스터에 존재하는 모든 노드에 대해 파드를 생성합니다. - 노드 추가:
이후 클러스터에 새로운 노드가 추가되면, 자동으로 DaemonSet에 정의된 파드가 해당 노드에 생성되어 일관된 환경을 유지합니다. - 관리:
특정 노드에서 파드가 실패하면, 쿠버네티스가 즉시 새로운 파드를 생성하여 그 노드에 다시 배포합니다.
예시)
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: kube-system # 1
labels:
k8s-app: fluentd-logging # 2
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
updateStrategy:
type: RollingUpdate # 3
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 # 4
env:
- name: testenv
value: value
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
#1 로그 수집기는 쿠버네티스 관리용 파드나 설정이므로, .metadata.namespace의 필드를 kube-system 네임스페이스로 설정합니다.
#2 .metadata.labels.k8s.app은 오브젝트를 식별하는 레이블로 키를 k8s-app인 값을 fluentd-loggin으로 설정합니다.
#3 데몬셋의 파드를 업데이트하는 방법으로 RollingUpdate로 설정합니다. .spec.updateStrategy.type 필드는 OnDelete와 RollingUpdate 두 가지 중 하나의 값을 설정합니다.
#4 로그 수집에 사용되는 fluentd(플루언트디)의 컨테이너 이미지를 설정합니다.
StatefulSet을 알기전에
Stateless Application
클라이언트와 서버 관계에서, 서버가 클라이언트의 상태를 보존하지 않는 형태의 서비스입니다. 말 그대로 상태가 없는 애플리케이션으로 대표적으로 Apache, Nginx와 같은 Web server가 있습니다.
Stateless 애플리케이션은 쿠버네티스에서 삭제/생성 시 같은 역할을 하는 애플리케이션을 생성하면됩니다. 이 때 앱의 이름은 중요하지 않습니다. Stateless 애플리케이션은 Volume이 반드시 필요하진 않지만 하나의 볼륨에 모든 애플리케이션이 연결되어 사용할 수 있습니다.
쿠버네티스에서는 Replication Controller, Replicaset, Deployment와 같은 컨트롤러를 이용하여 Stateless 파드들을 관리하였습니다.
Stateful Application
클라이언트와 서버 관계에서, 서버가 클라이언트의 상태를 보존하는 형태의 서비스입니다. 말 그대로 상태를 저장하는 형태의 애플리케이션으로 대표적으로 Mongodb, redis와 같은 Database가 있습니다.
Stateful 애플리케이션은 쿠버네티스에서 삭제/생성 시 역할에 따라 다르게 애플리케이션을 생성해야합니다. 위의 그림에서 Arbiter 역할을 하는 애플리케이션이 다운될 경우 Arbiter 애플리케이션을 생성해야합니다. 따라서 애플리케이션의 이름으로 어떤 역할을 하는 애플리케이션인지 식별해야하므로 이름이 변경되면 안됩니다. Stateful은 각각의 애플리케이션이 역할이 다른만큼 각각의 애플리케이션이 다른 Volume을 사용합니다. 보통 내부 시스템이 데이터베이스 저장을 위해 연결합니다.
쿠버네티스에서는 스테이트풀셋(StatefulSet)이라는 컨트롤러로 상태가 있는 파드(Stateful Application)들을 관리합니다.
StatefulSet이란?
StatefulSet은 쿠버네티스 클러스터에서 상태 정보를 유지해야 하는 애플리케이션을 안정적으로 배포하고 관리하기 위한 객체입니다. Deployment와 달리, 각 파드에 고유한 네트워크 ID와 영속적인 스토리지를 제공함으로써, 데이터베이스나 분산 시스템 같이 파드 간의 정교한 상태 관리가 필요한 애플리케이션에 적합합니다.
주요 특징
- 고정된 네트워크 ID:
StatefulSet으로 생성된 각 파드는 고유한 이름(예: pod-0, pod-1 등)을 부여받으며, 재시작이나 재배포 후에도 동일한 네트워크 식별자를 유지합니다. 이를 통해 클러스터 내에서 파드를 안정적으로 식별할 수 있습니다. - 영속적 스토리지:
각 파드는 별도의 PersistentVolumeClaim(PVC)을 통해 지속적인 스토리지를 할당받습니다. 이로 인해 파드가 재시작되더라도, 해당 파드의 데이터는 유지되어 상태를 보존할 수 있습니다. - 순차적 배포와 업데이트:
StatefulSet은 파드를 순차적으로 생성하고, 업데이트 시에도 순서를 유지합니다. 즉, 파드들이 정해진 순서대로 생성되고, 필요 시 순서대로 업데이트되거나 종료되어, 상태 정보를 정확히 관리할 수 있습니다. - 상태 유지:
데이터베이스, 메시지 큐, 캐시 등과 같이 상태를 관리해야 하는 애플리케이션의 경우, 각 파드의 상태와 데이터를 개별적으로 관리할 수 있어 안정적인 운영이 가능합니다.
사용 사례
- 데이터베이스:
MySQL, PostgreSQL, Cassandra 등 각 인스턴스가 고유한 ID와 데이터를 유지해야 하는 경우. - 분산 캐시 및 메시지 큐:
Redis, Kafka와 같이 상태 정보를 저장하며 클러스터로 구성되는 애플리케이션. - 클러스터 기반 애플리케이션:
복잡한 네트워크 토폴로지나 클러스터 상태를 필요로 하는 애플리케이션의 경우.
ReplicaSet과 StatefulSet의 차이점
ReplicaSet | StatefulSet | |
파드 생성시 이름 설정 | Random 이름으로 설정 ex) Pod-ska25, Pod-dk15d ... |
Ordinal index 이름으로 생성 ex) Pod-0, Pod-1, Pod-2 ... |
파드 생성 시 순서 | 동시 생성 | 순차 생성. 0->1->2... |
파드 Recreate 시 | 파드 이름 변경 ex) Pod-sdf34 -> Pod-vjng3 |
파드 이름 유지 ex) Pod-2 -> Pod-2 |
파드 삭제 시 순서 | 동시 삭제 | 인덱스 높은 순부터 순차 삭제 2-> 1-> 0 |
볼륨 생성 하는 방법 | PVC를 직접 생성 | volumeClaimTemplates을 통한 동적 생성 |
파드의 수를 늘리면 PVC는? | 1개의 PVC에 모두 연결 | 각각의 PVC를 생성한 뒤 연결 |
PVC 연결된 특정 파드가 죽으면? | NodeSelector가 설정되어 있다면 해당 노드에 동일한 서비스로 랜덤한 파드이름 생성 | 특정 파드와 동일한 파드를 생성 후 기존 PVC와 연결 |
PVC가 연결된 파드 수를 0으로 하면? | PVC도 삭제함 | PVC는 삭제하지 않음 |
사용 예시
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: example-statefulset
spec:
serviceName: "example-service" # StatefulSet 전용 헤드리스 서비스의 이름을 지정합니다.
replicas: 3 # 생성할 파드의 수를 정의합니다.
selector:
matchLabels:
app: example-statefulset
template:
metadata:
labels:
app: example-statefulset # 파드의 레이블을 지정해 StatefulSet이 관리할 파드를 식별합니다.
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html # 컨테이너 내 데이터 저장 경로
volumeClaimTemplates: # 각 파드에 개별적으로 할당될 영속 볼륨을 정의합니다.
- metadata:
name: www # 위의 volumeMounts에서 참조하는 이름과 일치해야 합니다.
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "standard" # 클러스터에 설정된 스토리지 클래스 이름
resources:
requests:
storage: 1Gi # 각 파드에 1Gi의 스토리지를 요청합니다.
YAML 설명
- apiVersion & kind:
- apiVersion: apps/v1와 kind: StatefulSet을 통해 이 객체가 StatefulSet임을 명시합니다.
- metadata:
- StatefulSet의 이름(example-statefulset)과 기타 메타데이터를 정의합니다.
- spec.serviceName:
- StatefulSet에 의해 관리되는 파드들이 사용할 헤드리스 서비스(headless service)의 이름을 지정합니다. 이 서비스는 각 파드의 DNS 이름 해석에 사용됩니다.
- spec.replicas:
- 클러스터에 생성할 파드의 수를 3개로 지정합니다.
- spec.selector & template.metadata.labels:
- StatefulSet이 관리할 파드를 선택하기 위해 동일한 레이블(app: example-statefulset)을 지정합니다.
- template.spec:
- 파드의 내부 사양을 정의합니다.
- terminationGracePeriodSeconds는 파드 종료 시 그레이스 기간을 설정해 안정적인 종료를 도와줍니다.
- containers:
- 여기서는 nginx 이미지를 사용하여 웹 서버를 실행합니다.
- 컨테이너는 포트 80을 열어 외부와 통신하며, volumeMounts를 통해 /usr/share/nginx/html 경로에 영속 볼륨을 연결합니다.
- volumeClaimTemplates:
- 각 파드에 대해 자동으로 생성되는 PersistentVolumeClaim(PVC)를 정의합니다.
- 각 파드는 별도의 볼륨을 할당받으며, 이 예제에서는 1Gi의 스토리지를 요청합니다.
- storageClassName은 클러스터에서 사용할 스토리지 프로비저너를 지정합니다.
참고:
https://nearhome.tistory.com/107
https://kimjingo.tistory.com/162
https://kimjingo.tistory.com/134
https://yoo11052.tistory.com/212
'쿠버네티스' 카테고리의 다른 글
[쿠버네티스] Kubernetes Service 종류(ClusterIP, NodePort, LoadBalancer, ExternalName, Headless Service) (0) | 2025.04.09 |
---|---|
[쿠버네티스] Job, CronJob 이란? (0) | 2025.04.02 |
[쿠버네티스] ReplicationController, ReplicaSet 이란? + 차이점 (0) | 2025.03.09 |
[쿠버네티스] Pod Resource 할당(Request, Limit) (0) | 2025.03.02 |
[쿠버네티스] Init,Infra Container 및 Static Pod란? (0) | 2025.03.02 |