개발놀이터

쿠버네티스 이론 : 컨트롤러 (ReplicaSet, StatefulSet) 본문

배포/kubernetes

쿠버네티스 이론 : 컨트롤러 (ReplicaSet, StatefulSet)

마늘냄새폴폴 2024. 9. 7. 21:47

이번 포스팅에선 쿠버네티스의 꽃인 (대체 꽃이 몇송이야) 컨트롤러에 대해서 공부한 내용을 정리해보도록 하겠습니다. 

 

컨트롤러는 파드를 관리하면서 애플리케이션을 안정적으로 운영할 수 있도록 도와줍니다. 컨트롤러는 크게 네 가지 기능을 제공하는데 순서대로 한번 보시죠!

 

  • Auto Healing : 만약 파드가 죽어서 애플리케이션을 사용할 수 없으면 자동으로 살려주는 역할을 합니다. 
  • Auto Scale Out / Scale In : 컨트롤러는 파드의 개수를 자유자재로 조절하면서 스케일아웃, 스케일인을 구현할 수 있습니다. 
  • Deployment : 애플리케이션의 버전을 업데이트 하는 과정에서 자연스러운 무중단 배포를 진행해주고 만약 문제가 생기는 경우 롤백까지 진행해줍니다. 
  • Job : 특정 파드가 잠깐 수행해야하는 일이 이싸으면 해당 파드에 자원을 할당해주고 일이 끝나면 자원을 회수하는 역할을 수행합니다. 

 

이번 포스팅에선 설정만 해놓으면 별일 없이 잘 수행되는 Auto Healing과 Job을 제외하고 Auto Scale Out / In과 Deployment를 중점적으로 살펴보도록 하겠습니다. 

 

Controller (컨트롤러)

컨트롤러에서 쿠버네티스는 기존에 Replication Controller를 사용했습니다. 하지만 이제 Deprecated 됨으로써 ReplicaSet을 사용해야하는데요. 

 

Replication Controller와 ReplicaSet에서 모두 지원하는 template과 replicas에 대해서 짚고 넘어가고 ReplicaSet에서만 지원하는 selector에 대해서 짚고 넘어가겠습니다. 

 

template / replicas

apiVersion: v1
kind: ReplicationController
meatdata:
  name: replication-1
spec:
  replicas: 3
  selector:
    type: web
  template:
    metadata:
      name: pod-1
      labels:
        type: web
    spec:
      containers:
      - name: container
        image: tmkube/app.v2

 

template은 어떤 파드를 기준으로 레플리카를 만들 것인지 설정하는 것입니다. 보통 파드의 메타정보와 스펙에 대해서 입력하면 그 파드를 기준으로 레플리카를 만들어주죠. 

 

apiVersion: v1
kind: Pod
metadata:
  name: pod-1
  labels:
    type: web
spec:
  containers:
  - name: container
    image:
      tmkube/app.v1

 

라벨로 선택할 파드가 존재해야 이 Replication Controller가 작동한다는 특징이 있습니다. 

 

selector

selector는 ReplicaSet에서만 존재하는 특징으로 Replication Controller는 라벨로 파드를 관리했던 것과 다르게 조금 더 세세하게 파드를 설정할 수 있다는 특징이 있습니다. 

 

ReplicaSet의 selector는 기존 라벨 방식의 matchLabels속성과 조금 더 세세한 설정이 가능한 matchExpressions 속성이 있습니다. 

 

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replica-1
spec:
  replicas: 3
  selector:
    matchLabels:
      type: web
    matchExpressions:
    - {key:ver, operator: Exists}
  template:
    metadata:
      name: pod

 

operator에는 Exists말고도 세 가지 속성이 더 있는데 한번에 정리해보죠!

 

  • Exists : Exists는 key에 적혀 있는 값이 존재하면 해당 파드와 컨트롤러를 연결하는 역할을 합니다. 
  • DoesNotExist : DoesNotExist는 Exists와 반대로 key에 적혀있지 않은 파드들을 연결합니다. 
  • In : In속성은 key말고도 value를 설정하여 더 세세하게 파드를 연결할 수 있게 합니다. 예를 들어서 key: A, value: 1이렇게 설정하면 A:1로 설정된 파드와 연결됩니다. 
  • NotIn : NotIn은 In과 반대되는 특징을 가집니다. 

