쿠버네티스에서는 컨테이너의 복제, 배포, 반복 작업 수행과 같이 복잡한 기능을 수행하는 리소스를 생성할 수 있습니다.
이번 글에선 Pod리소스를 기초로 더 다양한 기능을 수행하는 쿠버네티스 컨트롤러에 대해 살펴봅시다.
컨트롤러란?
컨트롤러는 쿠버네티스의 특정 리소스를 지속적으로 바라보며 리소스의 생명주기에 따라 미리 정해진 작업을 수행하는 주체입니다.
컨트롤러는 현재 상태가 사용자가 원한는 상태와 동일해지도록 정해진 작업을 수행합니다.
control-loop이라는 루프를 지속적으로 돌며 특정 리소스에 대해 관찰하며,
사용자의 요청에 따라 새로운 리소스가 생성되면 바라는 상태가 없데이트 됩니다
컨트롤러는 해당 리소스의 바라는 상태가 변경된 것을 인지하고 현재 상태가 바라는 상태와 동일해지도록 정해진 작업을 합니다.
이번엔 ReplicaSet, Deployment, Job&CronJob, DaemonSet, StatefulSet 등과 같은 컨트롤러를 살펴볼 예정입니다.
이런 컨트롤러들은 쿠버네티스 내장 컨트롤러로 kube-controller-manager 컴포넌트 안에서 동작합니다.
내장 컨트롤러 외에 사용자가 직접 정의하는 사용자 정의 컨트롤러도 생성할 수 있습니다.
https://kubernetes.io/docs/concepts/architecture/controller
Controllers
In robotics and automation, a control loop is a non-terminating loop that regulates the state of a system. Here is one example of a control loop: a thermostat in a room. When you set the temperature, that's telling the thermostat about your desired state.
kubernetes.io
위 링크를 통해 더 자세한 내용을 볼 수 있습니다.
ReplicaSet
ReplicaSet은 Pod를 복제합니다.
Pod를 복제하면 1개의 Pod에 문제가 생겨도 다른 Pod를 이용해 동일 서비스를 제공할 수 있습니다.
안정적인 서비스 운영을 위해 가용성을 높이는 역할을 담당하지요.
YAML 정의서를 살펴보겠습니다.
# myreplicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myreplicaset
spec:
replicas: 2
selector:
matchLabels:
run: nginx-rs
template:
metadata:
labels:
run: nginx-rs
spec:
containers:
- name: nginx
image: nginx
- replicas: 복제할 Pod의 개수를 정의합니다. ReplicaSet에서 복제할 Pod의 개수를 유지시킵니다.
- selector.matchLabels: Serice: 라벨링 시스템을 이용해 복제 개수를 유지할 Pod를 선택합니다.
- template: 복제할 Pod를 정의합니다.
ReplicaSet 리소스를 생성하고 리스트를 조회해보겠습니다.

