本文发表时间已超过一年。较早的文章可能包含过时的内容。请核实页面中的信息自发布以来是否仍然正确。

从云端落地:如何在任何地方打造生产级 Kubernetes

本文为在本地数据中心或边缘位置等环境中运行生产级 Kubernetes 集群提供了一些指导。

“生产级”是什么意思?

  • 安装是安全的
  • 部署采用可重复和有记录的流程进行管理
  • 性能可预测且一致
  • 更新和配置变更可以安全地应用
  • 具备日志记录和监控功能,用于检测和诊断故障和资源短缺
  • 考虑到可用资源(包括金钱、物理空间、电力等限制),服务应具备“足够高可用”的特性。
  • 具备恢复流程,并有文档记录且经过测试,可在发生故障时使用

简而言之,生产级意味着预见事故,并做好准备以最小的痛苦和延迟进行恢复。

本文针对在虚拟机监控程序或裸金属平台上进行本地 Kubernetes 部署,与主要公有云的可扩展性相比,此类环境面临有限的后端资源。但是,如果预算限制了您选择使用的资源,这些建议中的一些也可能在公有云中有用。

单节点裸金属 Minikube 部署可能既便宜又简单,但它不是生产级的。反之,您也不太可能在零售商店、分支机构或边缘位置实现 Google Borg 那样的体验,而且您可能也不需要它。

本文就如何在资源受限的情况下实现生产级 Kubernetes 部署提供了一些指导。

without incidence

Kubernetes 集群中的关键组件

在深入细节之前,了解整体 Kubernetes 架构至关重要。

Kubernetes 集群是一个高度分布式的系统,基于控制平面和集群式工作节点架构,如下图所示。

api server

通常,API 服务器、控制器管理器和调度器组件共同位于控制平面(又称主节点)的多个实例中。主节点通常也包含 etcd,尽管在高可用和大型集群场景下,需要在独立主机上运行 etcd。这些组件可以作为容器运行,也可以选择由 Kubernetes 管理,例如作为静态 Pod 运行。

为了实现高可用,会使用这些组件的冗余实例。冗余的重要性和所需程度各不相同。

从高可用角度看 Kubernetes 组件

kubernetes components HA

这些组件面临的风险包括硬件故障、软件 Bug、错误的更新、人为错误、网络中断以及系统过载导致的资源耗尽。冗余可以减轻其中许多风险的影响。此外,虚拟机监控程序平台的资源调度和高可用特性有助于超越仅使用 Linux 操作系统、Kubernetes 和容器运行时所能达到的能力。

API 服务器使用负载均衡器后的多个实例来实现扩展和可用性。负载均衡器是实现高可用的关键组件。如果您没有负载均衡器,多个 DNS API 服务器的 ‘A’ 记录可能是一种替代方案。

kube-scheduler 和 kube-controller-manager 通过 Leader 选举过程协作,而不是利用负载均衡器。由于特定类型的托管基础设施使用 cloud-controller-manager,且这些管理器有实现差异,本文将不再深入讨论,只说明它们是控制平面组件。

运行在 Kubernetes 工作节点上的 Pod 由 kubelet 代理管理。每个工作实例运行 kubelet 代理和 CRI 兼容的容器运行时。Kubernetes 本身旨在监控和从工作节点故障中恢复。但对于关键工作负载,可以使用虚拟机监控程序的资源管理、工作负载隔离和可用性特性来增强可用性并使性能更可预测。

etcd

etcd 是所有 Kubernetes 对象的持久化存储。etcd 集群的可用性和可恢复性应该是生产级 Kubernetes 部署的首要考虑因素。

如果条件允许,五节点 etcd 集群是最佳实践。为什么?因为您可以对其中一个节点进行维护,同时还能容忍一个节点的故障。即使只有一个虚拟机监控程序主机可用,三节点集群也是生产级服务的最低建议配置。不建议使用七个以上节点,除非是跨多个可用区的超大型安装

