之所以叫做 K3s 是因为希望安装的 Kubernetes 在内存占用方面只是一半的大小,而一半大的东西就是一个 5 个字母的单词,简写为 K3s。
K3s 特点
- 轻量级且完整:K3s 是由 Rancher Lab 开源的轻量级 Kubernetes。K3d 完美继承了 K3s 的简单、快速和占用资源少的优势,镜像大小只有 100 多 MB,启动速度快,支持多节点集群。虽然 K3s 对 Kubernetes 进行了轻量化的裁剪,但是提供了完整的功能,像 Istio 这样复杂的云原生应用都可以在 K3s 上顺利运行。
- 支持多架构:因为 K3s 本身应用场景主要在边缘侧,所以支持的设备和架构很多,如 ARM64 和 ARMv7 处理器。很多老旧 PC 和树莓派这样的设备都可以拿来做成 K3s 集群,为本地研发测试燃尽最后的生命。
- 单二进制文件打包:K3s 把 Kubernetes 相关的组件,比如
kube-apiserver、kube-controller-manager都打包到同一个二进制文件里面,这样的话,只需要启动这个文件就可以快速启动对应的组件。 - 灵活的存储后端:使用基于 SQLite3 的默认存储机制,同时支持使用 etcd3、MySQL 和 PostgreSQL 作为存储机制。
- 默认安全:在 K3s 中有一个默认的证书管理机制(默认一年有效期),也有一个可以轮转证书的功能(在小于 90 天之内重启 K3s,就会自动续一年)。
- Batteries-included 功能:虽然有些服务本身这个二进制文件并没有提供,但是可以通过内置的服务,将配置文件放到指定的目录下面,就可以在启动的时候一并将该服务启动或替换默认组件。
- 单进程架构:所有 Kubernetes control-plane 组件都封装在单个二进制文件和进程中。因为封装在二进制文件中,所以启动的时候只有一个进程。好处在于只需要管理这个单一进程就可以了,同时也具备操作复杂集群的能力。
- 最小外部依赖:最大程度减轻了外部依赖性,即稍新一点的 Linux 内核就可以了(需要 kernel 和 cgroup 挂载)。
K3s HA 实现原理
我们都知道 Kubernetes 的默认 datastore 是 etcd,而 K3s 是如何将针对 etcd 的相关操作转化到其他类型的 datastore 上的呢?这里 Rancher 开发了一个新的组件叫 Kine(https://github.com/rancher/kine),由它来完成这项工作。
Kubernetes(K3s)的 api-server 默认使用 etcd v3 的存储接口,etcd v3 中被 Kubernetes 使用的接口大致如下(https://github.com/etcd-io/etcd/blob/master/etcdserver/etcdserverpb/rpc.proto):

在 Kine 中,这些接口都依次被实现(Lease 相关还不支持),可以参考这里:https://github.com/rancher/kine/tree/master/pkg/server。
Kine 将这些接口暴露给 K3s 的 api-server。当我们给 K3s 设置相应的 datastore-endpoint 时,K3s 的 api-server 还是配置连接 etcd v3,但是 etcd-servers 的地址则配置为 Kine 的服务地址,相当于所有的 API 读写操作都通过 Kine 来处理,Kine 来把读写操作转给 MySQL/PostgreSQL/SQLite 等。如果我们设置真正的 etcd backend,Kine 会略过并直接暴露真实的 etcd-servers 给 K3s api-server。
Worker 节点中的 api-server 代理通过一个 tcpproxy(http://github.com/google/tcpproxy)来实现,参考:https://github.com/rancher/k3s/blob/master/pkg/agent/loadbalancer/loadbalancer.go。
tcpproxy 需要获取真实的 api-server 的服务地址,这里主要靠 worker 与 master 建立的 tunnel,也就是 websocket 数据通道获取,这个 tunnel 是 K3s 独有的。当 api-server 地址有更新,worker 依靠 websocket 获取新的地址,同时更新 worker 中的 tcpproxy 的配置。