- 1.需求背景
- 2.k3s与k8s对比
- 禁止防火墙 $ sudo ufw disable #关闭swap $ sudo swapoff -a #永久关闭swap分区 $ sudo sed -i ‘s/.swap./#&/‘ /etc/fstab #禁⽌selinux #安装操控selinux的命令 $ sudo apt install -y selinux-utils # 禁⽌止selinux $ setenforce 0 重启启操作系统 $ shutdown -r now 查看selinux是否已经关闭 $ sudo getenforce Disabled(表示已经关闭)
- 2.5.数据库与存储
- 2.6.通信
- 2.7.容器运行时
- 2.8.网络
- 2.9.其他
- 3.性能测试
1.需求背景
在实际的生产环境中,想要获得一个稳定的k8s环境,往往需要满足如下3个条件:
- 将worker节点和master分开,使用master运行控制平面,使用woker节点运行工作负载
- 在独立的集群上运行etcd,以确保它能够处理负载
- 理想状态下,分离Ingress节点,以便它们能够轻松处理进入的流量,即便一些底层节点已经十分忙碌
配置一个稳定的生产环境将需要3倍的k8s master、3倍的etcd、2倍的Ingress,至少需要8个实例,每个实例都有较高的最低配置需求。如果在一些IOT、边缘计算等小型场景中,k8s有如下缺点:
- K8S资源消耗大;
- 存在大量弱网情况,网络链接情况不稳定;
- 组件较多,部署运维麻烦;
这时,使用k8s进行部署往往要付出巨大的成本,因此可探索在这些场景中使用k3s替代k8s。
实际需求方
- 电网,ASE 云边协同 - 边缘 K8S 集群;
目前部署的是全量的K8S,用的是公有云的架构,节点上资源比较紧张;不排除之后用更轻量化的方案,需要提前有所调研; - 专有云底座轻量化的目标;
2.k3s与k8s对比
2.1.简介与历史
Kubernetes简称K8s,是Google于2014年6月基于其内部使用的Borg系统开源的容器编排平台,可用于大规模运行分布式应用和服务。2015年,Google、RedHat 等开源基础设施领域公司,共同牵头发起了一个名为 CNCF(Cloud Native Computing Foundation)的基金会,希望以Kubernetes项目为基础,建立一个由开源基础设施领域厂商主导的、按照独立基金会方式运营的平台级社区。Kubernetes可以说是Google 公司在容器化基础设施领域多年来实践经验的沉淀与升华,加上近几年不断壮大的开源社区对其贡献,现在已经基本成为容器编排调度框架的标准。
然而,在资源有限的边缘计算、物联网等场景下,由于Kubernetes本身会占用不少资源,且这些场景下大多不需要使用到Kubernetes的全部功能,Kubernetes显得臃肿。在当今边缘计算和物联网发展迅速的时候,需要一个应对这些场景的轻量级容器编排解决方案,于是K3s应运而生。
K3s 由Rancher公司于2019年3月发布,是首个进入 CNCF 沙箱项目的 K8s 发行版,同时也是当前全球用户量最大的 CNCF 认证轻量级 K8s发行版。Rancher希望发行版能做到安装后只需K8s一半的内存大小,Kubernetes由10个字母组成,简写为K8s,发行版只需一半大应为5个字母,因此取名K3s,K3s 没有全称,也没有官方的发音。
K3s满足日益增长的在边缘计算环境中运行在 x86、ARM64 和 ARMv7 处理器上的小型、易于管理的 Kubernetes 集群需求,自发布以来备受全球开发者们关注,至今GitHub Star数已超过 16000,是开源社区最受欢迎的边缘计算 K8s 解决方案。
2.2.架构和功能
K8s核心组件
- apiserver
提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制;
- controller manager
负责维护集群的状态,比如故障检测、自动扩展、滚动更新等; - kubelet
负责维护容器的生命周期,同时也负责 Volume(CSI)和网络(CNI)的管理; - etcd
保存了整个集群的状态; - scheduler
负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上; - kube-proxy
负责为 Service 提供 cluster 内部的服务发现和负载均衡; - container runtime
负责镜像管理以及 Pod 和容器的真正运行(CRI);
K8s架构图
K3s核心组件与功能的不同点
由于K3s只是轻量化的k8s,各组件设计理念都和k8s基本相同,为了获得更少的资源消耗,k3s组件有如下不同:
- 嵌入式SQLite数据库,作为可选的存储源,可外接SQLite / Mysql / PostgreSQL / DQlite和etcd作为外部数据库,但并非默认项。
- 移除过时的功能、Alpha功能、非默认功能,这些功能在大多数Kubernetes集群中已不可用。
- 删除内置插件(比如云供应商插件和存储插件),可用外部插件程序替换。K3s在默认状态下只会启动除自身进程之外的两个应用:coredns和traefik。
- 默认执行容器从docker换成了containerd。
- 增加基于websocket的tunnel-proxy,简化部署。
- 封装在简单的启动程序中,该启动程序处理很多复杂的 TLS 和选项。
- k3s server 只有一个进程体,单一进程包含kubelet、containerd等必须的组件,k3s agnet 分为两个进程体,其中一个是 Containerd,负责管理运行容器
- K3s server = API Server + Scheduler + Controller Manager + sqllite + Tunnel Proxy.
- K3s Agent = Tunnel Proxy + Kube Proxy + Flannel + Kubelet
- k3s支持ARM,很多K8s发行版无法支持ARM
K3s架构图

