IT/Kubernetes

[Kubernetes] Kubernetes Study: "컨트롤러 - ReplicaSet"

wookiist 2021. 7. 10. 21:49

Prologue

본 포스트는 인프런 쿠버네티스 스터디 그룹에서 진행하는 스터디 자료의 일환으로 작성하였습니다. 기본적으론 [대세는 쿠버네티스] 강의를 보고 내용을 정리합니다. 그리고 제 경험이나 이해를 곁들여 포스트를 작성했습니다. 그동안 공식 문서나 블로그 포스트, CKA 강의 등 다양한 경로로 쿠버네티스를 익혀왔지만, 한국어로 잘 정리된 강좌를 한번 듣고 깔끔하게 다듬어보는 시간을 가지면 좋겠다는 생각이 들었습니다.

강의와는 조금 다를 수 있지만, 쿠버네티스 공식 문서를 보고 내용을 정리해보겠습니다.

이번 포스트에선 "컨트롤러 - Replication Controller, ReplicaSet"을 다뤄봅니다. 다만, ReplicationController는 ReplicaSet의 레거시 개념이므로, ReplicaSet만을 다루도록 합니다.

Kubernetes Workload

지난 포스트에서 소개해드린 것처럼, 쿠버네티스 파드는 쿠버네티스 시스템에서 가장 작은 단위입니다. 그리고 이 파드를 직접 운용자가 하나 하나 관리해야 한다면 그 어려움은 이루 말할 수 없을 정도라는 것도 말씀드렸습니다. 쿠버네티스는 이러한 어려움을 해소하고자, 파드의 집합을 관리하는 워크로드 리소스를 사용할 수 있도록 제공하고 있습니다. 그리고 워크로드 리소스는 쿠버네티스 시스템이 운용자가 지정한 상태와 일치하도록 올바른 수의 올바른 파드가 잘 실행되고 있는지 확인하는 컨트롤러를 구성합니다. 본 강의에서는 이 워크로드 리소스를 컨트롤러라고 소개하고 있습니다. 제가 이해한 바로는 결국 같은 개념을 의미하고 있으므로, 둘 중에 편한 용어를 사용하시면 될 것 같습니다.

그렇다면 쿠버네티스가 자체적으로 제공하고 있는 빌트인(built-in) 워크로드 리소스에는 무엇이 있을까요?

  • Deployment & ReplicaSet. DeploymentDeployment의 모든 Pod가 필요할 때 서로 역할이 동등하고, 아무렇게나 교체가 가능하다면 사용하는 가장 일반적인 컨트롤러입니다. 보통, stateless한 애플리케이션을 관리할 때 Deployment로 배포하게 됩니다. ReplicaSet은 기존 ReplicationController를 대체하는 개념입니다. Deployment를 사용하게 되면 자연스럽게 ReplicaSet을 사용하게 되는데, 이는 Deployment가 ReplicaSet의 상위 개념이기 때문입니다. 실제 업무를 하게 되면, ReplicaSet을 사용하는 경우는 극히 드물고, 일반적으로 Deployment를 사용하여 워크로드를 관리합니다.
  • StatefulSet. StatefulSet은 Stateful 애플리케이션을 관리할 때 사용합니다. 이 컨트롤러는 추후 다음 포스트에서 다룰 기회가 있을 예정입니다.
  • DaemonSet. DaemonSet은 클러스터의 모든 노드에 하나씩 배포되어야 하는 애플리케이션을 배포할 때 사용합니다. 보통 CNI 파드를 이렇게 배포합니다.
  • Job & CronJob. Job과 CronJob은 실행 완료 후에 종료되는 작업을 정의합니다. CronJobJob 과는 달리 스케줄에 따라 주기적으로 반복할 수 있습니다.

강의 내용

컨트롤러는 다음과 같은 기능을 제공합니다.

  • Auto Healing
    • 파드 A가 실행 중이던 노드 A가 모종의 이유에 의해 Down 상태가 된 경우 파드 A는 실행이 중단됩니다. 컨트롤러는 이러한 문제를 해결하기 위해, 관리 중인 파드를 다른 정상적인 노드에 자동으로 스케줄해줍니다.
  • Software Update
    • 여러 파드의 버전을 업데이트할 때도 사용됩니다. 소프트웨어 업데이트를 수행하는 방법도 다양한데, 이는 따로 포스트에서 정리해보겠습니다.
  • Auto Scaling
    • 파드의 리소스를 일정량 이상 사용하게 되면, 컨트롤러가 이를 감지하여 파드를 특정 개수만큼 복제하여 Scale Out을 수행해줍니다. 이를 자동으로 수행하기 때문에 운용자의 어떤 제어도 필요하지 않습니다.
  • Job
    • 일시적인 작업을 수행해야 하는 경우에도 컨트롤러가 필요한 순간에만 파드를 만들어서, 그 순간에만 파드를 만들고 삭제하도록 하는 프로세스도 관리할 수 있습니다.

ReplicaSet

ReplicaSet은 기존 ReplicationController를 대체하는 컨트롤러입니다.

강의 내용

Template

ReplicaSet은 Template을 가지고 있어, ReplicaSet이 관리하던 파드에 문제가 있을 때, 해당 Template을 이용해 같은 역할, 같은 성능을 갖는 똑같은 대체용 파드를 생성해줍니다.

이러한 특징을 활용하면 파드의 버전 업데이트를 수행할 수 있습니다. ReplicaSet의 Template에 기록된 파드의 이미지 버전을 업데이트해주면, ReplicaSet이 관리하는 파드의 버전도 함께 업데이트 되기 때문입니다.

