쿠버네티스 공부 1 - node와 cluster
쿠버네티스 백업 쪽으로 뭘 만들 게 생겨서 공부 시작함. 컨테이너는 돌려봤고 서버 한 대에 프로그램 올려본 적도 있는데, 개념은 모르는 상태.
1편은 단어 세 개다. node · Pod · controller. 그리고 그거 배우다가 클러스터에서 크게 한 번 걸렸음.
컨테이너는 가벼운 가상머신이 아니었다
이것부터 잘못 알고 있었다. 컨테이너를 작은 VM 같은 걸로 생각했음.
가상머신은 가짜 컴퓨터다. 안에 운영체제가 통째로 하나 더 들어있어서 무겁고 켜는 데 수십 초 걸린다. 근데 컨테이너는 그냥 프로세스다. 내 노트북에서 도는 다른 프로그램이랑 똑같은 프로세스 하나. 다만 커널이 그 프로세스한테 거짓말을 해준다. "네가 볼 수 있는 파일 시스템은 이것뿐이야", "다른 프로세스는 없어", "네 IP는 이거야". 운영체제는 하나뿐이고 시야만 가려져 있는 거였음.
docker run 하면 거의 즉시 뜨는 이유가 이거였다. 새 OS를 부팅하는 게 아니라 프로세스 하나 실행하는 거니까.
여기서 중요한 결론 하나. 컨테이너는 죽으면 그냥 죽는다. 프로세스니까. 아무도 대신 안 살려준다. 이게 뒤에 나오는 거 전부를 끌고 간다.
서버 한 대로는 안 되는 네 순간
레슨이 좋았던 게, 단어부터 안 주고 곤란한 상황부터 보여줬다. 서버 한 대에 컨테이너 띄워놨는데 이런 일이 생긴다.
- 새벽 3시에 프로세스가 죽는다. 아침에 출근할 때까지 서비스 멈춰있음. 누가 대신 살려주지?
- 서버가 통째로 죽는다. 디스크 나갔거나 전원 나갔거나. 프로세스 살리는 걸로 해결이 안 된다. 다른 서버로 어떻게 옮기지?
- 트래픽 늘어서 서버가 세 대 필요해진다. 어디에 몇 개 띄울지 누가 계산하지? 한 대는 놀고 한 대는 터지고 있으면?
- 멈추지 않고 새 버전을 올려야 한다. 하나씩 내리고 올리고 확인하고 안 되면 되돌리고. 이걸 매번 손으로?
넷 다 사람이 붙어있으면 풀리는 문제다. 쿠버네티스는 그 네 가지 하는 사람 자리를 대신하는 프로그램이었음. 그게 전부라고.
이 순서가 편했다. 고통을 먼저 보면 단어를 외울 필요가 없다.
그래서 나온 단어 세 개
node
Pod이 실제로 도는 컴퓨터 한 대. 물리 서버든 클라우드 VM이든 상관없다. 2번 문제(서버가 통째로 죽는다) 풀려면 애초에 여러 대가 있어야 하니까 이 단어가 필요함.
Pod
거의 언제나 컨테이너 하나를 감싼 껍데기다. 왜 컨테이너를 직접 안 다루고 한 겹을 씌웠냐면, 가끔 두 컨테이너가 반드시 같은 기계에서, 같은 IP를 공유하며, 같이 살고 같이 죽어야 하는 경우가 있어서. 그 "한 몸"을 담을 그릇이 필요했던 것.
그리고 여기서 내 프로젝트에 바로 걸리는 게 하나 있었다. Pod은 일회용으로 설계됐다. 죽으면 되살리는 게 아니라 버리고 새로 만든다. 새로 만들어진 Pod은 이름도 다르고 IP도 다르다.
그래서 "실행 중인 Pod을 그대로 떠서 그대로 되돌린다"는 발상이 처음부터 성립을 안 한다. 백업이 지켜야 하는 건 Pod 자체가 아니라 "이런 Pod이 있어야 한다"는 기술이라고. 나중에 spec이랑 status 구분으로 돌아온다는데 아직 거긴 안 갔음.
controller
아주 단순한 루프를 영원히 도는 프로그램.
- 있어야 하는 상태를 읽는다 ("nginx Pod이 3개 있어야 한다")
- 지금 상태를 본다 ("2개뿐이네")
- 차이를 좁히는 행동을 한다 ("하나 더 만들자")
- 1번으로 돌아간다. 영원히.
공식 문서는 이걸 온도조절기에 비유한다. 25도로 맞춰두면 방이 지금 몇 도인지 보고 차이나면 보일러를 켜거나 끈다. "25도로 만들어라" 명령 한 번 받고 끝나는 게 아니라 계속 지켜보면서 계속 좁히는 것.
위의 네 문제가 전부 이걸로 풀린다. 죽으면 다시 만들고, 서버 나가면 다른 node에 만들고, 개수 모자라면 채우고, 새 버전 올릴 땐 원하는 상태를 바꿔주면 하나씩 교체한다. 새벽 3시에 깨던 사람 자리를 루프가 대신하는 거였음.
실습은 쿠버네티스 없이 했다
첫 실습이 클러스터 만들기가 아니라 Docker만으로 컨테이너 하나 띄우고 죽여보기였다. 안 돌아온다. 아무도 안 살려준다.
없을 때의 고통을 먼저 겪게 하는 구성인데, controller를 정의로 배우는 것보다 이게 빨랐다. "상태를 좁히는 루프"라는 말은 안 와닿는데 "죽였는데 아무도 안 살리네"는 바로 온다.
여기서 크게 한 번 걸렸다
퀴즈에서 node가 뭘 가리키는 말이냐는 문제에 "클러스터 전체를 묶는 이름"을 골라서 틀렸다.
틀린 것보다 왜 그렇게 골랐는지가 문제였음. 바로 이 질문이 나왔기 때문이다.
노드가 서버 한 대라면, 클러스터는 어디에 설치된 프로세스임?
이 질문 안에 오해가 다 들어있다. 쿠버네티스 개념을 전부 "어딘가에 설치되는 소프트웨어"로 생각하고 있었던 것. 서버 한 대에 프로그램 올려본 경험만 있으면 자연스럽게 나오는 모델인 것 같다.
cluster라는 프로세스는 없음
실제로 기계에 설치돼 있는 것만 적으면 이게 전부다.
[서버 A] kube-apiserver · etcd · kube-scheduler · kube-controller-manager · kubelet
[서버 B] kubelet · kube-proxy · containerd
[서버 C] kubelet · kube-proxy · containerd
cluster라는 이름의 프로세스가 없다. 찾아봐도 없음. 클러스터는 "같은 API 서버에 등록된 기계들의 집합"을 가리키는 이름이었다.
서버 B의 kubelet이 서버 A의 API 서버를 보게 설정돼 있으면 B는 그 클러스터 소속이고, 설정 바꿔서 다른 API 서버 보게 하면 재설치 아무것도 안 했는데 다른 클러스터 소속이 됨.
여기서 걍 이해가 됐다. 클러스터가 어디 존재하는 건지 궁금했는데, 논리적인 합의 같은 거구나 싶었음. 등록만 받고 클러스터라고 치는 거구나.
그럼 등록은 어떻게 하냐
기계 한 대 넣는 데 필요한 건 세 개뿐.
- API 서버 주소 — 누구한테 말 걸지
- CA 인증서 지문 — node가 API 서버를 믿는 근거
- 자격증명(부트스트랩 토큰) — API 서버가 node를 믿는 근거
신뢰가 양방향이라 둘이 아니라 셋임. 아무 서버나 "내가 API 서버야" 하면 안 되고, 아무 기계나 들어와도 안 되니까.
kubeadm join 10.0.0.5:6443 \
--token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:1a2b3c...
그다음이 등록이다. kubelet이 토큰으로 임시 인증해서 자기 클라이언트 인증서를 발급받고(TLS bootstrapping), 그 인증서로 API 서버에 자기를 Node 오브젝트로 만든다. 이후엔 "나 살아있음, 자원 이만큼 남음"을 주기적으로 갱신.
그러니까 이 기계에 설치되는 건 kubelet 하나고, 가입은 API 서버 목록에 줄 하나 생기는 일이었음.
탈퇴도 대칭이라 신기함. kubectl delete node 하면 그 줄만 지워지고 기계는 멀쩡히 돈다. kubelet이 살아있으면 좀 있다 자기를 다시 등록함. 이름 지우는 거랑 실체 없애는 거랑 다르다.
master node는 종류가 아니라 역할
하나 더 물어봤다. 난 마스터 노드가 따로 있는 걸로 알고 있었음. 클러스터 노드라는 게 따로 있는 건가 싶었다.
따로 있는 종류는 없었다. control plane node도 kubelet 돌고 위랑 똑같이 등록된 그냥 node다. 차이는 둘뿐.
- 위에서 도는 프로세스가 다름.
kube-apiserver,etcd,kube-scheduler,kube-controller-manager가 추가로 돈다. 근데 대개 이것들조차 Pod으로 떠 있음. - 표식이 하나 붙어있음.
node-role.kubernetes.io/control-plane:NoSchedule이라는 taint. "일반 앱은 여기 배치하지 마"라고 스케줄러한테 주는 규칙 문자열이지 물리적 제약이 아니다.
물리적 제약이 아니라는 건 떼면 그 기계에도 앱이 뜬다는 뜻. 실제로 kind로 만드는 단일 노드 클러스터는 저 taint 떼고 쓴다고 함. 노드가 하나뿐인데 앱을 못 올리면 아무것도 못 하니까.
master는 폐기된 이름이고 지금은 control plane node라고 부른다고. 한 대일 필요도 없어서 운영에선 etcd 정족수 때문에 보통 3대 이상이라는데, 이건 아직 안 해봐서 잘 모르겠다.
1편 정리
- 컨테이너는 VM이 아니라 시야가 가려진 프로세스다. 죽으면 그냥 죽는다.
- 서버 한 대로 안 되는 네 순간이 있고, 쿠버네티스는 거기 붙어있던 사람 자리를 대신한다.
node는 기계 한 대,Pod은 컨테이너를 감싼 껍데기,controller는 원하는 상태와 지금 상태를 좁히는 루프.Pod은 일회용이라 그대로 떠서 되돌리는 게 안 된다. 백업이 지킬 건 Pod이 아니라 기술이다.
그리고 내가 틀렸던 것들.
| 내가 생각한 거 | 실제 |
|---|---|
| 컨테이너는 가벼운 VM | 시야 가려진 프로세스 |
| 클러스터는 설치된 프로그램 | 등록된 기계들 부르는 이름 |
| 가입은 설치 | 가입은 등록 |
| master는 특별한 기계 | master는 그 기계가 맡은 역할 |
아래 셋은 전부 같은 오해였다. 실체가 아니라 이름인데 실체로 착각한 거. namespace나 Service 배울 때도 같은 데서 걸릴 것 같은 느낌.
아직 정리가 다 된 건 아니다. 근데 헷갈리는 거랑 별개로 감은 좀 오는 듯. 새 단어 나오면 일단 이게 프로세스냐 이름이냐부터 물어봐야겠다.
다음 편은 API 서버.