Kun

Kun

IT学徒、技术民工、斜杠青年,机器人爱好者、摄影爱好 PS、PR、LR、达芬奇潜在学习者


共 243 篇文章


​ 基于云原生的周边工具

K3s

K3s 是轻量级的 Kubernetes。K3s 易于安装,仅需要 Kubernetes 内存的一半,所有组件都在一个小于 100 MB 的二进制文件中。

它适用于:

  • Edge
  • IoT
  • CI
  • Development
  • ARM
  • 嵌入 K8s
  • 不去学习那么多的 Kubernetes 高深知识也能上手使用

K3s 是一个完全兼容的 Kubernetes 发行版,具有以下增强功能:

  • 打包为单个二进制文件。
  • 使用基于 sqlite3 作为默认存储机制的轻量级存储后端。同时支持使用 etcd3、MySQL 和 Postgres。
  • 封装在简单的启动程序中,可以处理很多复杂的 TLS 和选项。
  • 默认情况下是安全的,对轻量级环境有合理的默认值。
  • 添加了简单但强大的batteries-included功能,例如:

    • 本地存储提供程序
    • service load balancer
    • Helm controller
    • Traefik ingress controller
  • 所有 Kubernetes control plane 组件的操作都封装在单个二进制文件和进程中。因此,K3s 支持自动化和管理复杂的集群操作(例如证书分发等)。
  • 最大程度减轻了外部依赖性,K3s 仅需要现代内核和 cgroup 挂载。K3s 打包了所需的依赖,包括:

    • containerd
    • Flannel (CNI)
    • CoreDNS
    • Traefik (Ingress)
    • Klipper-lb (Service LB)
    • 嵌入式网络策略控制器
    • 嵌入式 local-path-provisioner
    • 主机实用程序(iptables、socat 等)

官方希望安装的 Kubernetes 只占用一半的内存。Kubernetes 是一个 10 个字母的单词,简写为 K8s。Kubernetes 的一半就是一个 5 个字母的单词,因此简写为 K3s。K3s 没有全称,也没有官方的发音

要求

K3s 非常轻量,但也有一些最低要求,如下所述。

无论 K3s 在容器中运行还是作为原生 Linux 服务运行,每个运行 K3s 的节点都应满足以下最低要求。这些要求是 K3s 及其打包组件的基准,不包括工作负载本身消耗的资源。

两个节点不能具有相同的主机名。

如果多个节点将具有相同的主机名,或者主机名可以被自动配置系统重复使用,请使用 --with-node-id 选项为每个节点附加一个随机后缀,或者使用 --node-name$K3S_NODE_NAME 为添加到集群的每个节点设计一个独特的名称。

K3s 适用于以下架构:

  • x86_64
  • armhf
  • arm64/aarch64
  • s390x

硬件要求取决于 K3s 集群的大小。对于生产和大型集群,我们建议使用具有外部数据库的高可用性设置。对于生产环境中的外部数据库,建议使用以下选项:

  • MySQL
  • PostgreSQL
  • etcd

磁盘

集群性能取决于数据库性能。为确保最佳速度,我们建议为 K3s 集群使用 SSD 磁盘。在云提供商上,你还需使用能获得最大 IOPS 的最小大小

网络

卷和存储

cli工具

命令 描述
k3s server 运行 K3s Server 节点,这将启动 Kubernetes apiserverschedulercontroller-managercloud-controller-manager 组件,以及数据存储和 Agent 组件。有关详细信息,请参阅 k3s server 命令文档
k3s agent 运行 K3s Agent 节点,这将启动 containerdflannelkube-router 网络策略控制器和 Kubernetes kubeletkube-proxy 组件。有关详细信息,请参阅 k3s agent 命令文档
k3s kubectl 运行嵌入式 kubectl 命令。这是用于与 Kubernetes apiserver 交互的 CLI。如果未设置 KUBECONFIG 环境变量,将自动尝试使用 /etc/rancher/k3s/k3s.yaml 中的 kubeconfig。
k3s crictl 运行嵌入式 crictl 命令。这是一个 CLI,用于与 Kubernetes 的容器运行时接口 (CRI) 交互。对调试很有用。
k3s ctr 运行嵌入式 ctr 命令。这是一个用于 containerd 的 CLI,containerd 是 K3s 使用的容器 daemon。对调试很有用。
k3s token 管理引导 Token。有关详细信息,请参阅 k3s token 命令文档
k3s etcd-snapshot 对 K3s 集群数据进行按需备份并上传到 S3。有关详细信息,请参阅 k3s etcd-snapshot 命令文档
k3s secrets-encrypt 在将 Secret 存储到集群中时加密 Secret。有关详细信息,请参阅 k3s secrets-encrypt 命令文档
k3s certificate 管理 K3s 证书。有关详细信息,请参阅 k3s certificate 命令文档
k3s completion 为 K3s 生成 shell 补全脚本
k3s help 显示命令列表或某个命令的帮助

