노드와 컨트롤 플레인 사이의 통신
노드와 컨트롤 플레인 사이의 통신 (Communication between Nodes and the Control Plane)
이 문서는 API 서버와 Kubernetes 클러스터 사이의 통신 경로를 정리해드려요. 목적은 사용자가 설치 환경을 커스터마이즈해서, 클러스터가 신뢰할 수 없는 네트워크(또는 클라우드 제공자의 완전 공용 IP)에서 실행될 수 있도록 네트워크 구성을 보강(harden)하게 하는 거예요.
출처: Kubernetes 공식 문서 — Communication between Nodes and the Control Plane
노드 → 컨트롤 플레인 (Node to Control Plane)
Kubernetes는 "허브-앤-스포크(hub-and-spoke)" API 패턴을 사용해요. 노드(또는 그 안에서 실행되는 Pod)에서 오는 모든 API 사용은 API 서버에서 끝납니다. 다른 컨트롤 플레인 컴포넌트 중 원격 서비스를 노출하도록 설계된 것은 없어요. API 서버는 한 가지 이상의 클라이언트 인증이 활성화된 보안 HTTPS 포트(보통 443)에서 원격 연결을 수신하도록 구성돼요. 특히 익명 요청이나 서비스 어카운트 토큰이 허용된다면 한 가지 이상의 권한 부여도 활성화해야 합니다.
노드는 API 서버에 안전하게 연결할 수 있도록, 유효한 클라이언트 자격 증명과 함께 클러스터의 공용 루트 인증서로 프로비저닝되어야 해요. 좋은 방법은 kubelet에 제공되는 클라이언트 자격 증명을 클라이언트 인증서 형태로 하는 거예요. kubelet 클라이언트 인증서의 자동 프로비저닝은 kubelet TLS 부트스트래핑을 참고하세요.
API 서버에 연결하려는 Pod는 서비스 어카운트를 활용해서 안전하게 연결할 수 있어요. 그러면 Kubernetes가 Pod를 인스턴스화할 때 공용 루트 인증서와 유효한 베어러 토큰을 자동으로 주입해주거든요. (default 네임스페이스의) kubernetes 서비스는 kube-proxy를 통해 API 서버의 HTTPS 엔드포인트로 리다이렉트되는 가상 IP 주소로 구성돼요.
컨트롤 플레인 컴포넌트도 보안 포트를 통해 API 서버와 통신해요.
결과적으로 노드와 노드에서 실행되는 Pod에서 컨트롤 플레인으로의 연결은 기본적으로 보안이 강화되어서, 신뢰할 수 없거나 공용인 네트워크에서도 실행될 수 있어요.
컨트롤 플레인 → 노드 (Control plane to node)
컨트롤 플레인(API 서버)에서 노드로 가는 통신 경로는 크게 두 가지가 있어요. 첫 번째는 API 서버에서 클러스터의 각 노드에서 실행되는 kubelet 프로세스로 가는 경로예요. 두 번째는 API 서버의 proxy 기능을 통해 API 서버에서 임의의 노드, Pod, 서비스로 가는 경로입니다.
API 서버 → kubelet
API 서버에서 kubelet으로의 연결은 다음에 사용돼요:
- Pod의 로그 가져오기.
- 실행 중인 Pod에 연결(보통
kubectl을 통해). - kubelet의 포트-포워딩(port-forwarding) 기능 제공.
이 연결들은 kubelet의 HTTPS 엔드포인트에서 종료됩니다. 기본적으로 API 서버는 kubelet의 서빙 인증서를 검증하지 않아서, 이 연결은 중간자(man-in-the-middle) 공격에 노출될 수 있고 신뢰할 수 없거나 공용인 네트워크에서 실행하기에는 안전하지 않아요.
이 연결을 검증하려면 --kubelet-certificate-authority 플래그를 사용해서 API 서버에 kubelet의 서빙 인증서를 검증하는 데 쓰는 루트 인증서 번들을 제공하세요.
그게 불가능하다면, 신뢰할 수 없거나 공용인 네트워크를 통한 연결을 피하기 위해 필요할 때 API 서버와 kubelet 사이에 SSH 터널링을 사용하세요.
마지막으로, kubelet API를 보호하기 위해 Kubelet 인증 및/또는 권한 부여를 활성화해야 해요.
API 서버 → 노드, Pod, 서비스
API 서버에서 노드, Pod, 서비스로의 연결은 기본적으로 일반 HTTP 연결이라 인증되지도 암호화되지도 않아요. API URL에서 노드, Pod, 서비스 이름 앞에 https:를 붙이면 보안 HTTPS 연결로 실행할 수 있지만, HTTPS 엔드포인트가 제공하는 인증서를 검증하지도 않을 뿐더러 클라이언트 자격 증명도 제공하지 않아요. 그래서 연결은 암호화되지만 무결성(integrity)은 보장하지 못해요. 이 연결은 신뢰할 수 없거나 공용인 네트워크에서 실행하기에 현재 안전하지 않아요.
SSH 터널
Kubernetes는 컨트롤 플레인에서 노드로의 통신 경로를 보호하기 위해 SSH 터널을 지원해요. 이 구성에서 API 서버는 클러스터의 각 노드로 SSH 터널을 시작하고(포트 22에서 수신하는 SSH 서버에 연결), kubelet, 노드, Pod, 서비스로 향하는 모든 트래픽을 터널을 통해 전달해요. 이 터널은 트래픽이 노드가 실행되는 네트워크 밖으로 노출되지 않도록 보장합니다.
참고:
SSH 터널은 현재 폐기(deprecated)됐으므로, 정확히 뭘 하는지 알지 못한다면 사용하지 않는 게 좋아요. Konnectivity 서비스가 이 통신 채널을 대체합니다.
Konnectivity 서비스
FEATURE STATE: Kubernetes v1.18 [beta]
SSH 터널의 대체로, Konnectivity 서비스는 컨트롤 플레인에서 클러스터로의 통신을 위한 TCP 수준 프록시를 제공해요. Konnectivity 서비스는 두 부분으로 구성됩니다: 컨트롤 플레인 네트워크의 Konnectivity 서버와 노드 네트워크의 Konnectivity 에이전트. Konnectivity 에이전트는 Konnectivity 서버로의 연결을 시작하고 그 네트워크 연결을 유지해요. Konnectivity 서비스를 활성화한 후에는 모든 컨트롤 플레인→노드 트래픽이 이 연결을 통과합니다.
클러스터에서 Konnectivity 서비스를 설정하려면 Konnectivity 서비스 태스크를 따르세요.
다음으로 볼 것 (What's next)
- Kubernetes 컨트롤 플레인 컴포넌트에 대해 읽어보세요
- 허브-앤-스포크 모델에 대해 더 배워보세요
- 클러스터 보안 강화 방법을 배워보세요
- Kubernetes API에 대해 더 배워보세요
- Konnectivity 서비스 설정
- 포트 포워딩으로 클러스터 안의 애플리케이션 접근
- Pod 로그 가져오기, kubectl port-forward 사용 방법 알아보기