2 분 소요

게시:

내부망(Private Network)에 위치하여 직접 접근할 수 없는 Kubernetes 클러스터 API 서버를 Bastion 서버를 경유하여 로컬 kubectl로 접근하고 제어하는 방법에 대해 설명합니다.

첫 번째 방법: SOCKS5 프록시 터널 (권장)

터널 하나로 여러 클러스터를 유연하게 관리할 수 있는 가장 권장되는 방식입니다.

Step 1: SOCKS5 SSH 터널 생성 (포그라운드)

로컬 머신에서 SOCKS5 프록시(터널 입구)를 엽니다. 이 터미널이 실행 중일 때만 프록시가 동작하며 Ctrl+C로 명확하게 종료할 수 있습니다.

  • -D <local_port>: 지정된 로컬 포트(예: 1080)를 SOCKS 프록시로 지정합니다.
  • -N: 원격 명령을 실행하지 않고 터널링만 수행합니다.
# <local_port>는 1080 등으로 지정
ssh -D 1080 -N <bastion_user>@<bastion_ip>

백그라운드 실행 방법 (-f 옵션)
터널을 백그라운드로 실행하려면 -f 옵션을 추가한다. (ssh -D 1080 -Nf ...)
이 경우, 터널을 종료하려면 ps aux | grep ssh 등으로 PID를 찾아 kill 해야 합니다.

Step 2: Kubeconfig 수정 (proxy-url 추가)

kubectl이 이 SOCKS5 프록시를 사용하도록 ~/.kube/config 파일의 cluster 섹션에 proxy-url을 추가합니다.

  • 중요: localhost 대신 127.0.0.1 (IPv4) 주소를 사용합니다. (IPv6(::1) 해석으로 인한 통신 오류 방지)
clusters:
- cluster:
    server: "https://192.168.2.185:6443"  # 내부 API 서버의 주소 (변경하지 않음)
    certificate-authority-data: ...
    proxy-url: "socks5://127.0.0.1:1080"  # 1단계에서 생성한 SOCKS5 프록시 터널 지정
  name: "remote-cluster1"
  ...

3단계: 연결 테스트

1단계의 SSH 터널이 실행 중인 상태에서 새로운 터미널 창을 열어 kubectl 명령을 실행합니다.

kubectl config use-context some-k8s-context
kubectl get nodes

두 번째 방법: 1:1 로컬 포트 포워딩 (ssh -L)

SOCKS5 프로토콜이 차단된 환경 등에서 사용할 수 있는 대안이다. 이 방식은 하나의 클러스터 API 서버와 로컬 포트를 1:1로 직접 매핑합니다.

Step 1: 1:1 포트 포워딩 실행 (포그라운드)

  • -L <local_port>:<k8s_api_ip>:<k8s_api_port>: 로컬 포트를 Bastion을 거쳐 지정된 내부 IP/포트로 1:1 연결합니다.
# 로컬 6443 포트를 192.168.2.185:6443으로 1:1 매핑
# (만약 로컬 6443 포트가 이미 사용 중이면 6444 등으로 변경)
ssh -L 6443:192.168.2.185:6443 -N <bastion_user>@<bastion_ip>

2단계: Kubeconfig 수정 (server 변경)

proxy-url을 사용하는 대신 server 주소 자체를 127.0.0.1과 매핑된 로컬 포트로 변경해야 합니다.

clusters:
- cluster:
    certificate-authority-data: ...
    server: "https://127.0.0.1:6443"  # 'server' 주소를 1:1 매핑된 로컬 주소로 변경합니다.
  name: "remote-cluster1"
# proxy-url 항목은 사용하지 않습니다.

SOCKS5 (-D) vs 1:1 포워딩 (-L) 비교

특징 SOCKS5 프록시 (ssh -D) 1:1 포트 포워딩 (ssh -L)
터널 방식 범용 터널 1:1 지정 터널
터널 1개당 **여러 클러스터 동시 접근 가능 단 하나의 클러스터만 접근 가능
Kubeconfig server (내부 IP)는 유지,<br>**proxy-url 추가 **server (127.0.0.1)를 수정,<br>proxy-url 미사용
단점 SOCKS 프로토콜 지원 필요 접근할 클러스터마다 별도 터널 실행
(로컬 포트 충돌 주의)

트러블슈팅

kubectl 실행 시 TLS handshake timeout 등의 에러가 발생하면 다음을 점검합니다.

  1. (로컬) 1단계의 ssh 터널이 포그라운드에서 정상 실행 중인지 확인합니다.
  2. (Bastion) Bastion 서버에 접속하여 내부 API 서버(192.168.2.185)로 TCP 연결이 가능한지 확인합니다.
     # Bastion 서버에서 실행
     nc -zv 192.168.2.185 6443
    
    • succeeded!가 출력되어야 합니다. 실패(Timeout) 시 Bastion의 방화벽(보안 그룹)을 확인합니다.
  3. (SOCKS5 방식) kubeconfigproxy-urlsocks5://127.0.0.1:1080로 정확히 설정되었는지 확인합니다.
  4. (SOCKS5 방식) 로컬 환경 변수 NO_PROXY 또는 no_proxy에 API 서버의 IP 대역이 포함되어 있는지 확인합니다. 포함 시 kubectlproxy-url을 무시하므로, 해당 변수를 unset 합니다.

     echo $NO_PROXY
    
  5. (1:1 포워딩 방식) kubeconfigserverhttps://127.0.0.1:<local_port>로 정확히 설정되었는지 확인합니다.

댓글남기기