托管 etcd 集群节点的最低建议配置是 2GB 内存和 8GB SSD 后备存储。通常,8GB 内存和 20GB 磁盘就足够了。磁盘性能会影响故障节点的恢复时间。关于这方面的更多信息,请参阅https://coreos.com/etcd/docs/latest/op-guide/hardware.html

特殊情况下的多个 etcd 集群考虑

对于超大型 Kubernetes 集群,考虑为 Kubernetes 事件使用独立的 etcd 集群,以便事件风暴不会影响主要的 Kubernetes API 服务。如果您使用 flannel 网络,它会将配置保存在 etcd 中,并且可能与 Kubernetes 的版本要求不同,这会使 etcd 备份复杂化 -- 考虑为 flannel 使用专用的 etcd 集群。

单主机部署

可用性风险清单包括硬件、软件和人员。如果您仅限于一台主机,使用冗余存储、纠错内存和双电源可以减少硬件故障风险。在物理主机上运行虚拟机监控程序可以实现冗余软件组件的运行,并在部署、升级和资源消耗治理方面增加操作优势,在压力下提供可预测和可重复的性能。例如,即使您只能负担运行主服务的单实例,它们也需要在与应用程序工作负载竞争时受到保护,避免过载和资源耗尽。虚拟机监控程序比配置 Linux 调度器优先级、cgroups、Kubernetes 标志等更有效且更容易管理。

如果主机上的资源允许,您可以部署三个 etcd 虚拟机。每个 etcd 虚拟机应由不同的物理存储设备支持,或者它们应使用具有冗余(镜像、RAID 等)的后备存储的不同分区。

如果您的单主机有资源,API 服务器、调度器和控制器管理器的双冗余实例将是下一个升级选项。

单主机部署选项,从最低生产级到更好

single host deployment

双主机部署

使用两台主机时,etcd 的存储问题与单主机相同,您需要冗余。并且您最好运行 3 个 etcd 实例。尽管这可能违反直觉,但最好将所有 etcd 节点集中在一台主机上。通过在两台主机上进行 2+1 分割并不能提高可靠性 - 因为丢失持有多数 etcd 实例的节点会导致中断,无论这个多数是 2 还是 3。如果主机不完全相同,请将整个 etcd 集群放在最可靠的主机上。

建议运行冗余的 API 服务器、kube-scheduler 和 kube-controller-manager。这些组件应分散在不同的主机上,以最大程度地减少由于容器运行时、操作系统和硬件故障带来的风险。

在物理主机上运行虚拟机监控程序层将允许操作冗余软件组件,并进行资源消耗管理,并且在计划性维护方面具有操作优势。

双主机部署选项,从最低生产级到更好

dual host deployment

三台(或更多)主机部署 -- 迈向无妥协的生产级服务 建议将 etcd 分布在三台主机上。单个硬件故障会降低应用程序工作负载容量,但不应导致服务完全中断。

对于超大型集群,将需要更多的 etcd 实例。

运行虚拟机监控程序层提供了操作优势和更好的工作负载隔离。这超出了本文的范围,但在三台或更多主机的级别,可能可以使用高级功能(集群式冗余共享存储、带动态负载均衡的资源治理、带实时迁移或故障转移的自动化健康监控)。

三台(或更多)主机选项,从最低生产级到更好

triple host deployment

Kubernetes 配置设置

主节点和工作节点应受到保护,避免过载和资源耗尽。虚拟机监控程序功能可用于隔离关键组件并保留资源。也有 Kubernetes 配置设置可以限制诸如 API 调用速率和每个节点上的 Pod 数量等。一些安装套件和商业发行版会处理这些,但如果您正在进行自定义 Kubernetes 部署,您可能会发现默认设置不合适,特别是如果您的资源较少或集群较大。

控制平面的资源消耗与 Pod 的数量和 Pod 的流失率相关。超大型和超小型集群将受益于 kube-apiserver 请求限流和内存的非默认设置。这些设置过高可能导致请求超出限制和内存不足错误。

在工作节点上,节点可分配资源 (Node Allocatable) 应根据每个节点合理可支持的工作负载密度进行配置。可以创建命名空间来将工作节点集群细分为多个虚拟集群,并设置资源 CPU 和内存配额。可以配置 Kubelet 如何处理资源不足的情况。

