K8s内网集群搭建与服务暴露
以后要研究 MLOps 了,深度依赖 K8s。之前没怎么用过实验室的两台服务器,所以打算搭建一个 K8s 集群,用于实验。
一、机器清单
两台大服务器,大概 250G 内存;另外自己安了个人用的 Ubuntu 20.04,内存 16G。
三台机器都在内网,而我又是长期外派,所以在自己的服务器上配了个 frpc,通过腾讯云的 frps 来 ssh 访问。
另外两台大机器未配置内外穿透。同时,小机器不配访问两台大机器的权限。就算这台小机器被黑了,大机器也是安全的。
同时,为了保证 master 不断联,将 frpc 设为 systemd service,开机自启。
以及使用 hdu-cli ,用于登录校园网。同样配置为 systemd service,开机自启。
二、K3s 集群搭建
选用的是 K3s,轻量,安装简单。以后有需要再换成 KubeSphere 一类的。
将小机器作为 master,两台大机器作为 worker。
官网教程很详细:K3s 快速入门指南
这里也再贴一下:
- 在小机器上安装 K3s master
curl -sfL https://get.k3s.io | sh -
- 在小机器上获取 token
cat /var/lib/rancher/k3s/server/node-token
- 在两台大机器上上安装 K3s worker,分别执行:
- K3S_URL 换成服务器的内网 IP 地址
- K3S_TOKEN 换成上一步获取的 token
curl -sfL https://get.k3s.io | K3S_URL=https://master-ip:6443 K3S_TOKEN=token sh -
上面三步做完后,就能在小机器上访问 K8s 集群了。
三、Kubectl Alias
K8s 命令太长了,可以用 kubectl alias 来缩短命令。
为什么用这个库?因为它 Star 最多~。
四、多集群管理 && 集群暴露到外网
4.1 多集群切换
好巧不巧,我有好几个 K8s 集群(其他几个是性能很弱的测试集群,甚至本地装的 Kind 也算哈哈哈。不过以后有了这个实验室集群,以后也不用自己电脑跑 Kind 耗性能了)。
所以需要一个多集群管理工具。工具如下:
- 使用 kubectx 来切换集群
- 使用 kubens 来切换命名空间
建议使用 krew 以 Kubectl 插件的形式来安装上面两个工具。
这里有个教程:使用 kubectx 和 kubens 快速切换
先别急着安装和切换,我们现在还没有多集群呢!!!
4.2 怎么把集群信息加到自己电脑上
K8s 用的是 ~/.kube/config
来存储集群信息的。所以我们只需要把集群信息加到这个文件里就行了。
步骤:
- 在小机器上获取集群信息
cat /etc/rancher/k3s/k3s.yaml
复制以上信息
- 集群信息添加到自己电脑里
在自己电脑的 ~/.kube/config
文件夹里,新建一个文件,例如 lab.yaml
,把刚才复制的信息粘贴进去。
注意,配置信息里有一项是 server
, 默认是 http://127.0.0.1:6443
。
但 127 肯定是访问不了的,需要改成小机器后通过 frp 穿透出来的域名和端口。(建议换个端口,不要用 6443,少被扫描更好一点)
(因为几年前懵懂的时候,在自己学生机上开了 Docker 的 2379 远程,结果被扫描到了,被挖矿了)
- 合并集群信息
自己电脑本来可能是有集群信息的,所以需要合并,可以用 kubecm 工具。
安装好 kubecm ,直接 kubecm add -f lab.yaml
就行了。
这里有一篇教程:使用 kubecm 合并 kubeconfig
- 切换集群
现在再运行 k ctx
就能看到多个集群了,可以用 k ctx lab
来切换到 lab 集群。
五、将服务器上的 K8s 集群的服务暴露到外网
做完以上步骤,我们就能随时在自己电脑上访问 lab 集群了。
虽然两个大机器,也就是 Worker 是完全在内网里的,没有任何穿透。
但是,因为我的 mac 和小机器(master)通过 frp 穿透了 6443 端口,所以我可以操控 master,然后三个 K8s 节点再完全通过内网通信。
5.1 基本思路
还是为了安全,我不打算在 Worker 上配任何穿透,完全在内网里(但是它们可以访问外网)。
K8s 里有个 Ingress ,类似于传统的 Nginx 反向代理,可以把外网的请求转发到内网的服务。
K3s 有个自带的 Ingress Controoler, Traefik,端口是 80。
假设我有个服务,端口是 8080,我想让外网能访问到它,那么我就需要在 K8s 里创建一个 Ingress 对象,把 80 端口转发到 8080 端口。
同时为了隔绝多个服务,可以使用域名来区分。 即,把 svc1.example.com
的请求转发到 8080
端口,把 svc2.example.com
的请求转发到 8081
端口。
5.2 穿透
[k3s-ingress-web]
type = tcp
local_ip = 127.0.0.1
local_port = 80
remote_port = 12345
大概这么配一下就行:这样就能
- 用户访问
http://svc1.example.com:12345
- 被 frp 转发到集群的
80
端口 - 被 Traefik 根据配置的规则,转发到不同的端口。比如这里 svc1 是
8080
。
(当然,这里的 12345
是写博客时随便写的端口,不是实际在用的)如果你的公网服务器 80
端口没被占用,可以直接用 80
端口,会更好看。
这样的好处在于,新增服务,不需要改动 frp,只需要在 K8s 里新增一个 Ingress 对象就行了,然后根据不同的域名,转发到不同的 service 。
(实际配的时候很艰辛,一直在调,试了根据 prefix 转发 service,根据域名,还配了中间件。以及试了各种 frp 的转发方式。怎么都搞不好,完全无法理解。后面才意识到,是不是自己泛域名没配。然后看了一下DNS控制台,发现很久以前把泛域名配到了阿里云CND的CNAME,所以最开始用域名作为Router Rule怎么都不行。。。)
5.3 网络拓扑
5.4 安全性分析(图一乐)
我其实对安全这块不太懂,但身边有些比较牛逼的 “黑客”, 所以耳濡目染(不得不防),开玩笑哈哈哈。
- 端口开放: 只暴露出了两个端口,一个用于命令行访问 K8s,一个用于访问 Ingress。
- 网络隔离: 两个大机器,完全在内网里,没有任何穿透。
- 攻击分析: 就算 Master 被入侵,也只能通过 K8s 访问到 Worker,用一下服务器资源。无法控制两台大机器。因为我压根没在 Master 里配置连两台大机器的SSH连接信息,连公钥都没有。平时直接用 Mac 将小机器作为跳板机免密登录大机器。
六、再进一步优化访问
可以看到,我上面那张拓扑图,有部分打码了。
是因为,我服务器的 80
端口已经被占用了,所以 frp
就分配了其他端口。
这就导致,访问 Inrgess 的时候,需要带上端口号。
所以解决思路是,在搭建了 frps
的服务器上,再配一层反代,例如将 *.k3s.example.com
(这个*代表svc)的请求全部转发给 frps
的 12345
端口。
相应的,Ingress 的域名路由规则,也要从 svc1.example.com
改成 svc1.k3s.example.com
。
(上图打码的就是这层反代,打算用 Caddy
,也可以用 Nginx
,目前还没搞)
七、有个东西忘写了
因为我的 master 是个小机器,所以给它配个"尽量不调度"的污点。(为什么不配"不调度"呢,因为我怕那两台大机子网络出问题失联了哈哈哈,这时候我还可以用小机子勉强测试一下)
记得把下面的 master-node
改成你的 master 节点名字。
可以用 kgno
查看所有节点名字。
kubectl taint nodes master-node node-role.kubernetes.io/master:PreferNoSchedule #master尽量不调度
有这些调度选项可以选:
- NoSchedule: 一定不能被调度
- PreferNoSchedule: 尽量不要调度
- NoExecute: 不仅不会调度, 还会驱逐Node上已有的Pod示例
去除污点可以用这个:
kubectl taint nodes master-node node-role.kubernetes.io/master- #允许master调度