Logo
活死人の行知路

IDEA远程开发


📅 | 📝 1225 字
#Go #K8S #Kubernetes

环境

Mac 本地 + 局域网 Ubuntu Server + Docker-in-Docker K8s

  • Mac(本地)
  • Ubuntu Server(宿主机)
  • Docker(在 Ubuntu 上)
  • Docker 里面跑了多个 VM(vm-1, vm-2, vm-3 是 Ubuntu 虚拟机)
  • K8s 集群实际跑在这些 VM 里面

Telepresence 可以让我们在本地运行 Go 程序,但让它“看起来”就像跑在 K8s 集群里一样,能访问集群内的 Service、ConfigMap、Database 等。


第一步:Mac 本地安装 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

或者在 Mac 上执行:

# 使用 brew 安装(推荐)
brew install telepresence

# 验证安装
telepresence version

第二步:配置 kubeconfig(最关键的一步)

步骤 1:在 Ubuntu 宿主机暴露 6443 端口(重要)

由于 vm-1 是 docker-compose 启动的容器,请修改 docker-compose.yml

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

考虑到我的环境, Ubuntu 宿主机上没有 ~/.kube/config,kubeconfig 在 其中一个 VM(通常是 master 节点,如 vm-1)里面。

步骤 2:在 VM 中找到并复制 kubeconfig

先进入我的 K8s master VM(假设是 vm-1):

# 在 Ubuntu 宿主机上执行,进入 vm-1
docker exec -it vm-1 bash

进入 VM 后执行:

# 在 vm-1 容器内执行
cat ~/.kube/config

如果有内容,复制出来(推荐用下面方式直接复制到 Ubuntu 宿主机):

方式 A(推荐):从 VM 直接复制到 Ubuntu 宿主机

Ubuntu 宿主机 新开一个终端,执行:

# 把 vm-1 里的 kubeconfig 复制到 Ubuntu 宿主机
docker cp vm-1:/root/.kube/config ~/k8s-remote-config.yaml

方式 B:手动复制(如果 docker cp 不方便)

在 vm-1 里面:

cat ~/.kube/config

复制内容,然后在 Ubuntu 宿主机上:

cat > ~/k8s-remote-config.yaml << 'EOF'
# 把复制的内容粘贴在这里
EOF

步骤 3:把 config 复制到 Mac 并修改

Ubuntu 宿主机 执行:

# 把文件复制到你的 Mac
scp ~/k8s-remote-config.yaml youruser@你的Mac的IP:~/.kube/configs/remote-dind.yaml

或者在 Mac 上执行(更直接):

# 在 Mac 执行
mkdir -p ~/.kube/configs
scp youruser@192.168.x.x:~/k8s-remote-config.yaml ~/.kube/configs/remote-dind.yaml

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

步骤 4:修改 kubeconfig 中的 server 地址

Mac 上编辑文件:

vim ~/.kube/configs/remote-dind.yaml

找到 server: 这一行,必须改成 Ubuntu Server 的局域网 IP

server: https://192.168.x.x:6443     # ← 改成 Ubuntu Server 的 IP

(注意:因为 K8s API Server 暴露在 Ubuntu 宿主机上)

在 cluster: 下面添加一行 insecure-skip-tls-verify

clusters:
- cluster:
    server: https://192.168.1.7:6443
    insecure-skip-tls-verify: true     # ← 加上这一行(关键)
  name: remote-dind

删除下面这一行(如果存在):

certificate-authority-data: xxxxxxxx(很长的一串)

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

- 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 这两行,保留原来的内容就可以。

步骤 5:设置并测试

验证(在 Ubuntu 宿主机执行):

$ curl -k https://127.0.0.1:6443/version
{
  "major": "1",
  "minor": "35",
  "emulationMajor": "1",
  "emulationMinor": "35",
  "minCompatibilityMajor": "1",
  "minCompatibilityMinor": "34",
  "gitVersion": "v1.35.0",
  "gitCommit": "66452049f3d692768c39c797b21b793dce80314e",
  "gitTreeState": "clean",
  "buildDate": "2025-12-17T12:32:07Z",
  "goVersion": "go1.25.5",
  "compiler": "gc",
  "platform": "linux/amd64"
}

如果返回 K8s 版本信息,则成功。

在 Mac 上执行:

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

kubectl get nodes
NAME   STATUS   ROLES           AGE   VERSION
vm-1   Ready    control-plane   60m   v1.35.0
vm-2   Ready    <none>          58m   v1.35.0
vm-3   Ready    <none>          57m   v1.35.0

kubectl get pods -A

第三步:在 K8s 集群中安装 Traffic Manager

Mac 上执行(会通过 kubeconfig 自动部署到远程 K8s):

