Computing

Pod 배포 - 워크로드 리소스 (1) (Replicaset, Deployment) 본문

Cloud/Kubernetes

Pod 배포 - 워크로드 리소스 (1) (Replicaset, Deployment)

jhson989 2022. 12. 6. 22:24

Pod 배포 케이스

앞선 포스터에서 Pod란 무엇인지에 대해서 간략히 정리하였다. 파드는 쿠버네티스에서 배포되는 가장 작은 컴퓨팅 단위이다. 개발자가 애플리케이션을 파드 단위로 개발하고, 이 쿠버네티스에게 파드들 실행(배포)을 명령한다. 이 명령은 선언적 방식으로, 이 파드의 배포는 어떻게 이루어져야 하는 지를 개발자가 구성 파일로 작성한다. 쿠버네티스는 그 파일을 읽어 그 구성대로 클러스터 내에 효율적으로 파드들을 배포한다.

 

Fig 1. Kubernetes의 Pod 운영 [1]

 

앞선 포스터에서 파드 하나만을 생성하는 yaml 파일(구성 파일, Manifest)에 대해서 정리하였다. 쿠버네티스는 yaml 파일에 정의된 방식으로 파드를 생성하고 그것을 클러스터 내의 임의 노드에 스케쥴링한다. 파드가 스케쥴링된 노드는 해당 파드를 실행한다. 파드 생성을 위한 yaml 파일은 파드를 클러스터내에 사용자의 요구조건에 맞는 노드(컴퓨터) 위에서 실행시킴으로서 맡은 역할이 끝난다.

 

실제 프로덕션 레벨 애플리케이션 배포 시 단순히 파드를 실행시키는 것 말고도 많은 것을 해줘야 한다. 애플리케이션은 기능 업데이트나 버그 패치가 필요할 수도 있다. 더 많은 사람들이 애플리케이션을 사용하여 스케일업 or 스케일아웃 해줘야 할 수도 있다. 애플리케이션 실행 시 에러에 의해 파드가 종료되어서 애플리케이션을 재실행해줘야 할 수도 있고, 아예 컴퓨터가 고장나 클러스터 내 다른 컴퓨터에서 애플리케이션을 실행시켜야 할 수도 있다.

 

쿠버네티스는 이러한 배포를 자동화해주는 소프트웨어로, 이를 위해 다양한 워크로드 리소스를 제공한다. 쿠버네티스에서 워크로드란 애플리케이션을 의미하는 것으로, 하나의 워크로드는 일련의 파드 집합으로 구성된다. 워크로드 리소스는 개발자를 대신하여 파드 집합을 관리한다. 쿠버네티스 컨트롤러는 리소스의 상태를 확인하고 워크로드 리소스가 제대로 작동하는 지 관리한다.

 

(리소스는 개발자가 원하는 배포 상태를 명시해둔 것이라면, 컨트롤러는 리소스에 따라서 배포를 하는 객체[2]라고 하는데 확실한 지는 모르겠다. 완벽히 구분되는 개념이 아닌 것 같기도 하고...)

(공식 문서에는 리소스와 컨트롤러의 관계를 다음과 같이 표현한다: Workload resources manage a set of pods on your behalf. These resources configure controllers that make sure the right number of the right kind of pod are running, to match the state you specified.)

(다른 블로그들에서는 리소스를 컨트롤러라고 하는데도 있고 하니 사실 정확히 구분하지는 못하겠다!)

 

 

워크로드 리소스 링크에서도 확인할 수 있지만 디플로이먼트(deployment), 레플리카셋(replicaset), 스테이트풀셋(statefulset), 데몬셋(daemonset), 잡(job), 크론잡(cronjob) 등이 있다. 각 워크로드 리소스는 애플리케이션의 목적에 따라 구별되어 사용된다. 앞으로의 포스터에서 각 워크로드 리소스에 대해서 정리해 보고자 한다.

 

 

 

Replicaset 레플리카셋

레플리카셋의 목적은 레플리카 파드 집압의 실행을 항상 안정적으로 유지하는 것[3]이다. 레플리카셋에 명시된 동일 파드 개수에 대한 가용성을 보장한다. 쉽게 말하면 파드를 몇 개 실행시킬 것인지를 명시하는 리소스이다. 예를 동일한 파드를 3개 실행시키고 싶을 때 사용하는 워크로드 리소스이다. 위 예와 같이, 어떤 파드를 몇 개 사용할 지를 개발자가 명시해두면 그 만큼의 파드가 실행되도록 쿠버네티스가 관리한다.

 

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # 케이스에 따라 레플리카를 수정한다.
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3

 

위는 레플리카셋 yaml 파일의 예시 코드이다. 레플리카셋 yaml 파일을 작성하기 위해서는 크게 3가지 셀렉터(matchLabels), 레플리카 개수(replicas), 파드 템플릿(template)을 명시해줘야 한다. 셀렉터는 파드가 동일한지를 식별하는 조건문, 레플리카 개수는 유지해야 하는 파드의 개수, 파드 템플릿은 새로운 파드를 생성할 시 사용되는 템플릿이다. 레플리카셋은 지정된 레플리카 개수를 유지하기 위해, 동일한 파드 개수가 부족하면 새로운 파드를 생성하고 파드 개수가 많으면 기존 파드를 삭제한다.

 