매니페스트 파일을 보면서 알아보겠습니다.

우선 파드의 매니페스트 파일입니다.

apiVersion: v1
kind: Pod
metadata:
  name: pod-1
  labels:
    type: web
spec:
  containers:
  - name: container-1
    image: busybox:1.31

이제 이 파드를 담는 ReplicaSet을 정의해보겠습니다.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-1
spec:
  replicas: 3
  selector:
    matchLabels:
      type: web
  template:
    metadata:
      name: pod-1
      labels:
        type: web
    spec:
      containers:
        - name: container-1
          image: 'busybox:1.31'

ReplicaSet의 매니페스트 파일을 보시면, 눈에 띄는 부분이 있습니다. 우선 selector라는 부분과 template 이라는 부분, 그리고 replicas 라는 부분입니다. 여기서는 먼저 template에 대해 알아보겠습니다. template은 이전에도 말씀드린 것처럼, 컨트롤러가 관리하게 될 파드의 모양새를 정의하는 파트입니다. 위의 파드 매니페스트 파일과 ReplicaSet의 매니페스트 파일을 보시면 아시겠지만, ReplicaSet 매니페스트 파일의 template 파트 아래는 파드의 매니페스트 파일에서 metadata 이하 파트와 완전히 동일합니다.

그리고 좀 전에 말씀 드린 것처럼, 컨트롤러가 관리하는 파드의 버전을 업데이트 하려면, template.spec.containers.image 의 버전을 업데이트해주면 됩니다. 예를 들어, 지금 busybox:1.31 버전이라면 업데이트를 한 이미지는 busybox:1.33 이 되겠죠.

Replicas

template을 소개드리면서 사용했던 매니페스트 파일을 그대로 이용해보겠습니다.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-1
spec:
  replicas: 3
  selector:
    matchLabels:
      type: web
  template:
    metadata:
      name: pod-1
      labels:
        type: web
    spec:
      containers:
        - name: container-1
          image: 'busybox:1.31'

이번엔 spec.replicas에 주목해주세요. spec.replicas에 적힌 숫자 3은 말 그대로, 이 컨트롤러가 관리할 파드가 몇 개나 동일하게 복제되어야 하는지 정의하는 필드입니다. 이 필드에 적힌 숫자가 달라지면, 컨트롤러는 그 숫자와 파드의 복제 개수가 일치하도록 파드의 개수를 줄여 나가거나 늘려 나가게 됩니다.

Selector

마지막으로 selector 를 설명드릴 차례입니다. 마찬가지로 위에서 설명드렸던 매니페스트 파일을 가져와서 보겠습니다. 다만 이전 매니페스트와는 조금 다른 점이 있으니 한 번 살펴봐주세요.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-1
spec:
  replicas: 3
  selector:
    matchLabels:
      type: web
    matchExpressions:
      - key: ver
        operator: Exists
  template:
    metadata:
      name: pod-1
      labels:
        type: web
    spec:
      containers:
        - name: container-1
          image: 'busybox:1.31'

이번에는 spec.selector 필드에 주목해주세요. 이는 이전 포스트에서 알아보았던 selector와 정확히 동일한 역할을 합니다. 다만 다른 점이라면, selector 이하 필드에 들어간 matchLabels 필드와 matchExpressions 필드겠네요. matchLabels 필드는 그 이름에서 알 수 있듯이, 해당 레이블이 레이블링 되어 있는 파드만 이 컨트롤러가 관리하겠다는 의미가 됩니다.

그렇다면 matchExpressions 필드는 무엇일까요?

matchExpressions 필드는 matchLabels 를 좀 더 세밀히 조정할 때 사용하게 됩니다. 위 매니페스트에서는 - {key: ver, operator: Exists} 라고 정의했네요. 이는 말 그대로, 파드에 레이블링된 레이블 중에 key 값이 ver 인 레이블이 Exists 존재하면 이 컨트롤러가 관리하겠다라는 의미가 됩니다.

이렇게 matchExpressionsoperator를 사용해서 좀 더 다이나믹하게 레이블을 정의할 수 있는데요. 다음과 같이 총 4개의 오퍼레이터가 존재합니다.

  • Exists - 이름 그대로, Key가 존재하는 파드를 컨트롤러에 연결해줍니다.
  • DoesNotExist - 해당 Key가 존재하지 않는 파드를 컨트롤러에 연결해줍니다.
  • In - 해당 Key와 Value가 일치하는 파드를 컨트롤러에 연결해줍니다.
  • NotIn - 해당 Key와 Value가 존재하지 않는 파드를 컨트롤러에 연결해줍니다.

matchExpressions에 사용된 오퍼레이터는 추후에도 다룰 일이 있으니 잘 알아두시면 좋겠습니다.

참고

마무리

이렇게 해서 인프런 강의의 "컨트롤러 - ReplicaSet" 을 다뤄보았습니다. 내용이 많이 부실하고, 설명이 어렵게 되어 있는 등의 문제가 있을 것으로 보입니다. 추후 수정을 통해 다듬어보겠습니다.

여기까지 따라오시느라 고생이 많으셨습니다. 만약 이 글이 도움이 되셨다면 글 좌측 하단의 하트❤를 눌러주시면 감사하겠습니다.

혹시라도 글에 이상이 있거나, 이해가 가지 않으시는 부분, 또는 추가적으로 궁금하신 내용이 있다면 주저 마시고 댓글💬을 남겨주세요! 빠른 시간 안에 답변을 드리겠습니다 😊

반응형