쿠버네티스는 마이크로 서비스 아키텍쳐를 따른다. 각각의 구성요소가 자신의 일만을 열심히 한다고 보면 된다.
API서버는 모든것의 중심에 있는 메인 타워같은 존재라고 보면 된다. 커멘드 센터라고 표현하지 않은 이유는 딱히 명령을 내리는게 아니고 그저 감시만 할 뿐이기 때문이다.
파드가 생성되는 흐름은 다음과 같다.
1. 사용자가 콘솔창에다가 kubectl create pod 입력을 하면 API 서버로 명령어가 날아간다.
2. API가 사용자로부터 파드 생성 요청을 받으면 컨트롤러 매니저에게 '파드 생성해!' 하는것이 아니고 상태값들을 업데이트하고 파드가 생성되는지를 감지하게 된다.
3. 컨트롤러 매니저가 API 서버의 상태값을 확인하고 파드를 생성해야하면 그때서야 파드를 생성한다.
4. 스케쥴러는 API 매니저를 보고 새로운 파드를 워커 노드에 넣어야함을 확인하면 해당 작업을 하도록 스케쥴링한다.
5. 파드를 실제로 생성하는 것은 kubelet이 담당한다. 정확하게 말하자면 kubelet은 파드의 동작을 관리하며 파드 생성은 컨테이너 런타임이 맡아서 진행한다.
6. 생성된 정보는 kubelet이 API 서버에게 알려준다.
쿠버네티스는 선언적인 시스템이다.
추구하는 상태와 현재 상태를 맞추려고 하는 것. 이것을 선언적인 시스템이라고 한다. 추구하는 상태는 API 서버가 가지고 있고 컨트롤러 매니저, 스케쥴러 등이 이 API 서버를 지속적으로 확인해서 싱크를 맞추도록 한다.
API 서버와 ETCD는 조금 다르다. 쿠버네티스 클러스터의 업데이트 정보가 있다면 API 서버는 이를 ETCD에다가 저장하게 된다. 보통은 API 서버가 감시만 하지만 ETCD는 본인(API 서버)이 직접 데이터를 전달한다.
간단 정리
- 쿠버네티스는 선언적인 구조이다.
- 각 요소는 자기 일만하는 마이크로 서비스 아키텍쳐를 따른다.
파드가 배포되는 흐름을 통해 다시한번 이해해보자
먼저 API 서버에게 명령어를 전달하는 방법은 직접 전달하는 것과 kubectl 명령어를 통해서 전달하는 방법이 있다. 실습에서는 계속 후자의 방법으로 진행한다.
1. API서버는 가장 먼저 해당 정보를 etcd에 업데이트한다. (문제가 생기면 etcd를 가지고 복원하면 된다)
2. 다음으로는 컨트롤러 매니저와 통신한다. 컨트롤러 매니저는 API 서버의 값을 확인해서 그에 맞게 자신의 값을 바꾸고 API 서버에 업데이트한다.
3. 다음은 스케쥴러이다. 스케쥴러는 워커노드에 파드를 골고루 할당해준다.
4. 이제 실제로 파드가 생성돼야하는 시점이다. kubelet이 API 서버를 확인하여 파드를 생성해야함을 확인하고 컨테이너 런타임에 파드 생성 요청을 보낸다. 요청을 받은 컨테이너 런타임은 파드를 생성한다. 이렇게 생성된 파드들은 쿠버 프록시를 통해 사용자와 통신하게 된다.
-> API서버는 쿠버네티스가 통신하는 모든것의 중심에 위치한다. 모든 요소의 집합체이며 시작이자 끝이다. 굉장히 중요한 요소이다!!
문제 해결을 통해 이해해보기
시나리오Ⅰ. 실수로 파드를 지웠을 때
만약 단일 파드라면 삭제되고 끝이지만 Deployment의 파드라면 다시 자동으로 생성된다.
이렇게 미리 준비된 yaml 파일로 파드와 디플로이먼트를 생성한다. (강사님이 제공해주신 파일로 간단하게 생성 ㅎ)
단일 파드를 삭제하면 이렇게 바로 삭제가 된다. 하지만 deployment의 파드를 삭제하면 아래와 같이 된다.
k7xc4 를 삭제했는데 곧바로 vhnk6 라는 이름의 파드가 생성된 것을 볼 수 있다. 해당 디플로이는 파드의 갯수를 3개로 유지하도록 설정이 되어있어서 이런 것이다.
시나리오 Ⅱ. 워커노드 - kubelet이 중단될 경우
워커 노드중 하나에 들어가서 systemctl stop kubelet을 해보자. 마스터 노드에서 deploy를 생성하려고 하면 하나가 펜딩상태로 나온다. 방금 한 워커노드의 kubelet을 중단시켰기 때문이다.
시나리오 Ⅲ. 워커노드 - 컨테이너 런타임이 중단될 경우
현재 실습환경은 런타임이 도커이다. 도커를 중단시키기 위해 systemctl stop docker 명령어를 입력한다. 도커를 중단시키고 나서 kubectl scale deployment del-deploy —replicas=6 명령어를 통해 del-deploy라는 이름의 디플로이먼트의 도커를 3개에서 6개로 늘려보자. 기존의 방식대로라면 각 워커노드에 2개씩 배정되어야하지만 한 워커노드의 도커가 중단되었으므로 남은 워커 2개에 3개의 파드가 배정된다.
그림을 통해 다시 생각해보면 컨테이너 런타임이 죽는다면 워커노드의 쿠버렛은 이를 인지하고 API 서버에 알려주고 스케쥴러가 이를 확인하여 문제가 발생한 워커노드에는 파드를 배정해주지 않는다. 처음에 봤었던 쿠버렛이 죽었을 경우에는 쿠버렛이 이를 알려주지 못해서 API 서버는 이 사실을 모르니 계속 Pending 상태로 남는 것이다.
✨✨ 스케쥴러의 기능 확인
워커노드 1번의 도커를 중지시킨후 replicas=6 으로 했을때 워커노드 3번이 혼자서 3개의 파드를 생성해놓은 상태이다. 만약 모든 워커노드의 도커를 start 해놓고 replicas=9 라고 한다면 모든 워커노드에 파드가 3개씩 골고루 배정된 상태가 될까?
모든 워커노드에 각각 3개의 파드가 생성된 것을 확인할 수 있다. 이처럼 스케쥴러는 모든 워커노드에 골고루 파드를 배치하는 역할을 한다. (열일하는 스케쥴러..!)
참고로 도커 안에 파드 보다는 도커(컨테이너 보관함)가 만드는 파드(컨테이너) 이라고 이해하는 것이 좋다.
시나리오 Ⅳ. 마스터노드 - 스케쥴러가 삭제될 경우
스케쥴러 삭제를 위해 스케쥴러의 이름을 알아보자
스케쥴러는 쿠버 시스템 안에 있다. 이름을 잘 보면 api 서버, 컨트롤러, 스케쥴러, etcd가 다 있다. -o wide 옵션을 주면 어떤 노드에 있는지도 확인이 가능하다. 이들은 마스터 노드의 속해 있을 것이다.
삭제 시에는 kube-system의 네임스페이스 안에 있는 것이므로 네임스페이스 옵션도 줘야한다.
근데 재밌는 점은 삭제 하고 몇분 뒤에 확인했더니 다시 생겨나있다!! 마스터노드의 중요 요소들은 특별 관리되기 때문에 파드라고 할지라도 삭제될 경우 다시 생성시킨다.
시나리오 Ⅴ. 마스터노드 - 스케쥴러가 삭제될 경우
워커 노드에서 쿠버렛을 삭제할 때와 똑같다. 먼저 systemctl stop kubelet으로 쿠버렛을 멈춘다. 그 다음 쿠버렛의 스케쥴러를 삭제한다. 그럼 삭제가 진행되지 않는다. 이유는 쿠버렛으로 삭제 명령어가 날아가서 실행되어야 하는데 (마스터 노드의 쿠버렛은 컨트롤러 매니저 스케쥴러 등을 관리함 얘네도 파드니까!!) 쿠버렛이 멈춰있으니 삭제가 진행되지 않는 것이다.
멈춰서 다음으로 넘어가질 않는다.. 삭제가 진행되지 않는 것이다.
컨트롤 C로 강제 종료 후 상태를 보면 Terminating이라고 나온다. 하지만 쿠버렛을 통해 삭제 명령어가 전달되지 않아서 로그만 저렇게 뜰 뿐 실제로는 멀쩡히 잘 동작하고 있다. pod를 생성하고 scale을 통해 늘려보면 모든 워커노드에 파드가 균일하게 잘 분배된다. 이후에 systemctl start kubelet을 하면 이때 삭제가 진행되고 다시 새로운 스케쥴러가 만들어진다.
시나리오 Ⅵ. 마스터노드 - 컨테이너 런타임이 삭제될 경우
마스터 노드에서 systemctl stop docker로 정지 시켜본다. 이렇게 된다면 생성한 파드들에 curl 명령어로 접속이 불가능해진다. 마스터 노드의 컨테이너 런타임은 API 서버를 관리하는 매우 중요한 요소이다. 마스터노드의 컨테이너 런타임은 문제 발생시 시스템 전체에 문제가 발생하므로 현업에서는 여러개의 마스터 노드를 둔다.
쿠버네티스 오브젝트
쿠버네티스에서 말하는 "오브젝트"란 원하는 상태가 기술된, 추구하는 상태를 가지고 있는 것을 의미한다. 마스터 노드에서는 api 서버, etcd, 스케쥴러 등등 쿠버렛 빼놓고 대부분 해당한다.
추구하는 상태란 것을 코드레벨로 한번 보자. kubectl edit deployment del-deploy
vim 처럼 열리는데 아래로 좀 내려보면 spec이 있다. 저 부분에 값을 변경하면 변경사항에 맞게 실제 상태가 이어서 변화될 것이다. 저 spec 부분이 추구하는 상태인 것이다.
이제 쿠버네티스에서 오브젝트라고 하면 어떤 선언적인 상태를 가지고 있는 것이라고 생각하면 된다. 쿠버네티스의 기본 오브젝트에는 다음의 4가지가 있다.
- 파드
- 서비스
- 네임 스페이스
- 볼륨
4번의 볼륨은 영속적인 데이터를 보존하기 위한 것이다. 파드는 언제든지 자유롭게 삭제되고 생성될 수 있다. 그렇기 때문에 볼륨이 필요한 것이다. 파드에 저장되는 데이터는 볼륨에 저장되어서 이후에 파드가 삭제되고 새로 파드가 만들어져도 이 볼륨 데이터가 붙어서 결국 데이터는 그대로 남아있게 된다.
관련글
https://www.inflearn.com/course/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%EC%89%BD%EA%B2%8C%EC%8B%9C%EC%9E%91/dashboard 를 들으며 정리한 글입니다.