k8s - ReplicaSet, Deployment!

리플리카셋 (ReplicaSet)

파드가 자동으로 상태검사, 정상화(재시작) 하며 상태를 복구하는 것이라면
리플리카셋은 파드의 수를 유지, 자동으로 새로운 파드를 시작한다.

매니페스트 기본 구성은 파드와 같다.
spec 부분만 다른부분이 있는데 알아보자.

필드 타입 설명
replicaset.spec.replicas Integer 클러스터 안에서 가동시킬 파드의 수 (기본값 1)
replicaset.spec.selector LabelSelector 어떤 파드를 가동할지 정의, 파드의 template.metadata.label 에 설정된 값과 일치해야함
replicaset.spec.template PodTemplateSpec 실제 클러스터 내부 파드 수가 replicas 에 설정된 수보다 적을때 새로작성되는 파드의 템플릿
replicaset.spec.template.metadata Object 템플릿의 이름, Label과 같은 메타데이터
replicaset.spec.template.spec PodSpec 파드의 상세정보를 설정

즉 리플리카셋을 사용하려면 리플리카셋의 spec 과 파드의 spec 을 모두 정의해야한다.

리플리카셋 CRUD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ReplicaSet/replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: photoview-rs
spec:
replicas: 5
selector:
matchLabels:
app: photoview
template:
metadata:
labels:
app: photoview
env: prod
spec:
containers:
- image: mydomain:5000/photo-view:v1.0
name: photoview-container
ports:
- containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
kubectl create -f ReplicaSet/replicaset.yaml
kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
photoview-rs-466w6 1/1 Running 0 3h35m app=photoview,env=prod
photoview-rs-fwv2f 1/1 Running 0 3h35m app=photoview,env=prod
photoview-rs-j46rr 1/1 Running 0 3h40m app=photoview,env=prod
photoview-rs-n64z2 1/1 Running 0 3h35m app=photoview,env=prod
photoview-rs-zk4bz 1/1 Running 0 3h35m app=photoview,env=prod

# 파일을 수정 후 apply 하면 기존 리플리카셋의 설정이 자동 수정/적용 된다.
kubectl apply -f ReplicaSet/replicaset.yaml
kubectl delete -f ReplicaSet/replicaset.yaml

리플리카셋은 철저히 spec.template.metadata.labels.app 을 통해서 관리된다.

먼저 라벨명이 photo-view파드 를 하나 생성

1
2
3
4
5
6
kubectl apply -f ReplicaSet/pod-nginx.yaml
pod/nginx-pod created

kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 27s

그리고 리플리카셋으로 photo-view 라벨을 가진 파드 5개를 생성하도록한다.

1
2
3
4
5
6
7
8
9
10
kubectl apply -f ReplicaSet/replicaset-nginx.yaml
replicaset.apps/nginx-replicaset created

kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 79s
nginx-replicaset-cg8l7 0/1 ContainerCreating 0 2s
nginx-replicaset-hgkkd 0/1 ContainerCreating 0 2s
nginx-replicaset-kg5ks 0/1 ContainerCreating 0 2s
nginx-replicaset-p2w5f 0/1 ContainerCreating 0 2s

기존에 파드 매니페스트로 생성했던 nginx-pod 파드와 함께 4개의 추가 파드가 생성된다.

디플로이먼트 (Deployment)

Deployment: 전개, 배치
https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/

쿠버네티스에선 어플리케이션의 유연한 CI/CD 를 위해 Deployment 를 제공한다.

DeploymentReplicaSet 의 상위개념이다.
똑같이 여러개의 파드를 생성하고 관리면서 업데이트 관련 기능을 추가 제공한다.
기본적으로 무중단 배포를 위해 Rolling Update 를 지원한다.

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: 10
revisionHistoryLimit: 2 # replicaset version 을 2개까지만 유지, default 10
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 50%
maxSurge: 50%
selector:
matchLabels:
app: nginx-pod # 템플릿 검색조건
# 파드 템플릿
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.14 # 컨테이너 이미지
ports:
- containerPort: 80