이 상황에서 컨트롤러가 사라지면 파드가 같이 사라진다는 특징이 있는데 이를 kubectl로 cascade 속성을 false로 주면 컨트롤러만 삭제시킬 수 있습니다. 

 

selector를 사용할 때 주의사항은 matchLabels에 적혀있는 라벨과 템플릿에 있는 라벨이 일치해야 ReplicaSet이 생성됩니다. 

 

마찬가지로 matchExpressions를 사용할 때도 템플릿에 있는 값들을 모두 포함해야합니다. 

 

 

Stateful vs Stateless

ReplicaSet이 파드를 복제해서 안정적인 서비스를 이뤄내는 것과는 별개로 조금 더 신경써야 하는 부분이 있습니다. 

 

바로 Stateful과 Stateless입니다. 

 

앞서 언급한 ReplicaSet은 사실 Stateless 애플리케이션에 적합한 오브젝트입니다. 여기서 Stateless 애플리케이션과 Stateful 애플리케이션을 짚고 넘어가도록 하겠습니다. 

 

Stateless 애플리케이션

Stateless한 애플리케이션에 적합한 예시는 Web Server들이 있는데 Apache Web Server나 Nginx같은 서비스가 바로 그것이죠. 

 

이런 서비스들의 특징은 각각의 파드들이 공통된 역할을 가지고 있다는 것입니다. 즉, 만약 레플리카를 만들더라도 이전에 배포했던 파드와 똑같은 파드를 만들어도 크게 문제될 것이 없다는 것입니다. 

 

이런 특성이 있어서 만약 파드에 볼륨을 만들어주려고 해도 모든 파드들이 동일한 볼륨을 바라봐도 상관없습니다. 

 

또한, Stateless 애플리케이션들의 네트워크 특징을 보면, 유저가 네트워크를 이용해 애플리케이션에 접근하고 이 트래픽은 한쪽에 쏠리면 안되기 때문에 동일한 비율로 로드밸런싱이 됩니다. 

 

Stateful 애플리케이션

반면 Stateful 애플리케이션은 Stateless 애플맄레이션과 반대로 각각의 파드들이 각자의 역할을 가지고 있고 이 때문에 볼륨도 다른 볼륨을 가지고 있어야하며 심지어 같은 노드에 배포되지 않아야 하는 경우도 있습니다. 

 

또한, 보통 Stateful 애플리케이션은 내부 시스템들이 접근하는 경우가 많고 이 트래픽도 역할에 따라 부하가 분배되는 곳이 다른 목적지를 가지는 경우가 많습니다. 

 

이런 Stateful 애플리케이션의 대표적인 예시는 바로 데이터베이스입니다. 

 

데이터베이스가 배포된 파드들은 읽기, 쓰기가 가능한 마스터와 읽기만 가능한 슬레이브가 있고 만약 마스터가 죽어버리면 슬레이브를 마스터로 승격시키기 위해 감시하고 있는 Arbiter (아비터)가 있습니다. 

 

일반적인 데이터베이스를 생각해보면 각 파드에서 접근해야하는 저장소도 다른 것이 당연하고 마스터가 들어있는 노드 전체가 죽어버리는 경우를 대비해 무조건 다른 노드에 배포되어야합니다. 

 

이런 특징 때문에 Stateless 애플리케이션과 Stateful 애플리케이션을 다르게 관리해줘야합니다. 

 

Stateless 애플리케이션은 이전에 봤던 ReplicaSet을 이용해 관리하고 이와 반대되는 Stateful 애플리케이션은 StatefulSet이라는 오브젝트로 관리됩니다. 

 

