深度解读:如何实现生产级别 K8S 全方位部署
技术
作者:小君君
译者:小君君
2018-08-21 10:58

本文将为用户在内部部署数据中心或在边缘位置等环境中,运行生产级 Kubernetes 集群提供指南,让用户在遇到资源限制时,可以实现 Kubernetes 部署。 

“生产级别”是什么意思?

  • 安全安装
  • Deployment 通过可重复和记录的流程进行管理
  • 性能可预测且一致
  • 可以安全地更新应用和更改配置
  • 利用日志和监控来检测故障和资源短缺
  • 考虑资源的可用性,包括对资金、物理空间、电力等限制,保证 Service 的高可用性。
  • 在发生故障时,恢复进程可用来记录和测试。

简而言之,生产级别的 Kubernetes 可以最小的代价和延迟实现事故预测和恢复准备。 

本文主要关注虚拟机监控程序或裸机平台进行本地 Kubernetes 部署问题。与公共云的可扩展性相比,私有云的支持资源更有限。如果,预算制约了你的选择,接下来的一些信息对于公有云也适用。 

单节点的裸机 Minikube 部署可能既便宜又容易,但这不属于生产级别。举例来说,你不太可能在零售商店、分支机构体验 Google 的 Borg,也不太可能用的到它。 

Kubernetes 集群中的关键组件 

在深入了解细节之前,有必要先了解一下 Kubernetes 的整体架构。 

Kubernetes 集群是基于 control plane 和集群节点架构的高度分布式系统,如下图所示: 

通常,API server、Controller Manager 和 Scheduler 组件共同位于 control plane(也称为 Master node)的多个实例中。高可用性系统和大型集群场景中会被要求在独立主机上运行 etcd(Master node中也包括 etcd)。组件可以选择利用 Kubernetes 来监督,作为容器ll来运行,也可以理解为当作静态容器运行。 

为了实现组件的高可用性,我们会使用这些组件的冗余实例,但在使用时实例的重要性和要求程度各有不同。 

从 HA 角度看 Kubernetes 组件 

这些组件的风险包括硬件故障、软件错误、错误更新、人为错误、网络中断以及导致资源耗尽的过载系统。冗余可以减轻这些危害的影响。此外,虚拟机监控程序平台的资源调度和高可用功能可以通过 Linux 操作系统、Kubernetes 和独立运行的容器功能来降低风险。 

API Server 使用负载均衡器后的多个实例来实现伸缩性和可用性。负载均衡器是 HA 的关键组件。如果你没有负载均衡器,则可能有多个 DNS API Server 的“A”记录。

多个 Kube-scheduler 和 kube-controller-manager 的选择通过“竞争上岗” ,而不是使用负载均衡器来实现。由于选择的托管基础设施类型是 cloud-controller-manager,但这些基础设施是会变化的。因此除了指明它们是 control plane 组件之外,将不予讨论。

在 Kubernetes Worker Nodes 上运行的 Pod 是由 kubelet 代理管理。在每个工作实例上都运行一个 kubelet 代理和 CRI 兼容容器。Kubernetes 本身旨在监视和恢复 Worker Node 中断。但对于关键 workloads,可以使用 hypervisor 资源管理、工作负载隔离和可用性功能来增强可用性,并使性能更具可预测性。   

etcd

etcd 是所有 Kubernetes 对象的持久存储组件。在生产级 Kubernetes 部署中首要考虑的问题应该是 etcd 集群的可用性和可恢复性。  

如果你能负担起五个节点的 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 service。如果你使用 flannel 网络部署,它就会有和 Kubernetes 版本不同的要求,它将保留 etcd 中的配置,这会使 etcd 备份变得复杂——请考虑为 flannel 使用专用的 etcd 集群。 

单主机部署 

可用性风险列表包括硬件、软件和人员。如果你仅限于一台主机,使用冗余存储、纠错内存和双电源可减少硬件故障。在物理主机上运行虚拟机管理程序,就会在程序的影响下产生可重复的性能,这些性能具有可预测性。整个过程将允许冗余组件运行,通过组件的运行来增加部署升级和资源消耗相关的操作优势。例如,即使你只能负担得起运行主服务的单例模式,也需要在与应用程序 workload 竞争时保证它们免受过载和资源耗尽之苦。与 Linux 调度优先级,Cgroup,Kubernetes  flags 等相比,虚拟机管理程序可以更有效,更容易地进行管理。 

如果主机的资源允许,你可以部署三个 etcd VM。每个 etcd VM 应由不同的物理存储设备支持,或者它们应在冗余(镜像,RAID 等)之后使用备份存储单独分区。 

如果你的单个主机具有资源,则 API server,scheduler 和 controller manager 的双冗余实例将是下一个升级对象。 

单主机部署选项,生产值越少越好 

双主机部署 