Deployment의 매니페스트 또한 spec 속성이 좀 다를뿐 나머지는 비슷하다.

  • strategy
    업데이트 방식 결정 가능, Recreate, RollingUpdate 사용 가능, 기본값은 RollingUpdate
    Recreate 는 오래된 파드를 정지시키고 새로운 파드를 다시 작성하는 방식, 가장 심플하고 빠르지만 서버가 모두 내려가 버리기에 다운타임이 발생한다.

  • rollingUpdate.maxUnavailable
    spec.replicas 수 기준 unavailable 상태인 Pod 의 최대 개수를 설정. 기본값은 25%

  • rollingUpdate.maxSurge
    spec.replicas 수 기준 최대 새로 추가되는 파드 수, 기본값은 25%.
    100% 설정시 신버전의 파드수가 리플리카수만큼 실행되어 한번에 20개의 파드가 동작하게 된다.
    리소스 상황에 따라 특이사항이 발생할 수 있음으로 maxSurge 는 작성하는 것을 권장한다.

Deployment 리플리카셋과 파드가 생성되는지 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 기본항목
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
# 디플로이먼트 스팩
spec:
replicas: 3
selector:
matchLabels:
app: nginx-pod # 템플릿 검색조건
# 파드 템플릿
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.15 # 컨테이너 이미지
ports:
- containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
kubectl apply -f Deployment/nginx-deployment.yaml
# deployment.apps/nginx-deployment created

kubectl get deploy
# NAME READY UP-TO-DATE AVAILABLE AGE
# nginx-deployment 3/3 3 3 24s

kubectl get replicaset,pod
# NAME DESIRED CURRENT READY AGE
# replicaset.apps/nginx-deployment-5bff7844cb 3 3 3 5m11s

# NAME READY STATUS RESTARTS AGE
# pod/nginx-deployment-5bff7844cb-6n2xh 1/1 Running 0 5m11s
# pod/nginx-deployment-5bff7844cb-9jmvt 1/1 Running 0 5m11s
# pod/nginx-deployment-5bff7844cb-kc7ph 1/1 Running 0 5m11s

디플로이먼트는 내부에서 리플리카셋, 파드 이력을 갖고 있다. kubectl get replicaset 명령에도 조회가 가능하다.

리소스의 네이밍 규칙이 있다.

Deployment - nginx-deployment
ReplicaSet - nginx-deployment-5bff7844cb
Pod - nginx-deployment-5bff7844cb-kc7ph

뒤에 특정 해시값이 라벨로도 붙어있으며 이를 사용해 Deployment가 리소스를 관리한다.

기존의 nginx:1.14 버전의 이미지를 nginx:1.15 로 변경해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
kubectl apply -f Deployment/nginx-deployment.yaml
deployment.apps/nginx-deployment configured

