关于 Kubernetes 规划的灵魂 n 问
日期: 2020-03-09 分类: 跨站数据 299次阅读
简介: Kubernetes 已经成为企业新一代云 IT 架构的重要基础设施,但是在企业部署和运维 Kubernetes 集群的过程中,依然充满了复杂性和困扰。
作者 | 易立 阿里云资深技术专家
阿里云容器服务自从 2015 年上线后,目前托管着上万的 K8s 集群来支撑全球各地的客户。我们对客户在规划集群过程中经常会遇见的问题,进行一些分析解答。试图缓解大家的“选择恐惧症”。
如何选择 Worker 节点实例规格?
裸金属还是虚拟机?
在 Dimanti 2019 年的容器调查报告中,对专有云用户选择裸金属服务器来运行容器的主要原因进行了分析。
- 选择裸金属服务器的最主要原因(超过 55%)是:传统虚拟化技术 I/O 损耗较大;对于 I/O 密集型应用,裸金属相比传统虚拟机有更好的性能表现;
- 此外近 36% 的客户认为:裸金属服务器可以降低成本。大多数企业在初始阶段采用将容器运行在虚拟机的方案,但是当大规模生产部署的时候,客户希望直接运行在裸金属服务器上来减少虚拟化技术的 license 成本(这也常被戏称为“VMWare 税”);
- 还有近 30% 的客户因为在物理机上部署有更少的额外资源开销(如虚拟化管理、虚拟机操作系统等);还有近 24% 的客户选择的原因是:可以有更高的部署密度,从而降低基础设施成本;
- 超过 28% 的客户认为,在物理机上可以更加灵活地选择网络、存储等设备和软件应用生态。
在公共云上,我们应该如何选择呢?2017 年 10 月,阿里云“神龙架构”横空出世。弹性裸金属服务器(ECS Bare Metal Instance)是一款同时兼具虚拟机弹性和物理机性能及特性的新型计算类产品,实现超强超稳的计算能力,无任何虚拟化开销。阿里云 2019 年 8 月重磅发布了弹性计算第六代企业级实例,基于神龙架构对虚拟化能力进行了全面升级。
- 基于阿里自研神龙芯片和全新的轻量化 Hypervisor - 极大减少虚拟化性能开销。基于阿里云智能神龙芯片和全新的轻量化 VMM,将大量传统虚拟化功能卸载到专用硬件上,大大降低了虚拟化的性能开销,同时用户几乎可以获得所有的宿主机 CPU 和内存资源,提高整机和大规格实例的各项能力,尤其是 I/O 性能有了大幅度提升;
- 使用最新第二代英特尔至强可扩展处理器 - E2E 性能提升。使用最新一代 Intel Cascade Lake CPU, 突发主频提升至 3.2GHz, 各场景 E2E 性能大幅提升,并在深度学习的多种场景有数倍的提升;
- 给企业级场景带来稳定和可预期的表现 - 全球最高水准 SLA。针对软硬件优化以及更加实施更细致的 QoS 手段,给企业级客户的负载提供更稳定可预期的性能。
一般而言建议:
- 对性能极其敏感的应用,如高性能计算,裸金属实例是较好的选择;
- 如果需要 Intel SGX,或者安全沙箱等技术,裸金属实例是不二选择;
- 六代虚拟机实例基于神龙架构,I/O 性能有了显著提升,同时有更加丰富的规格配置,可以针对自身应用需求灵活选择,降低资源成本;
- 虚拟机实例支持热迁移,可以有效降低运维成本。
阿里云 ACK K8s 集群支持多个节点伸缩组(AutoScalingGroup),不同弹性伸缩组支持不同的实例规格。在工作实践,我们会为 K8s 集群划分静态资源池和弹性资源池。通常而言,固定资源池可以根据需要选择裸金属或者虚拟机实例。弹性资源池建议根据应用负载使用合适规格的虚拟机实例来优化成本、避免浪费,提升弹性供给保障。此外由于裸金属实例一般 CPU 核数非常多,大规格实例在使用中的挑战请参见下文。
较少的大规格实例还是较多的小规格实例?
一个引申的问题是,如何选择实例规格?我们列表对比一下:
默认情况下,kubelet 使用 CFS 配额 来执行 pod 的 CPU 约束。当节点上运行了很多 CPU 密集的应用时,工作负载可能会迁移到不同的 CPU 核,工作负载的会受到 CPU 缓存亲和性以及调度延迟的影响。当使用大规格实例类型时,节点的 CPU 数量较多,现有的 Java,Golang 等应用在多 CPU 共享的场景,性能会出现明显下降。所有对于大规格实例,需要对 CPU 管理策略进行配置,利用 CPU set 进行资源分配。
此外一个重要的考虑因素就是 NUMA 支持。在 NUMA 开启的裸金属实例或者大规格实例上,如果处理不当,内存访问吞吐可能会比优化方式降低了 30%。Topology 管理器可以开启 NUMA 感知 。但是目前 K8s 对 NUMA 的支持比较简单,还无法充分发挥 NUMA 的性能。
https://kubernetes.io/docs/tasks/administer-cluster/topology-manager/
阿里云容器服务提供了 CGroup Controller 可以更加灵活地对 NUMA 架构进行调度和重调度。
如何容器运行时?
Docker 容器还是安全沙箱?
在 Sysdig 发布的 2019 容器使用报告中,我们可以看到 Docker 容器占据市场规模最大的容器运行时 (79%),containerd 是 Docker 贡献给 CNCF 社区的开源容器运行时,现在也占据了一席之地,并且得到了厂商的广泛支持;cri-o 是红帽公司推出的支持 OCI 规范的面向 K8s 的轻量容器运行时,目前还处在初级阶段。
很多同学都关心 containerd 与 Docker 的关系,以及是否 containerd 可以取代 Docker?Docker Engine 底层的容器生命周期管理也是基于 containerd 实现。但是 Docker Engine 包含了更多的开发者工具链,比如镜像构建。也包含了 Docker 自己的日志、存储、网络、Swarm 编排等能力。此外,绝大多数容器生态厂商,如安全、监控、日志、开发等对 Docker Engine 的支持比较完善,对 containerd 的支持也在逐渐补齐。
所以在 Kubernetes 运行时环境,对安全和效率和定制化更加关注的用户可以选择 containerd 作为容器运行时环境。对于大多数开发者,继续使用 Docker Engine 作为容器运行时也是一个不错的选择。
此外,传统的 Docker RunC 容器与宿主机 Linux 共享内核,通过 CGroup 和 namespace 实现资源隔离。但是由于操作系统内核的攻击面比较大,一旦恶意容器利用内核漏洞,可以影响整个宿主机上所有的容器。
越来越多企业客户关注容器的安全性,为了提升安全隔离,阿里云和蚂蚁金服团队合作,引入安全沙箱容器技术。19 年 9 月份我们发布了基于轻量虚拟化技术的 RunV 安全沙箱。相比于 RunC 容器,每个 RunV 容器具有独立内核,即使容器所属内核被攻破,也不会影响其他容器,非常适合运行来自第三方不可信应用或者在多租户场景下进行更好的安全隔离。
阿里云安全沙箱容器有大量性能优化,可以达到 90% 的原生 RunC 性能:
- 利用 Terway CNI 网络插件,网络性能无损;
- 利用 DeviceMapper 构建了⾼速、稳定的容器 Graph Driver;
- 优化 FlexVolume 和 CSI Plugin,把 mount bind 的动作下沉到沙箱容器内,从而避开了 9pfs 带来的性能损耗。
而且,ACK 为安全沙箱容器和和 RunC 容器提供了完全一致的用户体验,包括日志、监控、弹性等。同时,ACK 可以在一台神龙裸金属实例上同时混布 RunC 和 RunV 容器,用户可以根据自己的业务特性自主选择。
同时,我们也要看到安全沙箱容器还有一些局限性,现有很多日志、监控、安全等工具对独立内核的安全沙箱支持不好,需要作为 sidecar 部署在安全沙箱内部。
对于用户而言,如果需要多租户隔离的场景,可以采用安全沙箱配合 network policy 来完成,当然也可以让不同租户的应用运行在不同的虚拟机或者弹性容器实例上,利用虚拟化技术来进行隔离。
注意:安全沙箱目前只能运行在裸金属实例上,当容器应用需要资源较少时成本比较高。可以参考下文的 Serverless K8s 有关内容。
如何规划容器集群?
一个大集群还是一组小集群?
在生产实践中,大家经常问到的一个问题是我们公司应该选择一个还是多个 Kubernetes 集群。
Rob Hirschfeld 在 Twitter 上做了一个调查:
- 一个大一统的平台,支持多种应用负载、环境和多租户隔离;
- 或者,一组以应用为中心的小集群,支持不同应用和环境的生命周期管理。
https://thenewstack.io/the-optimal-kubernetes-cluster-size-lets-look-at-the-data/
大多数的用户选择是后者,典型的场景是:
- 开发、测试环境使用不同的集群
- 不同的部门使用不同的集群进行隔离
- 不同的应用使用不同的集群
- 不同版本的 K8s 集群
在用户反馈中,采用以多个小集群的主要原因在于爆炸半径比较小,可以有效提升系统的可用性。同时通过集群也可以比较好地进行资源隔离。管理、运维复杂性的增加是采用多个小集群的一个不足之处,但是在公共云上利用托管的 K8s 服务(比如阿里云的 ACK)创建和管理 K8s 集群生命周期非常简单,可以有效解决这个问题。
我们可以比较一下这两种选择:
源自 Google Borg 的理念,Kubernetes 的愿景是成为 Data Center Operating System,而且 Kubernetes 也提供了 RBAC、namespace 等管理能力,支持多用户共享一个集群,并实现资源限制。但是这些更多是 “软多租” 能力,不能实现不同租户之间的强隔离。在多租最佳实践中,我们可以有如下的一些建议:
- 数据平面:可以通过 PSP (PodSecurityPolicy) 或者安全沙箱容器,提升容器的隔离性;利用 Network Policy 提升应用之间网络隔离性;可以通过将 nodes 和 namespace 绑定在一起,来提升 namespace 之间资源的隔离;
- 控制平面:Kubernetes 的控制平面包括 master 组件 API Server, Scheduler, etcd 等,系统 addon 如 CoreDNS, Ingress Controller 等,以及用户的扩展,如 3 方的 CRD (Customer Resource Definition) controller。这些组件大多不具备良好的租户之间的安全、资源和故障隔离能力。一个错误的 CRD contoller 实现有可能打挂一个集群的 API Server。
关于 Kubernetes 多租户实践的具体信息可以参考下文。目前而言,Kubernetes 对硬隔离的支持存在很多局限性,同时社区也在积极探索一些方向,如阿里容器团队的 Virtual Cluster Proposal 可以提升隔离的支持,但是这些技术还未成熟。
精华推荐