K9s

k9s 是一个基于终端的 UI,用于与你的 Kubernetes 集群互动。这个项目的目的是使其更容易导航、观察和管理你在 kubernetes 集群部署的应用程序。k9s 持续观察 Kubernetes 的变化,并提供后续的命令来与你观察到的资源进行互动。

k9s 会以特定时间间隔监控 Kubernetes 资源,默认为 2 秒,并允许查看自己集群中的内容。它可以一目了然地提供了运行中 Pod、日志和部署的可视化视图,以及对 Shell 的快速访问。以下是该工具的主要特性:

  • 信息触手可及

    • 跟踪 Kubernetes 集群中运行的资源的实时活动
    • 处理 Kubernetes 标准资源和自定义资源定义
  • 集群指标

    • 跟踪与 Pod,容器和节点等资源关联的实时指标
  • 高级特性

    • 提供标准的集群管理命令,例如日志,扩展,端口转发,重启
    • 定义自己的命令快捷方式,以通过命令别名和热键快速导航
    • 支持插件扩展 k9s 来创建属于自己的集群操作管理命令
    • 强大的过滤模式,允许用户向下钻取并查看与工作负载相关的资源
  • 外观可定制

    • 通过 K9s 皮肤定义自己的外观
    • 自定义 / 安排要按资源显示的列

与K8s互动的操作面板

# Via Homebrew
brew install derailed/k9s/k9s

# Via MacPort
sudo port install k9s
 
# Linux
curl -sS https://webinstall.dev/k9s | bash

k9s的命令

(1)列出所有可用的CLI选项
k9s help

(2)获取有关K9s运行时间的信息(日志、配置等)。
k9s info

(3)在一个现有的kubeconfig上下文中启动k9s
k9s --context <your_context>

(4)在指定的命名空间中运行k9s
k9s -n <your_namespace>

(5)以只读模式启动K9s--禁用所有集群修改命令
k9s --readonly

启用k9s

cd .local/bin/
./k9s

K9s 的基本命令与 Vim 的命令类似,通过冒号加资源类型:resource 来定位到不同资源的浏览界面

Context 的界面下一层是 Pod。如果你的命名空间中的 Pod 太多,可以通过 /filter 的方式来过滤,例如输入 /nginx

当然你也可以先输入:deploy 跳转到 Deployment 的界面,选择 Nginx 对应的 Deployment,再按 ENTER 进入查看 Nginx 下面所有的 Pod。

K9s 内置了命令自动补全,例如输入 de 后,按 Tab 即可自动补全为 deploy。

启动后,会弹出 k9s 的基于文本的用户界面。在没有指定命名空间标志的情况下,它会向你显示默认命名空间中的 Pod。通过快捷键来导航 k9s,可以随时使用方向键和回车键来选择列出的项目。可能会注意到 k9s 设置为使用 Vim 命令键,包括使用 JK 键上下移动等。

https://k9scli.io/

https://www.escapelife.site/posts/d91f0590.html

wireguard

network-manager

Netmaker 是 Tailscale 的开源版本,不仅提供了非常友好的配置管理界面,还能够提供自定的网络段(我使用 Tailscale 不舒服的一点就是分配的内网 IP 都是随机的)

Netmaker 是一个开源的、基于 [[WireGuard]] 的网络(overlay network) 控制工具,可以非常快速的用来组建 WireGuard 网络

