인프런 쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2 강의를 들으며 학습하고 정리한 내용을 자유롭게 쓰고자 합니다.
kubernetes 기본 동작 방식
쿠버네티스의 기본 동작 방식은 다음과 같은 흐름으로 이루어진다.
pod 요청 -> kube API -> kubelet -> 컨테이너 런타임 -> 커널 레벨 격리(chroot), 리소스 분배(cgroup), 프로세스 격리(namespace)
이 과정에서 각 컴포넌트는 중요한 역할을 수행하게 된다.
사용자나 시스템이 pod 생성을 요청하면, 쿠버네티스 API 서버가 이를 처리하고 kubelet에게 지시를 내린다.
kubelet은 이 요청을 받아 컨테이너 런타임에게 실제 컨테이너 생성을 요청하고, 컨테이너 런타임은 Linux 커널의 기능들을 활용하여 컨테이너를 생성하고 격리한다.
과거 kubernetes 아키텍처 변화
v1.0 ~ v1.4 (초기 버전)
- 이 시기의 쿠버네티스는 Docker에 강하게 결합된 구조를 가지고 있었다.
- 컨테이너 런타임 인터페이스의 표준화가 없었기 때문에, 다른 컨테이너 런타임을 사용하기가 어려웠다.
v1.5 ~ 1.20 (CRI 도입 및 성숙)
- Container Runtime Interface(CRI) 도입
- v1.5에서 알파 버전으로 시작해 v1.7에서 베타로, v1.10에서 안정화 버전이 되었다.
- 이 기간 동안 Docker와 CRI가 공존했으며, 점진적으로 CRI 채택이 증가했다.
- 그리고 1.5 버전에서부터 kubelet과 CRI의 통신에 gRPC를 쓰기 시작하게 되었다.
그런데... gRPC가 뭐지?
gRPC(gRPC Remote Procedure Call)는 Google에서 개발한 고성능 오픈소스 RPC 프레임워크이다.
이는 마이크로서비스 아키텍처에서 서비스 간 통신을 효율적으로 처리하기 위해 설계되었다.
구글에서 HTTP/2를 기반으로 효율적 통신을 위해 커스텀 프로토콜을 개발했고, 그거에 맞게 구현체도 제공한다는 거구나!
HTTP 같은 경우에는 Spring이나 Node.js처럼 프레임워크가 자체적으로 HTTP 구현체를 만들어서 관리하는데 gRPC는 프로토콜도 제공하는데 gRPC 구현체도 중앙집중식으로 관리를 한다.
그래서 gRPC는 RPC 기술을 현대화하고 최적화한 것이고 커스텀 프로토콜 + 프레임워크구나!
gRPC의 주요 특징
1. HTTP/2 기반으로 빠르고 효율적인 통신
2. Protocol Buffers를 사용한 데이터 직렬화
3. 다양한 프로그래밍 언어 지원
4. 양방향 스트리밍 지원
그러면 MSA 환경에서 주문 서비스에서 비즈니스 로직을 처리하다 어!? 이거 회원정보가 필요한데, 나한테는 없네? 하면 이걸 gRPC를 이용해서 회원 서비스의 결과를 직접 받아올 수도 있다는 거구나?
gRPC의 Protocol Buffers는 뭘까?
Protocol Buffers는 gRPC와 함께 사용되는 데이터 직렬화 방식
JSON보다 더 효율적인 데이터 전송을 가능하게 한다.
언어 중립적이다.
바이너리 형식으로 직렬화해서 빠르고 가볍다.
스키마 정의로 타입 안전성 확보함.
그럼 MSA 환경에서 운영과 옵저빌리티는 어떻게 확보하지?
아! Istio가 있지!
Istio는 분산 추적, 중앙 집중식 모니터링, 로드 밸런싱, 보안 등 다양한 기능을 제공하니까 옵저빌리티 확보가 되겠구나 여기에 Jaeger와 같은 분산 추적 도구를 추가하여 더욱 정밀한 모니터링이 가능하겠다.
Istio: 서비스 A에서 B로 가는 트래픽이 많아요
Jaeger: 사용자 X의 요청이 서비스 A → B → C → D 순으로 0.5초, 0.3초, 0.7초, 0.2초 걸렸어요.
Jaeger는 애플리케이션에 일정 부분 통합이 필요하고 Istio와 함께 사용하면 많은 부분을 자동화할 수 있구나.
Jaeger 단독으로 쓴다면 트레이스 ID를 직접 생성해줘야 하는데 Istio와 함께 쓴다면 Istio가 트레이스 ID를 자동으로 관리하고 전파해서, Jaeger가 이를 수집하고 분석할 수 있게 해 준다.
Istio와 Jaeger는 상호보완적인 관계를 형성한다!
다시 현재의 kubernetes 아키텍처
v1.21 ~ 현재
- 1.24: Dockershim 제거, CRI 전면 도입
- CRI 내재화(built-in) 진행
- 컨테이너 런타임과의 통신 구조 단순화
컨테이너 런타임이 업데이트될 때마다 kubelet도 종속되어서 수정이 같이 이루어져야 하니까 CRI가 필요했던 건데 이제는 책임을 분리
kubelet-> (CRI 빌트인) -> 통신 -> (컨테이너 런타임 인터페이스) -> 컨테이너 런타임 코어
kubelet은 CRI 기능을 흡수하고 컨테이너 런타임도 인터페이스를 만들어서 인터페이스들끼리 통신으로 책임을 분리하고 상호 의존성을 약하게 하는 방향으로 발전했다!
이때 통신은 여전히 gRPC를 사용하고 이런 변화로 인해 두 컴포넌트 간의 느슨한 결합이 가능해졌고, 각각 독립적으로 발전할 수 있는 기반이 마련되었다.
이미지 출처 : https://inf.run/k7mF