ReplicaSet과 StatefulSet의 차이 : 파드의 생성과 삭제

StatefulSet은 ReplicaSet과 비슷하지만 두드러지게 다른 특징들이 있는데 하나씩 살펴보도록 하겠습니다. 

 

replicas가 1인 경우

  • ReplicaSet : 만약 replicas 속성이 1인 경우 ReplicaSet은 랜덤한 이름으로 파드의 이름을 짓습니다. ReplicaSet은 이렇게 해도 상관이 없는 것이, 어차피 레플리카들이 같은 역할을 하고 있는 복제품이기 때문입니다. 
  • StatefulSet : StatefulSet은 replicas 속성이 1인 경우 파드의 이름을 인덱싱해서 지어줍니다. Stateful한 애플리케이션들은 파드의 이름조차 고유한 역할을 부여받기 위해 사용되기 때문에 이 이름이 막 지어지면 뒤에서 언급할 Headless Service를 이용할 때 불편하기 때문에 정직하게 인덱싱하여 이름이 지어집니다. 

replicas가 3인 경우

  • ReplicaSet : replicas를 늘리게 되면 ReplicaSet은 동일한 역할을 하는 파드를 동시에 생성합니다. 어차피 동시에 생성되어도 상관없기 때문에 동시에 생성됩니다. 또한, 만약 파드가 죽어서 재생성 되더라도 랜덤하게 새로운 이름을 부여해주면서 파드를 재생성합니다. 
  • StatefulSet : StatefulSet은 replicas가 3이 되면 파드를 동시에 생성하지 않고 순차적으로 생성합니다. 이름도 인덱싱을 해주면서 순차적으로 생성됩니다. 또한, 만약 파드가 죽으면 죽은 파드와 동일한 이름으로 재생성해줍니다. 이 이유도 뒤에 언급할 Headless Service를 이용할 때 필요하기 때문입니다. 

replicas가 0인 경우

  • ReplicaSet : 만약 replicas를 0으로 바꾸면 ReplicaSet으로 관리되는 파드들은 모두 동시에 삭제됩니다. 
  • StatefulSet : StatefulSet은 replicas를 0으로 하더라도 파드가 삭제되는 것이 생성되었던 것의 역순으로 삭제됩니다. 

 

ReplicaSet과 StatefulSet의 차이 : PVC와 Headless Service

ReplicaSet과 StatefulSet의 차이는 파드의 생성과 삭제뿐만 아니라 볼륨을 연결할 때와 Headless Service의 관점에서도 두드러지는 차이를 보여줍니다. 

 

replicas가 0인 경우

  • ReplicaSet : ReplicaSet으로 생성된 파드들은 기존에 PV와 PVC가 생성되어있어야 파드와 볼륨이 적절하게 매칭이됩니다. 이 때문에 PVC와 PV를 직접 생성해야한다는 특징이 있습니다. 
  • StatefulSet : StatefulSet은 PV template이 존재해 이 템플릿을 기반으로 PVC가 동적으로 바인딩됩니다. 

replicas가 3인 경우

  • ReplicaSet : ReplicaSet으로 관리되는 파드들은 동일한 PVC를 바라보고 있어도 전혀 문제가 되지 않습니다. 왜냐하면 애플리케이션 자체가 상태를 공유하고 있을 필요가 없기 때문입니다. 이러한 특징 때문에 PV가 한 노드에 생성되면 모든 파드들이 PVC와 동일한 노드에 배치되어야합니다. 만약 다른 노드에 파드가 배치되면 이 PVC와 연결될 수 없습니다. 
  • StatefulSet : StatefulSet이 관리하는 파드들은 각자가 가지고 있는 고유한 볼륨이 있어야하고 이 때문에 파드가 전혀 다른 노드에 배치되더라도 새로운 PV를 할당해줍니다. 

