[K8S] 2.Replica Set & Deployment

들어가며

 

동일한 작업을 수행하는 애플리케이션(Pod)을 2개이상 띄우고 싶은경우 어떻게 해야할까?

아래처럼 파드를 필요한 만큼 정의해서 띄울 수 있을것이다.

apiVersion: v1 
  kind: Pod metadata:
    name: nginx-a 
      spec:
        containers:
          - name: nginx-container
            image: nginx:latest 
            ports:
            - containerPort: 80
              protocol: TCP
              
---

apiVersion: v1 
  kind: Pod metadata:
    name: nginx-b
      spec:
        containers:
          - name: nginx-container
            image: nginx:latest 
            ports:
            - containerPort: 80
              protocol: TCP

하지만 2개가 아닌 필요한개수가 많으면 많을 수록 번거로울 것이고 편하게 관리하기도 쉽지 않을것이다.

Replica Set은 이러한 문제점을 해결해준다.

 

 

ReplicaSet 이란?

 

ReplicaSet은 일정 개수의 Pod 를 유지시켜준다.

 

예를들어 파드가 띄워져있는 워커노드 하나가 죽으면 RepliacaSet은 의도한 Pod 개수를 충족하기 위해 다른 워커 노드에 새로운 Pod를 띄워 개수를 맞춘다. (즉 Pod를 지정된 개수만큼 추가하고 만약 초과되면 삭제한다.)

 

# nginx-replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-nginx
spec:
  replicas: 3 # 3개의 Pod가 띄워져있도록 항상 유지한다.
  selector:
    matchLabels:
      app: my-nginx-pods-label
  template:
    metadata:
      name: my-nginx-pod
      labels: 
        app: my-nginx-pods-label
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
kubectl apply -f nginx-replicaset.yaml
kubectl get rs

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset-nginx-5b9dc987c9           3         3         3       103s

# NAME : 레플리카셋 이름의 목록이다.
# DESIRED : 의도한 애플리케이션 레플리카의 수(Pod 수)를 표시한다.
# CURRENT : 현재 실행 중인 레플리카의 수(Pod 수)를 표시한다.
# READY : 사용자가 사용할 수 있는 애플리케이션 레플리카의 수(Pod 수)를 표시한다.
# AGE : 애플리케이션의 실행된 시간을 표시한다.

 

Replica Set은 spec.selector.matchLabel정의된 라벨을 통해 생성해야 하는 Pod를 찾는다.

 

출처: 시작하세요! 도커/쿠버네티스

 

임의로 Pod 하나를 삭제하더라도 Replica Set이 3개를 맞추기 위해 Pod 하나를 더 생성한다.

 

출처: 시작하세요! 도커/쿠버네티스

 

 

더 나아가 Deployment를 알아보자.

 

 

Deployment 란?

 

Deployment는 ReplicaSet을 관리하며 다른 유용한 기능과 함께 Pod에 대한 선언적 업데이트를 제공하는 상위 개념이다.

이름 그대로 컨테이너 애플리케이션(Pod)을 배포하고 관리하는 역할을 담당한다.

 

결론적으로 우리는 굳이 직접 ReplicaSet & Pod 종류의 오브젝트 yaml 파일을 작성 하는 대신 하위로 ReplicaSet & Pod 내용을 모두 포함하는 Deployment 오브젝트 yaml 파일만 작성하면된다.

 

# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3 
  selector: 
    matchLabels:
      app: my-nginx-pods-label
  template:
    metadata:
      name: my-nginx-pod
      labels: 
        app: my-nginx-pods-label
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
kubectl apply -f nginx-deployment.yaml
kubectl get deployments

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           24s

# NAME : 디플로이먼트 이름의 목록이다.
# READY : 사용자가 사용할 수 있는 애플리케이션의 레플리카의 수를 표시한다.
# UP-TO-DATE : 의도한 상태를 얻기 위해 업데이트된 레플리카의 수를 표시한다.
# AVAILABLE : 사용자가 사용할 수 있는 애플리케이션 레플리카의 수를 표시한다.
# AGE : 애플리케이션의 실행된 시간을 표시한다.

 

 

Pod 생성 확인

 

kubectl get pods

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-5dbc9f6694-5xsfz   1/1     Running   0          105s
nginx-deployment-5dbc9f6694-6gtkn   1/1     Running   0          105s
nginx-deployment-5dbc9f6694-9m2bl   1/1     Running   0          105s

 

 

Deployment 장점1: 이미지 버전 업데이트

 

Deployment는 Pod가 실행중이지만 Pod 내 컨테이너중 하나를 새로운 이미지 버전으로 업데이트해야할 경우 모든 Pod가 중단되지 않도록 롤링업데이트(롤아웃)라는 무중단 배포 제공한다.

 

