들어가기에 앞서...
- 본 글은 쿠버네티스 시리즈 중의 하나로, kubernetes 실습을 위한 기본 환경 세팅이 이루어져 있지 않은 분은 시리즈 1편을 확인해주시길 바란다.
- 쿠버네티스 실습 시리즈는 아래 학습 자료를 참고하고 있다.
0. 블로깅 목적
- ReplicaSet가 무엇이고 어떤 원리로 동작하는지 이해한다.
- ReplicaSet의 기본적인 생성 및 조회 방법을 이해할 수 있다.
- ReplicaSet의 변경 및 적용 흐름을 이해할 수 있다.
1. ReplicaSet가 무엇이고 어떤 동작원리를 거치는지 이해한다.
1) ReplicaSet은 무엇이고 무슨 역할을 할까?
(1) ReplicaSet?
- 도커-컴포즈에서 특정 컨테이너의 수를 동일 서비스 내에서 자유롭게 늘릴 수 있는 것처럼, 쿠버네티스에서도 Pod의 수를 동적으로 늘릴 수가 있다.
- Pod의 수를 늘리는 방법?
- 심플하게 생각해보면 동일한 역할을 하는 Pod를 여러개 찍어내면 된다고 할 수 있다. 하지만 yml파일로 관리한다 하더라도 매번 파일에 다른 이름의 Pod를 추가하는 것은 매우 비효율적인 일이다.
- 그래서 사용하는 것이 바로 ReplicaSet이다. ReplicaSet은 Pod의 수를 늘리는 목적으로 사용되는 API 리소스이다.
(2) ReplicaSet 역할
- ReplicaSet에서는 몇개의 파드를 띄울지 결정할 수가 있다. 그렇게 정해진 수의 Pod가 항상 실행될 수 있도록 관리하는 역할을 수행한다.
- 만약 4개의 파드가 있는데 그 중 1개의 파드가 정상적으로 동작되지 않는다면, ReplicaSet은 문제가 생긴 Pod를 새로운 노드에 다시 스케쥴링하는 작업을 진행하게 된다.
(3) ReplicaSet 참고사항
- 과거엔 ReplicationController라는 이름이었는데, 현재 ReplicaSet으로 바뀐 것이다. (ReplicaSet이 최신 버전 용어이다.)
- Pod와 마찬가지로 사용자가 ReplicaSet을 직접 관리하는 경우는 거의 없다. 기본적으로 ReplicaSet을 wrapping하고 있는 Deployment라는 리소스가 있기 때문에, 보통은 Deployment를 가지고 워크로드를 다루는 게 일반적이다.
2) ReplicaSet의 동작 원리
(1) 원리
- ReplicaSet Controller가 컨트롤 플레인에 존재한다.
- kube Controller Manager에 속한 API 리소스 컨트롤러 중 하나이다.
- spec.selector에 대응되는 Pod의 수가 spec.replicas와 동일한지 지속적으로 검사하고, 다를 경우 scale-out 혹은 scale-in을 진행한다.
(2) Label Selector
- 쿠버네티스 오브젝트는 모두 metadata.labels에 Key-Value 형태의 레이블 값을 가진다.
- 특정 오브젝트 목록을 필터링하기 위한 기능이 Label Selector이다.
- Label Selector는 matchLabels와 matchExpressions 옵션을 제공한다.
- matchLabels 옵션: matchLabels의 아래에 있는 labels를 가지고 있는 오브젝트들을 셀렉트 해준다.
- matchExpressions 옵션: matchLabels만으로는 해결할 수 없는 다양한 operator를 가지고 오브젝트를 셀렉트 할 수 있게 해준다.
matchLabels:
component: redis
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operatoer: NotIn, values: [dev]}
- key가 component이고 value가 redis인 모든 오브젝트를 셀렉트
- key가 tier이고 values가 cache인 모든 오브젝트를 셀렉트
- key가 environment이고 values는 dev가 아닌 모든 오브젝트를 셀렉트
- 많은 쿠버네티스 API 리소스간의 관계가 Label Selector를 통해 연결이 된다. 즉, Label Selector의 존재가 리소스 간 느슨한 결합을 유지해주는 것이다.
2. ReplicaSet의 기본적인 생성 및 조회 방법을 이해할 수 있다.
replicaset.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: hello
spec:
replicas: 3
selector:
matchLabels:
app: hello
template:
metadata:
name: hello
labels:
app: hello
spec:
containers:
- name: nginx
image: nginxdemos/hello:plain-text
ports:
- name: http
containerPort: 80
protocol: TCP
- spec 부분을 해석하면, labels가 app: hello인 Pod를 셀렉트 하여, 그 수가 3개로 유지되도록 하는 역할을 한다는 의미이다.
- cat replicaset.yml
- 파일 내용 확인부터 해준다.
- watch kubectl get pod --show=labes
- 새로운 터미널을 열고 watch 키워드를 활용해 실시간으로 확인할 수 있다.
- 참고로 watch 키워드가 안먹으면 brew install watch를 해주자.
- 현재는 아무것도 잡히지 않는 상태다.
- kubectl apply -f replicaset.yml
- 선언형 커맨드로 yml 파일을 수행하여 replicaset이 create되었다.
- Pod들이 실시간으로 생성되어 watch 터미널에서 확인된다. replicaset 설정값 그대로 3개의 Pod가 유지되고 있다.
- kubectl get replicasets
- 존재하는 replicas의 총 개수와 현재 준비완료 및 가동 중인 개수를 알 수 있다.
- 참고로 replicasets의 축약어는 rs이다. rs만으로도 커맨드가 다 적용되니 잘 활용해도 좋다.
- kubectl describe replicasets hello
- hello라는 이름의 replicaset들을 상세 조회할 수 있다.
- selector가 app=hello이면서, replicas는 3개 중에 3개가 모두 띄워져있다고 찍혀있다.
- 그리고 Pod 템플릿도 확인할 수 있다.
- kubectl delete -f replicaset.yml을 진행하여 정리해주자.
3. ReplicaSet labels의 변경 및 적용 흐름을 이해할 수 있다.
- ReplicaSet은 스스로의 replicaset 명세에 포함된 컨테이너를 가진 Pod인지 아닌지에 상관 없이, Pod의 labels가 같으면 selector에 의해 감지되어 같은 ReplicaSet으로 관리된다.
- 이를 Pod labels 수정을 통해 무슨 말인지 확인해보자.
- 일단 yml 파일을 하나더 만든다.
dummy-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: dummy
labels:
app: hello
spec:
containers:
- name: dummy
image: posquit0/doraemon:latest
- cat dummy-pod.yml
- 정상 출력된다.
- kubectl apply -f dummy-pod.yml
- create 한다.
- watch 터미널에 dummy라는 이름의 labels가 app=hello인 pod가 하나 뜬다.
- kubectl apply -f replicaset.yml
- 놀랍게도 dummy 이외에 3개가 새로 생성되는 게 아니라 dummy 포함 3개가 유지된다.
- 즉, replicaset.yml 명세에 속한 컨테이너만 인정되는 게 아니라, 어떤 Pod든 replicaset.yml 명세된대로 labels가 app=hello이기만 하다면 셀렉터에 감지되는 것이다. 그러므로 replica를 3개로 유지하겠다는 명세에 의해 2개만 추가로 만들어진 것이다.
- kubectl edit pod hello-76x8g
- 생성된 Pod 중에 하나를 수정해보면 어떻게될까?
- edit 명령어를 사용하면 vi로 특정 pod의 명세를 수정할 수 있게 된다.
- 여기서 app: hello 부분을 app: bye로 바꿔보았다.
- 참고로 vi의 수정모드는 i 를 누르면 시작된다. 수정이 끝났으면 esc로 수정모드를 끝낼 수 있고, :wq!를 입력하면 저장과 동시에 빠져나올 수 있다.
- edit 결과
- app=bye로 변경되면서 app=hello가 2개 밖에 남지 않은 걸 감지한 replicaset controller가 3개의 Pod를 유지하기 위해, 새롭게 하나의 Pod를 생성한 것을 확인할 수 있다.