본문으로 건너뛰기

크레이트 구조

kube는 단일 크레이트가 아니라 역할별로 분리된 5개 크레이트의 집합입니다. 각 크레이트가 왜 분리되어 있고, 어떤 계층을 이루는지 살펴봅니다.

왜 여러 크레이트인가

kube의 크레이트 분리는 최소 의존성 원칙을 따릅니다.

  • kube-core는 HTTP 의존성이 없습니다. 라이브러리 크레이트에서 Kubernetes 타입만 가져다 쓸 수 있습니다.
  • kube-client는 네트워크 계층만 담당합니다. Tower 미들웨어 기반의 HTTP 클라이언트와 Api<K> 핸들을 제공합니다.
  • kube-runtime은 operator 추상화만 담당합니다. watcher, reflector, Controller를 조합해 컨트롤러 루프를 구성합니다.
  • kube-derive는 proc-macro 크레이트입니다. #[derive(CustomResource)] 등 코드 생성을 담당합니다.

이 분리 덕분에 feature flag로 필요한 것만 활성화할 수 있고, 컴파일 시간과 바이너리 크기를 줄일 수 있습니다.

계층 다이어그램

핵심은 kube-core가 바닥에 있다는 것입니다. HTTP 의존성 없이 타입과 trait만 정의하고, 나머지 크레이트가 이 위에 쌓입니다.

각 크레이트의 역할

kube-core — 순수 타입

HTTP 의존성 없이 Kubernetes API와 상호작용하는 데 필요한 타입과 trait을 정의합니다. Go의 k8s.io/apimachinery에 대응합니다.

주요 모듈:

모듈역할핵심 타입
resource리소스 추상화Resource trait, ResourceExt
metadata메타데이터ObjectMeta, TypeMeta, ListMeta
object객체 래퍼Object<P, U>, ObjectList<K>
paramsAPI 파라미터ListParams, PatchParams, Patch enum
dynamic동적 타입DynamicObject, ApiResource
gvk타입 정보GroupVersionKind, GroupVersionResource
request요청 조립Request (URL path + query 생성, 전송 없음)
response응답 타입Status, WatchEvent
labels레이블 셀렉터Selector, Expression
crdCRD 확장CustomResourceExt
error_boundary역직렬화 보호DeserializeGuard

request 모듈이 핵심입니다. HTTP 요청의 URL path와 query parameter를 조립하지만, 실제로 요청을 보내지는 않습니다. 이 분리 덕분에 kube-core는 네트워크 의존성 없이 순수한 타입 크레이트로 유지됩니다.

kube-client — 네트워크 계층

실제 Kubernetes API 서버와 통신하는 HTTP 클라이언트를 제공합니다. Go의 client-go에 대응합니다.

주요 구성:

  • Client: Tower 기반 HTTP 클라이언트입니다. Buffer<BoxService<...>>로 type-erased되어 있어 Clone이 가볍습니다. 내부 구조는 Client 내부 구조에서 다룹니다.
  • Api<K>: 타입 안전한 CRUD 핸들입니다. get(), list(), patch(), delete() 등 Kubernetes API 작업을 제공합니다. K: Resource 바운드로 컴파일 타임에 리소스 타입을 검증합니다.
  • Config: kubeconfig 파일 또는 in-cluster 환경에서 설정을 로드합니다.
  • Discovery: 런타임에 API 서버가 지원하는 리소스를 조회합니다.

Api<K>의 생성자는 리소스의 스코프에 따라 컴파일 타임 검증을 제공합니다:

// Namespace 스코프 리소스
let pods: Api<Pod> = Api::namespaced(client.clone(), "default");

// Cluster 스코프 리소스
let nodes: Api<Node> = Api::all(client.clone());

// Namespace를 Api::namespaced()로 만들면 컴파일 에러
// let ns: Api<Namespace> = Api::namespaced(client, "default"); // ← 컴파일 안 됨

kube-runtime — Operator 추상화

컨트롤러 패턴을 구현하는 데 필요한 빌딩 블록을 제공합니다. Go의 controller-runtime에 대응합니다.

모듈역할
watcher자동 재연결 + 에러 복구가 포함된 watch 스트림
reflectorwatcher 스트림을 가로채 인메모리 캐시(Store)에 기록
controllerreflector + 스케줄링 + 동시성 제어를 조합한 컨트롤러 루프
finalizer삭제 전 정리 작업 헬퍼
scheduler스트림 항목의 지연 + 중복 제거
eventsKubernetes Event 리소스 발행
wait조건 대기 (await_condition)
utilsWatchStreamExt, predicates 등 스트림 유틸리티

이 모듈들이 어떻게 조합되는지는 Runtime Internals 섹션에서 자세히 다룹니다.

