Contents

ReplicaSet / Deployment / Deployment Strategy

   May 16, 2023     9 min read

ReplicaSet

  • 래플리카셋은 클러스터 안에서 움직이는 파드의 수유지하는 장치.
  • 클러스터의 파드의 실행을 항상 안정적으로 유지하는 것을 목표로 명시된 파드 개수에 대한 가용성을 보증하는 데 사용됨.
  • 만약 애플리케이션 오류나 노드 장애 등으로 파드가 정지된 경우 래플리카셋이 자동으로 새로운 파드를 시작함.

사진첨부

  • 레플리카셋은 labelSelector의 조건에 따라 파드를 검색하여 가동 중인 파드의 수가 매니페스트 파일의 replicas의 수와 일치하는지 아닌지를 확인함.
  • 만약 가동 중인 파드의 수가 부족한 경우 새로 파드를 추가하고, 파드의 수가 많을 때는 여분의 파드를 정지 시킨다.
  • 따라서 가동 중인 애플리케이션의 파드 수를 변경하고 싶을 때는 레플리카셋의 replicas의 값을 수정하기만 하면 된다.

사진첨부

방법

  • 1) 기본 항목
apliVersion: apps/v1
kind: ReplicaSet
metadata:
    name: nginx-replicaset



필드데이터형설명예시
apiVersion문자열API 버전, 존재하지 않는 값을 설정하면 오류가 발생apps/v1
kind문자열쿠버네티스 리소스의 종류ReplicaSet
metadataObject레플리카셋의 이름이나 Label과 같은 메타데이터name: photoview-rs
specPodSpec레플리카셋의 상세 정보를 설정-



  • 2) ReplicaSet 스펙
spec:
    replicas: 3 # Pod의 수
    selector:
        matchLabels:
            app: nginx-replicaset



필드데이터형설명
replicas정수클러스터 안에서 가동시킬 파드의 수, 기본값은 1
selectorLabelSelector어떤 파드를 가동시킬지에 대한 셀렉터, 파드의 Template에 설정된 라벨과 일치해야 함
templatePodTemplateSpec실제로 클러스터 안에서 움직이는 파드의 수가 replicas에 설정된 파드의 수를 만족시키지 않을 때 새로 작성되는 파드의 템플릿



  • 3) Pod 템플릿
template:
    metadata:
        labels:
            app: nginx-replicaset
            env: prod



필드데이터형설명
metadataObject템플릿의 이름이나 Label과 같은 데이터
specPodSpec파드의 상세 정보를 설정



  • 4) Pod 스펙
spec:
    containers:
    - image: nginx
      name: nginx-replicaset
      ports:
        - containerPort: 80



  • spec.template 하위의 [spec] 필드에는 Pod의 상세 정보를 설정함.
  • 특히 .spec.template.spec.containers[] 필드의 하위에 .name, .image, .ports[], .containerport 필드를 이용해 컨테이너의 구체적인 명세를 설정함.

# watch kubectl get all -o wide
# kubectl apply -f ex06.yaml



사진첨부

Deployment

  • 디플로이먼트(Deployment) : 쿠버네티스에서 상태가 없는(stateless) 앱을 배포할 때 사용하는 가장 기본적인 컨트롤러
  • 쿠버네티스가 처음 등장했을 때는 Replication Controller에서 앱을 배포했는데 최근에는 디플로이먼트를 기본적인 앱 배포에서 사용함.

  • Stateless Application : 클라이언트와 서버의 연결 구조에서 불필요한 상태의 반영을 위한 데이터나 리소스가 사용되지 않는 형태의 서비스 구조
  • 파드와 레플리카셋은 ‘이력’이라는 개념이 없기 때문이 릴리스 후에 변경이 없는 애플리케이션을 관리하는 데 적합함.

  • 디플로이먼트는 이름처럼 배포 기능을 세분화한 것으로 파드와 레플리카셋에 버전 관리 기능을 추가한 것 이라고 생각.
  • 단순히 실행시켜야 할 파드 개수를 유지하는 것 뿐만 아니라 앱을 배포할 때 롤링 업데이트 하거나, 앰 배포 도중 잠시 멈췄다가 다시 배포할 수 있다.
  • 또한 앱 배포 후 이전 버전으로 롤백도 가능함.
  • 레플리카셋과 완전히 다른 기능이라고 보기는 어렵고, 디플로이먼트가 레플리카셋을 관리하며 앱 배포를 더 세밀하게 관리하는 것

  • 디플로이먼트는 컨테이너 이미지 버전 업 등 업데이트가 있을 때 새로운 사양의 레플리카셋을 작성하고 순서대로 새로운 파드로 대체하여 롤아웃을 수행함.
  • 디플로이먼트는 레플리카셋과 달리 이력을 관리하기 때문에 1세대 이전으로 되돌리는 롤백을 할 수 있음.

