Logo
活死人の行知路

Telepresence实践指南


📅 | 📝 813 字
#Go #Kubernetes

1概述

复杂嵌套环境架构

  • Mac(本地开发机)
  • Ubuntu Server(宿主机)
  • Docker(在 Ubuntu 上运行)
  • Docker 内部运行多个 VM(vm-1, vm-2, vm-3,承载 K8s 节点)
  • K8s 集群实际运行在上述 VM 网络内

Telepresence 的核心作用

Telepresence 能够跨越上述多层网络边界,将本地 Mac 运行的 Go 程序“无缝接入”到远端 K8s 集群中。本地代码能够直接使用集群内 DNS 访问远端 Service、ConfigMap、Database,同时集群内的流量也能被劫持(Intercept)到本地进程,实现本地闭环。

前置条件:要使用 intercept 功能,K8s 集群中必须存在一个对应的 Service(即使底层是一个轻量级的占位 Pod)。


2Mac 本地安装 Telepresence

# 1. Ensure that no old binary exists. This is very important because Apple Silicon macs track the executable's
# signature and just updating it in place will not work.
sudo rm -f /usr/local/bin/telepresence

# 2. Download the binary.
sudo curl -fL https://github.com/telepresenceio/telepresence/releases/latest/download/telepresence-darwin-arm64 -o /usr/local/bin/telepresence

# 3. Make the binary executable:
sudo chmod a+x /usr/local/bin/telepresence

3配置 kubeconfig(打通网络的核心)

3.1暴露 API Server 6443 端口

如果控制面(master 节点,如 vm-1)是作为容器运行的,必须在 docker-compose.yml 中将其 6443 端口映射到 Ubuntu 宿主机:

services:
  vm-1:          # 你的 master 节点
    # ... 你的原有配置
    ports:
      - "6443:6443"     # ← 增加这一行,把 vm-1 的 6443 暴露到宿主机

3.2提取内层 VM 的 kubeconfig

进入 K8s master 节点,将配置文件复制到 Ubuntu 宿主机:

docker cp vm-1:/root/.kube/config ~/k8s-remote-config.yaml

3.3转移配置至 Mac 并修改

将提取出的配置拷贝至 Mac 本地,在 Mac 上执行:

mkdir -p ~/.kube/configs
scp ubuntu@192.168.1.7:~/k8s-remote-config.yaml ~/.kube/configs/remote-dind.yaml

3.4修改 kubeconfig 中的 server 地址

关键修改:编辑 ~/.kube/configs/remote-dind.yaml

  1. server 的 IP 修改为 Ubuntu 宿主机的局域网 IP
server: https://192.168.x.x:6443     # ← 改成 Ubuntu Server 的 IP
  1. 删除 certificate-authority-data 字段(如果存在)。
certificate-authority-data: xxxxxxxx(很长的一串)
  1. 增加 insecure-skip-tls-verify: true 绕过证书校验。
clusters:
- cluster:
    server: https://192.168.1.7:6443
    insecure-skip-tls-verify: true     # ← 加上这一行(关键)
  name: remote-dind

修改前后的对比示例,修改前(大概长这样):

- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0t...
    server: https://10.96.0.1:6443

修改后(应该变成这样):

- cluster:
    server: https://192.168.1.7:6443
    insecure-skip-tls-verify: true

不需要修改 client-certificate-data 和 client-key-data 这两行,保留原来的内容就可以。

3.5环境生效与测试

在 Mac 环境中挂载配置并验证:

export KUBECONFIG=~/.kube/configs/remote-dind.yaml
kubectl get nodes

(为了后续操作更方便,建议将 export KUBECONFIG=... 写入 ~/.zshrc 实现永久生效。)

echo 'export KUBECONFIG=~/.kube/configs/remote-dind.yaml' >> ~/.zshrc
source ~/.zshrc

4安装 Traffic Manager

Telepresence 需要在 K8s 集群侧安装一个流量管理器。在 Mac 上执行以下命令(会自动通过 kubeconfig 部署到集群):