# 推荐方式
telepresence helm install

# OR
telepresence helm install --namespace ambassador

# 如果想安装到 default namespace(更简单):
telepresence helm install --namespace default

解释

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

第四步:连接 Telepresence

# 基础连接
telepresence connect

# 推荐命令(适合你的 DinD 环境)
telepresence connect --docker --manager-namespace ambassador

成功后会显示类似:

Connected to context ...
Telepresence proxy: ON

第五步:使用 Telepresence测试拦截(Intercept)你的服务

# 查看当前集群中可以拦截的服务
telepresence list --docker

# 拦截你的 Golang 服务(把 go-app 替换成你 Deployment/Service 的名称)
telepresence intercept go-app --port 8080:8080 --docker

拦截成功后,你就可以:

  • 在 Mac 本地用 GoLand / IDEA 直接运行或 Debug 你的 Go 项目(端口使用 8080)。
  • 本地代码可以访问集群内的其他 Service、数据库等。
  • 集群内的其他 Pod 也可以通过 Service 名称访问到你本地的代码。

完整常用命令

# 连接
telepresence connect --docker --manager-namespace ambassador

# 查看状态
telepresence status --docker

# 列出可拦截服务
telepresence list --docker

# 拦截服务
telepresence intercept <service-name> --port 8080:8080 --docker

# 取消拦截
telepresence leave go-app --docker

# 断开连接
telepresence quit --docker

常用命令总结

telepresence connect                    # 连接
telepresence intercept <service> --port 8080:8080   # 拦截
telepresence list                       # 查看可拦截服务
telepresence status                     # 查看状态
telepresence quit                       # 断开连接
telepresence uninstall --everything     # 完全卸载(清理 Traffic Manager)

针对 Docker-in-Docker 的常见问题处理

  1. 网络问题:如果连接后无法解析 Service DNS,尝试:

    telepresence connect --docker   # 使用 Docker 模式的 daemon(有时更稳定)
    
  2. 权限问题:确保远程 K8s 中的用户有足够权限(cluster-admin)。

  3. 端口冲突:Telepresence 默认会接管本地 DNS,如果冲突可以加参数:

    telepresence connect --dns 8.8.8.8
    

请按顺序执行后,告诉我以下信息,我继续帮你排查:

  1. kubectl get nodes 的输出
  2. 执行 telepresence helm install 时的完整输出(尤其是是否有报错)
  3. telepresence connect 的完整输出
  4. 你的 K8s 是 kindk3sk3d 还是其他方式部署的?

把输出贴出来,我可以给你更针对性的修复命令。

SSH远程部署

  1. 文件同步

以 MacOS 版 IDEA 为例:点击 IDEA 的 [Settings] => [Build, Excution, Deployment] => [Development]:

  1. 输入服务器名称

  1. 填写服务器的基本信息如:ip,用户名以及密码

  1. 将本地的项目文件路径和远程服务器上的某一路径进行映射



真实环境

  • Mac(本地)
  • Ubuntu Server(宿主机)
  • Docker(在 Ubuntu 上)
  • Docker 里面跑了多个 VM(vm-1, vm-2, vm-3 是 CentOS 虚拟机)
  • K8s 集群实际跑在这些 VM 里面

所以 Ubuntu 宿主机上确实没有 ~/.kube/config,kubeconfig 应该在 其中一个 VM(通常是 master 节点,如 vm-1)里面。





第五步:安装并使用 Telepresence 在 Mac 上:

# 安装
brew install telepresence

# 安装 Traffic Manager(通过 Mac 安装到远程 K8s)
telepresence helm install --namespace ambassador

➜  telepresence helm install --namespace ambassador

Traffic Manager installed successfully

# 连接(强烈推荐 --docker 模式)
telepresence connect --docker --manager-namespace ambassador

