K3S/K3D使用
K3S 是 RANCHER 开源的一款轻量级 Kubernetes 实现,其安装简单,内存占用少,全部二进制文件小于 100M。
K3D 是一个简单的 K3S Dockers 封装,可以让 K3S 运行在 Docker 中,简化安装和运行。
在 WSL2 中安装#
在 Windows 中可以通过 WSL2(Windows Subsystem for Linux) 使用 K3S,如果没有升级到 WSL2 需要进行升级。
我用的 Ubuntu,通过 K3S 的官方安装脚本安装后,会报告说无法使用 Systemd 启动服务,因为 WSL2 不支持 Systemd。
手工启动也很简单,运行下面的命令就可以了:
sudo k3s server
避免使用 sudo#
启动后,当使用 k3s 的命令时都需要使用 sudo ,因为启动后生成的配置文件其它用户没有权限读取。
配置文件位置在:/etc/rancher/k3s/k3s.yaml 程序需要读取这个文件才能获取 K8S 的服务地址和密钥以进行 API 调用。
在启动时指定生成的文件权限就可以解决:
sudo k3s server --write-kubeconfig-mode=644
使用 kubectl#
服务启动后,可以使用: k3s kubectl 命令来使用 kubectl 的功能。
如果使用原始的 kubectl 命令,会报告连接不上,因为 kubectl 默认会在 ~/.kube/config 文件中获取 K8S 的配置。
简单的解决可以通过环境变量设置配置文件的地址,设置下面两个环境变量即可:
export KUBERNETES_MASTER=$( grep server: /etc/rancher/k3s/k3s.yaml | cut -c13-)
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
可以将这两个句写到 ~/.bashrc 文件中,就不用每次手工设置了。
ingress controller#
K3S 中默认使用 Traefik 作为 Ingress Controller,但通过 localhost 访问会发现没有程序监听 80 端口。
原因是 WSL 的 Ubuntu 使用的是另外一个IP地址,所以 K3S 并不会监听到 Windows 本机的端口上。
在 Ubuntu 的 shell 中,可以通过下面命令获取到其IP地址:
ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'
然后通过浏览器访问这个IP地址就可以看到 ingress 的相关网站了。
部署本地编译的镜像#
如果在本地编译了镜像,在 K3S 中去使用的话,会发现无法找到镜像。因为 K3S 默认使用 containerd 作为容器运行时,而不是 docker。
网上有资料说可以使用 sudo k3s server –docker 来指定 K3S 使用 docker 作为运行时,就可以使用本地 docker 镜像了。
不过 K3S 官方非常推荐使用 containerd。
另一个办法是将镜像导入到 K3S 中:https://cwienczek.com/2020/06/import-images-to-k3s-without-docker-registry/
还有一个办法是通过在本地启动一个 docker registry 服务,然后把镜像推送到这个服务上,再在 K3S 中使用这个镜像。
官方文档中及其它一些网页都对这种方法有描述:https://thoughtexpo.com/setup-k3d-cluster-for-local-testing-or-development/#local-registry
K3D 甚至专门有生成 docker registry 的参数:https://k3d.io/v5.2.2/usage/registries/
将镜像编译到 K3S 中#
下面这个文章介绍了用 nerdctl 编译镜像的方法,可以使用 K3S 内的 containerd 来进行镜像管理: http://kingsd.top/2021/09/30/nerdctl/
其内部使用 buildkit 进行镜像编译,需要先安装并启动 buildkit:
sudo buildkitd --containerd-worker-addr /run/k3s/containerd/containerd.sock --oci-worker=false --containerd-worker=true
我尝试通过 buildkit 直接编译,但无法将镜像编译到 k8s.io 命名空间内:
sudo ~/buildkit/buildctl build --frontend=dockerfile.v0 --local context=. --local dockerfile=. --output type=image,name=docker.io/image_name:image_tag
使用 nerdctl 通过指定 namespace 参数,可以实现将镜像存储到 k8s.io 命名空间中:
export CONTAINERD_ADDRESS=/run/k3s/containerd/containerd.sock
sudo -E nerdctl -n k8s.io build -t "image_name:image_tag" .
由于我本机使用了 k3s,需要给 nerdctl 指定 containerd 的 socket 地址,所以第一步定义了环境变量,第二步运行命令时因为要使用 sudo 所以指定了 -E 参数带入当前的环境变量。
但在实际编译时,系统显示好像是把镜像输出成 tar 包后,又导入到对应的命名空间中的。