kube-derive — 코드 생성

proc-macro 크레이트로, 세 가지 derive 매크로를 제공합니다.

매크로생성 결과
CustomResourceCRD 루트 struct + Resource impl + CustomResourceExt impl
Resource기존 타입에 대한 Resource trait impl
KubeSchemaCEL 검증 룰이 포함된 JsonSchema impl

#[derive(CustomResource)]가 생성하는 코드의 세부 내용은 CRD와 derive 매크로에서 다룹니다.

kube — facade

사용자가 Cargo.toml에 추가하는 유일한 크레이트입니다. feature flag에 따라 위 4개 크레이트를 re-export합니다.

// feature = "client" (기본 활성화)
pub use kube_client::{api, client, discovery};

// feature = "config" (기본 활성화)
pub use kube_client::config;

// feature = "derive"
pub use kube_derive::{CustomResource, Resource, KubeSchema};

// feature = "runtime"
pub use kube_runtime as runtime;

// 항상 사용 가능
pub use kube_core as core;

Go 생태계와 대응 관계

kube-rsGo역할
kube-corek8s.io/apimachinery타입, 메타데이터, API 파라미터
kube-clientclient-goHTTP 클라이언트, 인증, 설정
kube-runtimecontroller-runtime컨트롤러, watcher, 캐시
kube-derivekubebuilder (코드 생성)CRD struct 생성, 스캐폴딩

Go에서 controller-runtime을 쓰면 내부적으로 client-goapimachinery가 따라오는 것처럼, kube에서도 runtime feature를 켜면 kube-runtime이 kube-client와 kube-core를 함께 가져옵니다.

Feature flag 가이드

kube의 기본 feature는 client, rustls-tls, ring입니다. 용도에 따라 필요한 feature를 조합합니다.

용도별 조합

API 조회만 (기본)
[dependencies]
kube = "3.0.1"
컨트롤러 개발
[dependencies]
kube = { version = "3.0.1", features = ["runtime", "derive"] }
Pod exec/attach/portforward
[dependencies]
kube = { version = "3.0.1", features = ["runtime", "derive", "ws"] }
타입만 사용 (HTTP 의존성 없음)
[dependencies]
kube-core = "3.0.1"

전체 feature 목록

Feature기본설명
clientClient, Api<K>
configConfig (kubeconfig / in-cluster)
rustls-tlsRustls TLS 백엔드
ringRustls 암호화 provider
openssl-tlsOpenSSL TLS 백엔드 (rustls-tls와 동시 사용 불가)
aws-lc-rsAWS Libcrypto provider (Rustls와 함께)
webpki-rootsWebPKI 인증서 루트 (시스템 인증서 대신)
deriveCustomResource, Resource, KubeSchema 매크로
runtimewatcher, reflector, Controller
wsWebSocket (exec, attach, portforward)
gzip응답 gzip 압축 해제
jsonpatchPatch::Json 지원
oauthOAuth 인증
oidcOIDC 인증
socks5SOCKS5 프록시
http-proxyHTTP 프록시
admissionAdmission webhook 타입
kubelet-debugkubelet 디버그 인터페이스
unstable-runtime실험적 runtime 기능
unstable-client실험적 client 기능

k8s-openapi의 위치

kube 자체는 Pod, Deployment, Service 같은 Kubernetes 빌트인 타입을 정의하지 않습니다. 이 타입들은 별도 크레이트인 k8s-openapi가 제공합니다.

kube-core는 k8s-openapi 타입에 대해 blanket impl을 제공합니다:

kube-core의 blanket impl (단순화)
impl<K, S> Resource for K
where
K: k8s_openapi::Metadata<Ty = ObjectMeta>,
K: k8s_openapi::Resource<Scope = S>,
{
type DynamicType = ();
type Scope = S;
// kind(), group(), version() 등은 K::KIND, K::GROUP, K::VERSION에서 가져옴
}

이 blanket impl 덕분에 k8s-openapi의 모든 타입(Pod, Service, Deployment 등)이 자동으로 kube의 Resource trait을 구현합니다. 사용자가 별도로 impl을 작성할 필요가 없습니다.

Cargo.toml
[dependencies]
kube = { version = "3.0.1", features = ["runtime", "derive"] }
k8s-openapi = { version = "0.27.0", features = ["latest", "schemars"] }

k8s-openapi의 latest feature는 kube 버전에 맞는 Kubernetes API 버전을 활성화합니다. schemars feature는 CRD 스키마 생성에 필요합니다.

version feature는 하나만

k8s-openapi의 version feature (latest, v1_32 등)는 하나만 활성화해야 합니다. 여러 개를 동시에 켜면 컴파일 에러가 발생합니다.