Architecture/k8s

Kubernetes 아주 조금만 알아보자 - ReplicaSets,Deployments

KOOCCI 2019. 6. 5. 00:36

※ 개인적으로 받았던 Kubernetes 교육을 정리한 내용입니다.

1편 > Kubernetes 아주 조금만 알아보자 - Kubernetes란? : https://koocci-dev.tistory.com/3

2편 > Kubernetes 아주 조금만 알아보자 - Kubernetes의 흐름 : https://koocci-dev.tistory.com/5

3편 > Kubernetes 아주 조금만 알아보자 - 마스터, 노드 : https://koocci-dev.tistory.com/6

4편 > Kubernetes 아주 조금만 알아보자 - Model, Declared State, Pod : https://koocci-dev.tistory.com/10

5편 > Kubernetes 아주 조금만 알아보자 - ReplicaSets,Deployments : 현재 Post

6편 > Kubernetes 아주 조금만 알아보자 - Service : https://koocci-dev.tistory.com/12


ReplicaSets 란?

ReplicaSets 부터 알아보자.

우리는 앞서, Controller들의 역할에 대해 배웠다.

Controller를 다시 한 번 정리해보자.

변경 사항을 관찰하고 클러스터의 현 상태(Actual State)원하는 상태(Desire State) 와 일치하는지 확인

ReplicaSets는 위와 같은 Controller중 하나로, Pod를 복제해 생성하고, 복제된 Pod의 개수를 정의된 대로 지속적으로 유지하는 Controller 이다.

위 성격을 조금 더 떼어내어 알아보자.

  • Pod를 감싸고 Feature를 추가한다.
  • Pod 템플릿을 가져 와서 원하는 수의 복제본을 배포(deploy)한다.
  • 복제본의 수는 원하는 상태로 저장된다.
  • ReplicaSets(RS)는 직접 배포도 가능하지만, Deployments와 같이 더 높은 수준의 객체(Object)를 통해 간접적으로 RS를 배포한다.

Deployments는 다음 챕터에 설명하도록 하고, Object라 표현된 것은 Kubernetes의 상태를 나타내는 엔티티Object라고 한다.

따라서, 위 Controller의 대한 설명도 Object가 원하는 상태로 유지될 수 있도록 지속적으로 변화시키는 주체라고 볼 수 있다.

 

 

그럼 이를 선언하는 것은 어떻게 할 것인가?

우리는 바로 전 포스트에서 Manifest File을 보았다.

바로 이곳에 정의를 하는데, YAML 혹은 JSON 파일로 정의하며, 일반적으로 YAML을 사용한다.

YAML을 사용하는 이유는 규격이 매우 직관적이고, 읽기 쉽게 설정되어 있기 때문이다. (JSON도 그렇지 않냐고 할 수 있지만, 실제로 복잡하게 얽혀두면 읽기 힘들다. 그러나 YAML의 경우, space와 Enter로 규격이 이루어지기 때문에, 훨씬 읽기 좋게 작성될 수 있다)

apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
  name: xyz
spec:
  replicas: 2
...

더 많은 정보가 들어가지만, 우선 위 내용만 알아보도록 하자.

apiVersion: apps/v1beta2

위 내용은 Kubernetes의 api version을 의미하고, 특정 object는 v1beta2가 아니라, v1, v1beta를 사용하기도 한다.

kind: ReplicaSet

kind의 경우, 생성할 object, controller의 종류를 의미하고, 위에 보다시피 ReplicaSet을 생성하는 것을 볼 수 있다.

metadata:
  name: xyz

name의 경우, object의 고유 이름이 들어가며, 복수로 생성할 경우 prefix로 사용된다.

위 metadata에는 나중에 볼 labels도 들어가는데, 외부에서 Pod을 찾을 때 사용할 label이다.

복수의 label도 입력가능하며, 이 내용은 추후 좀 더 제대로 알아보도록 하자.

spec:
  replicas: 2

spec에는 우리가 기대한 상태, 즉 Desired State가 들어간다.

위에는 replicas 밖에 안들어 있지만, 더 많은 내용이 포함된다.

예를 들면, containers를 선언해, pod에 들어갈 containers를 넣고, 사용하고자하는 이미지를 선언할 수 있다.

위 containers에 대한 내용이 빠져있다는 것은 Pod template가 빠져있다는 것이고, Port Open등의 내용 역시 없다.

이는 추후, 차근히 알아보도록 하자.

 


Deployments 란?