如果你有两台连接互联网的设备,那么 Netmaker 可以组建一个安全的网络,并打通一个安全的隧道提供给两台机器通信。而如果你有数千台机器分布在不同的地区,不同的数据中心,不同的网络中,那么 Netmaker 也可以组建一个网络来提供给这些不同的节点通信。

如果熟悉 AWS,那么 Netmaker 就像 VPC 一样,不过 Netmaker 可以应用在任意的机器中。从 Netmaker 网络中的机器来看,同一个网络中的机器尽管在世界各地,但其相互通信就像是在同一个局域网中一样

Netmaker 和其他一些产品非常相似,比如 [[Tailscale]], [[ZeroTier]],[[Nebula]] 但不同于这些产品的是,Netmaker 连接更快,更加灵活。Netmaker 使用 [[WireGuard]] 所以更快,Netmaker 中的节点不管是服务端还是 Agent 都完全可配置,所以提供了更大的灵活性。

Netmaker 优于 [[Tailscale]] 的地方还在于 ,Netmaker 不需要 Google, Microsoft 或者 GitHub 账号。Netmaker 可以认为是一个可以自行托管的 Tailscale

工作原理

Netmaker 依赖于 WireGuard 来在机器间创建隧道(tunnel), Netmaker 通过管理不同机器的 WireGuard 来创建网络。简单来说,Netmaker 实现 Client/Server 架构:

  • the admin server 管理端,称为 Netmaker,管理网络的界面
  • the agent,客户端,称为 Netclient,客户端通过 gRPC 与服务端通信

K8s的问题和局限性

2014 年发布的 Kubernetes 在今天俨然已成为容器编排领域的事实标准,相信谈到 Kubernetes 的开发者都会一再复述上述现象。如下图所示,今天的大多数个人或者团队都会选择 Kubernetes 管理容器,而也有 75% 的人会在生产环境中使用 Kubernetes。

在这种全民学习和使用 Kubernetes 的大背景下,我们也应该非常清晰地知道 Kubernetes 有哪些局限性。虽然 Kubernetes 能够解决容器编排领域的大多数问题,但是仍然有一些场景是它很难处理、甚至无法处理的,只有对这些潜在的风险有清晰的认识,才能更好地驾驭这项技术,

集群管理

集群是一组能够在一起协同工作的计算机,我们可以将集群中的所有计算机看成一个整体,所有资源调度系统都是以集群为维度进行管理的,集群中的所有机器构成了资源池,这个巨大的资源池会为待运行的容器提供资源执行计算任务,这里简单谈一谈 Kubernetes 集群管理面对的几个复杂问题。

水平扩展性

集群大小是我们在评估资源管理系统时需要关注的重要指标之一,然而 Kubernetes 能够管理的集群规模远远小于业界的其他资源管理系统。集群大小为什么重要呢,我们先来看另一个同样重要的指标 — 资源利用率,很多工程师可能没有在公有云平台上申请过资源,这些资源都相当昂贵,在 AWS 上申请一个与主机差不多配置的虚拟机实例(8 CPU、16 GB)每个月大概需要 150 美金,约为 1000 人民币2

大多数的集群都会使用 48 CPU 或者 64 CPU 的物理机或者虚拟机作为集群中的节点,如果我们的集群中需要包含 5,000 个节点,那么这些节点每个月大概要 8,000,000 美元,约为 50,000,000 人民币,在这样的集群中提升 1% 的资源利用率就相当于每个月节省了 500,000 的成本

多数在线任务的资源利用率都很低,更大的集群意味着能够运行更多的工作负载,而多种高峰和低谷期不同的负载部署在一起可以实现超售,这样能够显著地提高集群的资源利用率,如果单个集群的节点数足够多,我们在部署不同类型的任务时会有更合理的组合,可以完美错开不同服务的高峰期。

Kubernetes 社区对外宣传的是单个集群最多支持 5,000 节点,Pod 总数不超过 150,000,容器总数不超过 300,000 以及单节点 Pod 数量不超过 100 个3,与几万节点的 Apache Mesos 集群、50,000 节点的微软 YARN 集群4相比,Kubernetes 的集群规模整整差了一个数量级。虽然阿里云的工程师也通过优化 Kubernetes 的各个组件实现了 5 位数的集群规模,但是与其他的资源管理方式相比却有比较大的差距