2.3.硬件需求
cpu和内存
K3s agent、具有工作负载的 K3s server的最低资源要求:
内存: 最低 512MB(建议至少为 1GB)
CPU: 最低 1
K3s server 中节点的最低 CPU 和内存要求:
| 部署规模 | 节点 | VCPUS | 内存 |
|---|---|---|---|
| Small | Up to 10 | 2 | 4 GB |
| Medium | Up to 100 | 4 | 8 GB |
| Large | Up to 250 | 8 | 16 GB |
| X-Large | Up to 500 | 16 | 32 GB |
| XX-Large | 500+ |
数据库
K3s 支持不同的数据库,包括 MySQL、PostgreSQL、MariaDB 和 etcd,以下是运行大型集群所需的数据库资源的大小指南:
| 部署规模 | 节点 | VCPUS | 内存 |
|---|---|---|---|
| Small | Up to 10 | 1 | 2 GB |
| Medium | Up to 100 | 2 | 8 GB |
| Large | Up to 250 | 4 | 16 GB |
| X-Large | Up to 500 | 8 | 32 GB |
| XX-Large | 500+ | 16 | 64 GB |
2.4.部署过程
K8s部署
K8s的部署原本比较麻烦,除了将各个组件编译成二进制文件外,用户还要负责为这些二进制文件编写对应的配置文件、配置自启动脚本,以及为 kube-apiserver 配置授权文件等等诸多运维工作。2017 年,Kubernetes社区才发起了一个独立的部署工具,名叫kubeadm,这个工具可以让用户通过两条命令完成一个k8s集群的部署:
- 创建一个Master节点:
kubeadm init - 将一个Node节点加入到当前集群中:
kubeadm join
kubeadm是使用容器进行部署k8s组件的,但是,由于kubelet配置容器网络、管理容器数据卷时,都需要直接操作宿主机,如果kubelet运行在一个容器里,那么直接操作宿主机就会变得很麻烦,kubeadm的部署方案是:把 kubelet 直接运行在宿主机上,然后使用容器部署其他的 Kubernetes 组件。
于是,部署k8s集群的步骤:
- 安装doceker,可手动下载docker-ce的安装包进行安装
- 禁止防火墙、关闭swap、禁止selinux
禁止防火墙 $ sudo ufw disable #关闭swap $ sudo swapoff -a #永久关闭swap分区 $ sudo sed -i ‘s/.swap./#&/‘ /etc/fstab #禁⽌selinux #安装操控selinux的命令 $ sudo apt install -y selinux-utils # 禁⽌止selinux $ setenforce 0 重启启操作系统 $ shutdown -r now 查看selinux是否已经关闭 $ sudo getenforce Disabled(表示已经关闭)
- 安装kubeadm、kubelet 和 kubectl
apt-get install kubeadm kubelet kubectl
- 初始化master节点
为了让pod网络不与任何主机网络重叠,应使用一个合适的CIDR块来代替,然后在执行 kubeadm init 时使用 —pod-network-cidr参数:
kubeadm init —pod-network-cidr=10.244.0.0/16
- 加入node节点。
kubeadm会为集群生成一个bootstrap token。在后面,只要持有这个token,任何一个安装了kubelet和kubadm的节点,都可以通过kubeadm join加入到这个集群当中。
K3s部署
K3s提供了一个安装脚本,安装非常简单
- Master节点上只需运行命令:
curl -sfL https://get.k3s.io | sh -
运行后,将安装其他实用程序,包括kubectl、crictl、ctr、k3s-killall.sh 和 k3s-uninstall.sh。
- Node节点运行如下命令即可加入集群:
curl -sfL https://get.k3s.io | K3S_URL=https://myserver:6443 K3S_TOKEN=mynodetoken sh -
其中,K3S_TOKEN的位置为
cat /var/lib/rancher/k3s/server/node-token
2.5.数据库与存储
K8s的etcd
Etcd是Kubernetes集群中的一个十分重要的组件,存储的信息有:
- 存储flannel网络信息
- Kubernetes对象的状态信息
K3s的数据库
K3s 支持以下数据存储选项:
- 嵌入式 SQLite
- PostgreSQL (经过认证的版本:10.7 和 11.5)
- MySQL (经过认证的版本:5.7)
- MariaDB (经过认证的版本:10.3.20)
- etcd (经过认证的版本:3.3.15)
- 嵌入式 etcd 高可用
k3s默认使用SQLite存储,保证了本身的轻量快速运行和部署的能力。k3s提供了切换对接多种存储的方式,如果SQLite不满足需求,可以根据实际生产要求使用选择不同的存储,存储切换的方式可以参考如下文档:https://docs.rancher.cn/docs/k3s/installation/datastore/_index/
简单总结不同的存储的使用场景如下:
| 存储类型 | 存储HA | 使用场景 |
|---|---|---|
| SQLite | 不支持 | 单机部署,或者开发测试,一体机环境 |
| etcd | 多节点 | 期望更高的存储性能和兼容性,能接受其对计算资源的消耗 |
| MySQL | 主从/多主… | 团队不擅长运维etcd,偏向企业级数据库 |
| PostgreSQL | 主动/多主… | 同上 |
| DQLite | 多节点 | 不希望存储占用太多资源,足够轻量并且能够支持HA,一般可用于边缘场景 |
k3s 删除了 k8s 内置 cloud provider 以及 storage 插件(可通过手动安装这些插件),内置了 Local Path Provider。可以通过使用外部的存储插件解决 k3s 存储问题,一些文章中推荐使用Longhorn,Longhorn轻量级、可靠且功能强大。可以使用kubectl apply命令或使用Helm charts在现有的Kubernetes集群上安装Longhorn。安装Longhorn之后,它将为Kubernetes集群添加持久卷支持。
GitHub地址: https://github.com/longhorn/longhorn
2.6.通信
k3s 为了简化部署,用 SQLite 实现了 list/watch 接口,由此增加了master节点与worker节点通信用的tunnel-proxy,其本质是websocket, 这个功能现在用在简化部署上面。在k8s中, 如果worker节点连接到master节点之后, 当需要修改master节点的ip地址的时候, 我们的做法是手动的改变worker节点的配置实现,而 k3s就可以通过tunnel-proxy实现。
- Server 就是 Kubernetes 管理面组件 + SQLite 和 Tunnel Proxy,
- Agent 即 Kubernetes 的数据面 + Tunnel Proxy。
2.7.容器运行时
k3s默认并不安装docker,使用containerd作为容器运行时,减少运行时的开销。
docker 与 containerd的常用命令对照:
| 容器相关功能 | docker | containerd |
|---|---|---|
| 显示容器列表 | docker ps | crictl ps |
| 创建容器 | docker create | crictl create |
| 启动容器 | docker start | crictl start |
| 停止容器 | docker stop | crictl stop |
| 镜像相关功能 | docker | containerd |
|---|---|---|
| 显示本地镜像列表 | docker images | crictl images |
| 下载镜像 | docker pull | crictl pull |
| 上传镜像 | docker push | 无 |
| 删除本地镜像 | docker rmi | crictl rmi |
| 查看镜像详情 | docker inspect | crictl inspecti |
2.8.网络
CNI
K3s 默认以 flannel 作为 CNI 运行,使用 VXLAN 作为默认后端。
Flannel 的默认后端是 VXLAN。
| CLI Flag 和 Value | 描述 |
|---|---|
| —flannel-backend=vxlan (默认) | 使用 VXLAN 后端。 |
| —flannel-backend=ipsec | 使用 IPSEC 后端,对网络流量进行加密。 |
| —flannel-backend=host-gw | 使用 host-gw 后端。 |
| —flannel-backend=wireguard | 使用 WireGuard 后端,对网络流量进行加密。可能需要额外的内核模块和配置。 |
k3s 除了内置 Flannel 网络插件以外,还内置了 CoreDNS、Traefik Ingress Controller、Service Load Balancer,如果不使用默认的组件,用户也可以自己部署其他组件,比如使用 MetalLB 替代内置的 load balancer。
Traefik 是一个现代的 HTTP 反向代理和负载均衡器,它是为了轻松部署微服务而生的。在设计,部署和运行应用程序时,它简化了网络复杂性。
网络入站规则
| 协议 | 端口 | 源 | 描述 |
|---|---|---|---|
| TCP | 6443 | K3s agent 节点 | Kubernetes API Server |
| UDP | 8472 | K3s server 和 agent 节点 | 仅对 Flannel VXLAN 需要 |
| TCP | 2379-2380 | K3s server 节点 | 只有嵌入式 etcd 高可用才需要 |
2.9.其他
操作系统
K3s 有望在大多数现代 Linux 系统上运行:
- CentOS: 7.8, 7.9, 8.2, 8.3
- RHEL: 7.8, 7.9, 8.2, 8.3
- SLES: 15SP2
- Ubuntu: 16.04, 18.04, 20.04
3.性能测试
3.1.测试1——资源需求测试
测试准备
资源测试的目的
- 在单节点集群上,确定运行整个 K3s server 堆栈所应预留的 CPU、内存和 IOPs 的合法最小值,假设真正的工作负载将部署在集群上。
- 在 agent(worker)节点上,确定应该为 Kubernetes 和 K3s 控制平面组件(kubelet 和 k3s agent)预留的 CPU、内存和 IOPs 的合法最小值。
测试的组件有:
- 已启用所有打包组件的 K3s 1.19.2
- Prometheus + Grafana 监控堆栈
- Kubernetes PHP Guestbook 应用示例
包括 IOPS 在内的资源仅适用于 Kubernetes 数据存储和控制平面,不包括系统级管理 agent 或日志记录、容器镜像管理或任何特定工作负载要求的开销。
方法
- 使用独立的 Prometheus v2.21.0 实例,通过 apt 安装的prometheus-node-exporter来收集主机 CPU、内存和磁盘 IO 统计数据。
- systemd-cgtop用于抽查 systemd cgroup 级别的 CPU 和内存利用率。system.slice/k3s.service跟踪 K3s 和 containerd 的资源利用率情况,而单个 pod 则在kubepods层次结构下。
- 使用集成到 server 和 agent 进程中的 kubelet exporter,从 process_resident_memory_bytes和 go_memstats_alloc_bytes 指标中收集了额外的详细 K3s 内存利用率数据。
结果
| 组件 | 处理器 | 最小 CPU | Kine/SQLite 的最小内存 | 嵌入式 ETCD 的最小内存 |
|---|---|---|---|---|
| 具有工作负载的 K3s server | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz | 10% of a core | 768 M | 896 M |
| 具有单个 agent 的 K3s 集群 | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz | 10% of a core | 512 M | 768 M |
| K3s agent | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz | 5% of a core | 256 M | 256 M |
具有工作负载的 K3s server#
这些是对单节点集群的要求,其中 K3s server 与工作负载共享资源。
对 CPU 的要求是:
| 所需资源 | 测试处理器 |
|---|---|
| 10% of a core | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz |
IOPS 和内存的要求是:
| 测试数据存储 | IOPS | KiB/sec | 延时 | RAM |
|---|---|---|---|---|
| Kine/SQLite | 10 | 500 | < 10 ms | 768 M |
| Embedded etcd | 50 | 250 | < 5 ms | 896 M |
具有单个 agent 的 K3s 集群#
这些是 K3s 集群的基本要求,它有一个 K3s server 节点和一个 K3s agent,但没有工作负载。
对 CPU 的要求是:
| 所需资源 | 测试处理器 |
|---|---|
| 10% of a core | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz |
IOPS 和内存的要求是:
| 测试数据存储 | IOPS | KiB/sec | 延时 | RAM |
|---|---|---|---|---|
| Kine/SQLite | 10 | 500 | < 10 ms | 512 M |
| Embedded etcd | 50 | 250 | < 5 ms | 768 M |
K3s Agent#
对 CPU 的要求是:
| 所需资源 | 测试处理器 |
|---|---|
| 5% of a core | Intel(R) Xeon(R) Platinum 8124M CPU, 3.00 GHz |
需要 256M 的内存。
结果分析
K3s server 的利用率数据主要是由支持 Kubernetes 数据存储(kine 或 etcd)、API Server、Controller-Manager 和 Scheduler 控制,以及实现系统状态变化所需的任何管理任务所驱动。给 Kubernetes 控制平面带来额外负载的操作,如创建/修改/删除资源,将导致暂时的利用率上升。使用大量使用 Kubernetes 数据存储的 operators 或应用程序(如 Rancher 或其他 operators 类型的应用程序)将增加 server 的资源需求。通过添加额外的节点或创建许多集群资源来扩展集群,将增加 server 的资源需求。
K3s agent 的利用率数据主要是由支持容器生命周期管理控制驱动的。涉及管理镜像、提供存储或创建/销毁容器的操作将导致利用率的暂时上升。拉取镜像通常会影响 CPU 和 IO,因为它们涉及将镜像内容解压到磁盘。如果可能的话,工作负载存储(pod 临时存储和卷)应该与 agent 组件(/var/lib/rancher/k3s/agent)隔离,以确保不会出现资源冲突。
由测试结果可知,相对于k8s最小1CPU/1GB的资源需求,k3s所需要的资源小很多,在边缘计算场景下无疑是更好的选择。
测试2——基础性能测试
测试目的
- 测试Master的性能,得到AVG、P50、P90、P99等多维度数据比较。
- 比较如下性能:
- 从Etcd换成SQLite造成的DB性能影响
- 吞吐量/QPS
- 支持Node/Pod数量
- 调度性能
- Node的性能:
- Pod数量
- 启动Pod速度
方法
模拟边缘计算场景,在较少的资源下,借助KubeMark来mock环境,分别使用K8s和k3s部署计算密集型、IO密集型应用,分别测试上述数据。
