这篇文章已发布一年以上。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。
走出云端,走向地面:如何使 Kubernetes 在任何地方都达到生产级
此博客为在类似本地数据中心或边缘位置的环境中运行生产级 Kubernetes 集群提供了一些指导方针。
“生产级”意味着什么?
- 安装是安全的
- 部署是通过可重复且记录的过程进行管理的
- 性能是可预测且一致的
- 可以安全地应用更新和配置更改
- 已部署日志记录和监控,以检测和诊断故障和资源短缺
- 考虑到可用资源(包括资金、物理空间、电力等方面的限制),服务“足够高可用”
- 存在一个恢复流程,已记录并经过测试,以在发生故障时使用
简而言之,生产级意味着预测意外情况,并为以最小的痛苦和延迟进行恢复做好准备。
本文针对在虚拟机管理程序或裸机平台上进行的本地 Kubernetes 部署,与主要公共云的扩展性相比,面临着有限的后备资源。但是,如果预算限制了您选择消耗的资源,那么其中一些建议也可能在公共云中很有用。
单节点裸机 Minikube 部署可能便宜且容易,但不是生产级的。相反,您不太可能在零售店、分支机构或边缘位置获得 Google 的 Borg 体验,也不太可能需要它。
此博客提供了一些关于如何实现值得生产的 Kubernetes 部署的指导,即使在处理一些资源限制时也是如此。
Kubernetes 集群中的关键组件
在深入研究细节之前,必须了解 Kubernetes 的整体架构。
Kubernetes 集群是一个高度分布式的系统,基于控制平面和集群工作节点架构,如下所示。
通常,API 服务器、控制器管理器和调度器组件位于控制平面(又名主节点)的多个实例中。主节点通常也包括 etcd,尽管在高可用性和大型集群场景中,需要将 etcd 运行在独立的宿主机上。这些组件可以作为容器运行,并且可以选择由 Kubernetes 监管,即作为静态 Pod 运行。
为了实现高可用性,使用了这些组件的冗余实例。重要性和所需的冗余程度各不相同。
从 HA 角度来看的 Kubernetes 组件
这些组件的风险包括硬件故障、软件错误、错误更新、人为错误、网络中断和导致资源耗尽的系统过载。冗余可以减轻许多这些危险的影响。此外,虚拟机管理程序平台的资源调度和高可用性功能可以用来超越仅使用 Linux 操作系统、Kubernetes 和容器运行时所能实现的目标。
API 服务器在负载均衡器后面使用多个实例来实现扩展和可用性。负载均衡器是高可用性的关键组件。如果没有负载均衡器,多个 DNS API 服务器“A”记录可能是一种替代方案。
kube-scheduler 和 kube-controller-manager 参与领导者选举过程,而不是使用负载均衡器。由于cloud-controller-manager 用于选定的托管基础设施类型,并且这些类型具有实现变体,因此除了表明它们是控制平面组件之外,将不再讨论它们。
在 Kubernetes 工作节点上运行的 Pod 由 kubelet 代理管理。每个工作实例都运行 kubelet 代理和兼容 CRI 的容器运行时。Kubernetes 本身旨在监控工作节点中断并从中恢复。但是,对于关键工作负载,可以使用虚拟机管理程序资源管理、工作负载隔离和可用性功能来增强可用性并使性能更具可预测性。
etcd
etcd 是所有 Kubernetes 对象的持久存储。etcd 集群的可用性和可恢复性应该是生产级 Kubernetes 部署中的首要考虑因素。
如果可以承担,五节点 etcd 集群是最佳实践。为什么?因为您可以在一个节点上进行维护,并且仍然可以容忍失败。三节点集群是生产级服务的最低建议,即使只有一个虚拟机管理程序主机可用。除非非常大的安装跨越多个可用区,否则不建议使用七个以上的节点。
托管 etcd 集群节点的最低建议是 2GB 的 RAM 和 8GB 的 SSD 支持的磁盘。通常,8GB 的 RAM 和 20GB 的磁盘就足够了。磁盘性能会影响故障节点恢复时间。有关更多信息,请参阅https://coreos.com/etcd/docs/latest/op-guide/hardware.html。
在特殊情况下考虑多个 etcd 集群
对于非常大的 Kubernetes 集群,请考虑为 Kubernetes 事件使用单独的 etcd 集群,这样事件风暴就不会影响主要的 Kubernetes API 服务。如果您使用 flannel 网络,它会将配置保留在 etcd 中,并且可能具有与 Kubernetes 不同的版本要求,这可能会使 etcd 备份变得复杂 - 请考虑为 flannel 使用专用的 etcd 集群。
单主机部署
可用性风险列表包括硬件、软件和人员。如果仅限于单主机,则使用冗余存储、纠错内存和双电源可以减少硬件故障暴露。在物理主机上运行虚拟机管理程序将允许冗余软件组件的运行,并增加与部署、升级和资源消耗治理相关的操作优势,并在压力下实现可预测和可重复的性能。例如,即使您只能负担运行主服务的单例,也需要保护它们免受过载和资源耗尽的影响,同时与您的应用程序工作负载竞争。与配置 Linux 调度程序优先级、cgroup、Kubernetes 标志等相比,虚拟机管理程序可能更有效且更易于管理。
如果主机上的资源允许,您可以部署三个 etcd VM。每个 etcd VM 都应由不同的物理存储设备支持,或者它们应使用具有冗余(镜像、RAID 等)的后备存储的单独分区。
如果您的单主机具有资源,则下一个升级将是 API 服务器、调度器和控制器管理器的双冗余实例。
单主机部署选项,从最不值得生产到更好
双主机部署
对于两台主机,etcd 的存储问题与单主机相同,您需要冗余。并且您最好运行 3 个 etcd 实例。虽然可能违反直觉,但最好将所有 etcd 节点集中在一台主机上。通过在两台主机上进行 2+1 拆分,您不会获得可靠性 - 因为丢失持有大多数 etcd 实例的节点会导致中断,无论该多数是 2 还是 3。如果主机不相同,请将整个 etcd 集群放在最可靠的主机上。
建议运行冗余 API 服务器、kube-scheduler 和 kube-controller-manager。这些应在主机之间拆分,以最大限度地减少由于容器运行时、操作系统和硬件故障造成的风险。
在物理主机上运行虚拟机管理程序层将允许冗余软件组件的运行,并具有资源消耗治理,并且可以具有计划的维护操作优势。
双主机部署选项,从最不值得生产到更好
三台(或更多)主机部署 - 进入不妥协的生产级服务,建议在三台主机上拆分 etcd。单次硬件故障将降低应用程序工作负载容量,但不应导致服务完全中断。
对于非常大的集群,将需要更多的 etcd 实例。
运行虚拟机管理程序层可提供操作优势和更好的工作负载隔离。本文超出本文范围,但在三台或更多主机级别,可能会提供高级功能(集群冗余共享存储、具有动态负载平衡的资源治理、具有实时迁移或故障转移的自动化运行状况监控)。
三台(或更多)主机选项,从最不值得生产到更好
Kubernetes 配置设置
应保护主节点和工作节点免受过载和资源耗尽的影响。虚拟机管理程序功能可用于隔离关键组件并保留资源。还有一些 Kubernetes 配置设置可以限制诸如 API 调用速率和每个节点的 Pod 数之类的东西。一些安装套件和商业发行版会处理此问题,但是如果您正在执行自定义 Kubernetes 部署,您可能会发现默认值不合适,尤其是在您的资源较小或集群较大时。
控制平面的资源消耗将与 Pod 的数量和 Pod 的流失率相关。非常大和非常小的集群将受益于 kube-apiserver 请求节流和内存的非默认设置。这些设置过高可能会导致超出请求限制和内存不足错误。
在工作节点上,应根据每个节点合理的、可支持的工作负载密度配置 节点可分配资源。可以创建命名空间,将工作节点集群细分为多个虚拟集群,并使用 CPU 和内存 配额 进行资源管理。可以配置 Kubelet 处理资源不足的情况。
安全
每个 Kubernetes 集群都有一个集群根证书颁发机构 (CA)。需要生成并安装控制器管理器、API 服务器、调度器、kubelet 客户端、kube-proxy 和管理员证书。如果使用安装工具或发行版,则可能会为您处理此问题。 此处描述了一个手动过程。您应该准备好在节点更换或扩展时重新安装证书。
由于 Kubernetes 完全由 API 驱动,因此控制和限制谁可以访问集群以及允许他们执行哪些操作至关重要。此文档中讨论了加密和身份验证选项。
Kubernetes 应用程序工作负载基于容器镜像。您希望这些镜像的来源和内容是可信的。这几乎总是意味着您将托管本地容器镜像存储库。从公共互联网拉取镜像可能会出现可靠性和安全性问题。您应选择支持镜像签名、安全扫描、镜像推送和拉取访问控制以及活动日志记录的存储库。
必须制定流程来支持应用主机固件、虚拟机管理程序、操作系统、Kubernetes 和其他依赖项的更新。应建立版本监控以支持审计。
建议
- 加强控制平面组件的安全设置,超出默认值(例如,锁定工作节点)
- 使用Pod 安全策略
- 考虑与您的网络解决方案集成的NetworkPolicy,包括如何完成跟踪、监控和故障排除。
- 使用 RBAC 来驱动授权决策和实施。
- 考虑物理安全,尤其是在部署到可能无人值守的边缘或远程办公室位置时。包括存储加密,以限制被盗设备带来的风险,并防止恶意设备(如 USB 密钥)的连接。
- 保护 Kubernetes 纯文本云提供商凭据(访问密钥、令牌、密码等)
Kubernetes secret 对象适用于保存少量敏感数据。这些数据保留在 etcd 中。这些数据可以很容易地用于保存 Kubernetes API 的凭据,但有时工作负载或集群本身的扩展需要功能更完善的解决方案。如果需要的不仅仅是内置的 secret 对象所能提供的,HashiCorp Vault 项目是一个流行的解决方案。
灾难恢复和备份
通过使用多个主机和虚拟机来利用冗余有助于减少某些类型的停机,但诸如全站点自然灾害、错误的更新、被黑客攻击、软件错误或人为错误等情况仍可能导致停机。
生产部署的关键部分是预测未来可能发生的恢复。
还值得注意的是,如果您需要在多个站点进行大规模复制部署,那么您在设计、记录和自动化恢复过程方面的部分投入也可能会重复使用。
DR 计划的要素包括备份(可能还有副本)、替换、计划流程、可以执行该流程的人员以及定期培训。定期测试演练和混沌工程原则可用于审计您的准备情况。
您的可用性要求可能需要您保留操作系统、Kubernetes 组件和容器镜像的本地副本,以便即使在互联网中断期间也能进行恢复。“气隙”场景中部署替换主机和节点的能力还可以提供安全性和部署速度的优势。
所有 Kubernetes 对象都存储在 etcd 上。定期备份 etcd 集群数据对于在灾难场景(例如,丢失所有主节点)下恢复 Kubernetes 集群非常重要。
可以使用 etcd 的内置快照机制完成 etcd 集群的备份,并将生成的快照文件复制到不同故障域中的存储。快照文件包含所有 Kubernetes 状态和关键信息。为了确保敏感 Kubernetes 数据的安全,请对快照文件进行加密。
基于磁盘卷的 etcd 快照恢复可能会出现问题;请参阅 #40027。基于 API 的备份解决方案(例如,Ark)可以提供比 etcd 快照更精细的恢复,但也可能更慢。您可以同时使用快照和基于 API 的备份,但您至少应执行一种 etcd 备份形式。
请注意,某些 Kubernetes 扩展可能会在独立的 etcd 集群、持久卷上或通过其他机制维护状态。如果此状态至关重要,则应制定备份和恢复计划。
某些关键状态保存在 etcd 之外。证书、容器镜像和其他配置和操作相关状态可能由您的自动化安装/更新工具管理。即使可以重新生成这些项,备份或复制也可能允许在故障后更快地恢复。考虑对这些项进行备份并制定恢复计划
- 证书和密钥对
- CA
- API 服务器
- Apiserver-kubelet-client
- ServiceAccount 签名
- “前端代理”
- 前端代理客户端
- 关键 DNS 记录
- IP/子网分配和预留
- 外部负载均衡器
- kubeconfig 文件
- LDAP 或其他身份验证详细信息
- 云提供商特定的帐户和配置数据
生产工作负载的注意事项
可以使用反亲和性规范将集群服务拆分到备份主机上,但目前这些设置仅在 pod 调度时使用。这意味着 Kubernetes 可以重新启动集群应用程序的失败节点,但没有本机机制在故障恢复后重新平衡。这是一个值得单独撰写博客的主题,但在主机或工作节点恢复或扩展后,补充逻辑可能有助于实现最佳工作负载放置。Pod 优先级和抢占功能可用于在故障或突发工作负载导致资源短缺时指定首选的分类。
对于有状态服务,外部附加卷挂载是非集群服务的标准 Kubernetes 建议(例如,典型的 SQL 数据库)。目前,Kubernetes 管理的这些外部卷的快照属于 路线图功能请求的范畴,很可能与容器存储接口 (CSI) 集成保持一致。因此,对此类服务执行备份将涉及特定于应用程序的、在 pod 内的活动,这超出了本文档的范围。在等待 Kubernetes 对快照和备份工作流提供更好支持的同时,在虚拟机而不是容器中运行数据库服务,并将其暴露给 Kubernetes 工作负载可能值得考虑。
集群分布式有状态服务(例如,Cassandra)可以受益于跨主机拆分,如果资源允许,可以使用本地持久卷。这将需要部署多个 Kubernetes 工作节点(可以是虚拟机管理程序主机上的虚拟机),以便在单点故障下保持仲裁。
其他注意事项
日志和指标(如果收集并持久保留)对于诊断停机很有价值,但鉴于可用技术的种类繁多,本文将不做介绍。如果可以进行互联网连接,则可能希望将日志和指标外部保留在中心位置。
您的生产部署应使用自动化安装、配置和更新工具(例如,Ansible、BOSH、Chef、Juju、kubeadm、Puppet 等)。手动过程将存在重复性问题,劳动强度大,容易出错且难以扩展。认证发行版很可能包括跨更新保留配置设置的功能,但如果您实现自己的安装和配置工具链,则保留、备份和恢复配置工件至关重要。考虑将您的部署组件和设置保存在版本控制系统(如 Git)下。
停机恢复
记录恢复程序的运行手册应经过测试并离线保留——甚至可以打印出来。当值班人员在周五晚上凌晨 2 点被叫醒时,可能不是即兴发挥的好时机。最好从预先计划好的、经过测试的清单中执行操作——由远程和现场人员共享访问权限。
最后的想法
购买商业航空公司的机票既方便又安全。但是,当您前往跑道短的偏远地区时,那架商业空客 A320 航班就不是一个选择了。这并不意味着乘飞机旅行是不可能的。这确实意味着一些妥协是必要的。
航空领域的格言是,在单引擎飞机上,发动机故障意味着你坠毁。有了双引擎,至少你会有更多选择在哪里坠毁。少量主机上的 Kubernetes 也是如此,如果您的业务案例证明了这一点,您可以扩展到更大规模的混合大型和小型车辆(例如,联邦快递、亚马逊)。
设计生产级 Kubernetes 解决方案的人有很多选择和决定。一篇博客文章的长度无法提供所有答案,也无法了解您的具体优先级。我们希望这能提供一个需要考虑的事项清单,以及一些有用的指导。一些选项被“删除”(例如,使用自托管而不是静态 pod 运行 Kubernetes 组件)。如果有兴趣,这些可能会在后续文章中介绍。此外,Kubernetes 的高增强率意味着,如果您的搜索引擎在 2019 年之后找到了这篇文章,某些内容可能已过“保质期”。