Kubernetes - Controller: Deployment
Devops/Kubernetes

Kubernetes - Controller: Deployment

뉴비뉴 2020. 5. 20.

Deployment

현재 한 서비스가 운영중이라고 가정하고, 기능 업데이트가 있어 배포를 해야할 때 도움을 주는 컨트롤러입니다.

  • ReCreate
    • v1 파드들을 삭제합니다.
    • 서비스에 다운타임 발생
    • v2 파드들을 생성합니다.
  • Rolling Update
    • v2의 파드를 생성, v1의 한개의 파드를 삭제 반복
    • 배포 중간에 추가적인 자원을 요구하지만 큰 장점은 다운타임이 없다는 것 입니다.
  • Blue/Green
    • ReplicaSet를 이용하여 새로운 컨트롤러를 만들어서 셀렉터로 연결
    • 새로운 컨트롤러는 서비스에 연결하고, 기존의 컨트롤러를 제거
    • 다운타임이 없습니다.
    • 상당히 많이 사용하고, 단점은 자원이 더 필요하다는 것 입니다.
  • Canary
    • Canary라는 새에서 유래가 되었습니다.
    • 실험체를 통해서 위험을 검증하고, 위험이 없다는게 확인이 되면 정식으로 배포를 하는 방식입니다.
    • 기존 컨트롤러는 잘 통신되어있을 것이다, 기존 컨트롤러가 연결되어있는 서비스에 테스트 컨트롤러를 연결하여 테스트를 진행하고 이상이 없으면 새로운 Service를 생성한 뒤 배포를 진행한다.
    • Ingress 컨트롤러를 이용하여 path 앞에 /v2 가 붙인 URL은 테스트를 할 수 있는 환경이 됩니다.

 

Deployment를 생성할 때 selector, replicas, template를 입력한다. 입력한 명세대로 ReplicaSet을 생성하고, ReplicaSet은 파드를 생성하게 됩니다. 그리고 Serivce를 생성하여 연결합니다.

 

ReCreate

1. ReplicaSet의 파드 생성 수를 0으로 변경합니다.

2. 파드가 삭제되고 잠깐의 다운타임이 생기고, 업데이트 된 템플릿 명세에 따라 새로운 파드가 생성됩니다.

revisionHistoryLimit: 1 새로운 레플리카셋이 생기면서 전에 있던 레플리카셋을 삭제한다.

아예 안넣게되면 기본 10개를 남기게 됩니다.

0이 된 레플리카셋은 이전 버전으로 돌아가고 싶을 때 사용됩니다.

 

 

Rolling Update (default)

1. v2의 레플리카 수를 +1, v1의 레플리카 수를 -1 반복

 

 

실습

Recreate

 

Deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-1
spec:
  selector:
    matchLabels:
      type: app  # label
  replicas: 2
  strategy:
    type: Recreate
  revisionHistoryLimit: 1  # 여러번 배포를 하더라도 하나의 replicaset만 남는다.
  template:
    metadata:
      labels:
        type: app  # label
    spec:
      containers:
      - name: container
        image: kubetm/app:v1
      terminationGracePeriodSeconds: 10

template 안에 컨테이너의 명세에 맞게끔 파드를 2개 생성합니다.

strategy에 어떤식으로 배포가 진행될지 정할 수 있습니다.

라벨을 선언해두면 Service에서 해당 라벨을 Select 하여 Service로 Pod을 연결할 때 편리합니다.

 

Service.yaml

apiVersion: v1
kind: Service
metadata:
  name: svc-1
spec:
  selector:
    type: app
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080

Deployment를 생성할 때 생성한 Label을 선택자로 가지고 있습니다.

선택자로 선택 된 Pod들을 특정 포트로 연결할 수 있게 포트포워딩 해줍니다.

 

강의해서는 1초마다 버전을 확인하는 커맨드를 가지고 테스트를 합니다.

while true; do curl 10.99.5.3:8080/version; sleep 1; done

