본문 바로가기
Kubernetes(쿠버네티스)

[Kubernetes] Ch2. 워크로드 API 카테고리 - (2) ReplicaSet, Deployment

by 잭피 2022. 11. 21.

레플리카셋

파드의 레플리카를 생성하고 지정한 파드 수를 유지하는 리소스입니다

레플리카셋이 생성하는 파드는 ‘레플리카셋 이름 - 임의의 문자열’로 명명

파드 정지와 자동화된 복구

레플리카셋에서는 노드나 파드에 장애가 발생했을 때, 지정한 파드 수를 유지하기 위해 다른 노드에서 파드를 기동시켜준다

이는 쿠버네티스의 중요한 콘셉트 중 하나로, ‘자동화된 복구’ 기능이다

레플리카셋 레이블

레플리카셋은 쿠버네티스가 파드를 모니터링하여 파드 수를 조정한다

모니터링은 특정 레이블을 가진 파드 수를 계산하는 형태로 이뤄진다

레플리카 수가 부족하면 매니페스트에 기술된 spec.template 파드를 생성하고,

레플리카 수가 더 많은 경우 레이블이 일치하는 파드 중 하나를 삭제한다

# 어떤 레이블을 가진 파드를 계산할지는 spec.selector 부분에 지정
selector:
  matchLabels:
    app: sample-app

# spec.template.metadata.lables 부분에 해당하는 레이블을 설정
spec
  template
    metadata:
      labels:
        app: sample-app

만약 spec.selector와 spec.template.metadata.labels의 레이블이 일치하지 않으면?

→ 에러가 발생하여 생성할 수 없음

# 파드 목록 표시 (app 레이블 추가 표시)
kubectl get pods -L app

레플리카셋 스케일링

스케일링에는 2가지 방법이 있다.

  1. 매니페스트를 수정하여 kubectl apply -f 명령어 실행
  2. kubectl scale 명령어를 사용하여 스케일 처리
# 레플리카 수 5로 변경
kubectl scale replicaset sample-rs --replicas=5

디플로이먼트

여러 레플리카셋을 관리하여 롤링 업데이트나 롤백 등을 구현하는 리소스이다

디플로이먼트는 레플리카셋을 관리하고 레플리카셋이 파드를 관리하는 관계

순서는 다음과 같다

  1. 신규 레플리카셋 생성
  2. 신규 레플리카셋의 레플리카 수(파드 수)를 단계적으로 늘림
  3. 이전 레플리카셋의 레플리카 수(파드 수)를 단계적으로 줄임
  4. (2,3) 반복
  5. 이전 레플리카셋은 레플리카 수 0으로 유지

💡 이는 쿠버네티스에서 가장 권장하는 컨테이너 기동 방법이다 파드 하나만 구동한다고 해도 레플리카셋이 아닌 디플로이먼트 사용을 권장한다

만약 파드로만 배포한 경우, 파드에 장애가 발생하면 자동으로 파드가 생성되지 않는다

만약 레플리카셋으로만 배포한 경우, 롤링 업데이트 등의 기능을 사용할 수 없다

디플로이먼트 생성

# 디플로이먼트 생성
kubectl create deployment sample-deployment --replicas=3 --image=nginx:1.16 --dry-run=client -o yaml > sample-deployment.yaml
vi sample-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - image: nginx:1.16
        name: nginx

# --record 옵션으로 업데이트 이력을 저장
kubectl apply -f sample-deployment.yaml --record

# 이력확인
kubectl get replicasets -o yaml | head

apiVersion: v1
items:
- apiVersion: apps/v1
  kind: ReplicaSet
  metadata:
    annotations:
      deployment.kubernetes.io/desired-replicas: "3"
      deployment.kubernetes.io/max-replicas: "4"
      deployment.kubernetes.io/revision: "1"
      kubernetes.io/change-cause: kubectl apply --filename=sample-deployment.yaml

# 디플로이먼트 확인
kubectl get deployments
sample-deployment   3/3     3            3           3m

# 레플리카셋 확인
kubectl get replicasets
sample-deployment-5c5fc78855   3         3         3       3m10s

# 파드 확인
kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
sample-deployment-5c5fc78855-lj27x   1/1     Running   0          3m19s
sample-deployment-5c5fc78855-sffl7   1/1     Running   0          3m19s
sample-deployment-5c5fc78855-tcxj9   1/1     Running   0          3m19s

디플로이먼트 업데이트 조건

spec.template (파드 설정의 변경)에 변경이 있으면 레플리카셋을 신규로 생성하고 롤링 업데이트를 한다

(이 변경에는 레플리카 수의 변경 등은 포함되어 있지 않으며 생성된 파드의 내용 변경이 있을 때다)\

변경 롤백

디플로이먼트에는 롤백이 기능이 있다