# 1. 尝试卸载可能存在的历史遗留
telepresence uninstall --everything 2>/dev/null || true

# 2. 安装到 ambassador 命名空间 (官方推荐环境隔离做法)
telepresence helm install --namespace ambassador

成功后会提示:Traffic Manager installed successfully

解释

  • telepresence helm install:在你的 K8s 集群中安装 Telepresence 的核心组件(Traffic Manager)。
  • --namespace ambassador:把组件安装到 ambassador 这个 namespace。
    • ambassador 不是固定的,只是官方推荐的名称(因为 Telepresence 以前属于 Ambassador 公司)。
    • 你也可以改成 telepresencedefault,但推荐使用 ambassador

5连接集群

使用标准命令建立从 Mac 到 K8s 的隧道连接:

telepresence connect --manager-namespace ambassador

成功后会提示已连接到相应的 context 和 namespace。


6部署 Go 空服务(占位锚点)

为了让 Telepresence 有目标可以注入 Envoy 代理,我们需要在 K8s 中部署一个轻量级的“占位”应用。针对国内网络环境,推荐使用华为云 SWR 的 Nginx 镜像。

创建 go-k8s-app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-k8s-app
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: go-k8s-app
  template:
    metadata:
      labels:
        app: go-k8s-app
    spec:
      containers:
        - name: go-k8s-app
          # 华为云 SWR 公开加速节点,秒拉官方 nginx:alpine
          image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:alpine
          ports:
            - containerPort: 80   # Nginx 的真实监听端口
              name: http
              protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: go-k8s-app
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: go-k8s-app
  ports:
    - port: 8080         # 前台分机号:集群内部其它服务访问本服务所使用的端口
      targetPort: http
      name: http

部署

确保在包含 go-k8s-app.yaml 文件的本地Mac目录下执行 apply:

kubectl apply -f go-k8s-app.yaml --validate=false

或者使用下面这种方式:

# 使用下面这条命令部署(加上 --kubeconfig 参数最稳)
kubectl apply -f go-k8s-app.yaml --kubeconfig=/Users/$(whoami)/.kube/configs/remote-dind.yaml --validate=false
  • --validate=false 表示关闭验证。

查看部署结果

在Mac上执行:

kubectl get pods
kubectl get svc go-k8s-app
kubectl get pods -l app=go-k8s-app

预期结果会看到一个 Pod 正在运行(初始是 nginx),和一个 Service。输出结果示例:

➜ kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
go-k8s-app-854f9d975b-cq792   1/1     Running   0          17s

➜ kubectl get svc go-k8s-app
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
go-k8s-app   ClusterIP   10.104.98.192   <none>        8080/TCP   33s

➜ kubectl get pods -l app=go-k8s-app
NAME                          READY   STATUS    RESTARTS   AGE
go-k8s-app-854f9d975b-cq792   1/1     Running   0          37s

7执行流量拦截 (Intercept)

确认服务就绪后,执行流量劫持。假设你本地(Mac)的 Go 服务监听在 4306 端口:

标准的两段式拦截流程(推荐):

# 1. 显式连接(消除隐式连接警告,如果上面执行过这里则不用重复执行)
telepresence connect --manager-namespace ambassador

# 2. 执行纯净拦截,禁用文件挂载(消除 Error 报错)
# 语法结构:telepresence intercept <服务名> --port <本地项目端口>:<集群Service对内暴露的端口> --mount=false
telepresence intercept go-k8s-app --port 4306:8080 --mount=false

拦截成功后:

  • 在 IDE (GoLand/VSCode) 中启动监听在 4306 的 Go 项目。
  • K8s 集群内发往 go-k8s-app:8080 的请求,将在 Service 层被拦截,并直接路由到你本机监听 4306 的代码中。

端口调整提示:如果你的本地代码改为了其他端口(例如 8080),只需先退出当前拦截 (telepresence leave go-k8s-app),再重新执行拦截命令即可:telepresence intercept go-k8s-app --port 8080:8080全程不需要修改 YAML 文件内容

