1. 워크로드 리소스
애플리케이션을 클러스터에서 실행하고 관리하기 위한 객체를 말한다.
즉, 컨테이너화된 애플리케이션을 어떤 방식으로 배포하고, 스케일링하고, 업데이트하고, 관리할지를 정의하는 리소스다.
1) ReplicationController
- 언제든지 지정된 수의 Pod가 실행 중임을 보장해주는 리소스
- Pod가 죽으면 자동으로 template을 이용해 다시 생성하고, Pod가 많으면 최근에 생성된 Pod를 삭제해서 개수를 조정
- 쿠버네티스 초기 버전에 사용되던 워크로드 리소스로 현재는 업데이트나 롤백 같은 고급 기능이 없어 거의 사용되지 않고, 대체로 ReplicaSet이나 Deployment로 교체된 상태
2) ReplicaSet
- 레플리카 파드 집합의 실행을 항상 안정적으로 유지하는 것이 목적
- 레플리카셋은 보토 명시된 동일 파드 개수에 대한 가용성을 보충하는데 사용
- 지정된 수의 파드 리플리카가 항상 실행되도록 보장
- 별도의 사용자 정의 업데이트 오케스트레이션이 필요한 경우 또는 업데이트가 전혀 필요 없는 경우만 사용
- 리플리케이션 컨트롤러의 발전된 형태
2-1) ReplicationController vs ReplicaSet 비교
| 항목 | ReplicationController | ReplicaSet |
| 셀렉터 종류 | 등호(=) 기반 selector만 지원ex) app = nginx | 집합 기반(selector matchExpressions) 지원ex) in, notin, exists 등 |
| 롤링 업데이트 | 직접적으로는 불가능(RC 자체로는 롤링 업데이트 기능 없음. 수동으로 수행해야 함) | 단독으로는 불가능→ 대신 Deployment가 ReplicaSet을 감싸서 롤링 업데이트 수행 |
| 컨트롤러 목적 | 지정한 개수의 Pod 유지 | 지정한 개수의 Pod 유지 |
| 실무 사용 여부 | 구식. 더 이상 권장되지 않음 | Deployment 내부에서 사용됨 (단독 사용은 드묾) |
| apiVersion | v1 | apps/v1 |
| 등장 시기 | 쿠버네티스 초창기부터 존재 | ReplicationController 개선판으로 등장 (v1.2~) |
2-2) [실습] ReplicaSet 예시
# vi nginx-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-rs
spec:
replicas: 3
selector:
matchLabels:
app: webui
template:
metadata:
name: nginx-pod
labels:
app: webui
spec:
containers:
- name: nginx-container
image: nginx:1.14
2-3) POD가 완성되기까지의 모든 과정을 정리
# kubectl apply -f nginx-rs.yaml
1. 사용자 요청
- 사용자가 kubectl 명령어를 통해 ReplicaSet 리소스 정의 파일을 클러스터에 적용
2. API 서버 처리
- kube-apiserver가 요청 수신
- YAML 파일의 구문 및 리소스 유효성 검사
- 검증 통과시, etcd에 리소스 상태 저장
3. ReplicaSet 컨트롤러가 동작
- 컨트롤러 매니저 내 ReplicaSet 컨트롤러가 변화 감지
- replicas 수와 selector에 지정된 라벨 기준으로 관리할 Pod 수 계산
4. 필요한 Pod 생성 결정
- selector에 일치하는 Pod가 부족하면 부족한 개수만큼 Pod 생성 요청
- spec.template을 기반으로 Pod 정의
5. 스케줄링
- kube-scheduler가 새로 생성할 Pod들을 적절한 Node에 할당
- 각 Node의 리소스 사용량, taint/toleration, affinity 등을 고려
6. kubelet의 Pod 실행
- 각 Node의 kubelet이 해당 Node에 할당된 Pod의 스펙을 수신
- kubelet은 컨테이너 런타임(Containerd, Docker 등) 에게 명령을 내려 Pod 내 컨테이너를 실행
- 필요한 이미지를 image: 필드에 따라 Pull
7. 상태 반영 및 모니터링
- 컨테이너가 정상적으로 실행되면 Pod 상태가 Running으로 전환됨
- ReplicaSet 컨트롤러는 계속해서 Pod 수를 모니터링하고 3개를 유지하도록 감시

6으로 시작하는 pod 하나 삭제
kubectl delete pod nginx-rs-6grmp

ready 부분이 2로 변했다가 순식간에 3으로 바뀜
2-3) [실습]
다음 조건의 리플리카셋 사용하는 rs-lab.yml 파일을 생성하고 동작시킨다. 다음 조건을 가진 리플리카셋을 생성하고 실행한다.
- RS 이름: mainui-rs
- 파드 레이블(labels): name: apache, app: main, rel: stable
- 리플리카 개수: 2
- 컨테이너 이미지: httpd:2.2
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: mainui-rs
spec:
replicas: 2
selector:
matchLabels:
name: apache
app: main
rel: stable
template:
metadata:
labels:
name: apache
app: main
rel: stable
spec:
containers:
- name: mainui-container
image: httpd:2.2
ports:
- containerPort: 80
protocol: TCP