➜  ~ telepresence connect --docker --manager-namespace ambassador
 ✔ Launched Daemon                                                                                                         21.0s
 ✔ Connected to context kubernetes-admin@kubernetes, namespace default (https://192.168.1.7:6443)

连接成功后:

# 查看服务
telepresence list

➜  ~ telepresence list
No Workloads (Deployments, StatefulSets, ReplicaSets, or Rollouts)

# 拦截你的 Go 服务(把 go-app 换成你的 Service 名称)
telepresence intercept go-app --port 8080:8080 --docker

然后在 Mac 的 GoLand / IDEA 中直接运行你的项目即可调试。


清理命令(需要时使用)

telepresence quit --docker
telepresence uninstall --everything

# 删除端口转发容器
docker rm -f k8s-api-forward

 kubectl apply -f go-k8s-app.yaml --kubeconfig=/Users/$(whoami)/.kube/configs/remote-dind.yaml --validate=false
deployment.apps/go-k8s-app created
service/go-k8s-app created
echo $KUBECONFIG
kubectl config current-context
/Users/finnley/.kube/configs/remote-dind.yaml
kubernetes-admin@kubernetes

一键强制替换(最符合“销毁重建”语义)

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

方法二:先删后建(最稳妥的常规操作) 如果你想看清每一步,或者想等资源彻底清理干净再创建,可以分两步走:

  1. 销毁(根据文件定义删除):
kubectl delete -f go-k8s-app.yaml

重建(再次应用):

kubectl apply -f go-k8s-app.yaml

检查是否成功:

kubectl get pods
kubectl get svc go-k8s-app

步骤 2:用 Telepresence 拦截

# 1. 连接 Telepresence
telepresence connect --docker --manager-namespace ambassador

# 2. 拦截(把本地 8080 端口映射到集群的 go-k8s-app 服务)
telepresence intercept go-k8s-app --port 8080:8080 --docker

成功后,你会看到提示说拦截成功。

步骤 3:在本地 Mac 运行你的 Go 项目 现在在 GoLand / IDEA 中直接运行你的 Go 项目,监听端口 8080。 此时:

你本地运行的 Go 代码 = 集群中的 go-app 服务 集群内其他服务可以通过 go-app:8080 访问到你本地的代码 你本地代码也可以通过 Service 名称访问集群内的其他服务(如数据库)

常见问题解答

go-app 是什么? 它是你给这个服务的名字,你可以改成 my-go-service、just-do-it 等,只要前后一致即可。 端口 8080:8080 是什么意思? 左边的 8080:本地 Mac 的端口 右边的 8080:K8s Pod/Service 的端口

我不想先部署 nginx 占位,有没有更简单的方法? 有,但第一次使用推荐上面这种方式,更稳定。


**✅ 问题已定位**。

虽然 Pod 已经 Running,但 **Telepresence 无法识别 Deployment 中的端口**。这是 Telepresence 比较常见的严格匹配问题。

---

### **最终修复方案(请严格按顺序执行)**

#### 1. 修改 `go-k8s-app.yaml`(加上端口名称)

请**完整替换**为以下内容:

```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
        image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: http          # ← 必须加上 name
          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

2.重新部署

# 清理旧的
kubectl delete deployment go-k8s-app --force --grace-period=0

# 重新部署
kubectl apply -f go-k8s-app.yaml

3.验证 Deployment 端口配置

kubectl get deployment go-k8s-app -o yaml | grep -A 10 "ports:"

4.执行 Telepresence 拦截(使用端口名称)

telepresence quit --docker 2>/dev/null || true
telepresence connect --docker --manager-namespace ambassador

# 关键命令:使用端口名称
telepresence intercept go-k8s-app --port 8080:http --docker

请现在执行上面 1~4 步,然后把以下输出贴给我:

  1. kubectl get pods -l app=go-k8s-app 的输出
  2. telepresence intercept go-k8s-app --port 8080:http --docker 的完整输出

额外说明

  • 你的本地 Go 服务需要监听 8080 端口(左边的数字是本地端口)。
  • 如果你本地想用 4311 端口,就用 --port 4311:http

我们这次应该能成功。把输出发给我。


清理

1. 先清理旧的 Deployment/Service(重要)

# 1. 清理旧资源
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


# 2. 部署新资源
kubectl apply -f go-k8s-app.yaml

# 3. 等待 Pod 就绪
kubectl get pods -l app=go-k8s-app -w

# 4. Telepresence
telepresence connect --docker --manager-namespace ambassador
telepresence intercept go-k8s-app --port 8080:80 --docker

部署

kubectl apply -f go-k8s-app.yaml

检查是否正常:

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

3.Telepresence 操作

# 重新连接(保险起见)
telepresence quit --docker 2>/dev/null || true
telepresence connect --docker --manager-namespace ambassador

# 拦截服务(关键:端口映射要正确)
telepresence intercept go-k8s-app --port 8080:80 --docker

解释端口映射

  • 8080:80 = 本地 Mac 端口 8080 : K8s 容器端口 80

4.在 Mac 本地启动你的 Go 服务

重要:现在在 GoLand / IDEA 中启动你的 Go 项目:

  • 把你的 Go 服务监听端口改为 8080(推荐),或者改成其他端口(如 3000),然后对应修改上面的 --port 3000:80

启动后,在浏览器访问 http://localhost:8080 测试是否正常。



请按顺序执行上面流程,然后告诉我以下结果:

  1. kubectl get pods -l app=go-k8s-app 的输出
  2. telepresence intercept ... 的完整输出

有任何错误请直接贴出来,我马上调整。