kubectl exec pod 를 치면 일어나는 일

Jisu·2024년 8월 27일

Kubernetes

목록 보기
11/12

배경

인프라를 운영하다보면 다양한 이유로 쿠버네티스에서 운영중인 파드에 kubectl exec 명령어를 통해 해당 파드의 쉘을 실행하게 된다!

k9s를 이용하면 해당 명령어를 단순히 s 단축키를 통해 아주 쉽게 쉘을 실행할 수 있다.

갑자기 어떻게 저 명령어를 입력하면 해당 파드에서 관리하는.. 격리된 SW 패키지인 컨테이너 쉘을 쓸 수 있을지 궁금하였고, 이를 파헤치는 과정에서 배운 것이 많아 정리해본다.


Rest API를 사용하는 Control Plane api server

쿠버네티스의 컨트롤플레인의 컴포넌트로, api server가 있다.
다른 여느 서버와 마찬가지로, 이 서버는 Restful API 형태로 쿠버네티스 내부 자원의 CRUD를 관리하고 있다. 파드의 생성과 삭제 및 상태 조회는 모두 이 api server에 Rest API 엔드포인트로 request를 보내는 방식으로 이루어진다.

(각 노드에서 실행되고 있는 kubelet이 필요할 때마다 api server로 rest api를 호출하고 있다.)


kubectl 및 kubeconfig

kubectl은 쿠버네티스 클러스터와 상호작용하는 CLI인데 한마디로 실행파일이다. 그냥 다운받을 수 있다 !

실행 파일을 터미널에서 쉽게 실행할 수 있도록 kubectl 실행파일 경로를 PATH에 넣어줬기 때문에 우리는 쉽게 kubectl 명령어로 api server에 설계된 Rest API를 호출할 수 있다.

예를 들어 아래 터미널에서 특정 파드로 접속하는 exec 명령어를 입력하면 파드의 ID를 쿼리파라미터로 하고, base URL은 쿠버네티스의 api server 엔드포인트로 설정되어 POST request를 보내게 된다.

이 때 api server의 주소, 현재 사용자의 인증정보들이 필요한데 그것을 저장하는 파일이 kubeconfig 파일이다. 기본적으로 ~/.kube/config 경로에 위치해 있고 여러개 클러스터가 등록될 수 있다.


api server와 kubelet

exec pod_id /bin/bash를 입력하면 결국 컨테이너에서 /bin/bash를 명령어를 실행하라는 것이다.

따라서 해당 파드에서 실행되고 있는 컨테이너가 어떤 노드에서 실행되는지 알아야하므로 각 노드에서 실행되고 있는 kubelet과 통신이 필수적이다.

먼저 api server에서 요청을 받게 되면 해당 파드가 어떤 노드에 스케줄링되어 운영중인지 확인하기 위해 쿠버네티스 내부 db인 etcd를 참조한다.

그럼 해당 노드의 kubelet으로 API 요청을 전달하게 된다.


컨테이너 런타임과 /bin/bash

API 요청을 수신한 kubelet은 해당 노드의 컨테이너런타임을 통해 해당 컨테이너 내부에서 새로운 워커 프로세스를 만들게 된다. 이것이 바로 /bin/bash 쉘 인 것이며, 해당 워커 프로세스와 kubectl을 입력한 사용자의 쉘 간에 표준 입출력 스트림을 연결한다.

그렇게 해서 내가 마치 해당 컨테이너의 쉘에 접속한 것처럼 되는 것이다!!


요약

kubectl: 사용자 입력을 REST API 요청으로 변환하여 API 서버에 전송한다.

api server: 해당 요청을 인증 및 권한 부여 후 처리, 해당 파드가 있는 노드의 kubelet에 요청을 전달한다.

kubelet: api server로부터 받은 요청을 파드 내 컨테이너에서 명령어를 실행하는 작업으로 변환한다.

컨테이너 런타임: kubelet의 명령에 따라 컨테이너 내부에서 셸 프로세스를 생성하고 실행한다.

표준입출력 연결: 사용자 터미널과 컨테이너 셸 간의 스트림 연결을 통해 상호작용을 가능하게 만든다.

profile
기술 공유를 즐기는 DevOps Engineer 장지수입니다.

0개의 댓글