每个 Kubernetes 集群都有一个集群根证书颁发机构 (CA)。需要生成和安装 Controller Manager、API Server、Scheduler、kubelet 客户端、kube-proxy 和管理员证书。如果您使用安装工具或发行版,这部分工作可能会由工具或发行版处理。手动过程在此描述。您应做好在节点替换或扩展时重新安装证书的准备。

由于 Kubernetes 完全由 API 驱动,因此控制和限制谁可以访问集群以及允许他们执行哪些操作至关重要。有关加密和身份验证选项,请参阅此文档

Kubernetes 应用程序工作负载基于容器镜像。您希望这些镜像的来源和内容是可信的。这几乎总是意味着您将托管本地容器镜像仓库。从公共互联网拉取镜像可能会带来可靠性和安全问题。您应选择一个支持镜像签名、安全扫描、镜像推拉访问控制以及活动日志记录的仓库。

必须有相应的流程来支持应用主机固件、hypervisor、操作系统、Kubernetes 和其他依赖项的更新。应进行版本监控以支持审计。

建议

  • 加强控制平面组件的默认安全设置(例如,锁定工作节点)。
  • 使用Pod 安全策略
  • 考虑您的网络解决方案提供的网络策略集成,包括如何实现追踪、监控和故障排除。
  • 使用 RBAC 进行授权决策和强制执行。
  • 考虑物理安全性,尤其是在部署到可能无人值守的边缘或远程办公室位置时。包括存储加密,以限制设备被盗造成的风险,并防止恶意设备(如 USB 驱动器)的连接。
  • 保护 Kubernetes 明文云提供商凭据(访问密钥、令牌、密码等)

Kubernetes Secret 对象适用于存储少量敏感数据。这些数据保存在 etcd 中。Secret 可以方便地用于存储 Kubernetes API 的凭据,但有时工作负载或集群本身的扩展需要更全面的解决方案。如果您需要的功能超出内置 Secret 对象所能提供,HashiCorp Vault 项目是一个流行的解决方案。

灾难恢复与备份

disaster recovery

通过使用多台主机和虚拟机来实现冗余有助于减少某些类型的宕机,但像全站自然灾害、错误的更新、被黑客攻击、软件缺陷或人为错误等场景仍然可能导致宕机。

生产部署的关键部分是预见到未来可能的恢复需求。

值得注意的是,您在设计、记录和自动化恢复流程方面的一些投入,如果需要在多个站点进行大规模复制部署,也可能可以重复使用。

灾难恢复(DR)计划的要素包括备份(可能还有副本)、替换、计划好的流程、能够执行流程的人员以及定期的培训。定期的测试演练和混沌工程原则可用于检查您的准备情况。

您的可用性要求可能需要您保留操作系统、Kubernetes 组件和容器镜像的本地副本,以便即使在互联网中断期间也能进行恢复。在“气隙”(air-gapped)场景下部署替换主机和节点的能力也能提供安全性和部署速度优势。

所有 Kubernetes 对象都存储在 etcd 中。定期备份 etcd 集群数据对于在灾难场景下(例如丢失所有主节点)恢复 Kubernetes 集群至关重要。

可以通过 etcd 的内置快照机制来备份 etcd 集群,并将生成的文件复制到位于不同故障域的存储中。快照文件包含所有 Kubernetes 状态和关键信息。为了保护敏感的 Kubernetes 数据安全,请加密快照文件。

使用基于磁盘卷的 etcd 快照恢复可能存在问题;请参阅#40027。基于 API 的备份解决方案(例如,Ark)可以提供比 etcd 快照更细粒度的恢复,但速度也可能更慢。您可以同时使用快照备份和基于 API 的备份,但至少应执行一种形式的 etcd 备份。

请注意,某些 Kubernetes 扩展程序可能在独立的 etcd 集群、持久卷或其他机制中维护状态。如果此状态至关重要,则应有相应的备份和恢复计划。