replicas가 0인 경우

  • ReplicaSet : ReplicaSet은 replicas가 0이 되면 PV와 PVC가 static으로 만들어진만큼 삭제되지는 않습니다. 하지만 이후 이 PV와 PVC가 다시 재활용되지는 않습니다. 이 내용은 쿠버네티스 이론 : 볼륨 포스팅에 자세히 나와있습니다. 참고해주시면 감사하겠습니다. 
  • StatefulSet : 반면 StatefulSet으로 만들어지는 PV와 PVC는 파드가 삭제된다고 하더라도 삭제되어서는 안됩니다. 그 볼륨 자체가 이 파드들의 상태를 보관하고 있는 또 하나의 기준이 될 수 있기 때문입니다. 

    또한, StatefulSet이 Headless Service와 연결하면 내부 시스템인 파드가 해당 파드를 바라볼 때 DNS Server의 FQDN에 의해 관리되는 도메인 이름으로 접근할 수 있습니다. 이렇기 때문에 이 파드가 죽어서 재생성되더라도 해당 파드의 이름으로 그대로 살려줘야 쿠버네티스 내부 시스템들이 이 파드를 바라볼 때 동일한 도메인 명으로 관리될 수 있습니다. 

 

마지막으로 ReplicaSet과 StatefulSet의 yaml파일을 비교해보고 해당 섹션을 마무리지어보도록 하겠습니다. 

 

ReplicaSet

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replica-web
spec:
  replicas: 1
  selector:
    matchLabels:
      type: web
  template:
    metadata:
      labels:
        type: web
    spec:
      containers:
      - name: container
        image: kubetm/app
      terminationGracePeriodSeconds: 10

 

StatefulSet

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: replica-web
spec:
  replicas: 1
  selector:
    matchLabels:
      type: db
  template:
    metadata:
      labels:
        type: db
    spec:
      containers:
      - name: container
        image: kubetm/app
      terminationGracePeriodSeconds: 10

 

Deployment

ReplicaSet을 이용해서 버전을 업데이트하는 방법은 네 가지가 있습니다. Recreate, Rolling Update, Blue / Green, Canary 이렇게 네 가지를 하나씩 살펴보도록 하겠습니다. 

 

Recreate

Recrate는 기존에 동작하던 파드를 삭제시키고 다시 띄우는 방법으로서 다운 타임이 존재한다는 단점이 존재합니다. 

 

Recreate는 기존의 ReplicaSet의 replicas 속성을 0으로 만들고 난 뒤 새로운 ReplicaSet의 템플릿을 v2로 설정하고 다시 만들면 됩니다. 

 

Recreate는 여러개의 ReplicaSet을 가지고 잇고 이 많은 ReplicaSet을 구별하기 위해 따로 label과 selector를 부여받습니다. 

 

Rolling Update

Rolling Update는 기존의 동작하던 파드와 새로운 버전의 파드를 동시에 Service와 연결시켜 하나씩 새로운 버전으로 넘어가도록 하는 전략으로서 다운타임이 발생하지 않지만 새로 추가하는 파드만큼의 리소스가 필요하다는 단점이 있습니다. 

 

Rolling Update는 기존의 ReplicaSet에서 동작하던 v1을 냅둔 상태에서 v2의 새로운 ReplicaSet을 만드고 새로운 파드의 라벨을 현재 운영중인 Service와 맞춥니다. 그리고 ReplicaSet의 replicas를 조절하면서 배포를 진행합니다. 

 

Blue / Green

블루그린 배포는 쿠버네티스의 Deployment에서 기본적으로 제공해주는 배포방식은 아닙니다. 

 

기존의 존재하던 파드와 새로운 버전의 파드를 순식간에 바꿔치기 하면서 트래픽을 이동시켜 다운타임이 발생하지 않지만 현재 운영중이던 파드의 개수만큼의 리소스가 필요해서 여타 다른 배포 방식보다 리소스가 많이 든다는 단점이 있습니다. 

 

블루그린 배포는 ReplicaSet을 두개 만들고 Service가 바라보고 있는 라벨을 ver1에서 ver2로 바꿔줌으로써 순식간에 트래픽을 움직인다는 특징이 있습니다. 

 

