쿠버네티스 API 서버 우회 접속(Proxy) 메커니즘 이해하기
쿠버네티스 클러스터 내부에서 실행되는 파드(Pod)나 서비스(Service)는 기본적으로 외부 인터넷에 노출되지 않는 프라이빗 네트워크(ClusterIP) 환경에 격리되어 있습니다. 관리자나 개발자가 디버깅, 테스트, 또는 내부 관리 도구(예: 쿠버네티스 대시보드)에 접속하기 위해 매번 Ingress나 LoadBalancer를 생성하는 것은 보안상으로나 리소스 측면에서 매우 비효율적입니다.
이러한 문제를 해결하기 위해 쿠버네티스는 Kube-apiserver를 강력한 '보안 관문(Bastion)'이자 '리버스 프록시(Reverse Proxy)'로 활용하는 우회 접속 메커니즘을 제공합니다. 이 가이드에서는 kubectl proxy, kubectl port-forward, 그리고 API 서버의 내부 라우팅 아키텍처가 어떻게 안전한 터널링을 구현하는지 심층적으로 해부합니다.

1. kubectl proxy: API 서버 인증의 로컬 오프로딩
가장 흔히 접하는 첫 번째 우회 메커니즘은 kubectl proxy 명령어입니다. 많은 사용자가 이를 단순히 "파드에 접속하게 해주는 도구"로 오해하지만, 그 본질은 Kube-apiserver에 대한 인증/인가 처리를 로컬 환경으로 오프로딩(Offloading)하는 로컬 HTTP 프록시 서버입니다.
사용자가 터미널에서 kubectl proxy를 실행하면, 로컬 머신(예: localhost:8001)에 가벼운 HTTP 서버가 구동됩니다. 사용자가 웹 브라우저나 curl을 통해 이 로컬 주소로 요청을 보내면, 로컬 프록시 서버는 사용자의 kubeconfig 파일에 있는 인증서(X.509)나 베어러 토큰을 헤더에 자동으로 주입하여 실제 Kube-apiserver로 요청을 안전하게 릴레이합니다.
- 아키텍처적 이점: 외부 클라이언트 스크립트나 브라우저가 복잡한 TLS 인증 과정이나 토큰 갱신을 직접 구현할 필요가 없어집니다.
- 주요 사용 사례: 쿠버네티스 대시보드 접속, 클러스터 외부의 커스텀 스크립트에서 Kube-apiserver의 REST API를 직접 호출(
GET /api/v1/pods)할 때 사용됩니다.
2. API 서버를 통한 내부 리소스 프록시 (Service/Pod Proxy)
kubectl proxy로 API 서버와의 인증 터널이 뚫렸다면, 이제 API 서버에 내장된 '리버스 프록시' 기능을 활용하여 클러스터 내부의 특정 서비스나 파드에 도달할 수 있습니다. Kube-apiserver는 특정 URL 패턴을 인식하면, 요청을 자신이 처리하지 않고 목적지 파드로 포워딩합니다.
URL 라우팅 구조:/api/v1/namespaces/{네임스페이스}/services/{서비스명}:{포트이름}/proxy/
- 사용자가 위 URL로 HTTP 요청을 보냅니다.
- Kube-apiserver는 요청된 서비스의 엔드포인트(Endpoints)를 조회하여 실제 대상 파드의 내부 IP를 찾습니다.
- API 서버 자신이 클라이언트가 되어, 클러스터 내부 네트워크를 통해 해당 파드의 IP와 포트로 HTTP 요청을 릴레이합니다.
- 파드의 응답을 받아 다시 최초 요청자에게 반환합니다.
이 메커니즘은 L7(HTTP) 레이어에서 동작하며, 서비스의 로드밸런싱 기능을 그대로 타게 됩니다. API 서버가 모든 트래픽의 중계자가 되므로, 대용량 파일 전송이나 트래픽이 많은 통신에 사용하면 API 서버에 극심한 병목 현상을 유발할 수 있어 순수 디버깅 및 관리 목적으로만 제한해야 합니다.
3. kubectl port-forward: Kubelet을 통한 L4 직접 터널링
HTTP가 아닌 TCP 수준의 직접적인 연결(예: 로컬 데이터베이스 클라이언트로 클러스터 내부의 MySQL 파드에 접속)이 필요할 때는 kubectl port-forward를 사용합니다. 이는 API 서버의 리버스 프록시 기능과는 완전히 다른 아키텍처로 동작합니다.
kubectl port-forward의 데이터 흐름은 다음과 같은 다단계 터널링을 거칩니다.
- SPDY/WebSocket 업그레이드:
kubectl클라이언트는 Kube-apiserver에 연결한 뒤, HTTP 연결을 양방향 스트리밍이 가능한 SPDY 또는 WebSocket 프로토콜로 업그레이드해 달라고 요청합니다. - API 서버와 Kubelet 통신: API 서버는 대상 파드가 실행 중인 워커 노드를 확인하고, 해당 노드의 Kubelet(일반적으로 10250 포트)으로 연결을 파생시킵니다.
- Kubelet과 컨테이너 런타임 통신: 요청을 받은 Kubelet은 CRI(Container Runtime Interface)를 통해 containerd 등의 컨테이너 런타임에게 스트리밍 포트 포워드 요청을 전달합니다.
- 네임스페이스 진입: 컨테이너 런타임은 호스트 노드의 프로세스에서 해당 파드의 네트워크 네임스페이스(Network Namespace)로 직접 진입하여 로컬 루프백(
127.0.0.1)과 연결되는 I/O 파이프를 생성합니다.
이 과정에서 트래픽은 서비스(Service)나 Kube-proxy의 iptables 룰을 전혀 거치지 않고 타겟 파드의 단일 컨테이너로 직행(L4 TCP 터널링)합니다. 따라서 네트워크 정책(NetworkPolicy) 디버깅 시 서비스 라우팅 문제를 배제하고 파드 자체의 애플리케이션 응답 여부만 순수하게 테스트할 때 매우 유용합니다.
4. 컨트롤 플레인과 워커 노드의 격리: Konnectivity 아키텍처
퍼블릭 클라우드의 관리형 쿠버네티스(EKS, GKE 등)에서 보안을 위해 컨트롤 플레인(마스터 노드)과 워커 노드의 네트워크를 완전히 격리(VPC Peering 미사용 등)하는 경우가 많습니다. 이때 API 서버가 워커 노드의 Kubelet에 접근하지 못하면 kubectl port-forward, kubectl exec, kubectl logs와 같은 명령어가 모두 실패하게 됩니다.
이러한 네트워크 단절 상황에서 터널링을 구현하기 위해 도입된 차세대 아키텍처가 Konnectivity (과거 apiserver-network-proxy) 입니다.
- 리버스 터널링(Reverse Tunneling): 방화벽은 일반적으로 외부에서 내부로 들어오는 인바운드 트래픽은 막지만, 내부에서 외부로 나가는 아웃바운드 트래픽은 허용합니다.
- 에이전트 구동: 각 워커 노드(또는 별도의 게이트웨이 노드)에
Konnectivity Agent가 배포됩니다. 이 에이전트는 컨트롤 플레인에 위치한Konnectivity Server를 향해 선제적으로 아웃바운드 연결(gRPC 기반)을 시도하여 영구적인 터널을 뚫어놓습니다. - 트래픽 라우팅: 사용자가
kubectl port-forward를 실행하면, Kube-apiserver는 Kubelet의 포트로 직접 연결을 시도하지 않고 이 Konnectivity 터널을 통해 트래픽을 흘려보냅니다. 트래픽은 터널을 역류하여 워커 노드의 에이전트에 도달하고, 에이전트가 로컬 Kubelet으로 요청을 전달합니다.
이 아키텍처를 통해 워커 노드의 인바운드 포트를 외부 망에 일절 개방하지 않고도, 완벽한 양방향 디버깅 파이프라인과 프록시 통신망을 구축할 수 있습니다.
5. 보안 및 RBAC 권한 통제 메커니즘
프록시와 포트 포워드 기능은 클러스터 네트워크의 방화벽을 우회하는 강력한 기능이므로, 엄격한 RBAC(Role-Based Access Control) 인가 통제가 필수적입니다.
쿠버네티스 API에서 이러한 우회 기능은 일반적인 get, list 동사(Verb)가 아니라, 리소스의 하위 리소스(Subresource) 에 대한 create 권한으로 엄격하게 제어됩니다.
kubectl proxy를 통한 서비스 접근:services/proxy또는pods/proxy에 대한get,create권한 필요.kubectl port-forward사용:pods/portforward하위 리소스에 대한create권한 필요.
운영 환경에서는 일반 개발자에게 이 권한을 클러스터 전역(ClusterRole)으로 절대 부여해서는 안 되며, 오직 개발 네임스페이스에 한정된 RoleBinding으로 제한해야 합니다. 또한 Kube-apiserver의 감사 로그(Audit Log)를 통해 누가, 언제, 어떤 파드로 포트 포워딩 세션을 열었는지 철저히 기록하여 내부자 위협이나 측면 이동(Lateral Movement) 공격에 대비하는 것이 엔터프라이즈 보안 아키텍처의 기본입니다.
'1. K8s Core & Architecture > 1.1. 컨트롤 플레인 (Control Plane) 심층 분석' 카테고리의 다른 글
| 클러스터 상태(State)와 명세(Spec)의 차이: 선언적 API의 본질 (0) | 2026.03.19 |
|---|---|
| etcd 스토리지 백엔드(bbolt)의 내부 구조와 동작 방식 (0) | 2026.03.19 |
| 가비지 컬렉션(Garbage Collection) 컨트롤러의 동작 원리 (0) | 2026.03.18 |
| Kube-apiserver의 캐싱 아키텍처와 성능 향상 원리 (0) | 2026.03.18 |
| 리더 선출(Leader Election) 메커니즘: 컨트롤 매니저와 스케줄러의 HA 구성 (0) | 2026.03.18 |