SOCKS5 프록시로 쿠버네티스 API에 접근하기

SOCKS5 프록시로 쿠버네티스 API에 접근하기 (Use a SOCKS5 Proxy to Access the Kubernetes API)

이 페이지는 SOCKS5 프록시를 사용해 원격 쿠버네티스 클러스터의 API에 접근하는 방법을 보여 줘요. 접근하려는 클러스터가 공개 인터넷에 API를 직접 노출하지 않을 때 유용해요.

출처: 문서

본문

시작하기 전에

쿠버네티스 클러스터가 필요하고, kubectl 명령줄 도구가 클러스터와 통신하도록 설정돼 있어야 해요. 이 튜토리얼은 제어 플레인 호스트 역할을 하지 않는 노드가 최소 두 개 있는 클러스터에서 실행하는 것을 권장해요. 아직 클러스터가 없다면 minikube를 사용하거나 다음 쿠버네티스 플레이그라운드 중 하나를 사용해 만들 수 있어요.

  • iximiuz Labs
  • Killercoda
  • KodeKloud

쿠버네티스 서버는 버전 v1.24 이상이어야 해요. 버전을 확인하려면 kubectl version을 입력하세요.

SSH 클라이언트 소프트웨어(ssh 도구)와 원격 서버에서 실행 중인 SSH 서비스가 필요해요. 원격 서버의 SSH 서비스에 로그인할 수 있어야 해요.

작업 맥락 (Task context)

참고:

그림 1은 이 작업에서 달성하려는 것을 나타내요.

  • 쿠버네티스 API와 통신할 요청을 만들 클라이언트 컴퓨터가 있어요. 앞으로의 단계에서는 이를 'local'이라고 해요.
  • 쿠버네티스 서버/API는 원격 서버에 호스팅돼요.
  • SSH 클라이언트와 서버 소프트웨어를 사용해 local과 원격 서버 사이에 보안 SOCKS5 터널을 만들 거예요. 클라이언트와 쿠버네티스 API 사이의 HTTPS 트래픽은, 그 자체가 SSH 위에 터널링된 SOCKS5 터널을 통해 흐를 거예요.

그림 1. SOCKS5 튜토리얼 구성 요소

graph LR;
  subgraph local[Local client machine]
  client([client])-. local traffic .-> local_ssh[Local SSH SOCKS5 proxy];
  end
  local_ssh[SSH SOCKS5 proxy]-- SSH Tunnel -->sshd
  subgraph remote[Remote server]
  sshd[SSH server]-- local traffic -->service1;
  end
  client([client])-. proxied HTTPs traffic going through the proxy .->service1[Kubernetes API];
  classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000;
  classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff;
  classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5;
  class ingress,service1,service2,pod1,pod2,pod3,pod4 k8s;
  class client plain;
  class cluster cluster;

ssh로 SOCKS5 프록시 만들기

다음 명령은 클라이언트 머신과 원격 SOCKS 서버 사이에 SOCKS5 프록시를 시작해요.

# 이 명령을 실행하면 SSH 터널이 포그라운드에서 계속 실행됨

ssh -D 1080 -q -N [email protected]

SOCKS5 프록시는 다음 구성에 따라 클러스터의 API 서버에 연결하게 해줘요.

  • -D 1080: 로컬 포트 1080에 SOCKS 프록시를 염.
  • -q: quiet 모드. 대부분의 경고와 진단 메시지를 억제함.
  • -N: 원격 명령을 실행하지 않음. 포트 포워딩만 하는 데 유용함.
  • [email protected]: 그 뒤에서 쿠버네티스 클러스터가 실행되는 원격 SSH 서버(예: 베스천 호스트).

클라이언트 구성 (Client configuration)

프록시를 통해 쿠버네티스 API 서버에 접근하려면 kubectl이 앞서 만든 SOCKS 프록시를 통해 쿼리를 보내도록 지시해야 해요. 적절한 환경 변수를 설정하거나, kubeconfig 파일의 proxy-url 속성을 통해 이 작업을 해요. 환경 변수 사용:

export HTTPS_PROXY=socks5://localhost:1080

특정 kubectl 컨텍스트에서 항상 이 설정을 사용하려면 ~/.kube/config 파일의 관련 cluster 항목에 proxy-url 속성을 지정하세요. 예를 들어:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LRMEMMW2 # 읽기 쉽도록 줄임
    server: https://<API_SERVER_IP_ADDRESS>:6443 # "Kubernetes API" 서버, 즉 kubernetes-remote-server.example의 IP 주소
    proxy-url: socks5://localhost:1080  # 위 다이어그램의 "SSH SOCKS5 proxy"
  name: default
contexts:
- context:
    cluster: default
    user: default
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
  user:
    client-certificate-data: LS0tLS1CR== # 읽기 쉽도록 줄임
    client-key-data: LS0tLS1CRUdJT=     # 읽기 쉽도록 줄임

앞서 언급한 ssh 명령으로 터널을 만든 뒤 환경 변수나 proxy-url 속성을 정의했다면, 그 프록시를 통해 클러스터와 상호작용할 수 있어요. 예를 들어:

kubectl get pods
NAMESPACE     NAME                                     READY   STATUS      RESTARTS   AGE
kube-system   coredns-85cb69466-klwq8                  1/1     Running     0          5m46s

참고:

  • kubectl 1.24 이전에는 kubectl exec를 제외한 대부분의 kubectl 명령이 socks 프록시를 사용할 때 동작했어요.
  • kubectl은 HTTPS_PROXYhttps_proxy 환경 변수를 모두 지원해요. 이들은 curl 같은 SOCKS를 지원하는 다른 프로그램도 사용해요. 따라서 일부 경우에는 명령줄에서 환경 변수를 정의하는 것이 더 나을 수 있어요: HTTPS_PROXY=socks5://localhost:1080 kubectl get pods
  • proxy-url을 사용하면 프록시는 관련 kubectl 컨텍스트에서만 사용되는 반면, 환경 변수는 모든 컨텍스트에 영향을 줘요.
  • socks5 대신 socks5h 프로토콜 이름을 사용하면 k8s API 서버 호스트 이름을 DNS 누출로부터 더 보호할 수 있어요. 이 경우 kubectl은 kubectl이 실행되는 시스템에서 k8s API 서버 도메인 이름을 해석하는 대신 프록시 서버(예: ssh 베스천)에 해석을 요청해요. 또한 socks5h에서는 https://localhost:6443/api 같은 k8s API 서버 URL이 로컬 클라이언트 컴퓨터를 가리키지 않아요. 대신 프록시 서버(예: ssh 베스천)가 아는 localhost를 가리켜요.

정리하기 (Clean up)

실행 중인 터미널에서 CTRL+C를 눌러 ssh 포트 포워딩 프로세스를 중지하세요.

터미널에서 unset https_proxy를 입력해 http 트래픽이 프록시를 통해 전달되는 것을 중지하세요.

더 알아보기 (Learn more)