Kubernetes已经成为企业新一代云IT架构的重要基础设施,但是在企业部署和运维Kubernetes集群的过程中,依然充满了复杂性和困扰。阿里云容器服务自从2015年上线后,一路伴随客户和社区的成长,目前托管着上万的K8s集群来支撑全球各地的客户。我们对客户在规划集群过程中经常会遇见的问题,进行一些分析解答。试图缓解大家的“选择恐惧症”。
在Dimanti 2019年的容器调查报告中,对专有云用户选择裸金属服务器来运行容器的主要原因进行了分析。
在公共云上,我们应该如何选择呢?
2017年10月,阿里云“神龙架构”横空出世。弹性裸金属服务器(ECS Bare Metal Instance)是一款同时兼具虚拟机弹性和物理机性能及特性的新型计算类产品,实现超强超稳的计算能力,无任何虚拟化开销。阿里云2019年8月重磅发布了弹性计算第六代企业级实例,基于神龙架构对虚拟化能力进行了全面升级
ECS实例类型 | 第六代裸金属实例 | 六代虚拟机实例 |
---|---|---|
CPU | 目前包含80/104两种规格 | 2~104 |
CPU与内存配比 | 1:1.8 ~ 1:7.4 | 1:2 ~ 1:8 |
虚拟化资源开销 | 没有 | 极小 |
GPU支持 | 是 (部分型号) | 是 (部分型号) |
支持Intel SGX | 是 (部分型号) | 否 |
支持安全沙箱容器(如KataContainer, 阿里云安全沙箱容器等) | 是 | 否 |
支持License绑定硬件 | 是 | 是 (DDH支持) |
支持热迁移 | 否 (支持宕机迁移) | 是 |
一般而言建议:
阿里云ACK K8s集群支持多个节点伸缩组(AutoScalingGroup),不同弹性伸缩组支持不同的实例规格。在工作实践,我们会为K8s集群划分静态资源池和弹性资源池。通常而言,固定资源池可以根据需要选择裸金属或者虚拟机实例。弹性资源池建议根据应用负载使用合适规格的虚拟机实例来优化成本、避免浪费,提升弹性供给保障。
此外由于裸金属实例一般CPU核数非常多,大规格实例在使用中的挑战请参见下文。
一个引申的问题是,如何选择实例规格?我们列表对比一下
较少的大规格实例 | 较多的小规格实例 | 备注 | |
---|---|---|---|
节点管理开销 | 较低 | 较高 | |
操作系统额外开销 | 较低 | 较高 | |
节点部署密度 | 较高 | 较低 | |
节点调度复杂性(如NUMA) | 较高 | 较低 | 部署密度增加之后,需要更加合理的资源调度来保障应用SLA |
节点稳定性 | 较低 | 较高 | 随着部署密度增加,节点自身的稳定性也会随之下降 |
节点失效爆炸半径 | 较大 | 较小 | 一个大规格实例失效,会影响更多的应用容器。也需要预留更多的资源进行宕机迁移。 |
Master组件压力 | 较小 | 较大 | Worker节点数量是影响Master节点容量规划和稳定性的因素之一。K8s 1.13版本引入的NodeLease功能让节点数量对master组件的压力降低很多。 |
默认情况下,kubelet 使用 CFS 配额 来执行 pod 的 CPU 约束。当节点上运行了很多 CPU 密集的应用时,工作负载可能会迁移到不同的 CPU 核,工作负载的会受到 CPU 缓存亲和性以及调度延迟的影响。当使用大规格实例类型时,节点的CPU数量较多,现有的Java,Golang等应用在多CPU共享的场景,性能会出现明显下降。所有对于大规格实例,需要对CPU管理策略进行配置,利用CPU set进行资源分配。
此外一个重要的考虑因素就是NUMA支持。在NUMA开启的裸金属实例或者大规格实例上,如果处理不当,内存访问吞吐可能会比优化方式降低了30%。Topology管理器可以开启NUMA感知 https://kubernetes.io/docs/tasks/administer-cluster/topology-manager/ 。但是目前K8s对NUMA的支持比较简单,还无法充分发挥NUMA的性能。
阿里云容器服务提供了 CGroup Controller 可以更加灵活地对NUMA架构进行调度和重调度。
在 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性能
而且,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服务(比如阿里云的ACK)创建和管理K8s集群生命周期非常简单,可以有效解决这个问题。
我们可以比较一下这两种选择
单一大集群 | 多个应用为中心集群 | |
---|---|---|
爆炸半径 | 大 | 小 |
硬多租(安全、资源强隔离) | 复杂 | 简单 |
混合调度多种类型资源 (GPU等 ) | 复杂 | 简单 |
集群管理复杂性 | 较低 | 较高(自建)/较低(采用托管K8s服务) |
集群生命周期的灵活性 | 困难 | 简单(不同集群可以有不同的版本和伸缩策略) |
规模化引入的复杂性 | 复杂 | 简单 |
源自Google Borg的理念,Kubernetes的愿景是成为Data Center Operating System,而且Kubernetes也提供了RBAC、namespace等管理能力,支持多用户共享一个集群,并实现资源限制。 但是这些更多是 “软多租” 能力,不能实现不同租户之间的强隔离。在多租最佳实践中,我们可以有如下的一些建议
关于Kubernetes多租户实践的具体信息可以参考下文。目前而言,Kubernetes对硬隔离的支持存在很多局限性,同时社区也在积极探索一些方向,如阿里容器团队的Virtual Cluster Proposal 可以提升隔离的支持,但是这些技术还未成熟。
另一个需要考虑的方案是Kubernetes自身的可扩展性,我们知道一个Kubernetes集群的规模在保障稳定性的前提下受限于多个维度,一般而言Kubernetes集群小于5000节点。当然,运行在阿里云上还受限于云产品的quota限制。阿里经济体在Kubernetes规模化上有丰富的经验,但是对于绝大多数客户而言,是无法解决超大集群的运维和定制化复杂性的。
对于公共云客户我们一般建议,针对业务场景建议选择合适的集群规模
如果需要对多个集群的应用进行统一管理,有如下几个考虑
另外利用托管服务网格服务ASM,可以利用Istio服务网格轻松实现对多个K8s集群的应用的统一路由管理。
在所有的调查中,K8s的复杂性和缺乏相应的技能是阻碍K8s企业所采用的主要问题,在IDC中运维一个Kubernetes生产集群还是非常具有挑战的任务。阿里云的Kubernetes服务ACK简化了K8s集群的生命周期管理,托管了集群的master节点被,但是用户依然要维护worker节点,比如进行升级安全补丁等,并根据自己的使用情况进行容量规划。
针对K8s的运维复杂性挑战,阿里云推出了Serverless Kubernetes容器服务 ASK。
完全兼容现有K8s容器应用,但是所有容器基础设施被阿里云托管,用户可以专注于自己的应用。它具备几个特点
在ASK中,应用运行在弹性容器实例 - ECI (Elastic Container Instance)中,ECI基于轻量虚拟机提供的沙箱环境实现应用安全隔离,并且完全兼容Kubernetes Pod语义。在ASK中我们通过对Kubernetes做减法,将复杂性下沉到基础设施,极大降低了运维管理负担,提升用户体验,让Kubernetes更简单,让开发者更加专注于应用自身。除了无需管理节点和Master外,我们将DNS, Ingress等能力通过阿里云产品的原生能力来实现,提供了极简但功能完备的Kubernetes应用运行环境。
Serverless Kubernetes极大降低了管理复杂性,而且其自身设计非常适合突发类应用负载,如CI/CD,批量计算等等。比如一个典型的在线教育客户,根据教学需要按需部署教学应用,课程结束自动释放资源,整体计算成本只有使用包月节点的 1/3。
在编排调度层,我们借助了CNCF社区的Virtual-Kubelet,并对其进行了深度扩展。Virtual-Kubelet提供了一个抽象的控制器模型来模拟一个虚拟Kubernetes节点。当一个Pod被调度到虚拟节点上,控制器会利用ECI服务来创建一个ECI实例来运行Pod。
我们还可以将虚拟节点加入ACK K8s集群,允许用户灵活控制应用部署在普通节点上,还是虚拟节点上。
值得注意的是 ASK/ECI 是 nodeless 形态的pod,在K8s中有很多能力和node相关,比如NodePort等概念不支持,此外类似日志、监控组件经常以DaemonSet的方式在K8s节点上部署,在ASK/ECI中需要将其转化为Sidecar。
用户该如何选择ACK和ASK呢?ACK主要面向的是基础设施运维团队,具备和K8s高度的兼容性和灵活性控制性。而ASK则是面向业务技术团队或者开发者,用户完全不需具备K8s的管理运维能力,即可管理和部署K8s应用。而ACK on ECI,则同时支持用户负载运行在ECS实例或者ECI实例上,可以允许用户进行灵活控制。
ACK on ECI/ASK则可以将弹性的负载通过ECI的方式运行,有几个非常典型的场景:
ACK on ECI还可以和Knative这样的Serverless应用框架配合,开发领域相关的Serverless应用。
合理规划K8s集群可以有效规避后续运维实践中的稳定性问题,降低使用成本。期待与大家一起交流阿里云上使用Kubernetes的实践经验。
原文链接:
领取专属 10元无门槛券
私享最新 技术干货