사진첨부

  • 1) 기본 항목
apiVersion: apps/v1
kind: Deployment
metadata:
    name: nginx-deployment
    labels:
      app: nginx-deployment



  • 2) Deployment 스펙
spec:
    replicas: 3
    selector:
      matchLabels:
        app: nginx-deployment



  • 3) Pod 템플릿
template:
    metadata:
      labels:
        app: nginx-deployment



  • 4) Pod 스펙
spec:
    containers:
     - name: nginx-deployment
       image: nginx
       ports:
         - containerPort: 80



# watch kubectl get all -o wide
# kubectl apply -f ex07.yaml



# kubectl scale deployment.apps/nginx-deployment --replicas=2
# kubectl scale deployment.apps/nginx-deployment --replicas=4
# kubectl scale deployment.apps/nginx-deployment --replicas=1

or

# kubectl edit deployment.apps/nginx-deployment
"1을 6으로 수정하기"
# kubectl edit deployment.apps/nginx-deployment
"6을 1로 수정하기"

or

# vi ex07.yaml
"1을 6으로 수정하기"
# kubectl apply -f ex07.yaml

# vi ex07.yaml
"6을 1로 수정하기"
# kubectl apply -f ex07.yaml

-------------------------------
# kubectl delete deployment.apps/nginx-deployment



사진첨부

Deployment 수정

  • 이 상태에서 nginx-deployment의 컨테이너 이미지 설정 정보를 업데이트 해 보자.
  • 업데이트 하는 방법
    1. kubectl set 명령으로 직접 컨테이너 이미지를 지정
    2. kubectl edit 명령으로 현재 파드의 설정 정보를 연 다음 컨테이너 이미지 정보를 수정
    3. 처음 적용했던 템플릿의 컨테이너 이미지 정보를 수정한 다음 kubectl apply 명령을 실행해서 변경

  • 1번 방식을 사용하여 실행 중인 디플로이먼트에서 image 필드를 nginx:1.9.1버전으로 변경해보기.
# kubectl set image deployment/nginx-deployment nginx-deployment=nginx:1.9.1



Deployment 롤백

  • 컨테이너 이미지를 변경한 내역을 보기 위하여 다음과 같이 명령어를 입력함.
# kubectl rollout history deploy nginx-deployment



  • 위에서 이미지를 한 번 변경하였기 때문에 두 개의 리비전이 보이며, 현재 리비전은 2이다.
  • 특정 리비전의 상세 내용을 확인하려면 --revision=리비전번호 옵션을 사용함.
# kubectl rollout history deploy nginx-deployment --revision=2



  • 이 상태에서 컨테이너 이미지를 수정하기 전인 리비전 #1로 롤백하기
# kubectl rollout undo deploy nginx-deployment --to-revison=1



  • 리비전#2의 레플리카셋인 7b779c9598에 있던 파드들이 삭제되고 다시 리비전#1의 레플리카셋인 69cfdf4bc 파드들이 생성된 것을 확인할 수 있음.
# kubectl rollout history deploy nginx-deployment



Deployment Strategy

  • 서비스 배포 전략 기법에는 Recreate, Rolling Update, Blube/Green, Canary 배포 전략이 있다.

Recreate

  • 가장 단순한 배포 전략, 기존 버전의 서버를 모두 삭제한 다음 새로운 버전의 서버를 생성하는 방법
  • 서비스에 대한 일시적인 DownTime(중단 시간)이 존재한다. (무중단 배포 X)

  • 방법)

사진첨부

사진첨부

사진첨부

  • Deployment를 만들면 v1 파드들이 만들어짐
  • 파드 하나당 자원 하나 사용한다고 가정
  • 먼저 파드 삭제 후, Downtime 동안 자원을 사용하지 않음
  • 그 다음 파드 v2를 만들고 다시 자원 할당
  • 단점은 Downtime이 발생해서 일시적으로 중단 가능한 서비스에만 쓰임.

# watch kubectl get all -o wide

# kubectl get pods --show-labels

# kubectl get pods -l type   // -l (label) 옵션 사용하기
# kubectl get pods -l type=app   // -l (label) 옵션 사용하기

# kubectl describe pod/deployment-1-7fb6d9dc-2np2t
Controlled By: ReplicaSet/deployment-1-7fb6d9dc

# kubectl describe replicaset.apps/deployment-1-7fb6d9dc
Controlled By: Deployment/deployment-1



  • master에서 Cluster IP에 반복해서 접근하기