이런 특징 때문에 만약 ver2에서 문제가 발생하면 Service의 라벨만 다시 ver1으로 바꿔주면 되기 때문에 롤백이 쉽다는 장점이 있습니다. 

 

Canary

카나리 배포는 먼저 배포중이던 파드와 새로운 버전의 파드를 동시에 배포해 새로운 버전의 안정성을 검사한 뒤에 모든 파드를 새로운 버전으로 옮기는 방법으로서 다운타임이 발생하지 않고 자원이 적게든다는 장점이 있습니다. 

 

카나리 배포는 여러개의 Service를 바라보는 Ingress Controller가 있고 Ingress 트래픽을 url로 나눠 안정성을 체크합니다. 모든 안정성 테스트를 마치게 되면 새로운 버전으로 모두 바꿔 배포를 완료합니다. 

 

이 카나리 배포는 바로 뒤에 언급할 Ingress Controller에서 자세히 다루겠습니다. 

 

나머지 배포 방식은 쿠버네티스 실습 : 컨트롤러 편에서 더 자세히 다루도록 하겠습니다. 

 

Ingress Controller

MSA를 위해서라면 서로 다른 서버에 들어오는 트래픽을 API로 관리해야하고 이를 관리하기위해 Ingress 라는 오브젝트가 필요합니다. 

 

하지만 Ingress는 오브젝트 그 자체로는 뭔가 할 수 있는게 없어서 Ingress를 구현하는 구현체가 있어야합니다. 

 

이를 위해 각기 다른 파드를 만들고 이 파드들과 연결되는 서비스를 만들어 외부로 노출합니다. 그리고 Ingress를 구현하는 구현체가 배포된 파드를 만들면 그 파드가 Ingress rule과 맞는 Ingress를 매치합니다. 

 

이런 Ingress 구현체들이 있는 것을 Ingress Controller라고 하며 보통 Ingress Controller는 Nginx같은 웹서버가 됩니다. 

 

Ingress Controller를 만들기 위해서는 Nginx를 위한 네임스페이스가 만들어져야하고 이 네임스페이스에 Deployment를 만들어야합니다. 이를 위해 ReplicaSet을 만들고 template을 Nginx이미지로 설정합니다. 

 

보통 Ingress Controller의 역할은 크게 세 가지가 있는데 Service LoadBalancing, Canary Upgrade, HTTPS입니다. 

 

  • Service LaodBalancing : 말 그대로 서비스들을 로드밸런싱하기 위해 사용하는 것으로서 파드와 그 파드를 연결하는 서비스를 만듭니다. 그리고 이 서비스를 Ingress 오브젝트에 등록합니다. 이후 Nginx같은 Ingress Controller를 만든 뒤 이 파드와 연결되는 서비스를 NodePort로 배포합니다. 이때 배포된 포트번호와 Ingress 오브젝트에서 설정해둔 path를 이용해 매칭이됩니다. 
  • Canary Upgrade : 이런 Ingress Controller를 이용하면 카나리 배포를 진행할 수 있습니다. 기존에 운영되던 파드와 서비스에 대한 Ingress가 있을 것이고 이를 NodePort 서비스로 다시 연결하여 외부로 연결한 상태에서 새로운 버전의 파드를 생성하고 이를 서비스와 연결합니다. 이 새로운 파드와 연결된 서비스를 새로운 Ingress 오브젝트에 등록하고 @weight 어노테이션을 이용해서 가중치를 둡니다. 그리고 이 테스트가 끝나면 weight를 100퍼센트로 바꾸어 배포를 완료합니다. 
  • HTTPS : Ingress Controller에서 HTTPS를 설정하는 경우는 파드에서 자체적으로 인증서를 이용해서 HTTPS를 해결할 수 없는 경우에 사용합니다. HTTPS를 위해 Ingress 오브젝트에 host와 service를 연결하는 rules를 만들고 tls라는 속성에 secretName속성을 이용해 우리가 따로 만든 Secret오브젝트와 연결할 수 있습니다. Secret오브젝트에는 인증기관의 개인키와 인증서가 들어있으며 이를 Ingress Controller가 사용하게 하며 HTTPS를 적용할 수 있습니다. 