对于两台主机,etcd 的存储问题与单个主机相同,也需要进行冗余。你最好运行 3 个 etcd 实例,并将所有的 etcd 节点集中在一台主机上,尽管这样做会有违视觉感但在两台主机上进行 2 + 1 拆分是不可靠的——无论节点数是 2 还是 3,只要丢失拥有大多数 etcd 实例的节点就会导致进程中断。如果主机不相同,请将整个 etcd 集群放在最可靠的主机上。 

建议运行冗余 API  Servers,kube-scheduler 和 kube-controller-managers。这些冗余应该在主机之间进行拆分,在容器运营时最大程度地降低操作系统和硬件故障造成的风险。

在物理主机上运行一个 hypervisor 层,可实现冗余组件使用资源消耗管理,并可以有计划地维护操作。

双主机部署选项,生产值越少越好   

三重(或更大)主机部署 - 进入 uncompromised 生产级服务建议跨三台主机拆分etcd。单个硬件故障将降低应用程序的 workload 容量,但这也不会使整个服务中断。 

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

运行虚拟机管理程序层可以提供更好的操作和 workload 隔离,但这些将超出本文的指导范围。在三个或更多主机级别上,是可以使用高级功能的(集群冗余共享存储,动态负载平衡资源管理,实时迁移或自动健康监控的故障转移)。 

三重(或更多)主机选项,保证精质精量 

Kubernetes 的配置设置 

应保护 Master node 和 Worker Node 免受过载和资源耗尽的影响。虚拟机监控程序可用在隔离关键组件上,并保留资源。Kubernetes 配置设置可限制诸如 API 接口调用率和每个节点的 Pod 。其实你也不用担心配置设置这个问题,因为一些安装套件和商业发行版会负责处理此类问题。但如果你正在执行一个定制的 Kubernetes 部署,就会发现默认值并不合适,尤其是在资源较小或集群较大的情况下。 

Control plane 的资源消耗会与 Pod 数量和 Pod 流失率相关。极大或极小的集群将受益于  kube-apiserver 的请求限制和内存的非默认设置。如果这些值过高,会超出请求限制从而导致内存不足。 

在 Worker Node 上,应根据每个节点上的 workload 密度来分配节点。可以通过创建 Namespaces 将 Worker Node 集群细分为具有 CPU 资源和内存配额的多个虚拟集群,同时可以利用配置 kubelet 来处理资源不足的情况。 

安全 

每个 Kubernetes 集群都有一个 cluster root 证书颁发机构(CA)。需要生成并安装 Controller Manager,API Server,Scheduler,kubelet 客户端,kube-proxy 和管理员证书。如果你使用安装工具或分布式,这里描述了一个手动过程。你应准备好在节点替换或扩展时重新安装证书。 

由于 Kubernetes 完全由 API 驱动,因此控制和限制谁可以访问集群,以及允许谁执行哪些操作至关重要。接下来本文将介绍加密和身份验证选项。 

Kubernetes 应用程序 workload 基于容器镜像。这些镜像的来源和内容必须是值得信赖的。这意味着你将托管整个本地容器镜像存储库。从公网中提取镜像可能会带来可靠性和安全性问题。你应该选择一个支持镜像签名、安全扫描、推送和拉取镜像的访问控制以及活动记录的存储库。 

必须具备支持应用主机固件,虚拟机管理程序,操作系统,Kubernetes 和其他依赖项的更新流程。应该进行版本监控以支持审核。 

建议

  • 加强 Control plane 组件上的安全设置超出默认值(例如,锁定 Worker Node)
  • 利用 Pod 安全策略
  • 根据自身的网络解决方案与可用的 NetworkPolicy 集成。包括如何完成跟踪,监控和故障排除
  • 使用 RBAC 来推动授权决策和执行。
  • 考虑物理安全性,尤其是在部署到可能无人值守的边缘或远程办公室位置时。包括存储加密,以限制被盗设备的暴露,并防止附加 USB 密钥等恶意设备。
  • 保护 Kubernetes 纯文本云供应商程序凭据(访问密钥,令牌,密码等)

Kubernetes secret 对象可以保存少量敏感数据。这些敏感信息都保留在 etcd 中。这些可以很容易地用于保存 Kubernetes API 凭据,但有时 workload 或集群的扩展本身需要功能更全的解决方案。如果你需要的内容多于内置的 secret 对象,HashiCorp Vault 项目是一种很流行的解决方案。

灾难恢复和备份  



通过使用多个主机和 VM 达到冗余效果,以此减少一些类别的中断情况,但是诸如全站点自然灾害,不良更新,黑客入侵,软件错误或人为错误等情况时仍会出现中断。

生产部署的一个关键部分是预测未来的所有可能性。

值得注意的是,如果你要在多个站点进行大规模复制部署。那么设计、记录和自动化恢复流程也是重中之重。  

恢复计划(Disaster Recovery)的要素包括备份(可能是副本)、替换、计划流程、执行者的重复培训。定期的测试练习和 Chaos Engineering 可用于审核部署。 