# kubectl set image deployment/<deployment 명> <업데이트하고하자는 container 명>=이미지명:태그 --record
# --record=true 옵션으로 Deployment 변경하면 변경 사항을 Deployment에 기록함으로써 해당 버전의 replicaset을 보존한다.(revision 보존) 
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record


# 또는


# deployment를 edit 하여 nginx:1.14.2 부분을 1.16.1로 변경 후 저장하는 방법도 있다.
kubectl edit deployment.v1.apps/nginx-deployment

 

 

롤링업데이트이란?

 

Pod 내 컨테이너 변경사항이 있을 경우 Pod를 새로 생성해야하는데 모든 Pod가 죽고 다시 생겨날 경우 죽은 시간동안은 서비스가 중단되기 때문에 Deployment는 업데이트 되는 동안 일정한 수의 Pod만 중단되도록 보장한다.

 

기본적으로 의도한 파드 수의 75% 이상이 동작하도록 보장한다. 또한 롤링업데이트 과정에서 새로운 Pod를 먼저 생성 후 이전 Pod를 삭제하는식으로 업데이트가 되는데,충분한 수의 새로운 Pod가 생성될 때 까지는 이전 Pod를 삭제하지 않는다, 반대로 충분한 수의 이전 Pod들이 삭제되기 전까지 새로운 Pod를 생성하지 않는다.

그리고 Deployment는 의도한 Pod 수 보다 더 많이 생성되는 Pod의 수를 제한한다. 의도한 Pod의 수 기준 최대 125%까지만 추가 Pod가 동작할 수 있도록 제한한다.

 

롤링업데이트가 성공하면 Deployment는 새로운 ReplicaSet을 생성해서 Pod를 업데이트한다. 아래와 같이 ReplicatSet를 조회 해보면 이전 ReplicaSet은 스케일 다운, 최신 ReplicaSet은 스케일 업 된것을 확인할 수 있다.

 

kubectl get replicaset

# NAME                          DESIRED   CURRENT   READY   AGE
# nginx-deployment-5dbc9f6694   3         3         3       22m
# nginx-deployment-788bb68657   0         0         0       3m12s

 

 

디플로이먼트는 포드의 정보를 업데이트함으로써 새로운 레플리카셋과 포드를 생성했음에도 불구 하고 이전 버전의 례플리카셋을 삭제하지 않고 남겨두고 있습니다. 즉, 디플로이먼트는 포드의 정보 가 변경되어 업데이트가 발생했을 때 이전의 정보를 리비전으로서 보존합니다.

 

Deployment 장점2: revision 보존

 

롤링업데이트 과정에서 개발자가 컨테이너 태그명 1.6.1을 1.61 로 잘못입력했다고 가정하자. Deployment는 1.61 버전의 이미지를  도커허브에서 못찾기 때문에 에러로인해 롤링업데이트를 중지함과 동시에 새로운 ReplicaSet의 스케일 업을 중지한다.

 

예를들어 Replica Pod를 4개로 의도했을 경우 이전 Pod는 75%인 3개는 남겨두고 새로운 Pod를 의도했던 Pod수의 125%만큼인 2개 더 생성을 한다. 

 

하지만 Deployment는 롤링업데이트 과정에서 오류를 발견하고 롤 스케일다운, 스케일업을 중지한다. 그냥 이대로 멈춘다.. 다행히 제약으로인해 이전 Pod 는 75%가 유지되어있기에 서비스는 중단되지는 않는다.

 

NAME                                READY   STATUS             RESTARTS   AGE
nginx-deployment-5dbc9f6694-5rcbm   1/1     Running            0          2m19s
nginx-deployment-5dbc9f6694-9m6dk   1/1     Running            0          2m19s
nginx-deployment-5dbc9f6694-s77pq   1/1     Running            0          2m19s
nginx-deployment-6f965dbf6-fx5jv    0/1     ImagePullBackOff   0          56s
nginx-deployment-6f965dbf6-spbnz    0/2     ImagePullBackOff   0          56s

 

이 문제를 해결하려면 Deployment를 안정적인 이전 수정 버전으로 롤백해야한다.

 

롤링업데이트 히스토리를 조회하면 원하는 시점에 롤백을 하기위한 revision을 조회할 수 있다.

 

kubectl rollout history deployment.v1.apps/<deployment 명>

kubectl rollout history deployment.v1.apps/nginx-deployment



REVISION  CHANGE-CAUSE
1         ...
2         kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.61 --record=true



# REVISION 값에 해당하는 시점으로 롤백한다.
kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=1



# 이전 버전으로 롤백한다.
kubectl rollout undo deployment.v1.apps/nginx-deployment

 

 

 

 

'☸ Kubernetes' 카테고리의 다른 글

[K8S] 1.Pod  (0) 2021.10.02