ReplicaSet

개요

레플리카셋의 목적은 언제든 파드들의 안정적인 복제 집합을 유지하는 것이다. 통상적으로 디플로이먼트를 정의하여 디플로이먼트가 레플리카셋을 관리하게 한다.[1]

디플로이먼트의 하위 리소스라고 보면 되겠다.
디플의 기능 중 하나인 파드 개수 유지라는 것은 사실 이 레플리카셋을 통해서 이뤄지는 기능이다.

[[#ReplicationController]]의 후속작이다.

기능

위에서 말했듯이 파드 개수를 유지해주는 것이 바로 레플리카셋이 하는 역할이다.
사용자가 원하는 파드의 개수가 5개인데, 어쩌다 한 파드가 비정상 종료되는 일이 발생할 수 있다.
이런 경우에 레플리카셋이 5개라는 상태를 맞추기 위해 새로운 파드를 띄우라고 해주는 것이다.

동작 방식

레플리카셋은 라벨 셀렉터를 이용해 자신이 관리할 파드를 추적한다.
만약 클러스터에 자신의 소유인 파드의 개수가 명시된 레플리카 수와 일치하지 않는다면?
바로 이를 반영하는 명령을 apiserver에 전달하게 된다.

파드의 입장에서 레플은 자신을 소유, 관리하는 주체이다.
Pasted image 20241223130130.png
그래서 파드에는 생성 당시 .metadata.ownerReferences 필드에 레플이 명시되는데, 이걸 통해 레플은 자신의 파드의 상태를 체크하고 관리한다.
참고로, 이 ownerReferences는 생성 시에만 붙는 게 아니라, 레플이 추적한 순간 파드에 기입돼버린다.
그래서 자칫하다가는 T-워크로드 템플릿에 없는 파드를 포착한다면의 상황이 나오게 될 수 있으니 주의하자.

양식

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: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5

문서에 나온 예시인데, 사실 직접 이렇게 만들 일은 절대로 없다고 봐도 무방하다.
실질적으로 여기에서 kind 부분만 Deployment라고 바꿔도 리소스는 잘 동작하게 된다.

그래도 간단하게 보자면..
라벨 셀렉터를 지정하여 관리할 파드를 탐색한다.
레플리카에서 원하는 파드의 개수를 지정한다.
파드 템플릿에서 관리할 파드의 양식을 지정한다.

레플 활용

분명히 말하지만, 역시 레플을 직접 사용하는 것은 문서에서조차 권장하지 않는다.
그럼에도 레플을 직접 가지고 놀면서 몇 가지 재미난 짓거리들을 할 수 있는데, 간략하게만 정리하고자 한다.

파드는 없애지 않으면서 레플리카만 없애기

kubectl delete --cascade=orphan를 하게 되면 파드를 관리하는 해당 리소스만 삭제된다.
api 상으로는 바디에 {"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}를 전달하는 것과 같은 효과이다.
전파 정책을 고아로 만들어버리는 ㄷㄷ
아무튼 이렇게 한 다음에 같은 셀렉터를 가진 레플을 만들면, 해당 파드들은 다시 그 레플의 영향을 받게 된다.

레플에서 파드 독립시키기

레플리카셋에서 관리하는 파드에 셀렉터에 해당하는 라벨을 지워버리면 해당 파드는 ownerReferences 필드가 없어지면서 레플로부터 독립된다.
레플은 자신의 파드가 하나 없어졌다는 것을 인식하고 또 새롭게 한 파드를 만들게 될 것이다.

내가 원하는 순서대로 파드 지우기(pod-deletion-cost)

1.22부터 베타 버전인 기능.

annotations:
	controller.kubernetes.io/pod-deletion-cost: "10"

이런 식으로 어노테이션을 달면 이 가치가 반영된다.
코스트가 낮은 파드들이 높은 파드에 비해 먼저 삭제된다.
근데 이렇게 하더라도 최대한 클러스터는 이를 따르려고 할 뿐이지 무조건적인 순서를 보장하는 것도 아니다.

언제 사용할까?
가령 파드의 사용량을 토대로 순서를 정하는 행위를 할 수 있을 것이다.
근데 이게 매우 위험한 작업인 것이, 요청을 수행하는 것에 맞춰 파드의 어노테이션을 매번 업데이트하게 하게 되면 매번 업데이트 요청이 apiserver에 날아가면서 엄청난 부하가 걸리게 될 것이다.
그래서 무의미한 것은 아니지만, 사용에 주의할 필요가 있다.

이밖에도 직접적으로 HPA 대상으로 걸어둔다던지 하는 일들도 할 수 있다.

ReplicationController

apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

호랑이가 담배 필 적에 존재했던 리소스.[2]
이 친구와 레플리카셋의 차이는 셀렉터이다.
이 당시의 셀렉터는 집합 기반의 라벨을 지원하지 않았고, 레플리카셋이 나오며 운명을 달리 하게 됐다..
레플리카셋 자체도 세심하게 알 필요 없는 마당에 이건 더 몰라도 된다고 생각한다.

관련 문서

이름 noteType created

참고


  1. https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ ↩︎

  2. https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/ ↩︎