kubectl describe deploy nginx-deployment
Name: nginx-deployment
Namespace: default
...
...
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-f75fb748c (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 28m deployment-controller Scaled up replica set nginx-deployment-5bff7844cb to 3
Normal ScalingReplicaSet 18s deployment-controller Scaled up replica set nginx-deployment-f75fb748c to 1
Normal ScalingReplicaSet 4s deployment-controller Scaled down replica set nginx-deployment-5bff7844cb to 2
Normal ScalingReplicaSet 4s deployment-controller Scaled up replica set nginx-deployment-f75fb748c to 2
Normal ScalingReplicaSet 3s deployment-controller Scaled down replica set nginx-deployment-5bff7844cb to 1
Normal ScalingReplicaSet 3s deployment-controller Scaled up replica set nginx-deployment-f75fb748c to 3
Normal ScalingReplicaSet 2s deployment-controller Scaled down replica set nginx-deployment-5bff7844cb to 0

nginx-deployment-5bff7844cb 이름의 리플리카셋의 파드를 하나씩 줄이며
nginx-deployment-f75fb748c 이름의 새로운 리플리카셋의 파드를 하나씩 생성한다.

Roll out, Roll back

디플로이먼트 이력(history)을 확인하려면 rollout history 옵션을 사용한다.

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
kubectl rollout history deploy nginx-deployment --revision=1
# deployment.apps/nginx-deployment with revision #1
# Pod Template:
# Labels: app=nginx-pod
# pod-template-hash=85c65c75d8
# Containers:
# nginx:
# Image: nginx:1.15
# Port: 80/TCP
# Host Port: 0/TCP
# Environment: <none>
# Mounts: <none>
# Volumes: <none>

kubectl rollout history deploy nginx-deployment --revision=2
# deployment.apps/nginx-deployment with revision #2
# Pod Template:
# Labels: app=nginx-pod
# pod-template-hash=67d4595779
# Containers:
# nginx:
# Image: nginx:1.16
# Port: 80/TCP
# Host Port: 0/TCP
# Environment: <none>
# Mounts: <none>
# Volumes: <none>

디플로이먼트를 업데이트하고 문제가 생기면 다시 이전버전으로 돌릴 수 있는 기능(롤백) 을 사용해보자.

방금 nginx version 을 1.15 -> 1.16 으로 업데이트(rollout) 했다.

describe 명령으로 출력된 Annotations 속성으로 revision 값 확인
해당 디플로이먼트가 몇번 업데이트 되었는지 확이 가능하다.

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
kubectl describe deploy nginx-deployment
# Name: nginx-deployment
# Namespace: default
# CreationTimestamp: Fri, 23 Jan 2020 09:57:02 +0900
# Labels: <none>
# Annotations: deployment.kubernetes.io/revision: 2
# Selector: app=nginx-pod
# Replicas: 10 desired | 10 updated | 10 total | 10 available | 0 unavailable
# StrategyType: RollingUpdate
# MinReadySeconds: 0
# RollingUpdateStrategy: 50% max unavailable, 50% max surge
# Pod Template:
# Labels: app=nginx-pod
# Containers:
# nginx:
# Image: nginx:1.16
# Port: 80/TCP
# Host Port: 0/TCP
# Environment: <none>
# Mounts: <none>
# Volumes: <none>
# Conditions:
# Type Status Reason
# ---- ------ ------
# Available True MinimumReplicasAvailable
# Progressing True NewReplicaSetAvailable
# OldReplicaSets: nginx-deployment-85c65c75d8 (0/0 replicas created)
# NewReplicaSet: nginx-deployment-67d4595779 (10/10 replicas created)
# Events:
# Type Reason Age From Message
# ---- ------ ---- ---- -------
# Normal ScalingReplicaSet 119s deployment-controller Scaled up replica set nginx-deployment-67d4595779 from 0 to 5
# Normal ScalingReplicaSet 119s deployment-controller Scaled down replica set nginx-deployment-85c65c75d8 from 10 to 5
# Normal ScalingReplicaSet 119s deployment-controller Scaled up replica set nginx-deployment-67d4595779 from 5 to 10
# Normal ScalingReplicaSet 101s deployment-controller Scaled down replica set nginx-deployment-85c65c75d8 from 5 to 4
# Normal ScalingReplicaSet 100s deployment-controller Scaled down replica set nginx-deployment-85c65c75d8 from 4 to 3
# Normal ScalingReplicaSet 100s deployment-controller Scaled down replica set nginx-deployment-85c65c75d8 from 3 to 2
# Normal ScalingReplicaSet 99s deployment-controller Scaled down replica set nginx-deployment-85c65c75d8 from 2 to 1
# Normal ScalingReplicaSet 95s deployment-controller Scaled down replica set nginx-deployment-85c65c75d8 from 1 to 0

85c65c75d8 -> 67d4595779 해시의 변경값이다.

nginx:1.16 에 문제가 있단 가정 하에, deployment 파일에 nginx:1.15 설정 후 다시 apply

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
kubectl describe deploy nginx-deployment
# Name: nginx-deployment
# Namespace: default
# CreationTimestamp: Fri, 23 Jan 2026 09:57:02 +0900
# Labels: <none>
# Annotations: deployment.kubernetes.io/revision: 3
# Selector: app=nginx-pod
# Replicas: 10 desired | 10 updated | 10 total | 10 available | 0 unavailable
# StrategyType: RollingUpdate
# MinReadySeconds: 0
# RollingUpdateStrategy: 50% max unavailable, 50% max surge
# Pod Template:
# Labels: app=nginx-pod
# Containers:
# nginx:
# Image: nginx:1.15
# Port: 80/TCP
# Host Port: 0/TCP
# Environment: <none>
# Mounts: <none>
# Volumes: <none>
# Conditions:
# Type Status Reason
# ---- ------ ------
# Available True MinimumReplicasAvailable
# Progressing True NewReplicaSetAvailable
# OldReplicaSets: nginx-deployment-67d4595779 (0/0 replicas created)
# NewReplicaSet: nginx-deployment-85c65c75d8 (10/10 replicas created)

revision값은 3이 되었고 해시값이 새롭게 변하지 않고 다시 85c65c75d8 로 돌아갔다.
[Deployment, Replicaset, Pod] 모두 매니페스트 이력을 가지고 롤아웃/롤백을 진행하고 있기 때문.

이 외에도 현재 사용중인 매니페스트 수정하거나 kubectl rollout 명령을 사용해 롤백이 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 먼저 롤백할 revision 확인
kubectl rollout history deployment/nginx-deployment --revision=2
# deployment.apps/nginx-deployment with revision #2
# Pod Template:
# Labels: app=nginx-pod
# pod-template-hash=67d4595779
# Containers:
# nginx:
# Image: nginx:1.16
# Port: 80/TCP
# Host Port: 0/TCP
# Environment: <none>
# Mounts: <none>
# Volumes: <none>

kubectl rollout undo deployment/nginx-deployment --to-revision=2
# deployment.apps/nginx-deployment rolled back

파일로 구성관리가 유지되지 않음으로 매니페스트 파일의 갱신(선언적 관리)으로 롤아웃/롤백 하는것을 권장한다.

블루/그린 디플로이먼트

블루/그린 이라고 별다른 기법이 있는건 아니다.

서로 다른 버전의 2개의 디플로이먼트를 각각 생성하고 이에 접근하는 Service 리소스를 변경하는 것이다.

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
# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-blue
labels:
version: blue
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
version: blue
template:
metadata:
labels:
app: nginx
version: blue
spec:
containers:
- name: nginx
image: nginx:1.15 # Blue 버전: nginx 1.15
ports:
- containerPort: 80
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
# green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment-green
labels:
version: green
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
version: green
template:
metadata:
labels:
app: nginx
version: green
spec:
containers:
- name: nginx
image: nginx:1.16 # Green 버전: nginx 1.16
ports:
- containerPort: 80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
kubectl apply -f Deployment/blue-deployment.yaml
# deployment.apps/blue-deployment created

kubectl apply -f Deployment/green-deployment.yaml
# deployment.apps/green-deployment created

kubectl get pod
# NAME READY STATUS RESTARTS AGE
# blue-deployment-58d5d4869b-kmn88 1/1 Running 0 19s
# blue-deployment-58d5d4869b-vlx2c 1/1 Running 0 19s
# blue-deployment-58d5d4869b-w4729 1/1 Running 0 19s
# green-deployment-5466fc4568-7hxqp 1/1 Running 0 15s
# green-deployment-5466fc4568-mvs2w 1/1 Running 0 15s
# green-deployment-5466fc4568-t8hp2 1/1 Running 0 15s

그리고 이 Deployment 에 접근하는 서비스를 작성하고 실행한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
name: webserver
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
protocol: TCP
selector: # 접근할 파드 수정
app: photo-view
ver: v1.0
1
2
kubectl apply -f Deployment/service.yaml
# service/webserver created

이제 service.yml 매니페스트 파일만 수정해서 두 버전의 디플로이먼트에 접근할 수 있도록 설정하면 된다.

오토스케일링

순간적으로 많은양의 요청이 들어올 경우 시스템 처리능력을 높이는 방법
시스템 처리능력을 높이는 방법은 2가지가 있다.

  • 스케일 아웃(수평 스케일): 시스템 구성 서버 대수를 늘림으로 처리능력 향상, 로드밸런서를 추가해야 하며 시스템의 가용성이 높아진다.
  • 스케일 업(수직 스케일): 서버의 리소스(CPU, Memory) 를 증가 시켜 처리능령 향상시킨다.

처리량의 증가정도에 따라 파드를 스케일할지 노드를 스케일할지 결정한다.

가장 쉽게 스케일 아웃하는 방법은 kubectl scale 명령으로 수동으로 진행하는 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-replicaset
spec:
replicas: 3
selector:
matchLabels:
app: photo-view
template:
metadata:
labels:
app: photo-view
spec:
containers:
- image: nginx
name: photoview-container

nginx 파드를 3개 생성하고 kubectl scale 명령으로 replicas 개수를 8개 까지 스케일 아웃

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
kubectl apply -f HPA/pod-scale.yaml
replicaset.apps/nginx-replicaset created

kubectl scale --replicas=8 rs/nginx-replicaset
replicaset.apps/nginx-replicaset scaled

kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-replicaset-4bv5g 1/1 Running 0 19s
nginx-replicaset-4cjjq 1/1 Running 0 19s
nginx-replicaset-5z9qk 1/1 Running 0 19s
nginx-replicaset-bt98h 1/1 Running 0 19s
nginx-replicaset-c5fkk 1/1 Running 0 2m29s
nginx-replicaset-hnv8w 1/1 Running 0 2m29s
nginx-replicaset-nxtcn 1/1 Running 0 19s
nginx-replicaset-zbsd6 1/1 Running 0 2m29s

HPA(Horizontal Pod Autoscaler)

HPA(Horizontal Pod Autoscaler) 를 사용하면 CPU 사용률에 따라 사용해 자동으로 스케일 아웃 가능하다.

k8s 의 마스터 컴포넌트인 컨트롤러 매니저가 주기적으로 파드들의 CPU 를 감시하며 HPA 설정대로 스케일 아웃한다.

스케일 아웃 조건은 아래와 같다.

1
목표 파드 개수 = (현재 파드의 CPU 사용률을 모두 더한 값 / 목표 CPU 사용률) 올림값

목표 CPU 사용률이 60 이고 파드 2개 CPU 사용률이 각각 50, 80 일 때
위 수식값은 130/60=2.17, 올림하면 3 이다.
목표 파드개수는 3개가 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: kubernetes-simple-app-hpa
namespace: default
spec:
minReplicas: 1 # 최소 설정개수
maxReplicas: 10 # 최대 설정개수
scaleTargetRef: # 오토스케일링 대상
apiVersion: extensions/v1beta1
kind: Deployment
name: kubernetes-simple-app
targetCPUUtilizationPercentage: 30 # CPU 사용률

Deployment, Relication Controller, StatefuleSet 등의 리소스에서 오토스케일링 가능

kubectl autoscale 명령으로도 설정 가능하다.

1
2
3
4
kubectl autoscale \
deployment kubernetes-simple-app \
--cpu-percent=30 \
--min=1 --max=10

autoscaling/v2 부턴 metrics 설정을 통해 CPU 외에 다른 메트릭 데이터를 통해 오토스케일링 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: kubernetes-simple-app-hpa
namespace: default
spec:
minReplicas: 1 # 최소 설정개수
maxReplicas: 10 # 최대 설정개수
scaleTargetRef: # 오토스케일링 대상
apiVersion: extensions/v1beta1
kind: Deployment
name: kubernetes-simple-app
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 30 # CPU 가 30% 되도록 조정

한번 스케일 아웃 HPA 가 발동하면 다음번 HPA 는 3분뒤에 다시 발동가능하다.
(줄어드는건 5분)

아래 k8s 컨트롤 매니저 설정파일에서 조절 가능하다.

1
2
3
4
/etc/kubernetes/manifests/kube-controller-manager.yaml

--horizontal-pod-autoscaler-upscale-delay=3m0s
--horizontal-pod-autoscaler-downscale-delay=5m0s