Ingress Controller는 쿠버네티스 실습 : 컨트롤러 편에서 더 자세히 다뤄보도록 하겠습니다. 

 

Autoscaler

컨트롤러의 주요 기능 중 하나는 Auto Scale이 있습니다. Auto Scale에도 똑같은 파드를 복제하는 Horizontal Pod Autoscaler (HPA), Vertical Pod Autoscaler (VPA), Cluster Autoscaler (CA)가 있습니다. 

 

HPA는 파드가 사용하는 자원이 임계치를 넘어갈 때 컨트롤러와 연결된 HPA가 있다면 이 HPA가 파드의 자원 상태를 모니터링하고 있다가 컨트롤러의 replicas를 늘려줍니다. 

 

이렇게 파드의 개수를 증가시키는 것을 Scale Out, 반대로 자원을 보고 파드의 개수를 다시 줄이는 것을 Scale In이라고 합니다. 

 

VPA는 파드가 사용하고 잇는 자원이 임계치를 넘어갈 때 컨트롤러와 연결된 VPA가 있다면 VPA가 파드의 자원 상태를 모니터링 하고있다가 파드의 자원 임계치를 높여줍니다. 

 

이렇게 파드의 자원의 양을 늘려주는 것을 Scale Up, 반대로 낮추는 것을 Scale Down이라고 합니다. 

 

HPA의 주의사항

HPA는 주로 Stateless 애플리케이션에서 사용해야합니다. 그 이유는 Stateful 애플리케이션의 경우 각각의 파드가 정해진 역할이 있기 때문에 무작정 막 늘릴 수 없기 때문입니다. 

 

HPA가 봤을 때 어떤 역할의 파드를 어떻게 늘려야하는지 감지할 수 없기 때문에 HPA는 기동이 빠르게 되는 애플리케이션과 Stateless 애플리케이션에 사용하는 것을 권장하고 있습니다. 

 

VPA의 주의사항

VPA는 HPA와 반대로 Stateful 애플리케이션에 잘 어울리는 확장 방식입니다. Stateful 애플리케이션의 경우 무작정 파드를 늘릴 수 없기 때문에 이렇게 자원의 양 자체를 늘려버리는 것을 선택하는 것이 권장됩니다. 

 

보통 Stateful 애플리케이션의 경우 우리 비즈니스의 상황에 맞게 미리 레플리카를 준비하는 경우가 많아 무작정 파드의 개수를 늘리는 것이 아닌 자원의 양을 늘려주는 것이 일반적입니다. 

 

CA의 특징

CA는 현재 클러스터 내부에 존재하는 노드의 자원이 없는 경우 노드를 새로 생성해서 그 노드에 파드를 배치해주는 것입니다. 

 

보통 노드 = 서버이기 때문에 쿠버네티스 입장에선 이 서버를 직접 늘려주지는 못하지만 각종 클라우드 서비스들이 Auto Scaling Group을 지원하고 있기 때문에 ASG와 CA가 연결되어 노드를 하나 늘려주는 역할을 합니다. 

 

이 상황에서 만약 노드의 자원이 안정적으로 돌아오는 경우 CA가 새롭게 만들었던 노드를 없애고 그 노드 안에 들어있던 파드를 로컬 노드에 다시 재배치하면서 마무리됩니다. 

 

HPA, VPA, CA가 어떻게 파드를 늘릴까? : 아키텍처의 관점에서

쿠버네티스 아킽넥처에서 크게 쿠버네티스를 관장하는 마스터노드와 실제 애플리케이션이 들어있는 워커노드로 분리할 수 있습니다. 

 

