본문으로 건너뛰기

Replica-Set-And-Deployment

1 Replica Set

  • 쿠버네티스 1.8 버전부터 베타로 업데이트되고 1.9 버전에서 정식 버전으로 업데이트 됨
  • 일반적으로 레플리카셋을 직접 생성하지 않고 상위 수준의 디플로이먼트 리소스를 통해 간접적으로 생성한다.

ReplicationController와 비교

  • 레플리카셋은 레플리케이션 컨트롤러를 완전히 대체한다.
  • 레플리카셋은 ReplicationController보다 풍부한 selector를 지원한다.
  • spec.selector.matchExpressions 으로 보다 강력한 셀렉터를 지원한다.
  • ReplicationController는 env=production, env=devel 라벨을 동시에 만족하는 파드를 매칭시킬 수 없다.
  • ReplicationController는 값에 상관없이 키의 존재만으로 파드를 매칭시킬 수 없다.

1.1 Replica Set을 사용하는 이유

pod를 사용자가 직접 정의하고 사용하는 경우

  • yaml 파일에 pod만 정의해 사용하는 경우 해당 포드는 사용자에 의해서 관리된다
  • 단순 테스트 용도로는 가능할지 몰라도 운영 단계에서 이런 방식은 사용하기 어렵다
    • 여러 개의 동일한 pod로 요청을 분산해야한다.
    • pod가 삭제되거나 장애가 발생한 경우 자동으로 pod를 다른 노드에 다시 생성되지 않아 직접 pod를 다시 생성하고 복구해야한다.
  • 따라서 pod만 정의해서 사용하는 경우는 거의 없다
    • 이러한 한계점을 해결해주는 Replica Set이라는 쿠버네티스 오브젝트를 사용한다

1.2 Replica Set의 역할

  • 사용자가 직접 pod를 관리하는 것이 아니라 Replica Setpod를 관리해준다
  • 정해진 수의 동일한 pod가 항상 실행되도록 관리한다
  • 장애 등의 이유로 포드를 사용할 수 없다면 다른 노드에 pod를 다시 생성한다.

1.3 Replica Set 사용하기

replicaset-nginx.yaml 작성

apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-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

spec.replicas

  • 동일한 pod를 몇 개 유지할 것인지 설정한다.

spec.template

  • pod를 생성할 때 사용할 템플릿을 정의한다.
  • 어떠한 pod를 생성할 것인지 명시하는 것으로 보통 포드 스펙, 포드 템플릿이라고 불린다.

Replica Set 사용하기

$ kubectl apply -f replicaset-nginx.yaml
replicaset.apps/replicaset-nginx created

## pod 목록 확인
$ kubectl get po
NAME READY STATUS RESTARTS AGE
replicaset-nginx-bnjcs 1/1 Running 0 24s
replicaset-nginx-cb5d8 1/1 Running 0 24s
replicaset-nginx-s8pmc 1/1 Running 0 24s

## replica set 목록 확인
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
replicaset-nginx 3 3 3 47s

## replica set 삭제
$ kubectl delete -f replicaset-nginx.yaml

1.4 Replica Set의 동작 원리

  • replica setpod와 라벨 셀렉터로 느슨하게 연결되어 있다
  • replica setspec.selector.matchLabels에 정의된 라벨을 통해 생성할 포드를 찾는다
  • 정의된 라벨을 가지는 포드의 개수가 spec.replicas 항목에 정의된 개수와 일치하지 않으면 포드를 생성하거나 삭제하여 개수를 일치시킨다

Label

  • 쿠버네티스 리소스를 분류할 때 사용하는 메타데이터
  • 서로 다른 오브젝트가 서로를 찾을 때 사용한다

1.5 레이블 셀렉터

  • **matchLabels**은 기존의 레플리케이션컨트롤러와 크게 다를게 없다.
  • 레플리카셋의 더 강력한 matchExpressions 을 사용해보자.
  • 여러 표현식을 지정하는 경우 모든 표현식이 true여야 한다.
apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
name: kubia
spec:
replicas: 3
selector:
matchExpressions:
- key: app
operator: In
values:
- kubia
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia

key

  • 레이블의 키를 지정한다.

operator

  • In은 레이블의 값이 지정된 값 중 하나와 일치해야한다.
  • NotIn은 레이블의 값이 저정된 값과 일치하지 않아야한다.
  • Exists는 파드의 레이블에 지정된 레이블 키가 포함되어야 한다. 값이 필요없으므로 values의 값을 지정하지 않는다.
  • NotExists는 파드의 레이블에 지정된 레이블 키가 포함돼 있지 않아야 한다. 값이 필요없으므로 values의 값을 지정하지 않는다.

values

  • 레이블의 값을 지정한다.

1.6 이미지 업데이트

  • 레플리카셋의 파드 템플릿을 수정하여 애플리케이션의 버전을 업데이트하면 자동으로 기존의 파드가 내려리고 새로운 버전의 파드가 올리지 않는다.

  • 업데이트를 위해선 직접 기존 파드를 삭제한다. 그러면 레플리카셋이 새 템플릿을 기반으로 업데이트 버전의 파드를 생성 할 것이다.

작동중인 레플리카셋의 이미지를 kubectl edit 명령어로 수정하면 자동 업데이트 되는지 아래와 같이 레플리카셋 데피니션을 정의해보고 직접 해보자.

test-rs.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: test-rs
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:1.12.2
## 레플리카셋 생성
$ kubectl delete -f test-rs.yaml

## 레플리카셋 확인
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
test-rs 3 3 3 39s

## 이미지 변경 nginx의 이미지를 1.12.2에서 1.23.2로 변경한다.
$ kubectl edit rs test-rs

## 파드 확인
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
test-rs-6vwfj 1/1 Running 0 3m41s
test-rs-kpspg 1/1 Running 0 3m41s
test-rs-wv7nq 1/1 Running 0 3m41s

## 파드의 상세를 확인해 이미지의 버전이 업데이트 되었는지 확인하지만 그대로다.
$ kubectl describe pod test-rs-6vwfj
...
Containers:
nginx-container:
Container ID: containerd://a58a5edf6be97df0495f9da4e6a4cfe8ff53bafacc95f16be79e08e309ae3788
Image: nginx:1.12.2
...

## 방금 확인한 파드를 지운다.
$ kubectl delete pod test-rs-6vwfj

## 파드 목록 확인
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
test-rs-g6s6x 1/1 Running 0 19s
test-rs-kpspg 1/1 Running 0 3m41s
test-rs-wv7nq 1/1 Running 0 3m41s

## 새로 생성된 파드 상세 확인하면 1.23.2 버전의 nginx가 사용됨
$ kubectl describe pod test-rs-g6s6x
...
Containers:
nginx-container:
Container ID: containerd://6be66d457506797a91f1033a1c8d30fef9f9d09e52d37ea5553f14d8012b5d1c
Image: nginx:1.23.2
...

결과적으로 이미지 버전을 수정해도 자동 업데이트가 되지 않는다. 이러한 단점을 보완해 레플리카셋을 직접 사용하지 않고 롤링 업데이트 기능을 제공하는 상위 객체 Deployment를 사용한다.

2 Deployment

  • 레플리카셋으로 충분할 것 같지만 운영 환경에서 레플리카셋을 직접 정의하고 사용하는 경우는 거의 없다
  • 보통 레플리카셋과 포드 정보를 정의하는 Deployment 오브젝트를 정의해 사용한다
  • Deployment는 레플리카셋의 상위 오브젝트이기 때문에 Deployment 생성시 레플리카셋도 함께 생성된다
  • 따라서 Deployment를 사용하면 레플리카셋과 포드를 직접 생성할 필요가 없다
  • 실제 파드는 디플로이먼트가 아니라 디플로이먼트의 레플리카셋에 의해 생성되고 관리된다.

2.1 Deployment 를 사용하는 이유

