쿠버네티스 공부 1 - node와 cluster

쿠버네티스 백업 쪽으로 뭘 만들 게 생겨서 공부 시작함. 컨테이너는 돌려봤고 서버 한 대에 프로그램 올려본 적도 있는데, 개념은 모르는 상태.

1편은 단어 세 개다. node · Pod · controller. 그리고 그거 배우다가 클러스터에서 크게 한 번 걸렸음.

컨테이너는 가벼운 가상머신이 아니었다

이것부터 잘못 알고 있었다. 컨테이너를 작은 VM 같은 걸로 생각했음.

가상머신은 가짜 컴퓨터다. 안에 운영체제가 통째로 하나 더 들어있어서 무겁고 켜는 데 수십 초 걸린다. 근데 컨테이너는 그냥 프로세스다. 내 노트북에서 도는 다른 프로그램이랑 똑같은 프로세스 하나. 다만 커널이 그 프로세스한테 거짓말을 해준다. "네가 볼 수 있는 파일 시스템은 이것뿐이야", "다른 프로세스는 없어", "네 IP는 이거야". 운영체제는 하나뿐이고 시야만 가려져 있는 거였음.

docker run 하면 거의 즉시 뜨는 이유가 이거였다. 새 OS를 부팅하는 게 아니라 프로세스 하나 실행하는 거니까.

여기서 중요한 결론 하나. 컨테이너는 죽으면 그냥 죽는다. 프로세스니까. 아무도 대신 안 살려준다. 이게 뒤에 나오는 거 전부를 끌고 간다.

서버 한 대로는 안 되는 네 순간

레슨이 좋았던 게, 단어부터 안 주고 곤란한 상황부터 보여줬다. 서버 한 대에 컨테이너 띄워놨는데 이런 일이 생긴다.

  1. 새벽 3시에 프로세스가 죽는다. 아침에 출근할 때까지 서비스 멈춰있음. 누가 대신 살려주지?
  2. 서버가 통째로 죽는다. 디스크 나갔거나 전원 나갔거나. 프로세스 살리는 걸로 해결이 안 된다. 다른 서버로 어떻게 옮기지?
  3. 트래픽 늘어서 서버가 세 대 필요해진다. 어디에 몇 개 띄울지 누가 계산하지? 한 대는 놀고 한 대는 터지고 있으면?
  4. 멈추지 않고 새 버전을 올려야 한다. 하나씩 내리고 올리고 확인하고 안 되면 되돌리고. 이걸 매번 손으로?

넷 다 사람이 붙어있으면 풀리는 문제다. 쿠버네티스는 그 네 가지 하는 사람 자리를 대신하는 프로그램이었음. 그게 전부라고.

이 순서가 편했다. 고통을 먼저 보면 단어를 외울 필요가 없다.

그래서 나온 단어 세 개

node

Pod이 실제로 도는 컴퓨터 한 대. 물리 서버든 클라우드 VM이든 상관없다. 2번 문제(서버가 통째로 죽는다) 풀려면 애초에 여러 대가 있어야 하니까 이 단어가 필요함.

Pod

거의 언제나 컨테이너 하나를 감싼 껍데기다. 왜 컨테이너를 직접 안 다루고 한 겹을 씌웠냐면, 가끔 두 컨테이너가 반드시 같은 기계에서, 같은 IP를 공유하며, 같이 살고 같이 죽어야 하는 경우가 있어서. 그 "한 몸"을 담을 그릇이 필요했던 것.

그리고 여기서 내 프로젝트에 바로 걸리는 게 하나 있었다. Pod은 일회용으로 설계됐다. 죽으면 되살리는 게 아니라 버리고 새로 만든다. 새로 만들어진 Pod은 이름도 다르고 IP도 다르다.

그래서 "실행 중인 Pod을 그대로 떠서 그대로 되돌린다"는 발상이 처음부터 성립을 안 한다. 백업이 지켜야 하는 건 Pod 자체가 아니라 "이런 Pod이 있어야 한다"는 기술이라고. 나중에 spec이랑 status 구분으로 돌아온다는데 아직 거긴 안 갔음.

controller

아주 단순한 루프를 영원히 도는 프로그램.

  1. 있어야 하는 상태를 읽는다 ("nginx Pod이 3개 있어야 한다")
  2. 지금 상태를 본다 ("2개뿐이네")
  3. 차이를 좁히는 행동을 한다 ("하나 더 만들자")
  4. 1번으로 돌아간다. 영원히.

공식 문서는 이걸 온도조절기에 비유한다. 25도로 맞춰두면 방이 지금 몇 도인지 보고 차이나면 보일러를 켜거나 끈다. "25도로 만들어라" 명령 한 번 받고 끝나는 게 아니라 계속 지켜보면서 계속 좁히는 것.

위의 네 문제가 전부 이걸로 풀린다. 죽으면 다시 만들고, 서버 나가면 다른 node에 만들고, 개수 모자라면 채우고, 새 버전 올릴 땐 원하는 상태를 바꿔주면 하나씩 교체한다. 새벽 3시에 깨던 사람 자리를 루프가 대신하는 거였음.

실습은 쿠버네티스 없이 했다

첫 실습이 클러스터 만들기가 아니라 Docker만으로 컨테이너 하나 띄우고 죽여보기였다. 안 돌아온다. 아무도 안 살려준다.

없을 때의 고통을 먼저 겪게 하는 구성인데, controller를 정의로 배우는 것보다 이게 빨랐다. "상태를 좁히는 루프"라는 말은 안 와닿는데 "죽였는데 아무도 안 살리네"는 바로 온다.

여기서 크게 한 번 걸렸다

퀴즈에서 node가 뭘 가리키는 말이냐는 문제에 "클러스터 전체를 묶는 이름"을 골라서 틀렸다.

틀린 것보다 왜 그렇게 골랐는지가 문제였음. 바로 이 질문이 나왔기 때문이다.

노드가 서버 한 대라면, 클러스터는 어디에 설치된 프로세스임?

이 질문 안에 오해가 다 들어있다. 쿠버네티스 개념을 전부 "어딘가에 설치되는 소프트웨어"로 생각하고 있었던 것. 서버 한 대에 프로그램 올려본 경험만 있으면 자연스럽게 나오는 모델인 것 같다.

cluster라는 프로세스는 없음

실제로 기계에 설치돼 있는 것만 적으면 이게 전부다.

TEXT
[서버 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 서버야" 하면 안 되고, 아무 기계나 들어와도 안 되니까.

Bash
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 서버.