通过 VS Code 优雅地编辑 Pod 内的代码(非 NodePort)
1. 概述
今天聊点啥呢,话说,你有没有想过怎样用 VS Code 连上 K8s 集群内的某个 Pod,然后直接更新 Pod 内的代码?
当我听到这个需求的时候,第一反应是在 Pod 内搞一个 sshd,然后 NodePort 方式暴露 Pod,接着用 VS Code 的某个远程调试插件。当然我没有具体用过 VS Code 远程开发的能力,不过我用过 Goland 里类似的功能,总之这些 IDE 一定有办法访问远程的文件系统,通过一些 FTP/SFTP 之类的协议完成文件传输/同步的过程。
再进一步,如果将这个功能做到产品里,那用 NodePort 就有点 low 了,毕竟暴露一堆的端口,很多场景下是不允许的,所以下一步自然就想到了 Ingress。
不过 Ingress 只能转发 http/https 或者 TCP/UDP 流量,你发现没有,这里其实不支持 ssh/ftp 这类协议……
行,今天就聊聊怎样在不暴露一堆 NodePort 的前提下,通过 VS Code 更新 Pod 内的代码。
2. NodePort 方式
NodePort 方式暴露 Pod 的 sshd 服务是最容易被想到的方案,这种方式在逻辑上没有啥问题,NodePort 将 Pod 的 ip:pod
映射到 Nodes 的特定端口,从而实现 TCP 流量转发(SFTP 协议下面是 SSH,SSH 协议在传输层用的是 TCP)。
在这个方案下,每个用户最后会占用一个 Nodes 层面的端口。换言之,单用户,本地测试开发,没问题。但是作为一个产品,部署上线,那你要么做好和公司的运维、安全团队辩论的准备,要么另寻出路。
3. Ingress 方式
为了解决 NodePort 方式占用多端口的问题,其实很容易往 Ingress 方向考虑,尽管 Ingress 一般用在 http 负载的代理上。不过大家可能会进一步想到 Ingress 配置的时候,不是可以根据 host 路由嘛。那是不是在客户端 hosts 里配置一堆的 域名/IP 映射关系,然后在 Ingress 里根据 host 区分用户,从而实现不同用户的流量转发到不同 Pod 的目的?
再往前想一步,其实 host 是 http 流量转发的时候用到的规则,也就是在 http 请求头里的属性,这个不能用在非 http 流量上。
那么往 TCP 流量代理的方向去考虑呢?比如 Traefik 实现的 Ingress Control 中支持类似如下配置:
|
|
是不是看起来挺和谐的?TCP 流量,根据 host 信息区分流量。
然而这个 SNI 信息是 SSL 协议里用到的,也就是用到 TLS 才能用这个特性,SSH 协议其实并不使用 TLS,换言之,这个字段配置不配置,对 SSH 流量来说,没啥用。
对于 TCP 包来说,包头有 IP 和 Port 信息,并没有 host,所以代理层是无法区分网络流量来自哪个用户的,自然也就不能相应转发到不同的 Pod 中去。
那么有没有支持 SSH 协议的 Ingress Control 实现呢?我瞟了下,没找到。如果你找到了,可以在评论区告诉我。
4. 救命稻草
Ingress 这条路走不通了,其实就是 TCP 没有 host 字段,回过头来我们还是要依赖 http 协议的 host 属性。不过文件传输协议里可不包含 http,用 http 协议转发“远程调试”这类流量,想想,应该没有人去这样实现。
除了 Ingress 这个口子外,和 K8s 交互的另外一个入口就是 apiserver 了,就像 kubectl 可以用 exec/logs 之类的子命令和 Pod 建立长连接一样,或许有人会做一些插件,通过和 apiserver 交互实现 Pod 内文件的操作呢?
OK,直接说答案:在 VS Code 里装上 Kubernetes
和 Dev Containers
两个插件:
然后就能直接 Attach 进 Pod 了:
如上图,找到你放代码的 Pod,然后右键 - “Attach Visual Studio Code”,接着会弹出一个新的 VS Code:
然后你就可以像操作本地文件系统一样,在这个新的 VS Code 里点击 Open Folder 来打开你在 Pod 内的某个目录了。如下图,我这里在容器内放了一个 gopool 项目的代码,效果是这样的:
还不错吧,你可以开始愉快地开发了。
5. 其他
不好,中午吃多了,犯困了。就这样吧,留点东西下次再发。
我知道你还好奇这2个插件的工作原理;我也知道这套方案要落地还差了权限控制(RBAC 控制一个用户只能访问自己名下的 Pods);我也知道你要睡午觉了……
Anyway,关注公众号“胡说云原生”,咱“明天”见。