(시리즈4) 쿠버네티스 코드 분석하기 : kubectl apply -f nginx.yaml 을 입력하면 일어나는 일(4) - Deployment Controller

msyhu·2021년 7월 6일
1
post-thumbnail

안녕하세요 이번 시간에는 첫 번째 글에서 쓴 '청사진' 기준으로 'kubectl apply -f 를 입력하면 일어나는 일' 의 4번째 단계인 Deployment Controller 에 대해 알아보겠습니다.

Deployment Controller

3.지속적으로 etcd의 상태를 확인하고 있던 controller는 새 yaml 파일의 존재를 확인하고, API-Server로 할당요청을 한다. API-Server는 etcd에 있던 Pod 생성요청 상태를 Pod 할당요청 상태로 바꾼다.

디플로이먼트(Deployment) 는 파드와 레플리카셋(ReplicaSet)에 대한 선언적 업데이트(yaml) 를 제공한다.
디플로이먼트에서 의도하는 상태(desired state) 를 설명하고, 디플로이먼트 컨트롤러(Controller)는 현재 상태(current state) 에서 의도하는 상태(desired state)로 비율을 조정하며 변경한다. 새 레플리카셋을 생성하는 디플로이먼트를 정의하거나 기존 디플로이먼트를 제거하고, 모든 리소스를 새 디플로이먼트에 적용할 수 있다.
https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/

명령형 프로그래밍이란 '어떻게'를 정의하는 프로그래밍이다. 반면 선언형 프로그래밍이란 '무엇을'을 정의하는 프로그래밍이다.
https://velog.io/@mgm-dev/선언적-VS-명령적

[pkg/controller/deployment/deployment_controller.go](https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/deployment/deployment_controller_test.go) 에 관련 로직이 있다.

새로운 DeploymentController 를 만드는 NewDeploymentController 함수이다.

DeploymentController 코드 내부적으로 deployment informer, replicaset informer, pod informer 3 가지를 등록한다. 그렇다면 informer 가 무엇인가?

출처 : 선배 연구원님의 controller 발표 자료

informer는 Kubernetes 클러스터와 Controller 사이에서 중개자 역할을 한다. informer는 특정 resource 타입에 대해 클러스터에서 변화가 생길 때마다 해당 이벤트를 들을 수 있는 이벤트 핸들러를 등록할 수 있다.
이벤트 핸들러를 통해 넘어온 이벤트들은 보통 큐에 저장하고 Controller는 큐의 반대편에서 informer가 넘긴 이벤트를 구독하여 이벤트가 넘어올 때마다 이벤트의 타입에 따라서 적절하게 핸들링한다.
https://getoutsidedoor.com/2020/05/09/kubernetes-controller-구현해보기/

deployment informer에 CUD 이벤트를 등록한다.

새로운 deployment를 apply 하고 있는 상황이므로, addDeployment 함수를 따라가 보았다.

informer 설명대로, 새로운 deployment 가 들어온 이벤트를 큐에 집어넣고 있었다.

enqueueDeployment를 구현한 enqueue 함수이다.

여기서 큐에 넣은 아이템이 어떻게 처리되지 싶은데, 조사 결과 디플로이먼트 컨트롤러가 실행될 때 다수의 worker가 고루틴으로 작동되고, 워커들이 큐를 감시하고 있다가 큐에 아이템이 삽입되면 하나의 워커가 깨어나서 이를 처리한다고 한다. 해당 worker 로직이 들어있는 함수 processNextWorkItem 이다.

큐에 들어온 아이템을 꺼내서, 비즈니스 로직을 수행(syncHandler)하고 있다.

또, Run 함수에서 worker 고루틴들이 실행되고 있는 모습이다.

syncDeployment : deployment controller 의 핵심 로직

syncDeployment함수는 해당 deployment의 desired state를 current state로 synchronize 해주는 컨트롤러 핵심 비즈니스 로직을 담당하고 있다.

위에서 말한 syncHander 함수가 보이는데, 이 함수가 syncDeployment 함수이다.

기존에 있던 deployment의 롤백, 롤아웃 등의 파드 개수 처리 등의 로직이 있었다.

이것을 위해서 중간 쯤에 레플리카셋을 얻어오는 부분이 보인다. 디플로이먼트는 직접 파드들을 관리하지 않고 레플리카셋을 관리하며, 레플리카셋이 파드들을 관리한다.


가져온 replicaset list를 찍어본 모습
여기서 얻은 replicaset List를 인자로 하여 파드 갯수를 관리해 준다.

syncDeployment 함수의 맨 밑 부분이다. 콘솔 출력 결과 새로 Deployment 배포 시 두 번째 Case 인 RollingUpdate로 들어가는 것을 확인했다. 그래서 그 부분을 따라 들어갔다.

pkg/controller/deployment/rolling.gorolloutRolling 함수이다.

이 함수에는 기존 레플리카셋이 있고, 필요하다면 scale up, down 하는 로직이 있고 맨 밑에서 new ReplicaSet 상태와 old ReplicaSet 상태를 비교 후, current state 를 desired state로 만들어 주는syncRolloutStatus 함수를 실행한다.

pkg/controller/deployment/progress.gosyncRolloutStatus함수

함수에 deadline 관리 혹은 replicaset 생성 실패에 관련한 로직이 있지만, 결국 맨 밑 줄에 있는 client-go 의 UpdateStatus 함수를 이용해 API-Server로 etcd에 들어있는 해당 리소스 정보를 '할당 요청' 상태로 업데이트 rest 호출한다.

client-go 의 UpdateStatus 함수. Put() 을 이용해 업데이트 요청하는 모습을 볼 수 있다.

다음 글에서는 최적의 노드로 pod을 배분하는 Scheduler 부분을 알아보도록 하겠습니다.
잘못된 부분이 있으면 댓글 남겨주시면 감사하겠습니다!!

추가 연구 사항

  • etcd에 상태 정보가 업데이트 된 전후 데이터 확인해 보기

reference

profile
컨테이너, k8s, 마이크로서비스 등 클라우드 네이티브 환경에 관심이 많습니다.

2개의 댓글

comment-user-thumbnail
2021년 7월 20일

웹 서칭 하다가 들어온 블로그가 여기라니!

1개의 답글