replicaset을 조회하면 목표 현재 준비상태 속성이 보입니다.
pod를 조회하면 replicaset을 통해 생성된 pod가 보입니다.
쿠버네티스에선 컨트롤러들이 직접 모든 일을 다 수행하지 않고 책임과 역할에 따라 다른 리소스를 활용합니다.
위처럼 ReplicaSet은 복제와 유지의 기능만 담당하고 실제 프로세스 실행은 Pod 리소스를 활용하는 것을 볼 수 있죠.
나중에 Deployment 리소스 같은 경우엔 내부적으로 ReplicaSet리소스를 활용합니다.
위에 myreplicaset-xxx와 같이 임의의 문자가 보이는데 이는 ReplicaSet이 지정해준 문자열입니다.
# 복제본 개수 확장
kubectl scale rs --replicas <NUMBER> <NAME>
위 명령을 통해 Desire 개수를 4로 지정하면 2개의 Pod이 임의의 문자열을 달고 실행되게 되고,
이 상태에서 delete로 Pod을 지정하여 삭제하더라도 자동으로 다른 Pod이 실행되게 됩니다.
이를 통해 서비스의 가용성을 챙길 수 있게됩니다.
# ReplicaSet 정리
kubectl delete rs --all
리소스 정리 후 다음 컨트롤러를 살펴봅시다.
Deployment
Deployment 리소스는 ReplicaSet 리소스와 유사하지만 이름에서 느낄 수 있듯 애플리케이션 업데이트와 배포에 특화된 기능이 있습니다.
이는 다음과 같은 기능을 가집니다.
- 롤링 업데이트를 지원하고 업데이트되는 Pod 비율 조절이 가능힙니다.
- 업데이트 히스토리를 저장하고 다시 롤백살 수 있는 기능을 제공합니다.
- ReplicaSet과 마찬가지로 Pod의 개수를 늘릴 수 있습니다.
- 배포 상태를 확인할 수 있습니다.
직접 리소스를 생성해봅시다.
# mydeploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mydeploy
spec:
replicas: 10
selector:
matchLabels:
run: nginx
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
run: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
- replicas: ReplicaSet과 동일하게 유지할 Pod의 개수를 정의합니다.
- selector.matchlabels: 마찬가지로 라벨을 기반으로 배포를 수행할 Pod을 선택합니다.
- strategy.type: 배포 전략 종류를 선택합니다.
- RollingUpdate: 롤링배포를 진행합니다.
- Recreate: 일시적으로 전체 Pod가 삭제되고 새로운 Pod가 전체 생성됩니다.
- 개발중 말곤 대부분 RollingUpdate를 사용합니다.
- strategy.rollingUpdate: type이 rollingUpdate일 경우에만 사용
- maxUnavailable: 최대 중단 Pod허용 개수(비율)를 지정합니다. 예로 총 10개의 replica에 maxUnavailable의 비율이 25%면 2개(소수점 내림)의 예전 Pod가 RollingUpdate 중에 일시 중단될 수 있음을 의미합니다.
- maxSurge: 최대 초과 Pod 허용 개수(비율)를 지정합니다. 예로 총 10개 replica에 maxSurge의 비율이 25%면 약 3개 (소수점 올림)의 새로운 Pod가 초과해 최대 13개까지 생성될 수 있다는 것을 의미합니다.
- template: 복제할 Pod를 정의합니다. 앞에서 살펴본 Pod의 spec과 동일합니다.
위 설정으로 RollingUpdate를 하면 최소 8개에서 최대 13개까지의 Pod가 점진적으로 업데이트 됩니다.
위 YAML파일로 Deployment 리소스를 생성해봅시다. (실습 환경이 좋지 못해 글로 대신합니다.)
Pod 생성이 완료될 때까지 시간이 좀 걸릴 수 있습니다.
kubectl apply --record -f mydeploy.yaml
# deployment.apps/mydeploy created
kubectl get deployment # 축약 시, deploy
# NAME READY UP-TO-DATE AVAILABLE AGE
# mydeploy 10/10 10 10 10m
kubectl get rs
# NAME DESIRED CURRENT READY AGE
# mydeploy-649xxx 10 10 10 1m
kubectl get pod
# NAME READY STATUS RESTARTS AGE
# mydeploy-649xxx-bbxx 1/1 Running 0 9s
# mydeploy-649xxx-dtxx 1/1 Running 0 2m9s
# ...
Deployment 리소스를 이용하여 애플리 케이션을 만들면,
이 리소스가 ReplicaSet을 만들고, 해당 ReplicaSet이 Pod 복제본들을 생성하는걸 볼 수 있지요.
정리하면
- Deployment: 배포 담당
- ReplicaSet: 복제 담당
- Pod: 컨테이너 실행 담당
이제 롤링 업데이트 과정을 확인해 봅시다.
kubectl set image라는 명령을 이용해 nginx의 버전을 업그레이드 해보겠습니다.
# 기존 nginx 버전 1.7.9에서 1.9.1로 업데이트
kubectl set image deployment mydeploy nginx=nginx:1.9.1 --record
# deployment.apps/mydeploy image updated
# 업데이트 진행 상황 확인합니다.
kubectl get pod
# NAME READY STATUS RESTARTS AGE
# mydeploy-649xxx-bbxx 1/1 ContainerCreating 0 9s
# mydeploy-649xxx-dtxx 1/1 Running 0 2m9s
# ...
# 배포 상태확인
kubectl rollout status deployment mydeploy
# Waiting for deployment "mydeploy" rollout to finish:
# 7 out of 10 new replicas have been updated...
# Waiting for deployment "mydeploy" rollout to finish:
# 7 out of 10 new replicas have been updated...
# Waiting for deployment "mydeploy" rollout to finish:
# 7 out of 10 new replicas have been updated...
# Waiting for deployment "mydeploy" rollout to finish:
# 8 out of 10 new replicas have been updated...
# ...
# deployment "mydeploy" successfully rolled out
# 특정 Pod의 이미지 tag 정보를 확인합니다.
kubectl get pod mydeploy-xxx-xxx -o yaml | grep "image: nginx"
# - image: nginx:1.9.1
rollingUpdate 설정값에 따라 점진적으로 새로운 Pod가 생성되는 것을 볼 수 있습니다.
이렇게 Deployment 리소스의 롤링 업데이트와 Service 리소스를 통해 중단 없이 어플리케이션을 배포할 수 있습니다.
이번에는 롤백 기능에 대해 알아봅시다.
배포시 의도치 않게 문제가 발생할 수 있습니다. Deployment 리소스는 이러한 상황을 염두하고 만들어졌는데요.
우선 의도적으로 존재하지 않는 nginx버전으로 이미지를 수정하고 배포 상태를 확인해보겠습니다.
# 1.9.1 버전에서 (존재하지 않는) 1.9.21 버전으로 업데이트 (에러 발생)
kubectl set image deployment mydeploy nginx=nginx:1.9.21 --record
# deployment.apps/mydeploy image updated
# Pod의 상태확인
kubectl get pod
# NAME READY STATUS RESTARTS AGE
# mydeploy-6498-bbk9v 1/1 Running 0 9m38s
# mydeploy-6498-dt5d7 1/1 Running 0 9m28s
# mydeploy-6498-wrpgt 1/1 Running 0 9m38s
# mydeploy-6498-sbkzz 1/1 Running 0 9m27s
# mydeploy-6498-hclwx 1/1 Running 0 9m26s
# mydeploy-6498-98hd5 1/1 Running 0 9m25s
# mydeploy-6498-5gjrg 1/1 Running 0 9m24s
# mydeploy-6498-4lz4p 1/1 Running 0 9m38s
# mydeploy-6fbf-7kzpf 0/1 ErrImagePull 0 48s
# mydeploy-6fbf-rfgbd 0/1 ErrImagePull 0 48s
# mydeploy-6fbf-v5ms5 0/1 ErrImagePull 0 48s
# mydeploy-6fbf-rccw4 0/1 ErrImagePull 0 48s
# mydeploy-6fbf-ncqd2 0/1 ImagePullBackOff 0 48s
maxUnavaliable 값으로 인해 최소 8개의 Running 중인 Pod를 유지하고 있고 새로 생성된 Pod가 정상적으로 동작하지 않기 때문에 더 이상 기존 Pod를 삭제하지 않고 있습니다.
또한 maxSurge 설정값으로 최대 Pod 개수가 13개를 넘지 않습니다.
잘못된 배포임을 확인 후 배포 설정을 이전으로 롤백하지요.
# 지금까지의 배포 히스토리를 확인합니다.
kubectl rollout history deployment mydeploy
# deployment.apps/mydeploy
# REVISION CHANGE-CAUSE
# 1 kubectl apply --record=true --filename=mydeploy.yaml
# 2 kubectl set image deployment mydeploy nginx=nginx:1.9.1
# --record=true
# 3 kubectl set image deployment mydeploy nginx=nginx:1.9.21
# --record=true
# 잘못 설정된 1.9.21에서 --> 1.9.1로 롤백
kubectl rollout undo deployment mydeploy
# deployment.apps/mydeploy rolled back
kubectl rollout history deployment mydeploy
# deployment.apps/mydeploy
# REVISION CHANGE-CAUSE
# 1 kubectl apply --record=true --filename=mydeploy.yaml
# 3 kubectl set image deployment mydeploy nginx=nginx:1.9.21
# --record=true
# 4 kubectl set image deployment mydeploy nginx=nginx:1.9.1
# --record=true
kubectl get deployment mydeploy -oyaml | grep image
# image: nginx:1.9.1
- 지금까지 --record라는 옵션을 붙인 이유는 rollout history에서 실제 사용한 명령을 기록하기 위함입니다. 그렇지 않으면 사용한 명령이 <NONE>으로 표시됩니다.
- rollout undo명령을 통해 이전 배포 상태로 롤백할 수 있었습니다.
- 다시 rollout history 명령을 수행하면 직전 배포 버전인 2가 최종 배포 버전인 4로 옮겨진 것을 확인할 수 있습니다.
직접 배포 버전을 명시하여 곧바로 해당 버전으로 롤백할 수도 있습니다.
# 1.9.1 --> 1.7.9 (revision 1)로 롤백 (처음으로 롤백)
kubectl rollout undo deployment mydeploy --to-revision=1
# deployment.apps/mydeploy rolled back
이번엔 배포된 Pod의 개수를 줄여보겠습니다.
마찬가지로 scale 명령으로 Pod의 개수를 조절할 수 있습니다.
kubectl scale deployment mydeploy --replicas 5
# deployment.apps/mydeploy scaled
# 10개에서 5개로 줄어가는 것을 확인할 수 있습니다.
kubectl get pod
# NAME READY STATUS RESTARTS AGE
# mydeploy-6498-bbk9v 1/1 Running 0 9m38s
# mydeploy-6498-dt5d7 1/1 Running 0 9m28s
# mydeploy-6498-wrpgt 1/1 Running 0 9m38s
# mydeploy-6498-sbkzz 1/1 Running 0 9m27s
# mydeploy-6498-98hd5 1/1 Running 0 9m27s
# mydeploy-6498-3srxd 0/1 Terminating 0 9m25s
# mydeploy-6498-5gjrg 0/1 Terminating 0 9m24s
# mydeploy-6498-4lz4p 0/1 Terminating 0 9m38s
# mydeploy-6fbf-7kzpf 0/1 Terminating 0 9m38s
# mydeploy-6fbf-d245c 0/1 Terminating 0 9m38s
# 다시 Pod의 개수를 10개로 되돌립니다.
kubectl scale deployment mydeploy --replicas=10
# deployment.apps/mydeploy scaled
# 5개가 새롭게 추가되어 다시 10개가 됩니다.
kubectl get pod
# NAME READY STATUS RESTARTS AGE
# mydeploy-6498-bbk9v 1/1 Running 0 9m38s
# mydeploy-6498-dt5d7 1/1 Running 0 9m28s
# mydeploy-6498-wrpgt 1/1 Running 0 9m38s
# mydeploy-6498-sbkzz 1/1 Running 0 9m27s
# mydeploy-6498-98hd5 1/1 Running 0 9m25s
# mydeploy-6498-30cs2 0/1 ContainerCreating 0 5s
# mydeploy-6fbf-sdjc8 0/1 ContainerCreating 0 5s
# mydeploy-6498-w8fkx 0/1 ContainerCreating 0 5s
# mydeploy-6498-qw89f 0/1 ContainerCreating 0 5s
# mydeploy-6fbf-19glc 0/1 ContainerCreating 0 5s
마지막으로 Deployment 리소스도 edit 명령으로 직접 YAML 파일을 수정할 수 있습니다.
kubectl edit deploy mydeploy
# apiVersion: apps/v1
# kind: Deployment
# metadata:
# ...
# spec:
# progressDeadlineSeconds: 600
# replicas: 10 # --> 3으로 수정
# revisionHistoryLimit: 10
# selector:
# matchLabels:
# run: nginx
#
# <ESC> + :wq
replicas 개수를 3으로 수정하고 저장하면 Pod의 개수가 줄어들게 됩니다.
kubectl get pod
# NAME READY STATUS RESTARTS AGE
# mydeploy-6498-bbk9v 1/1 Running 0 12m8s
# mydeploy-6498-dt5d7 1/1 Running 0 12m8s
# mydeploy-6498-wrpgt 1/1 Running 0 12m8s
쿠버네티스의 많은 경우 이 리소스를 통해 서비스를 운영합니다.
쿠버네티스 리소스 컨셉

쿠버네티스는 작은 기능들 수행하는 다양한 리소스를 조합할 수 있습니다.
컨테이너를 실행하는 Pod 부터 네트워킹을 책임지는 Service, 복제 담당 ReplicaSet과 배포를 관리하는 Deployment까지 각각의 기능을 수행하는 리소스들을 조합하여 큰 애플리케이션을 구축합니다.
'개발 > DevOps' 카테고리의 다른 글
| [kubernetes] helm 패키지 매니저 (0) | 2025.10.06 |
|---|---|
| [Kubernetes] 쿠버네티스 컨트롤러 2 - StatefulSet, Job & CronJob (0) | 2025.10.04 |
| [Kubernetes] 쿠버네티스 네트워킹(Service) - ClusterIP, NodePort, LoadBalancer, ExternalName (0) | 2025.09.27 |
| [Kubernetes] Pod 파해치기 3 - ConfigMap, Secret, Downward (0) | 2025.09.23 |