需要注意的是 Kubernetes 社区虽然对外宣称单集群可以支持 5,000 节点,同时社区也有各种各样的集成测试保证每个改动都不会影响它的伸缩性6,但是 Kubernetes 真的非常复杂,我们没有办法保证你使用的每个功能在扩容的过程中都不出问题。而在生产环境中,我们甚至可能在集群扩容到 1000 ~ 1500 节点时遇到瓶颈。

每个稍具规模的大公司都想要实现更大规模的 Kubernetes 集群,但是这不是一个改几行代码就能解决的简单问题,它可能需要我们限制 Kubernetes 中一些功能的使用,在扩容的过程中,etcd、API 服务器、调度器以及控制器都有可能出现问题。社区中已经有一些开发者注意到了其中的一些问题,例如在节点上增加缓存降低 API 服务器的负载7,但是要推动类似的改变还是很困难的,有志之士可以尝试在社区推动类似的项目。

多集群管理

单个集群的容量再大也无法解决企业面对的问题,哪怕有一天 Kubernetes 集群可以达到 50,000 节点的规模,我们仍然需要管理多个集群,多集群管理也是 Kubernetes 社区目前正在探索的方向,社区中的多集群兴趣小组(SIG Multi-Cluster)目前就在完成相关的工作8。在作者看来,Kubernetes 的多集群会带来资源不平衡、跨集群访问困难以及提高运维和管理成本三大问题,我们在这里谈一谈目前在开源社区和业界几种可供参考和选择的解决方案。

Kubefed项目是 Kubernetes 社区给出的解决方案,它同时提供了跨集群的资源和网络管理的功能,社区的多集群兴趣小组(SIG Multi-Cluster)负责了该项目的开发工作

kubefed 通过一个中心化的联邦控制面板管理多集群中的元数据,上层的控制面板会为管理器群中的资源创建对应的联邦对象

上层的控制面板会根据联邦对象 FederatedDeployment 的规格文件生成对应的 Deployment 并推送到下层的集群,下层集群可以正常根据 Deployment 中的定义创建特定数量的副本。

FederatedDeployment 只是一种最简单的分发策略,在生产环境中我们希望通过联邦的集群实现容灾等复杂功能,这时可以利用 ReplicaSchedulingPreference 在不同集群中实现更加智能的分发策略:

我们可以认为 kubefed 的主要作用是将多个松散的集群组成强耦合的联邦集群,并提供更加高级的网络和部署功能,这样我们可以更容易地解决集群之间资源不平衡和连通性的一些问题,然而该项目的关注点不包含集群生命周期的管理,

集群接口

Cluster API 也是 Kubernetes 社区中与多集群管理相关的项目,该项目由集群生命周期小组(SIG Cluster-Lifecycle)负责开发,其主要目标是通过声明式的 API 简化多集群的准备、更新和运维工作,

在该项目中最重要的资源就是 Machine,它表示一个 Kubernetes 集群中的节点。当该资源被创建时,特定提供商的控制器会根据机器的定义初始化并将新的节点注册到集群中,在该资源被更新或者删除时,也会执行操作达到用户的状态。

这种策略与阿里的多集群管理的方式有一些相似,它们都使用声明式的 API 定义机器和集群的状态,然后使用 Kubernetes 原生的 Operator 模型在更高一层的集群中管理下层集群,这能够极大降低集群的运维成本并提高集群的运行效率10,不过类似的项目都没有考虑跨集群的资源管理和网络管理。

应用场景

应用分发

Kubernetes 主项目提供了几种部署应用的最基本方式,分别是 DeploymentStatefulSetDaemonSet,这些资源分别适用于无状态服务、有状态服务和节点上的守护进程,这些资源能够提供最基本的策略,但是它们无法处理更加复杂的应用。

随着 CRD 的引入,目前社区的应用管理小组(SIG Apps)基本不会向 Kubernetes 主仓库引入较大的改动,大多数的改动都是在现有资源上进行的修补,很多常见的场景,例如只运行一次的 DaemonSet11 以及金丝雀和蓝绿部署等功能,现在的资源也存在很多问题,例如 StatefulSet 在初始化容器中卡住无法回滚和更新12