异常排障补充

如果之前连接过可能出现connector.CreateIntercept: name resolver error: Unauthorized问题,可以采用彻底杀掉本地幽灵进程方式,让 Telepresence 把本地残余的网络代理和缓存全部清空:

# 断开当前连接
telepresence quit

# 强制杀掉所有后台 Daemon 进程
telepresence quit -s

# 重新建立纯净连接并拦截
telepresence connect --manager-namespace ambassador
telepresence intercept go-k8s-app --port 4306:8080 --mount=false

⚠️ 避坑警告:如果执行拦截时曾出现 Volume Mount Error: remote volume mounts are disabled: sshfs is not installed on your local machine强烈建议不要尝试安装 macFUSE 和 sshfs。在 Apple Silicon (M系列芯片) 的 Mac 上,这会触发系统底层的内核安全机制,需要降低系统安全级别,并极易引发无限弹出 System Extension Blocked 的死循环。 解决方案:直接在 intercept 命令尾部加上 --mount=false 即可完美消除报错,保持系统安全且不影响任何网络调试功能。


8运维、重置与清理(排障核心)

在反复测试或遇到诸如 Unauthorizedalready exists 等幽灵状态报错时,必须使用以下手段彻底净化环境。

8.1强刷 K8s 资源状态

如果你修改了 YAML 文件但 Kubernetes 提示 unchanged,或 Pod 卡在错误状态,直接强制重置:

kubectl replace --force -f go-k8s-app.yaml

8.2终极清理脚本(解决各类本地幽灵状态)

保存为 cleanup-telepresence.sh。此脚本加入了云端登出与强杀进程机制,能彻底解决同一个环境反复测试导致的缓存冲突。

#!/bin/bash
echo "=== 开始终极清理 Telepresence 状态 ==="

# 1. 退出云端登录(彻底解决 Unauthorized 报错)
echo "[1/4] 清除云端认证缓存..."
telepresence logout 2>/dev/null || true

# 2. 释放拦截并强制断开守护进程
echo "[2/4] 断开连接并强杀后台守护进程..."
telepresence leave --all 2>/dev/null || true
telepresence quit -s 2>/dev/null || true
# 兜底:强杀所有残存的僵尸进程
killall telepresence 2>/dev/null || true

# 3. 卸载集群侧组件
echo "[3/4] 卸载 K8s 集群内的 Traffic Manager..."
telepresence helm uninstall --namespace ambassador 2>/dev/null || true
telepresence uninstall -a 2>/dev/null || true

# 4. 清理占位资源
echo "[4/4] 清理 K8s 业务测试资源..."
kubectl delete deployment go-k8s-app --force --grace-period=0 2>/dev/null || true
kubectl delete service go-k8s-app --force --grace-period=0 2>/dev/null || true

echo "清理完成!您的环境已回归绝对纯净状态。"

8.3深度环境物理抹除(核弹级重置)

如果执行了清理脚本后依然存在诡异网络问题,请执行以下物理抹除命令,销毁 Mac 本地的所有持久化缓存和日志:

# 1. 强制删除整个控制面命名空间
kubectl delete namespace ambassador --force --grace-period=0 2>/dev/null || true

# 2. 抹除 Mac 本地的状态配置、缓存和日志
rm -rf ~/Library/Application\ Support/telepresence
rm -rf ~/Library/Logs/telepresence
rm -rf ~/.cache/telepresence

echo "本地物理缓存与日志已全数抹除。"

9常用命令速查备忘

# 建立纯净连接
telepresence connect --manager-namespace ambassador

# 查看当前连接状态与可拦截的工作负载
telepresence status
telepresence list

# 执行拦截 (本地应用端口 : 远端Service暴露端口),并禁用挂载引擎
telepresence intercept <service-name> --port 4306:8080 --mount=false

# 取消特定拦截
telepresence leave <service-name>

# 优雅断开本地隧道连接
telepresence quit