当我们在 Kubernetes 上工作时,有时会遇到这样的场景:我们需要从本地访问一个位于集群内部的 Redis 服务器,但出于安全考虑,这个 Redis 服务并没有直接暴露给外部。不过,集群里有一个 Pod 已经具备了访问这个 Redis 服务器的能力。

利用这个 Pod 作为跳板,我们可以安全地从本地连接到目标 Redis 服务器。由于这个 Pod 本身并不是 Redis 服务,我们不能直接使用 kubectl port-forward。相反,我们需要在 Pod 内部运行一个临时的代理进程。

下面是实现这个目标的详细步骤,可以作为你的操作笔记或博客文章。

借道 Kubernetes Pod 访问内部 Redis 服务器

步骤一:找到你的“跳板” Pod

首先,你需要确定那个能够连接到 Redis 服务器的 Pod 的名称。你可以使用 kubectl 命令列出集群中的所有 Pod:

1
kubectl get pods

从列表中找到你需要的 Pod,例如它的名字是 my-redis-client-pod

步骤二:在 Pod 内部启动一个端口转发代理

由于 Pod 本身没有 Redis 服务在运行,我们需要在它内部创建一个临时的代理。我们将使用 socat 工具来完成这项工作,它能够将流量从一个端口转发到另一个地址。

使用 kubectl exec 命令进入 Pod,并在其中运行 socat。你需要知道 Redis 服务器的实际地址(IP 或域名)和端口。

假设你的 Redis 服务器地址是 10.244.0.5:6379,执行以下命令:

1
kubectl exec -it my-redis-client-pod -- sh -c "socat TCP-LISTEN:6379,fork TCP:10.244.0.5:6379"

命令详解:

  • kubectl exec -it my-redis-client-pod: 这会进入你的目标 Pod 的交互式终端。
  • sh -c "...": 在 Pod 的 shell 中执行后面的命令。
  • socat TCP-LISTEN:6379,fork TCP:10.244.0.5:6379:
    • TCP-LISTEN:6379: 让 socat 在 Pod 内部监听 6379 端口。
    • ,fork: 为每一个新的连接请求创建一个独立的进程,确保可以处理多个连接。
    • TCP:10.244.0.5:6379: 将所有流量转发到 Redis 服务器的实际地址和端口。

重要提示:

  • 请将 10.244.0.5:6379 替换为你实际的 Redis 服务器地址。
  • 此方法要求你的 Pod 镜像中包含 socat 工具。如果缺少,你可能需要考虑使用一个包含此工具的镜像或手动安装。

此命令会持续运行,并在终端中保持阻塞状态。

步骤三:从本地执行端口转发

现在,Pod 的 6379 端口已经“活”了。接下来,你可以从本地将端口转发到这个 Pod。

打开一个新的终端窗口,并运行 kubectl port-forward 命令:

1
kubectl port-forward my-redis-client-pod 6379:6379

命令详解:

  • 第一个 6379: 这是你本地电脑的端口,你可以使用任何空闲端口。
  • 第二个 6379: 这是 Pod 内部我们刚刚用 socat 启动的监听端口。

这个命令会建立一个安全的隧道,将你本地 6379 端口的流量转发到 Pod 的 6379 端口。

步骤四:从本地连接 Redis

最后一步,使用你本地的 Redis 客户端连接到 localhost 和你在上一步指定的端口。

如果你使用的是 redis-cli,只需执行:

1
redis-cli -h 127.0.0.1 -p 6379

或者,如果你使用图形化 Redis 客户端(如 RedisInsight),只需将连接配置为:

  • 主机 (Host): 127.0.0.1
  • 端口 (Port): 6379

现在,你的连接将通过你本地的端口转发隧道,穿过 Pod 内部的 socat 代理,最终到达 Kubernetes 集群内部的 Redis 服务器。

如何结束 socat 代理?

如果你希望停止这个代理,你需要手动结束 socat 进程。

  • 如果 socat 在前台运行:回到运行 socat 的终端窗口,按 Ctrl + C 即可。
  • 如果 socat 在后台运行:你需要进入 Pod,找到并杀死该进程。
  1. 进入 Pod:

    1
    kubectl exec -it my-redis-client-pod -- sh
  2. 查找 socat 进程的 PID:

    1
    ps aux | grep socat

    在输出中,你会看到 socat 进程的 PID(通常在第二列)。

  3. 杀死进程:

    1
    kill <PID>

    <PID> 替换为实际的进程 ID。

通过这种方法,你可以灵活地从本地安全地访问任何在集群内部的资源,而无需将其暴露给公共网络。