我们可以理解社区不想在 Kubernetes 中维护更多的基本资源,通过几个基本的资源可以覆盖 90% 的场景,剩下的各种复杂场景可以让其他社区通过 CRD 的方式实现。不过作者认为如果社区能够在上游实现更多高质量的组件,这对于整个生态都是很有价值并且很重要的工作,需要注意的是假如各位读者想要在 Kubernetes 项目中成为贡献者,SIG Apps 可能不是一个很好的选择。

批处理调度

机器学习、批处理任务和流式任务等工作负载的运行从 Kubernetes 诞生第一天起到今天都不是它的强项,大多数的公司都会使用 Kubernetes 运行在线服务处理用户请求,用 Yarn 管理的集群运行批处理的负载。

在线任务和离线任务往往是两种截然不同的作业,大多数的在线任务都是无状态的服务,它们可以在不同机器上进行迁移,彼此很难有极强的依赖关系;但是很多离线任务的拓扑结构都很复杂,有些任务需要多个作业一同执行,而有些任务需要按照依赖关系先后执行,这种复杂的调度场景在 Kubernetes 中比较难以处理。

在 Kubernetes 调度器引入调度框架之前,所有的 Pod 在调度器看来是没有任何关联的,不过有了调度框架,我们可以在调度系统中实现更加复杂的调度策略,例如保证一组 Pod 同时调度的 PodGroup13,这对于 Spark 和 TensorFlow 任务非常有用。

Volcano 也是在 Kubernetes 上构建的批处理任务管理系统14,它能够处理机器学习、深度学习以及其他大数据应用,可以支持包括 TensorFlow、Spark、PyTorch 和 MPI 在内的多个框架。

虽然 Kubernetes 能够运行一些批处理任务,但是距离在这个领域上取代 Yarn 等老牌资源管理系统上还有非常大的差距,相信在较长的一段时间内,大多数公司都会同时维护 Kubernetes 和 Yarn 两种技术栈,分别管理和运行不同类型的工作负载。

硬多租户

多租户是指同一个软件实例可以为不同的用户组提供服务,Kubernetes 的多租户是指多个用户或者用户组使用同一个 Kubernetes 集群,今天的 Kubernetes 还很难做到硬多租户支持,也就是同一个集群的多个租户不会相互影响,也感知不到彼此的存在。

硬多租户在 Kubernetes 中是一个很重要、也很困难的课题,合租公寓就是一个典型的多租户场景,多个租客共享房屋内的基础设施,硬多租户要求多个访客之间不会相互影响,你可以想象这有多么困难,Kubernetes 社区甚至有一个工作小组专门讨论和研究相关的问题15,然而虽然感兴趣的工程师很多,但是成果却非常有限。

尽管 Kubernetes 使用命名空间来划分虚拟机群,然而这也很难实现真正的多租户。多租户的支持到底有哪些作用呢,这里简单列几个多租户带来的好处:

  • Kubernetes 带来的额外部署成本对于小集群来说非常高昂,稳定的 Kubernetes 集群一般都需要至少三个运行 etcd 的主节点,如果大多数的集群都是小集群,这些额外的机器会带来很高的额外开销;
  • Kubernetes 中运行的容器可能需要共享物理机和虚拟机,一些开发者可能在公司内部遇到过自己的服务被其他业务影响,因为主机上容器可能隔离了 CPU 和内存资源,但是没有隔离 I/O、网络 和 CPU 缓存等资源,这些资源的隔离是相对困难的;

如果 Kubernetes 能够实现硬多租户,这不仅对云服务商和小集群的使用者来说都是个福音,它还能够隔离不同容器之间的影响并防止潜在安全问题的发生,不过这在现阶段还是比较难实现的。

总结

每个技术都有自己的生命周期,越底层的技术生命周期会越长,而越上层的技术生命周期也就越短,虽然 Kubernetes 是当今容器界的扛把子,但是未来的事情没有人可以说的准。我们要时刻清楚手中工具的优点和缺点,花一些时间学习 Kubernetes 中设计的精髓,不过如果在未来的某一天 Kubernetes 也成为了过去,我们也应该感到喜悦,因为会有更好的工具取代它

如果你觉得我的文章对你有帮助的话,希望可以推荐和交流一下。欢迎關注和 Star 本博客或者关注我的 Github