마스터노드에는 파드의 형태로 쿠버니테스를 관리할 수 있는 여러개의 오브젝트들이 만들어져있습니다. 그 중 Controller Manager라는 파드는 Deployment, RepliicaSet, HPA, VPA같은 오브젝트들을 관리합니다. 

 

그리고 이 오브젝트들이 쿠버네티스 클러스터의 워커노드에 명령을 내릴 때는 kube-apiserver를 거쳐 이 API Server가 다른 워커노드에 쿠버네티스 명령어를 실행시킵니다. 

 

워커노드에 쿠버네티스를 설치하면 kubelet이라는 것이 설치가 되는데 쿠버네티스는 파드단위로 관리하지만 실제로 노드에 배포되어있는 것은 컨테이너이기 때문에 이 컨테이너들을 런타임시 관리해주는 도커같은 플러그인을 사용합니다. 

 

그래서 우리가 replicas같은 값을 변경해주면 

 

ReplicaSet -> kube-apiserver -> kubelet -> docker -> container 생성

 

이런 흐름도를 가지게 됩니다. 

 

이 상황에서 이 kubelet들의 메트릭들을 모니터링하는 파드를 생성하면 이 메트릭 정보를 받아서 특정 상황이 되면 Control Plane (마스터 노드) 에 있는 kube-apiserver에 자원을 요청하는 API를 날리게 되고 이 API가 다시 HPA를 호출하면 HPA가 ReplicaSet에 있는 replicas를 늘려주는 작업을 진행합니다. 

 

이 kubelet들의 메트릭을 모니터링하는 파드는 메모리와 CPU뿐만 아니라 프로메테우스같은 플러그인을 설치하면 좀 더 세세한 설정을 통해 (파드로 들어가는 패킷의 양이라던가, Ingress Controller로 들어가는 트래픽의 양이라던가) kube-apiserver에 자원을 요청할 수 있습니다. 

 

cf) HPA의 AutoScale 공식

HPA가 replicas를 늘리는 공식이 있는데 HPA를 설정할 때에는 target속성에 실제 관리해야하는 Controller를 적고 (ReplicaSet) maxReplicas와 minReplicas를 적습니다. 

 

그리고 Metrics속성으로 type을 Resource로 넣어준 뒤 averageUtilization 속성으로 자신이 원하는 자원의 양을 퍼센티지로 넣어주면 됩니다. 

 

  • averageUtilization이 50이고 (파드들의 자원이 50퍼센트를 유지했으면 좋겠다는 설정)
  • minReplicas가 2 (최소로 유지되는 파드의 개수가 2이면 좋겠다는 설정)
  • maxReplicas가 10 (최대 유지되는 파드의 개수가 10이면 좋겠다는 설정)
  • CPU request자원이 200m, limits가 500m
  • 현재 파드의 평균 자원이 300m

이런 상황이라면 목표 자원은 {파드의 requests} X {averageUtilization} = 100이 됩니다. 이 상황에서 파드의 limits가 500이기 때문에 현재 파드의 평균 자원이 300이어도 파드가 다운되지는 않습니다. 

 

하지만 이 상황이라면 Scale Out을 해야하는 상황이고 이때는 다음과 같은 공식을 따릅니다.

 

{현재 레플리카 수} X {현재 파드의 평균 자원} / {목표 자원} 이런 계산 공식을 가지고 따라서

 

2 X 300 / 100 = 6이 되므로 늘어나는 레플리카는 5개입니다. 

 

반대로 Scale In의 경우도 같은 공식을 이용해서 레플리카를 줄여줍니다. 

 

 

마치며

컨트롤러는 쿠버네티스의 꽃인만큼 공부해야할게 정말 많았습니다. 하지만 공부하고나니 쿠버네티스의 큰 축을 하나 공부했다는 뿌듯함이 남다르네요. 

 

파드와 서비스도 굉장히 강력하다고 생각했는데 컨트롤러는 정말 미쳤다는 말밖에 할 게 없네요. 

 

정말 긴 글이었네요. 긴 글 읽어주셔서 감사합니다. 오늘도 즐거운 하루 되세요!