Linkerd 아키텍처
큰 그림에서 보면 Linkerd는 **컨트롤 플레인(control plane)**과 **데이터 플레인(data plane)**으로 이루어져 있어요.
본문
컨트롤 플레인은 Linkerd 전체를 제어하는 서비스들의 집합이에요.
데이터 플레인은 각 서비스 인스턴스 "옆에서" 파드 안의 사이드카 컨테이너로 도는 투명한 마이크로 프록시들로 구성돼요. 이 프록시들은 서비스로 오고 가는 모든 TCP 트래픽을 자동으로 처리하고, 설정을 위해 컨트롤 플레인과 통신해요.
Linkerd는 컨트롤 플레인과 데이터 플레인을 다루는 데 쓰는 CLI도 제공합니다.
CLI
Linkerd CLI는 보통 클러스터 밖(예: 로컬 머신)에서 실행하면서 Linkerd와 상호작용하는 데 써요.
컨트롤 플레인
Linkerd 컨트롤 플레인은 전용 Kubernetes 네임스페이스(기본값 linkerd)에서 도는 서비스들의 집합이에요. 컨트롤 플레인에는 아래에 나열한 여러 컴포넌트가 있어요.
Destination 서비스
Destination 서비스는 데이터 플레인 프록시가 자기 동작의 여러 측면을 결정하는 데 사용해요. 서비스 디스커버리 정보(어디로 특정 요청을 보내고 상대편에 기대되는 TLS 아이덴티티가 무엇인지 등)를 가져오고, 어떤 종류의 요청이 허용되는지에 대한 정책 정보를 가져오고, 라우트별 메트릭·재시도·타임아웃에 쓰이는 서비스 프로파일 정보를 가져오는 데 쓰이며, 그 외에도 다양한 용도로 사용돼요.
Identity 서비스
Identity 서비스는 프록시의 CSR을 받아 서명된 인증서를 돌려주는 TLS 인증 기관(Certificate Authority) 역할을 해요. 이 인증서는 프록시 초기화 시점에 발급되며, 프록시 간 연결에서 mTLS를 구현하는 데 사용돼요.
Proxy Injector
Proxy Injector는 파드가 생성될 때마다 웹훅 요청을 받는 Kubernetes 어드미션 컨트롤러예요. 이 인젝터는 리소스에서 Linkerd 전용 어노테이션(linkerd.io/inject: enabled)을 검사해요. 해당 어노테이션이 있으면 인젝터가 파드의 스펙을 변형해서 파드에 proxy-init과 linkerd-proxy 컨테이너를 관련 시작 시점 설정과 함께 추가해요.
데이터 플레인
Linkerd 데이터 플레인은 애플리케이션 파드 안에 사이드카 컨테이너로 배포되는 초경량 마이크로 프록시들로 구성돼요. Linkerd 2.20부터 프록시는 기본적으로 네이티브 사이드카 컨테이너로 배포돼요. 이 프록시들은 linkerd-init(또는 선택적으로 Linkerd의 CNI 플러그인)이 만든 iptables 규칙 덕분에 각 파드로 오고 가는 TCP 연결을 투명하게 가로채요.
Proxy
Linkerd2-proxy는 Rust로 작성된 초경량의 투명한 마이크로 프록시예요. Linkerd2-proxy는 서비스 메시 사용 사례에 맞춰 특별히 설계됐으며, 범용 프록시로는 만들지 않았어요.
프록시의 기능은 다음과 같아요:
- HTTP, HTTP/2, 임의의 TCP 프로토콜에 대한 투명하고 설정이 필요 없는 프록싱.
- HTTP와 TCP 트래픽에 대한 자동 Prometheus 메트릭 내보내기.
- 투명하고 설정이 필요 없는 WebSocket 프록싱.
- 자동이며 지연 인지(latency-aware) 방식의 레이어-7 로드 밸런싱.
- non-HTTP 트래픽에 대한 자동 레이어-4 로드 밸런싱.
- 자동 TLS.
- 주문형(on-demand) 진단용 tap API.
- 그 외에도 훨씬 많아요.
프록시는 DNS와 destination gRPC API를 통해 서비스 디스커버리를 지원해요.
이 마이크로 프록시들에 대해 더 자세히 알고 싶다면 여기를 읽어보세요:
- Why Linkerd doesn't use Envoy
- Under the hood of Linkerd's state-of-the-art Rust proxy, Linkerd2-proxy
메시 연결 (Meshed Connections)
한 파드가 다른 파드에 TCP 연결을 만들고 두 파드 모두 Linkerd 프록시가 주입돼 있다면, 우리는 이 연결을 *메시 연결(meshed)*이라고 해요. 연결을 시작한 파드의 프록시를 아웃바운드(outbound) 프록시, 연결을 받아들인 파드의 프록시를 인바운드(inbound) 프록시라고 불러요.
아웃바운드 프록시는 서비스 디스커버리, 로드 밸런싱, 회로 차단기, 재시도, 타임아웃을 담당해요. 인바운드 프록시는 인가 정책 시행을 담당해요. 인바운드와 아웃바운드 프록시 모두 주고받은 트래픽에 대한 트래픽 메트릭을 보고해요.
Linkerd init 컨테이너
linkerd-init 컨테이너는 다른 컨테이너가 시작되기 전에 실행되는 Kubernetes init 컨테이너로, 각 메시 파드에 추가돼요. 이 컨테이너는 iptables를 사용해 파드로 오고 가는 모든 TCP 트래픽을 프록시를 통해 라우팅해요. Linkerd의 init 컨테이너는 어떤 iptables 변형을 쓸지 결정하는 여러 모드로 실행될 수 있어요.