1초 마다 버전의 정보가 나오고, 이제 Recreate 를 테스트하기 위해 Deployment의 app:v1을 v2로 업그레이드 하겠습니다. v1의 경우 삭제되어 잠깐 연결이 끊기고 v2가 생성되면서 다시 버전이 출력되는 것을 확인할 수 있습니다.

 

revisionHistoryLimit: 1 로 지정해두었기 때문에 전에 작업했던 v1의 RS가 아직 남아있는 걸 확인할 수 있습니다. 

revisionHistoryLimit 을 지정하지 않으면 디폴트가 10 이기 때문에 RS가 10개가 쌓이게 됩니다.

ex) v11 까지 갔다고 가정하면 v0 ~ v10의 RS 데이터가 남아있게 됩니다. 

 

kubectl rollout undo deployment deployment-1 --to-revision=2

롤백을 한다. deployment-1 에 대해 2번 째로 배포했던 RS를 롤백한다.

 

kubectl rollout history deployment deployment-1

deployment history 를 확인할 수 있다. 

 

RollingUpdate

Recreate 와 yaml 파일의 차이점은 type: RollingUpdate 로 변경되었다는 것과

revision . . .이 minReadySeconds: 10 으로 변경되었다는 것 입니다.

 

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-2
spec:
  selector:
    matchLabels:
      type: app2
  replicas: 2
  strategy:
    type: RollingUpdate
  minReadySeconds: 10
  template:
    metadata:
      labels:
        type: app2
    spec:
      containers:
      - name: container
        image: kubetm/app:v1
      terminationGracePeriodSeconds: 0

Service의 경우에도 app -> app2로 변경되었다는 것 말곤 차이점이 없습니다.

 

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: svc-2
spec:
  selector:
    type: app2
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080

Deployment 에서 v1을 v2로 변경하면 RollingUpdate는 v1의 한개의 파드를 죽이고, v2에 생성, v1에 남은 한개의 파드를 죽이고, v2에 생성할 것이다. 그렇다면 계속 요청하고 있던 commend 에서는 v1이 삭제되고, v2가 생성되는 과정이 있기 때문에 그 시간동안에는 v1과 v2에 요청을 보내게 됩니다.

 

서버의 다운타임이 존재하지 않습니다.

 

Blue/Green

Replicas.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replica1
spec:
  replicas: 2
  selector:
    matchLabels:
      ver: v1  # 중요
  template:
    metadata:
      name: pod1
      labels:
        ver: v1  # 중요
    spec:
      containers:
      - name: container
        image: kubetm/app:v1
      terminationGracePeriodSeconds: 0

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: svc-3
spec:
  selector:
    ver: v1
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080

Replicas.yaml v2 버전

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replica2
spec:
  replicas: 2
  selector:
    matchLabels:
      ver: v2  # 중요
  template:
    metadata:
      name: pod1
      labels:
        ver: v2  # 중요
    spec:
      containers:
      - name: container
        image: kubetm/app:v2
      terminationGracePeriodSeconds: 0

현재까지 생성 된 것들을 정리해보겠습니다.

 

Service -> Deployment v1을 바라보고 있습니다.

Deployment v2 RS와 파드들이 생성되어 있습니다.

 

다른 실습들은 Deployment 를 생성하였는데 Blue/Green은 왜 Replicaset이라는 질문이 있는데

 

'보통 레플리카셋을 단독으로 사용하기보단 디플로이먼트를 만드는게 일반적이다'

'실습 예제에서는 서비스에 라벨을 이용해서 블루그린 배포를 하는 부분에 초점을 둔거라 레플리카셋을 사용했다는 거에 대해서는 크게 염두하실 필요가 없다' 고 하네요.

 

v1을 바라보고 있던 service의 selector를 v2로 변경하겠습니다.

변경해서 업데이트를 하면 다운타임 없이 바로 v2로 버전이 호출되게 됩니다.

 

기존 v1의 replicaset은 남아있기 때문에 삭제하거나 파드만 삭제해도 됩니다.

 

댓글

💲 추천 글