레플리카셋의 셀렉터는 파드들이 동일한 지를 식별하는 조건문이라고 생각하면 된다. 같은 이미지에서 생성된 파드들이라도 하나의 파드는 테스트용으로 사용하고, 다른 파드는 배포용으로 사용한다면 다른 파드라고 개발자가 구분하고 싶을 수 있다. 이처럼 동일한 파드라는 것은 매우 주관적인 개념으로 개발자가 직접 명시할 수 있도록 하였다.

 

구체적으로, 파드의 레이블(labels) 속성을 통해 파드의 동일 여부를 결정한다. 레이블은 키, 값의 쌍으로 파드의 특성을 식별하는 데 사용된다. 이 파드가 "release" 용도인지, "test" 혹은 "development" 용도인지 등 개발자가 주관적으로 설정할 수 있는 속성이다. 레이블이 일치한다면 레플리카셋이 템플릿을 통해 생성하지 않은 파드 또한 레플리카셋이 자동으로 소유하게 된다. 즉 동일 파드라는 것은 같은 이미지를 쓴다든가로 확인되는 것이 아닌 개발자가 지정하는 레이블을 통해서 확인된다.

 

레플리카셋의 가장 중요한 사용 목적은 파드의 스케일링이 쉽다는 것이다. yaml 파일의 [.spec.replicas] 필드만 원하는 숫자로 업데이트해주면 쉽게 파드의 개수를 조절할 수 있다. 사용자가 갑자기 많아졌을 때 쉽게 실행되는 파드 숫자를 늘릴 수 있고, 반대로 사용자가 적어질 때 실행되는 파드 숫자를 쉽게 줄일 수 있다. 나아가 추가적인 설정을 하면 오토스케일링까지 지원 가능하다.

 

이러한 레플리카셋은 단독으로 사용할 수 있지만, 쿠버네티스는 레플리카셋 단독 사용보다는 디플로이먼트 사용을 권장한다[4]. 디플로이먼트는 레플리카셋을 내부적으로 사용하는 또다른 워크로드 리소스이다.

 

추가적으로 쿠버네티스 예전 버전의 레플리케이션 컨트롤러(Replication controller)를 대체한다. 둘 사이의 기능적 차이는 없지만 레플리케이션 컨트롤러는 레이블이 정확히 일치하는 파드만을 관리했다면, 레플리카셋의 셀렉터(matchLabels) 표현력이 더 좋아져 다양한 레이블 선택 조건문 작성이 가능해졌다고 한다.

 

 

 

Deployment 디플로이먼트

디플로이먼트는 파드와 레플리카셋에 대한 선언적 업데이트를 제공하는 워크로드 리소스[5]이다. 파드와 레플리카셋에 하듯이, 디플로이먼트를 통해 선언적으로 파드를 어떻게 배포할지 상태를 정의할 수 있다. 디플로이먼트 컨트롤러는 디플로이먼트로 선언된 상태가 유지되도록 파드를 운영한다. 다음 코드는 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

 

앞서 말했듯 디플로이먼트는 내부적으로 레플리카셋을 사용한다. 따라서 디플로이먼트는 레플리카셋이 사용되는 목적인 쉬운 스케일링을 지원한다. 레플리카셋처럼 replicas 값을 원하는 숫자로 바꿔주면 쿠버네티스가 자동으로 파드를 해당 숫자에 맞게 생성 or 제거해준다.

 

이러한 기능 뿐만 아니라 디플로이먼트는 애플리케이션의 중단없는 업데이트(롤아웃, roll out) 및 롤백(rool back)을 지원한다. 디플로이먼트의 파드 템플릿이 변경될 경우 디플로이먼트의 롤아웃이 트리거된다. 예를 들어 이미지의 버전을 바꿀 경우(nginx:1.14.2 -> 1.16.1) 디플로이먼트의 롤아웃이 실행된다.

 

쿠버네티스는 중단없는 업데이트, 즉 롤아웃을 지원한다. 롤아웃은 rolling update를 의미하는 것으로 다음 Fig 2.와 같다.

 

Fig 2. Rollout 과정

 

Fig 2.는 파드를 old 버전에서 new 버전으로 바꾸는 예제이다. 각 버전은 레플리카셋에 의해 2개씩 생성된다. 롤아웃 시 디플로이먼트는 new 버전의 파드를 템플릿으로 하는 레플리카셋을 생성한다. 그리고 해당 레플리카셋은 new 버전 파드를 생성한다. (step 2) new 버전 파드 하나의 생성이 완료되면, old 버전 파드 하나를 제거한다. (step 3) 한 번 더 new 버전 파드를 생성하고, 생성이 완료되면 old 버전 파드 나머지를 제거한다. (step4) 최종적으로 new 버전 파드 2개가 생성된다. 전 과정에서 파드 2개가 계속 실행되고 있기에, 사용자(client)는 계속해서 서비스를 통해 파드 서비스를 이용할 수 있다.

 

버전을 되돌리는 롤백 시에도 Fig 2.와 같은 중단없는 롤백이 가능하다.

 

 

 

Reference

[1] https://www.suse.com/c/rancher_blog/understanding-the-kubernetes-node/

[2] https://stackoverflow.com/questions/59950463/objects-resources-and-controllers-in-kubernetes

[3] https://kubernetes.io/ko/docs/concepts/workloads/controllers/replicaset/

[4] https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/#deployment-recommended

[5] https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/