레플리카셋을 직접 사용하지 않고 Deployment를 사용하는 이유

  • 애플리케이션의 업데이트와 배포를 더욱 편하게 하기 위해서
  • 애플리케이션을 업데이트 할 때 레플리카셋의 변경 사항을 저장하는 리비전을 남겨 롤백을 가능하게 해준다
  • 무중단 서비스를 위해 pod의 롤링 업데이트를 지원한다

2.2 Deployment 생성하기

  • 디플로이먼트는 레플리카셋을 만드는 것과 다르지 않다.
  • 레이블 셀렉터, 원하는 레플리카 수, 파드 템플릿으로 구성된다.
  • 또한 리소스가 수정될 때 업데이트 수행 방법을 정의하는 디플로이먼트 전략을 지정하는 필드가 있다.

deployment-nginx.yaml 작성

apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-nginx
progressDeadlineSeconds: 600
revisionHistoryLimit: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
template:
metadata:
name: my-nginx-pod
labels:
app: my-nginx
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80

2.2.1 Deployment Spec

spec.progressDeadlineSeconds

  • 업데이트가 되지 않으면 지정된 시간 후에 undo한다.
  • 기본 값 600

spec.revisionHistoryLimit

  • 리비전 최대 저장 개수를 지정한다.

spec.minReadySeconds

  • 새로 생성된 포드의 상태가 available로 간주되려면 레디니스 프로브를 성공시켜야 한다. minReadySeconds를 지정하면 지정된 시간동안 컨테이너에 준비 시간을 주고 이후에 레디니스 프로브를 시작한다.
  • 기본값은 0이다
    • 팟은 준비되는 즉시 사용 가능한 것으로 간주된다.
  • minReadySeconds가 지나기 전에 새 파드가 제대로 작동하지 않고 레디니스 프로브가 실패하면 새 버전의 롤아웃이 효과적으로 차단된다.
  • minReadySeconds를 올바르게 설정하지 않고 레디니스 프로브만 정의하는 경우 레디니스 프로브의 첫 번째 호출이 성공하면 즉시 새 파드가 사용 가능한 것으로 간주된다.

spec.strategy.type

  • 업데이트 방식을 지정한다.
  • Recreate또는 RollingUpdate가 가능하다
  • 기본값 RollingUpdate

spec.strategy.rollingUpdate.maxSurge

  • 지정된 replicas 대비 최대로 허용할 수 있는 파드의 개수를 비율로 지정

    • 비율 말고 절대값도 지정할 수 있다.
  • 반올림한다.

    • 3(replicas)의 25% 는 0.75 반올림하면 1 즉 최대 4개의 파드를 허용한다.
  • 기본값 25%

  • 해당 값이 높으면 보다 빠른 업데이트가 가능하다.

spec.strategy.rollingUpdate.maxUnavailable

  • 업데이트시 지정된 replicas 대비 최대로 허용할 수 있는 다운 파드의 개수를 비율로 지정

    • 비율 말고 절대값도 지정할 수 있다
  • 기본값 25%

  • replicas가 100이라면 최대 25개 까지 파드를 다운시킬 수 있다.

Deployment 생성하기

  • create를 사용할 때는 리비전 히스토리를 기록하기 위해 반드시 --record 옵션을 사용하자
$ kubectl create -f deployment-nginx.yaml --record=true
deployment.apps/my-nginx-deployment created

2.2 Deployment 롤아웃 상태 출력

kubectl get deployment

$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
my-nginx-deployment 3/3 3 3 18s

## Replica set 조회 Deployment 생성시 Replica set도 생성된 것을 볼 수 있다
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
my-nginx-deployment-7484748b57 3 3 3 45s
  • NAME: Deployment의 이름
  • READY: livenessProbe를 성공한 파드의 수 / 전체 파드 수 ?
  • UP-TO-DATE: 업데이트를 성공한 파드의 수
  • AVAILABLE: readinessProbe를 성공한 파드의 수 / 전체 파드 수 ?
  • AGE: 생성된 시간

kubectl rollout status deployment

  • 디플로이먼트 상태를 확인하기 위해 만들어진 특별한 명령어
$ kubectl rollout status deployment my-nginx-deployment
deployment "my-nginx-deployment" successfully rolled out

2.3 Deployment 업데이트하기

