使用 SOCKS5 代理访问 Kubernetes API
功能状态:
Kubernetes v1.24 [稳定]
此页面展示如何使用 SOCKS5 代理访问远程 Kubernetes 集群的 API。当您要访问的集群没有直接在公网上公开其 API 时,这很有用。
开始之前
您需要拥有一个 Kubernetes 集群,并且 kubectl 命令行工具必须配置为与您的集群通信。建议在至少有两个节点的集群上运行本教程,这些节点不充当控制平面主机。如果您还没有集群,您可以使用 minikube 创建一个集群,或者使用以下 Kubernetes 游乐场之一
您的 Kubernetes 服务器必须是 v1.24 或更高版本。要检查版本,请输入kubectl version
。您需要 SSH 客户端软件 (ssh
工具) 和在远程服务器上运行的 SSH 服务。您必须能够登录到远程服务器上的 SSH 服务。
任务上下文
注意
此示例使用 SSH 传输流量,其中 SSH 客户端和服务器充当 SOCKS 代理。您可以改用任何其他类型的 SOCKS5 代理。图 1 表示您将在本任务中实现的目标。
- 您有一台客户端计算机,在后面的步骤中称为本地计算机,您将从这里创建请求与 Kubernetes API 通信。
- Kubernetes 服务器/API 托管在远程服务器上。
- 您将使用 SSH 客户端和服务器软件在本地和远程服务器之间创建安全的 SOCKS5 隧道。客户端和 Kubernetes API 之间的 HTTPS 流量将在 SOCKS5 隧道上流动,该隧道本身通过 SSH 隧道化。
graph LR; subgraph local[本地客户端机器] client([客户端])-. local
traffic .-> local_ssh[本地 SSH
SOCKS5 代理]; end local_ssh[SSH
SOCKS5
代理]-- SSH 隧道 -->sshd subgraph remote[远程服务器] sshd[SSH
服务器]-- 本地流量 -->service1; end client([客户端])-. 代理的 HTTPS 流量
通过代理 .->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;
traffic .-> local_ssh[本地 SSH
SOCKS5 代理]; end local_ssh[SSH
SOCKS5
代理]-- SSH 隧道 -->sshd subgraph remote[远程服务器] sshd[SSH
服务器]-- 本地流量 -->service1; end client([客户端])-. 代理的 HTTPS 流量
通过代理 .->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 代理
# The SSH tunnel continues running in the foreground after you run this
ssh -D 1080 -q -N username@kubernetes-remote-server.example
SOCKS5 代理允许您根据以下配置连接到集群的 API 服务器
-D 1080
: 在本地端口 :1080 上打开 SOCKS 代理。-q
: 静默模式。导致大多数警告和诊断消息被抑制。-N
: 不执行远程命令。对于仅转发端口很有用。username@kubernetes-remote-server.example
: 运行 Kubernetes 集群的远程 SSH 服务器(例如:堡垒主机)。
客户端配置
要通过代理访问 Kubernetes 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 # shortened for readability
server: https://<API_SERVER_IP_ADDRESS>:6443 # the "Kubernetes API" server, in other words the IP address of kubernetes-remote-server.example
proxy-url: socks5://localhost:1080 # the "SSH SOCKS5 proxy" in the diagram above
name: default
contexts:
- context:
cluster: default
user: default
name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
user:
client-certificate-data: LS0tLS1CR== # shortened for readability
client-key-data: LS0tLS1CRUdJT= # shortened for readability
通过前面提到的 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
命令在使用 socks 代理时都可以工作,除了kubectl exec
。 kubectl
支持HTTPS_PROXY
和https_proxy
环境变量。这些由支持 SOCKS 的其他程序(例如curl
)使用。因此,在某些情况下,最好在命令行上定义环境变量HTTPS_PROXY=socks5://localhost:1080 kubectl get pods
- 使用
proxy-url
时,代理仅用于相关的kubectl
上下文,而环境变量将影响所有上下文。 - 可以通过使用
socks5h
协议名称(而不是上面显示的更常见的socks5
协议)进一步保护 k8s API 服务器主机名免受 DNS 泄漏。在这种情况下,kubectl
将要求代理服务器(例如 ssh 堡垒)解析 k8s API 服务器域名,而不是在运行kubectl
的系统上解析它。还要注意,使用socks5h
时,https://localhost:6443/api
之类的 k8s API 服务器 URL 不会引用您的本地客户端计算机。相反,它引用代理服务器(例如 ssh 堡垒)已知的localhost
。
清理
通过在运行它的终端上按 CTRL+C
停止 ssh 端口转发进程。
在终端中键入 unset https_proxy
以停止通过代理转发 http 流量。
进一步阅读
上次修改时间:2024 年 2 月 13 日下午 2:14 PST: 修复 mermaid 语法错误 (69706582d4)