현재 동작 중인 http:2.2 버전의 컨테이너를 1개로 축소한다. 대신 yaml 파일을 변경하여 업데이트 한다.

3) Deployment
- 디플로이먼트는 리플리카셋을 관리하고 다른 유용한 기능과 함께 파드에 대한 선언적 업데이트를 제공하는 상위 개념
- 상태가 없는 애플리케이션 배포 시 사용
- 대부분의 쿠버네티스 코드가 Deployment로 되어 있음
3-1) 기능
- 리플리카셋을 컨트롤해서 파드 수를 보장
- 롤업데이트와 롤백 기능 지원
- 파드와 리플리카셋에 대한 선언적 업데이트 제공
- 디플로이먼트가 외부로 노출되면 서비스는 업데이트가 이루어지는 동안 오직 가용한 파드에게만 트래픽을 로드밸런스함
3-2) [실습]
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 3
selector:
matchLabels:
app: webui
template:
metadata:
name: nginx-pod
labels:
app: webui
spec:
containers:
- name: nginx-container
image: nginx:1.14



나머지 워크로드 리소스는 다음 시간에
2. 롤링 업데이트 & 롤링 백
1) 롤링 업데이트란?
새로운 버전의 애플리케이션을 배포할 때, 기존 버전을 한 번에 교체하는 것이 아니라, 조금씩 순차적으로 업데이트하는 방식이다.
이렇게 하면 서비스 중단 없이 지속적으로 서비스를 제공하면서 새로운 기능을 적용하거나 버그를 수정할 수 있다.
새로운 버전이 정상적으로 작동이 되는 경우만 기존 애플리케이션을 대체하기 때문에 배포 과정에서 문제가 생겨도 이전 서비스를 제공한다.
2) 롤링 업데이트를 하는 여러 가지 방법
- kubectl set 명령으로 직접 컨테이너 이미지 지정
- # kubectl set image deployment <deploy_name> <container_name>=<new_version>
- kubectl edit 명령으로 현재 파드의 설정을 수정
- # kubectl edit deploy <deploy_name>
- YAML 파일을 수정 후 다시 적용
- # kubectl apply -f deploy-rollingupdate.yml
3) 롤링 업데이트 과정
1. 기존의 deploy가 아닌 수정 버전의 파일을 작성
2. 업데이트 시작
3. 새로운 RS가 생성 - 템플릿을 통한 hash 값을 생성하여 RS 뒤에 붙임
4. 이전 RS에서 기존 파드 삭제
5. 새 버전 파드를 생성하고 이전 버전 파드를 삭제
6. 최종적으로 신규 RS의 Pod로만 구성이 완료
4) 롤링 백
# kubectl rollout history deploy <deploy_name>
# kubectl rollout undo deploy <deploy_name>
# kubectl rollout undo deploy <deploy_name> --to-revision=#
Deployment에서 롤링 업데이트 설정 예시
spec:
progressDeadlineSeconds: 600 # 10분 안에 rollout 되지 않으면 실패
replicas: 3
revisionHistoryLimit: 10 # 최대 10개의 리비전만 보존
selector:
matchLabels:
app: webui
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 새로 생성될 수 있는 최대 Pod 수 (비율 또는 정수)
maxUnavailable: 25% # 동시에 내려갈 수 있는 최대 Pod 수
4) Change-Cause 어노테이션
- 변경 원인(로그)을 사람이 이해하기 쉬운 형태로 남기기 위해 사용
- 기본적으로 자동으로 남지 않기 때문에 수동으로 기록해야 함
코드로 적용하는 방법
kubectl annotate deployment <deploy_name> kubernetes.io/change-cause="설명 추가"
YAML에서 직접 쓰는 방법 <- 권장
metadata:
annotations:
kubernetes.io/change-cause: "버전 1.2 이미지 적용"
annotate를 사용하면 동일한 리비전에 두 번 생길 수 있어서 YAML에서 직접 쓰는 방법이 권장된다.
3. 리소스 식별
1) Label
- 쿠버네티스 오브젝트에 부착할 수 있는 Key-Value 형태의 메타데이터
- 주요 용도:
- Controller(Pod, ReplicaSet 등)가 관리 대상을 식별할 때 사용
- 서비스 선택자(Service Selector), 모니터링, 롤링 업데이트, 디버깅 등에 활용
- 특정 Node에만 Pod를 배치하고 싶을 때도 사용 가능 (nodeSelector)
- 특징:
- 문자열 기반의 단순한 정보
- 중복 허용
- 변경 시 Controller가 관리 대상에서 제외할 수 있음 (자동화 주의)
- 리소스 분류 및 그룹화 가능
2) Selector
- 특정 Label을 가진 리소스를 위한 필터 조건
- 종류 :
- 정확히 일치하는 Label
- matchLabels: { app: nginx }
- 복잡한 조건식을 위한 Label
- matchExpressions: [{key: app, operator: In, values: [nginx]}]
- 정확히 일치하는 Label
2-1) matchExpressions 연산자
| Operator | 설명 |
| In | 지정한 값이 포함된 경우 (key=version, 값이 2.1 or 2.2) |
| NotIn | 지정한 값을 포함하지 않을 경우 |
| Exists | 해당 Key가 존재하기만 하면 됨 (값 상관 X) |
| DoesNotExist | 해당 Key가 존재하지 않아야 함 |
4. 환경 설정 - ConfigMap
- 컨테이너에서 필요한 환경 설정을 컨테이너와 분리해서 제공
- Pod와 ConfigMap은 동일한 네임스페이스에 위치해야 함
- 사용 시기 :
- 컨테이너 커맨드와 인수 내
- 컨테이너에 대한 환경 변수
- 애플리케이션이 읽을 수 있도록 읽기 전용 볼륨에 파일 추가
- 쿠버네티스 API를 사용하여 ConfigMap을 읽는 Pod 내에서 실행할 코드 작성
5. [실습]
1) LAB1
다음 조건의 디플로이먼트를 사용하는 deploy-lab.yaml 파일 작성하고 실행
- 디플로이먼트 이름 : web-deploy
- 어노테이션 : kubernetes.io/change-cause: verson2.2를 추가로 설정
- 레플리카 수 : 2
- 파드 이름 : web-pid
- 파드 레이블 : web: apache, app: main, rel: stable, tier: frontend
- 이미지 이름 : httpd: 2.2
Pod와 나머지를 검색하기 위해 기존의 다른 파일 몇가지를 가동
그리고 라벨 필터링을 통해 deploy-lab의 Pod, replica 등만 출력하기
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deploy
annotations:
kubernetes.io/change-cause: "version 2.2"
spec:
replicas: 2
selector:
matchLabels:
app: main
web: apache
rel: stable
tier: frontend
template:
metadata:
name: web-pod
labels:
app: main
web: apache
rel: stable
tier: frontend
spec:
containers:
- name: web-container
image: httpd:2.2
ports:
- containerPort: 80
protocol: TCP