可用性需求会要求你保留操作系统、Kubernetes 组件和容器镜像的本地副本,保证在 网络中断期也可进行部署恢复。在“空隙”场景中部署替换主机和节点将会提高安全性和部署速度。 

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

可以使用 etcd 的内置快照机制来备份 etcd 集群,并将生成的文件复制到不同故障域中进行存储。快照文件包含所有的 Kubernetes 状态和关键信息。为了保证 Kubernetes 的数据安全,需要对快照文件进行加密。 

使用基于磁盘卷的 etcd 快照恢复可能会出现问题; 会看见错误命令#40027。基于 API 备份解决方案(例如,Ark)可提供比 etcd 快照更细致的恢复,但恢复时间更慢。在使用 etcd 备份时,你可以使用快照和基于 API 的备份。

请注意,一些 Kubernetes 扩展可能在独立的 etcd 集群中、在持久卷上或在其他机制中维护状态。如果此状态至关重要,还需要存在备份和恢复计划。  

除了 etcd 之外会存在很多关键状态。证书、容器镜像和其他与配置操作相关的状态可以由你的自动安装/更新工具来管理。这些项目可以考虑使用恢复计划进行备份。这样在发生故障后就可以通过重置、备份或复制来进行快速恢复。

  • 证书和密钥对
  • CA
  • API Server
  • API 服务器-kubelet-客户端
  • ServiceAccount 签名
  • “Front proxy”
  • 前代理客户端
  • 关键 DNS 记录
  • IP /子网划分和预留
  • 外部负载平衡器
  • Kubeconfig 文件
  • LDAP 或其他身份验证的详细信息
  • 云提供商特定帐户和配置数据 

 生产 workloads 的注意事项 


Anti-affinity 规范可用于跨备份主机拆分集群服务,但该服务仅在调度 Pod 时进行设置。这就意味着 Kubernetes 可以重新启动集群应用程序的故障节点,但在恢复故障后将不存在平衡本机的机制。这是一个值得单独成文的主题,但这种补充逻辑对于主机或 Worker Node 恢复或扩展后的最佳 workloads 分配状态可能会有用。在故障或 workloads 激增而导致资源短缺的情况下,因为 Pod 存在优先级和抢占功能,所以 Pod 可作为指定的首选分类。 

在 Kubernetes 的建议部署下,对于有状态的服务来说外部附加卷挂载利用非集群服务(例如,典型 SQL 数据库)标准。此时,Kubernetes 管理的外部卷快照属于路线图功能请求范畴,会与容器存储接口(CSI)的集成保持一致。因此,执行此类服务的备份将涉及一些特定应用程序的 in-pod 活动(但这将超出本文范围)。在 VM(而不是容器)中运行数据库服务和等待 Kubernetes 快照支持及备份工作流时,应将该活动暴露给 Kubernetes workload 。 

集群分布式存在状态服务(例如,Cassandra)可以在资源允许的情况下使用本地持久卷来跨主机进行拆分获得受益。但是这需要部署多个 Kubernetes Worker Node(可能是虚拟机管理程序上的 VM)用于在单点故障下保留仲裁。 

其他考虑 

日志和监控指标(如果收集并持续保留)对诊断中断进程很有价值,但鉴于可用的技术种类繁多,本文不予解决这些问题。如果 Internet 连接可用,则最好在中心位置外部保留日志和参数标准。 

你的生产部署应使用自动安装、配置和更新工具(例如,Ansible,BOSH,Chef,Juju,kubeadm,Puppet 等)。手动过程会有重复性问题且劳动强度大,容易出错、难以扩展。经过认证的发行版可能包含一个保留更新配置的设置工具,但如果你想自己去实现安装和配置,就要考虑将部署组件和设置放在版本控制系统(如 Git)下,在这种情况下组件的保留、备份和恢复将非常重要。 

停电恢复 

被测试的 Runbook 应该保持离线状态 —— 甚至打印出来。就比如在星期五凌晨 2 点时突然召唤工作人员进行工作可能不大妥当。这就需要提前计划,通过测试过的清单严格执行 —— 由远程和现场人员共同访问。 

最后的想法 

在航空公司购买机票既方便又安全。但是当你前往一个跑道很短的偏远地区时,商用空中客车 A320 飞机就不太合适了。这并不意味着航空旅行就免谈了。这只是表明我们必须做出一定地妥协。

航空铁律是,在单引擎飞机上,发动机故障意味着坠毁。使用双引擎,至少可以让你对坠毁地点作出更多选择。这与 Kubernetes 在少数主机上运行是相似的,如果你的商业案例证明了这一点,你可能会把成功经验应用到更大的混合大型和小型“交通工具”上(例如,FedEx,Amazon)。  

那些设计生产级 Kubernetes 解决方案的人可以有很多选择。一篇文章肯定无法提供所有答案,也无法了解你的具体情况。我们希望这篇文章为你提供一个需要考虑的事项清单,以及一些有用的指导。 


184 comCount 0