롤백 기능의 실체는 현재 사용 중인 레플리카세의 전환과 같은 것이다

롤백 대상 레플리카셋 수를 변경시켜 다시 사용할 수 있도록 한다

# 이미지 변경
kubectl set image deployment sample-deployment nginx=nginx:1.17 --record
# (--record를 쓰지 않았다면 히스토리에 보이지 않는다)

# 변경 이력을 확인
kubectl rollout history deployment sample-deployment
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=sample-deployment.yaml --record=true
2         kubectl set image deployment sample-deployment nginx=nginx:1.17 --record=true

# 초기상태 
kubectl rollout history deploy sample-deployment --revision 1
Pod Template:
  Labels:	app=sample-app
	pod-template-hash=5c5fc78855
  Annotations:	kubernetes.io/change-cause: kubectl apply --filename=sample-deployment.yaml --record=true
  Containers:
   nginx:
    Image:	nginx:1.16
    Port:	<none>
    Host Port:	<none>
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>

# 한번 업데이트된 디플로이먼트
kubectl rollout history deploy sample-deployment --revision 2
Pod Template:
  Labels:	app=sample-app
	pod-template-hash=95bb9bcd
  Annotations:	kubernetes.io/change-cause: kubectl set image deployment sample-deployment nginx=nginx:1.17 --record=true
  Containers:
   nginx:
    Image:	nginx:1.17
    Port:	<none>
    Host Port:	<none>
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>
# 버전 번호를 지정하여 롤백
kubectl rollout undo deployment sample-deployment --to-revision 1

# 바로 이전 버전으로 롤백하는 경우 (기본값인 --to-revision 0이 지정되어 바로 이전으로 롤백)
kubectl rollout undo deployment sample-deployment
# 롤백 전
kubectl get replicasets
NAME                           DESIRED   CURRENT   READY   AGE
sample-deployment-5c5fc78855   0         0         0       23m
sample-deployment-95bb9bcd     3         3         3       6m59s

# 이전 버전으로 롤백
kubectl rollout undo deployment sample-deployment

# 롤백 후 이전 레플리카셋에서 파드가 기동
kubectl get replicasets
NAME                           DESIRED   CURRENT   READY   AGE
sample-deployment-5c5fc78855   3         3         3       23m
sample-deployment-95bb9bcd     0         0         0       7m54s

💡 실제 환경에서는 롤백 기능을 사용하지 경우가 많지 않다 

kubectl rollout 명령어보다 이전 매니페스트를 다시 kubectl apply 명령어로 실행하여 적용하는 것이 호환성 면에서 더 좋기 때문이다

디플로이먼트 변경 일시정지

디플로이먼트를 업데이트하면 바로 적용되어 업데이트 처리가 실행된다

어떤 경우에는 바로 업데이트를 적용하지 않는 것을 원할 것이다

즉시 적용을 일시 정지하고 싶을 때 rollout pause를 실행한다

다시 시작할 때는 kubectl rollout resume을 실행한다

# 업데이트 일시 정지
kubectl rollout pause deployment sample-deployment
# 업데이트 일시 정지 해제
kubectl rollout resume deployment sample-deployment

pause 상태에서는 디플로이먼트 업데이트가 즉시 반영되지 않는다

또한, 롤백도 되지 않는다

디플로이먼트 업데이트 전략

디플로이먼트를 업데이트하면 롤링 업데이트가 실행되었다

업데이트 전략을 지정하는 spec.strategy.type이라는 항목의 기본값은 RollingUpdate로 되어있다

업데이트 전략에는 2개가 있다

Recreate

모든 파드를 한 번 삭제하고 다시 파드를 생성한다

다운타임이 발생하지만, 추가 리소스를 사용하지 않고 전환이 빠른 것이 장점이다

RollingUpdate

동시에 정지 가능한 최대 파드 수(maxUnavailable)와 업데이트 중에 동시에 생성할 수 있는 최대 파드 수 (maxSurge)를 설정할 수 있다.

(maxUnavailable, maxSurge 값은 백분율로 지정할 수도 있다. 지정하지 않을 경우 기본값은 각각 25%로 지정된다)

이 설정을 사용하여 추가 리소스 사용하지 않도록 하거나 많은 리소스를 소비하지 않고 빠르게 전환하는 등 업데이트 하면서 동작을 제어할 수 있다

디플로이먼트 스케일링

레플리카셋과 같은 방법으로 스케일할 수 있다

  1. 매니페스트를 수정하여 kubectl apply -f 명령어 실행
  2. kubectl scale 명령어를 사용하여 스케일 처리
# 레플리카 수 5로 변경
kubectl scale  deployment sample-deployment --replicas=5

매니페스트를 사용하지 않고 디플로이먼트 생성

kubectl create deployment sample-deployment --image=nginx:1.16

댓글