root@mster.~3 while true; do curl 10.96.251.8:8080/version; sleep 1; done



  • Deployment 편집으로 image를 v1에서 v2로 변경하고 마스터 노드 쉘 보기
# kubectl edit deployment.apps/deployment-1



  • ReplicaSet 확인 : 기존 파드 v1은 2->0이 되고, v2는 2개가 생성됨
# watch kubectl get all -o side

# kubectl describe pod/deployment-1-6d995d446d-2dn6q
Image: kubetm/app:v2



  • Deployment에서 image v3으로 변경하고 ReplicaSet 확인
  • ReplicaSet v1은 삭제되고 v2, v3만 남음
  • revisionHistoryLimit: 1이기 때문
# kubectl edit deployment.apps/deployment-1



  • Deployment에서 image를 v3->v2로 변경하여 롤백 시행해도 되지만 명령어로 롤백 시행
  • deployment-1 : 롤백할 대상
  • –to-revision=2: 2번째로 배포한 대상으로 롤백하겠다
  • revison 확인 방법 : 대시보드, 명령어
# kubectl rollout undo deployment deployment-1 --to-revision=2



Roiing Update

  • 기존 버전의 서버를 하나씩 죽이고, 새로운 버전의 서버를 하나씩 띄우면서 순차적으로 교체하는 방법
  • 즉, 서버를 하나하나씩 버전을 업그레이드하는 방식
  • 배포 중 추가 자어ㅜㄴ을 요구하지만, 서비스 DownTime 시간이 없음.
  • 하지만, 이전의 버전과 새로운 버전의 공존하는 시간이 발생하는 단점이 있음.

  • 방법)

사진첨부

  • master에서 Cluser IP에 반복해서 접근하기
# while true; do curl 10.96.251.8.8080/version; sleep 1;done



  • Deployment 편집으로 image를 v1에서 v2로 변경하고 마스터 노드 쉘 보기
# kubectl edit deployment.apps/deployment-2


  • Downtime 없이 v1, v2 번갈아가면서 접속되다가 v2로 변경됨.

사진첨부

  • ReCreate과 달리 v1을 삭제하지 않고 v2를 생성
  • 자원은 3개가 되고, 접속하는 사람은 v1이나 v2에 접속하게 됨.
  • v1을 삭제하고, v2 생성
  • 마지막으로 남은 v1을 삭제하여 v2로 업데이트 완료
  • 단점 : 자원을 추가로 요구, 장점 : DownTime이 없음.

Blue/Green

  • 구 버전과 새로운 버전의 2가지를 서버에 마련하고, 이를 한꺼번에 교체하는 방법
  • 이전 버전을 블루, 신버전을 그린이라고 함.
  • 서비스 DownTime이 존재하지 않고, 롤백이 쉬움.
  • 이전 버전과 새로운 버전의 공존하는 시간이 존재하는 Rolling Updatd의 문제를 해결할 수 있다.
  • 운영 환경에 영향을 주지 않고 실제 서비스 환경으로 새 버전 테스트가 가능
  • 배포 시 시스템 자원의 2배를 사용하는 단점이 있음.

  • 방법)

사진첨부

사진첨부

사진첨부

사진첨부

  • Deployment에서 제공되는 기능이 아님
  • Replicas를 관리하는 컨트롤러 이용함
  • Controller를 만들고 Pod v1 생성하고 Service 에 연결
  • 컨트롤러를 추가로 만들고 v2 버전 파드 생성
  • 이때 자원 사용량은 2배가 됨.
  • 서비스의 셀렉터를 v2로 변경하여 v2 버전의 파드와 연결 -> 순간적으로 변경
  • v2에 문제가 발생하면 서비스의 라벨을 v1으로 변경하여 문제 시 롤백 가능
  • 문제가 없으면 기존 버전 파드 삭제
  • 상당히 많이 사용하고 안정적인 배포 방식이지만 자원이 2배로 필요

$ watch kubectl get all -o wide

# kubectl edit service/svc-3

$ kubectl delete service/svc-1
$ kubectl delete replicaset.apps/replica1



  1. ReplicaSet 생성
  2. 서비스 생성
  3. 서비스의 cluster ip를 복사하여 다음 명령어 실행
# while true; do curl 10.104.8.101:8080/version;sleep 1;done



  1. ReplicaSet2 생성
  2. 서비스의 selector에서 ver: v1-> ver:v2로 변경
    • 다운 타임 없이 바로 v2를 호출함.
  3. 기존 ReplicaSet은 삭제를 해도 되고, replicas를 0으로 만들면 됨.