Creating a Deployment

  • 아래의 nginx-deployment.yaml로 실습 진행
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
$ kubectl create -f nginx-deployment.yaml --record=true

결과 확인

$ kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out

Updating a Deployment

  • 아래와 같은 명령어로 nginx 이미지를 업데이트 할 수 있다.
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record=true
deployment.apps/nginx-deployment image updated

레플리카셋 확인

  • Deployment는 새로운 레플리카셋을 만들어고 pod를 업데이트했다.
  • 68fc675d59가 새로운 레플리카셋이고 7fb96c846b 는 예전 레플리카셋이다.
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-68fc675d59 3 3 3 7s
nginx-deployment-7fb96c846b 0 0 0 77s

2.3.1 디플로이먼트 전략

  • 디플로이먼트 전략으로 RollingUpdate와 Recreate 전략이 있다.
  • 기본값은 RollingUpdate이다.

Recreate 전략

  • Recreate 전략을 사용하면 새 파드를 만들기 전에 이전 파드를 모두 삭제한다.
  • 애플리케이션이 여러 버전으로 병렬적으로 실행하는 것은 지원하지 않는다.
  • 이 전략은 애플리케이션을 완전히 사용할 수 없는 짧은 서비스 다운타임이 발생한다.

RollingUpdate 전략

  • 이전 파드를 하나씩 제거하고 동시에 새 파드를 추가해 전체 프로세스에서 애플리케이션이 계속 사용할 수 있도록 한다.
    • 서비스 다운타임이 없다.
  • 의도하는 레플리카 수보다 많거나 적은 파드 수에 관한 상한과 하한을 설정할 수 있다.
  • 애플리케이션이 이전 버전과 새 버전을 동시에 실행할 수 있는 경우에만 이 전략을 사용해야 한다.

2.3.2 롤아웃 속도 제어

  • 롤링 업데이트 전략의 경우 maxSurgemaxUnavailable 속성으로 롤아웃 속도를 제어할 수 있다.
  • 이 두개의 속성이 롤링 업데이트 중에 한 번에 몇개의 파드를 교체할지 결정한다.

spec.strategy.rollingUpdate.maxSurge

  • 지정된 replicas 대비 최대로 허용할 수 있는 파드의 개수를 비율로 지정

  • 반올림한다.

    • 3(replicas)의 25% 는 0.75 반올림하면 1 즉 최대 4개의 파드를 허용한다.
  • 기본값 25%

  • 해당 값이 높으면 보다 빠른 업데이트가 가능하다.

spec.strategy.rollingUpdate.maxUnavailable

  • 업데이트시 지정된 replicas 대비 최대로 허용할 수 있는 다운 파드의 개수를 비율로 지정
  • 기본값 25%
  • replicas가 100이라면 최대 25개 까지 파드를 다운시킬 수 있다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-nginx
progressDeadlineSeconds: 600
revisionHistoryLimit: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
template:
metadata:
name: my-nginx-pod
labels:
app: my-nginx
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80

2.4 디플로이먼트 롤아웃 이력 표시

  • 디플로이먼트의 레플리카셋은 개정 이력으로 사용되기 떄문에 수동으로 삭제해서는 안된다.
    • 그렇게 하면 디플로이먼트 기록에서 특정 버전을 읽어 롤백할 수 없게 된다.
  • 개정 내역의 수는 디플로이먼트 리소스의 revisionHistoryLimit 속성에 의해 제한된다.
    • 기본값은 10로 설정되어 현재와 이전 버전만 표시된다.

리비전 목록 보기

$ kubectl rollout history deployment nginx-deployment
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
1 kubectl create --filename=nginx-deployment.yaml --record=true
2 kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record=true

2.5 리비전 롤백

바로 이전 리비전으로 롤백하기

$ kubectl rollout undo deployment/nginx-deployment

특정 리비전으로 롤백하기

$ kubectl rollout undo deployment/nginx-deployment --to-revision=2

2.6 scale out

## 'foo'라는 deployment를 1으로 스케일
kubectl scale --replicas=1 deployment foo

참고