2) LAB2
이전에 동작 중인 디플로이먼트에 대한 롤링 업데이트 진행
httpd:2.2 -> httpd:2.4
# vi deploy-lab.yaml
...
annotations:
kubernetes.io/change-cause: "version 2.2 to 2.4"
...
spec:
containers:
- name: web-container
image: httpd:2.4
...
# kubectl apply -f deploy-lab.yaml

3) LAB3
현재의 Web-deploy 동작 중인 디플로이먼트의 롤링 백을 진행
httpd:2.4 -> httpd:2.2
# kubectl rollout undo deployment web-deploy

✍️ 하루 회고
오늘 수업에서 가장 기억에 남았던 부분은 단연 롤링 업데이트와 롤백 실습이었다.
과거에 Docker와 GitHub Actions를 이용해 무중단 배포를 구성해본 경험이 있어서 그런지, 이번 주제는 더 흥미롭게 다가왔다.
특히 Kubernetes에서는 이를 Deployment 리소스 안의 전략만으로도 간편하게 설정할 수 있다는 점이 인상 깊었다.
요즘처럼 서비스 중단 없이 배포하는 것이 당연시되는 환경에서는 롤링 업데이트가 필수적인 기능이라는 생각이 들었다.
또 문제가 발생했을 때 kubectl rollout undo 명령어 하나로 빠르게 롤백할 수 있다는 점은 운영 환경에서도 굉장히 유용할 것 같았다.
실습을 통해 maxSurge, maxUnavailable 같은 설정 값에 따라 Pod가 어떻게 순차적으로 교체되는지 시각적으로 확인해볼 수 있었고, CHANGE-CAUSE 어노테이션을 통해 변경 이력을 명확하게 남기는 습관도 중요하다는 걸 배웠다.
'TIL' 카테고리의 다른 글
| [에스넷시스템 부트캠프] TIL Day 35 - SDDC, ESXi, vCenter Server (1) | 2025.07.08 |
|---|---|
| [에스넷시스템 부트캠프] TIL Day 34 - Kubernetes DaemonSet, StatefulSet, Service, Job, CronJob, Volume (2) | 2025.07.07 |
| [에스넷시스템 부트캠프] TIL Day 32 - 쿠버네티스 Pod 2 (0) | 2025.07.03 |
| [에스넷시스템 부트캠프] TIL Day 31 - 쿠버네티스 Pod 1 (1) | 2025.07.02 |
| [에스넷시스템 부트캠프] TIL Day 30 - 쿠버네티스 아키텍처 (0) | 2025.07.01 |