某些关键状态保存在 etcd 之外。证书、容器镜像以及其他与配置和操作相关的状态可能由您的自动化安装/更新工具进行管理。即使这些项可以重新生成,备份或复制也可能有助于在故障后更快地恢复。考虑对这些项进行备份并制定恢复计划

  • 证书和密钥对
    • CA
    • API Server
    • Apiserver-kubelet-client
    • ServiceAccount 签名
    • “Front Proxy”
    • Front Proxy 客户端
  • 关键 DNS 记录
  • IP/子网分配和预留
  • 外部负载均衡器
  • kubeconfig 文件
  • LDAP 或其他身份验证详情
  • 云提供商特定账户和配置数据

生产工作负载注意事项

反亲和性(Anti-affinity)规范可用于将集群服务分散到不同的支持主机上,但目前这些设置仅在 Pod 调度时使用。这意味着 Kubernetes 可以重启集群应用程序中发生故障的节点,但没有原生机制在故障恢复后进行重新平衡。这是一个值得单独撰写博客的主题,但在主机或工作节点恢复或扩展后,补充逻辑可能有助于实现最佳工作负载放置。此Pod 优先级和抢占功能可用于在因故障或工作负载突增导致资源短缺时指定优先处理顺序。

对于有状态服务,外部挂载卷是 Kubernetes 对于非集群服务(例如典型的 SQL 数据库)的标准建议。目前,Kubernetes 管理这些外部卷的快照属于路线图功能请求类别,可能与容器存储接口(CSI)集成对齐。因此,对此类服务执行备份将涉及应用程序特定的 Pod 内活动,这超出了本文档的范围。在等待 Kubernetes 更好地支持快照和备份工作流程的同时,考虑将数据库服务运行在虚拟机而不是容器中,并将其暴露给 Kubernetes 工作负载可能是值得的。

集群分布式有状态服务(例如 Cassandra)可以通过跨主机分布来受益,如果资源允许,可以使用本地持久卷。这需要部署多个 Kubernetes 工作节点(可以是 hypervisor 主机上的虚拟机)以在单点故障下保持仲裁(quorum)。

其他考虑事项

日志指标(如果收集并持久保留)对于诊断宕机非常宝贵,但考虑到现有技术的 다양性,本文将不予讨论。如果互联网连接可用,将日志和指标集中外部存储可能更为可取。

您的生产部署应利用自动化安装、配置和更新工具(例如,AnsibleBOSHChefJujukubeadmPuppet 等)。手动过程将存在重复性问题、劳动密集、容易出错且难以扩展。认证发行版可能包含在更新时保留配置设置的功能,但如果您实现自己的安装和配置工具链,则配置工件的保留、备份和恢复至关重要。考虑使用版本控制系统(如 Git)管理您的部署组件和设置。

宕机恢复

运行手册(Runbooks)应测试记录恢复过程的运行手册,并离线保存——甚至可以打印出来。当值班人员在周五凌晨 2 点被叫醒时,可能不是进行即兴发挥的好时机。最好是按照预先计划并经过测试的清单执行操作——并提供远程和现场人员的共享访问权限。

总结

airplane

乘坐商业航班既方便又安全。但当您前往跑道较短的偏远地区时,商业航班空客 A320 就不是一个可选项了。这并不意味着航空旅行完全不可能。这意味着需要进行一些妥协。

航空领域有一句格言:单引擎飞机发动机故障意味着坠毁。双引擎飞机至少提供了更多选择,让你决定在哪里坠毁。少量主机上的 Kubernetes 类似,如果您的业务需求证明其合理性,您可以扩展到更大的混合大小机组(例如,FedEx、Amazon)。

设计生产级 Kubernetes 解决方案的人员有很多选项和决策。一篇博客篇幅的文章无法提供所有答案,也无法了解您的具体优先事项。我们希望这能提供一份需要考虑的清单,以及一些有用的指导。有些选项被省略了(例如,使用自托管(self-hosting)而不是静态 Pods 运行 Kubernetes 组件)。如果大家感兴趣,这些内容可能会在后续文章中介绍。此外,Kubernetes 的高迭代速度意味着如果您在 2019 年后通过搜索引擎找到这篇文章,部分内容可能已经过时。