[참고: https://bcho.tistory.com/1266]

앞서, Deployments에 대해서 알아보기로 하였다.

ReplicaSet을 쓰면, 아주 자연스럽게 원하는 갯수의 Pod를 생성하고, 아주 자연스럽게 진행이 될 것이라 생각된다.

 

그런데 예를 들어보자, 우리가 만들었던 하나의 서비스를 고도화하여, Version 2를 개발하였다.

현재 Version 1에서 중단하지 않고, Version 2를 하려면 어떻게 해야할까?

 

단순히 앞서 말한, Template를 바꾸면 자연스럽게 맞추어서 변경될 것이라 생각될 수 있다.

그러나, Template가 바뀌면 그에 상응하는 Pod가 올라오지만, 이전 Template가 바뀌지는 않는다. (Label이 같을 경우)

그래서 할 수 있는 방법은 다음과 같다.

 

  • 블루/그린 배포
    • ToBE 모델을 만들어 두고, 트래픽을 AsIS에서 한번에 옮기는 방법
    • 새로운 Replica Set을 만들어, ToBE모델을 만드는 것.
  • 롤링 업데이트
    • Pod를 하나씩 업데이트하는 방법
    • 새로운 Replica Set을 통해, AsIS Replica를 하나씩 줄이고, ToBE의 Replica를 하나씩 늘리는 것
    • Label을 똑같이 해주면, 자연스럽게 교체가 된다.
    • 배포가 잘못될 경우, 다시 동일한 방법으로 롤백시킨다.

위 두가지는 모드 새로운 Replica Set을 만들어주어, 진행되는 것을 볼 수 있다. 물론, 수동적인 면도 매우 크고, 이를 명령어로 진행할 수 있지만, (kubectl rolling-update) 클라이언트에서 진행되는 명령어다 보니, 클라이언트와 연결이 끊어졌을 때, 문제가 생길 수 있는 점이 있다.

 

따라서, 실제 배포 때에는 Replica Set보다 조금 더 상위 추상화된 개념인 Deployment를 사용한다.

 

Deployment는 위와 같이 Replica Set을 새롭게 만들지 않고, 자동화해준다. 또한, 기본적으로 Replica Set을 생성해주며, 관리한다.

 

YAML파일로 한번 보도록 하자.

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: hello-deployment
spec:
  replicas: 3
  minReadySeconds: 5
  selector:
    matchLabels:
      app: hello-deployment
  template:
    metadata:
      name: hello-deployment-pod
      labels:
        app: hello-deployment
    spec:
      containers:
      - name: hello-deployment
        image: gcr.io/terrycho-sandbox/deployment:v1
        imagePullPolicy: Always
        ports:
        - containerPort: 8080

이전보다 내용이 길어졌다.

더 많은 내용이 있겠지만, 우선 위 내용을 알면 기본적인 운영이 가능해진다.

spec:
  replicas: 3
  minReadySeconds: 5

앞서, Replica Set을 보았기 때문에, replicas에 대한 내용은 알 것이다.

minReadySeconds의 경우 5로 설정되어 있는데, 이는 Pod가 배포된 후, 서비스가 시작되는 시간에 5초정도 딜레이를 주는 것이다.

  selector:
    matchLabels:
      app: hello-deployment

selector는 사실 이후에 배워볼 Service개념이 들어갈 때, 필요성이 강해진다.

Pod는  AutoScaling기능 때문에 자유롭게 사라지고 새롭게 생성된다. 이런 상황에 IP는 항상 동적으로 바뀌게 되니, IP로 접근이 불가능해진다.

따라서, 지정할 수 있는 이름이 추가로 필요하고 그 부분이 Label이다.

같은 Label을 가진 것들 끼리 같은 서비스로 묶이고, 로드벨런싱이 된다.

즉, 모든 replica들이 동일한 label로 묶이며, 아래 spec을 동일하게 가지게 된다.

이 내용은 Service에 들어가서 좀더 자세히 보도록 하자.

template:
   metadata:
     name: hello-deployment-pod
     labels:
       app: hello-deployment
   spec:
     containers:
     - name: hello-deployment
       image: gcr.io/terrycho-sandbox/deployment:v1
       imagePullPolicy: Always
       ports:
       - containerPort: 8080

앞서, Template에 대해 한두번 언급했다.

위와 같이, label이 hello-deployment인 template를 선언하였다.

spec해당 리소스의 상세 스팩이며, 내부에 있을 container를 정의하고 있다.

또한, 내부에 어떤 image를 가져올 것인지, 이미지 Pulling의 정책은 어떤지, 등이 적혀있고, Port 연결에 대한 내용까지 있는 것을 볼 수 있다.

 

다음 포스트에는 서비스에 대한 내용을 알아보자.