释放云原生价值才是拥抱 Kubernetes 的正确姿势

在 Kubernetes 中对于故障机的处理要"简单和粗暴"得多,不再要求对应用先扩容,而是直接把故障机上的容器进行删除,删除后才由负载控制器进行扩容。这种方案乍一听简直胆大妄为,落地 Kubernetes 的时候很多 PaaS 的同学都非常排斥这种方法,认为这会严重影响业务的稳定性。事实上呢,绝大多数核心的业务应用都维护着一定的冗余容量,以便全局的流量切换或者应对突发的业务流量,临时删除一定量的容器根本不会造成业务的容量不足。

我们所面临的关键问题是如何确定业务的可用容量,当然这是个更难的问题,但对于自愈的场景完全不需要准确的容量评估,只需要一个可以推动自愈运转的悲观估计就可以。在 Kubernetes 中可以通过 PodDisruptionBudget 来定量地描述对应用的可迁移量,例如可以设置对应用进行驱逐的并发数量或者比例。这个值可以参考发布时的每批数量占比来设置。假如应用发布一般分 10 批,那么可以设置PodDisruptionBudget 中的 maxUnavailable 为 10%(对于比例,如果应用只有 10 个以内的实例,Kubernetes 还是认为可以驱逐 1 个实例)。万一应用真的一个实例都不允许驱逐呢,那么对不起,这样的应用是需要改造之后才能享受上云的收益的。一般应用可以通过改造自身架构,或者通过 operator 来自动化应用的运维操作,从而允许实例的迁移。

不过,阿里巴巴传统的容器形态是富容器,即应用程序服务器,以及日志采集进程这些相关的组件都部署在一个大的系统容器中,这造成了日志采集等组件的资源消耗无法单独限制,也无法方便地进行独立的升级。因此,在阿里巴巴这次上云中, 开始把系统容器中除业务应用外的其他组件都拆分到独立的 sidecar 容器,我们称之为轻量化容器改造。改造后,一个 pod 内会包括一个运行业务的主容器的,一个运行着各种基础设施 agent 的运维容器,以及服务网格等的 sidecar。轻量化容器之后, 业务的主容器就能以比较低的开销运行业务服务,从而为更方便进行 serverless 的相关改造。

因此,相比 pod 层次的不可变,我们认为坚持容器级别的不可变原则,更能发挥 Kubernetes 多容器 pod 的技术优势。为此,我们建设了支持应用发布时,只原地修改 pod 中部分容器的能力,特别的,建设了支持容器原地升级的工作负载控制器,并替换 Kubernetes 默认的 deployment 和 statefulset 控制器作为内部的主要工作负载。另外,还建设了支持跨应用进行 sidecar 容器升级的 sidecarset, 方便进行基础设施以及中间件组件的升级。此外,通过支持原地升级还带来了集群分布确定性、加速镜像下载等的额外优势。这部分能力,我们已经通过 OpenKruise 项目开源出来。OpenKruise 中的 Kruise 是 cruise的谐音,‘K’ for Kubernetes, 寓意 Kubernetes 上应用的自动巡航,满载着满载阿里巴巴多年应用部署管理经验和阿里经济体云原生化历程的最佳实践. 目前,OpenKruise 正在计划发布更多的 Controller 来覆盖更多的场景和功能比如丰富的发布策略,金丝雀发布,蓝绿发布,分批发布等等。

阿里云上万个 Kubernetes 集群大规模管理实践


一般讲到单元化,大家都会联想到单机房容量不够或二地三中心灾备等场景。那单元化和 Kubernetes 管理有什么关系?对我们来说,一个地域(比如:杭州)可能会管理几千个 Kubernetes,需要统一维护这些 Kubernetes 的集群生命周期管理。作为一个 Kubernetes 专业团队,一个朴素的想法就是通过多个 Kubernetes 元集群来管理这些guest K8s master。而一个 Kubernetes 元集群的边界就是一个单元

曾经我们经常听说某某机房光纤被挖断,某某机房电力因故障而导致服务中断,容器服务 ACK 在设计之初就支持了同城多活的架构形态,任何一个用户 Kubernetes 集群的 master 组件都会自动地分散在多个机房,不会因单机房问题而影响集群稳定性;另外一个层面,同时要保证 master 组件间的通信稳定性,容器服务 ACK 在打散 master 时调度策略上也会尽量保证 master 组件间通信延迟在毫秒级。

大家都知道,Kubernetes 集群的 master 组件的负载主要与 Kubernetes 集群的节点规模、worker 侧的 controller 或 workload 等需要与 kube-apiserver 交互的组件数量和调用频率息息相关,对于上万个 Kubernetes 集群,每个用户 Kubernetes 集群的规模和业务形态都千差万别,我
们无法用一套标准配置来去管理所有的用户 Kubernetes 集群。同时,从成本经济角度考虑,我们提供了一种更加灵活、更加智能的托管能力。考虑到不同资源类型会对 master 产生不同的负载压力,因此我们需要为每类资源设置不同的因子,最终可归纳出一个计算范式,通过此范式可计算出每个用户 Kubernetes 集群 master 所适应的档位。另外,我们也会基于已构建的 Kubernetes 统一监控平台实时指标来不断地优化和调整这些因素值和范式,从而可实现智能平滑换挡的能力。
元集群托管用户 Kubernetes 集群的 master

针对每个集群,需要采集的主要指标类别包括
OS 指标,例如节点资源(CPU, 内存,磁盘等)水位以及网络吞吐;
元集群以及用户集群 Kubernetes master 指标,例如 kube-apiserver, kube-controller-manager, kube-scheduler 等指标;
Kubernetes 组件(kubernetes-state-metrics,cadvisor)采集的关于 Kubernetes 集群状态;
etcd 指标,例如 etcd 写磁盘时间,DB size,Peer 之间吞吐量等等。

为了合理的将监控压力负担分到多个层次的 Prometheus 并实现全局聚合,我们使用了联邦 Federation 的功能。在联邦集群中,每个数据中心部署单独的 Prometheus,用于采集当前数据中心监控数据,并由一个中心的 Prometheus 负责聚合多个数据中心的监控数据。基于 Federation 的功能,我们设计的全球监控架构图如下,包括监控体系、告警体系和展示体系三部分。

常用的透传 Kubernetes 集群内 Prometheus 指标到集群外的方式是通过 API server 代理功能,优点是可以重用 API server 的 6443 端口对外开放数据,管理简便;缺点也明显,增加了 API server 的负载压力。如果使用 API Server 代理模式,考虑到客户集群以及节点都会随着售卖而不断
扩大,对 API server 的压力也越来越大并增加了潜在的风险。对此,针对边缘 Prometheus 增加了 LoadBalancer 类型的 service,监控流量完全 LoadBalancer,实现流量分离。即便监控的对象持续增加,也保证了 API server 不会因此增加 Proxy 功能的开销。

中心 Prometheus 只收集需要使用的指标,一定不能全量抓取,否则会造成网络传输压力过大丢失数据。

Label 用于在级联 Prometheus 上标记 region 和元集群,所以在中心 Prometheus 汇聚是可以定位到元集群的颗粒度。同时,尽量减少不必要的 label,实现数据节省。

2019 年 6 月,阿里巴巴将内部的云原生应用自动化引擎 OpenKruise 开源,这里我们重点介绍下其中的 BroadcastJob 功能,他非常适用于每台 worker 机器上的组件进行升级,或者对每台机器上的节点进行检测。(Broadcast Job 会在集群中每个 node 上面跑一个 pod 直至结束。类似于社区的 DaemonSet, 区别在于 DaemonSet 始终保持一个 pod 长服务在每个 node 上跑,而 BroadcastJob 中最终这个 pod 会结束。)

深入 Kubernetes 的“无人区” :蚂蚁金服双11 的调度系统

蚂蚁金服在落地 Kubernetes 实现统一调度目标时遵循了标准化的扩展方式:
一切业务扩展均围绕 Kubernetes APIServer,通过 CRD + Operator 方式完成业务功能的适配和扩展;
基础服务通过 Node 层定义的资源接口完成个性化适配,有益于形成资源接入的最佳实践。

在大促过程中,不同业务域的洪峰流量通常都是在不同时间段来临,而应对这些不同时间到来的业务流量往往都需要大量的额外计算资源做保障。在以往的几次活动中,我们尝试了通过应用快速腾挪的方式来做到资源上的分时复用,但是服务实例上下线需要预热,腾挪耗时不可控,大规模调度的稳定性等因素都影响了最终腾挪方案的实践效果。

今年 双11 我们采用了资源共享调度加精细化切流的技术以达到资源分时利用的目标,为了达到资源充分利用和极速切换的目标,我们在以下方面做了增强:
在内部的调度系统引入了联合资源管理(Union-Resource Management),他可以将波峰波谷不重叠的业务实例摆放在相同的资源集合内,达到最大化的资源利用。
研发了一套融合资源更新,流量切换及风险控制的应用分时复用平台,通过该平台 SRE 可以快速稳定的完成资源切换以应对不同的业务洪峰。

在蚂蚁金服内部我们持续的使用 Kubernetes 支持各类计算业务,例如各类AI 训练任务框架,批处理任务和流式计算等。他们都有一个共同的特点:资源按需申请,即用即走。
我们通过 Operator 模型适配计算型任务,让任务在真正执行时才会调用 Kubernetes API 申请 Pod 等资源,并在任务退出时删除 Pod 释放资源。同时我们在调度引擎中引入了动态资源调度能力和任务画像系统,这为在线和计算的不同等级业务提供了分级资源保障能力,使在线业务不受影响的情况下资源被最大化的利用。

蚂蚁金服是目前少数运行了全球最大规模的 Kubernetes 集群的公司之一,单集群机器规模过万,Pods 数量数十万。随着类似计算型任务混部和资源分时复用这类业务的落地,资源的动态使用以及业务自动化运维都对 Kubernetes 的稳定性和性能带来了巨大的挑战。
首先需要面对的挑战是调度性能,社区的调度器在 5k 规模测试中调度性能只有 1~2 pods/s,这显然无法满足蚂蚁金服的调度性能需求。
针对同类业务的资源需求往往相同的特点,我们自研了批量调度功能,再加上例如局部的 filters 性能优化等工作,最终达到了百倍的调度性能提升!

面对这种“核按钮”不在集群管理员手上的情况,蚂蚁内部通过两方面入手解决规模化带来的问题:
我们通过持续总结迭代过程中的经验,形成了内部的最佳实践原则,以帮助业务更好的设计 Operator
CRD 在定义时需要明确未来的最大数量,大量 CR 业务最好采用 aggregate-apiserver 进行扩展;
CRD 必须 Namespaced scope,以控制影响范围;
MutatingWebhook + 资源 Update 操作会给运行时环境带来不可控破坏,尽量避免使用这种组合;
任何 controllers 都应该使用 informers,并且对写操作配置合理限流;
DaemonSet 非常高阶,尽量不要采用这类设计,如果必需请在 Kubernetes 专家的辅导下使用

我们已经在 Kubernetes 实施了一系列的优化,包含多维度流量控制,WatchCache 处理全量 List 请求,controller 自动化解决更新冲突,以及 APIServer 加入自定义索引等。

当前我们面对的一大挑战是多租户带来的不确定性。蚂蚁金服内部不可能为每个业务部门都维护一套 Kubernetes 集群,而单个 Kubernetes 集群的多租户能力十分薄弱,这体现在以下两个维度:
APIServer 和 etcd 缺少租户级别的服务保障能力;
Namespace 并不能有效的隔离全部资源,并且由于Namespace 只提供了部分资源能力,对平台型的接入方也很不友好。

为此我们接下来一起推动 Operator 的标准化工作。从接入标准,Operator 框架,灰度能力建设和控制治理上入手,让 Kubernetes 上的自动化运维变的更加可视可控。

云原生应用万节点分钟级分发协同实践

随着云原生技术的迅速普及,Kubernetes 已经成为事实上应用容器化平台的标准,成为了云原生领域的“一等公民”。Kubernetes 以一种声明式的容器编排与管理体系,让软件交付变得越来越标准化。Kubernetes 提供了统一模式的 API,能以 YAML 格式的文件定义 Kubernetes 集群内的资源。这一些 YAML 格式的资源定义使得 Kubernetes 能轻松被上下游系统所集成,完成一系列原本需要用非标准化脚本、人工来完成的操作。同时社区根据应用交付场景及需求,在原生 YAML 格式的资源定义文件之外衍生出了更多系列的云原生应用交付标准,例如 Helm Chart、Opeartor、Open Application Model 等。

通过控制容器镜像大小、采用 P2P 分发镜像层、优化 Registry 服务端等方式,我们极大优化了大规模分发的性能,最终达成了万节点分钟级分发的目标:

阿里巴巴大规模神龙裸金属 K8s 集群运维实践

在阿里 双11 大规模迁移到神龙架构前,通过在 618/99 大促的验证,我们发现集团电商的容器运行在云上神龙反而比非云物理机的性能要好 10%~15%,这令我们非常诧异。经过分析,我们发现主要的原因是因为虚拟化开销已经 offload 到 MOC 卡上,神龙的 CPU/Mem 是无虚拟化开销的,而上云后运行在神龙上的每个容器都独享 ENI 弹性网卡,性能优势明显。同时每个容器独享一块 ESSD 块存储云盘,单盘 IOPS 高达 100 万,比 SSD 云盘快 50 倍,性能超过了非云的 SATA 和 SSD 本地盘。这也让我们坚定了大规模采用神龙来支撑 双11 的决心。

ASI Pod 运行在神龙裸金属节点上,将网络虚拟化和存储虚拟化 offload 到独立硬件节点 MOC 卡上,并采用 FPGA 芯片加速技术,存储与网络性能均超过普通物理机和 ECS;MOC 有独立的操作系统与内核,可为 AVS(网络处理)与 TDC(存储处理)分批独立的 CPU 核;

双11 需要海量的计算资源来扛住洪峰流量,但这部分资源不可能常态化持有,所以需要合理划分日常集群与大促集群,并在 双11 前几周,通过大规模节点弹性扩容能力,从阿里云弹性申请大批量神龙,部署在独立的大促集群分组里,并大规模扩容 Kubernetes Pod 交付业务计算资源。在 双11 过后,立即将大促集群中的 Pod 容器批量缩容下线,大促集群神龙实例整体销毁下线,日常只持有常态化神龙实例,通过大规模集群弹性扩缩容能力,可大幅节约大促成本。另外从神龙交付周期而言、今年上云后从申请到创建机器,从小时/天级别缩短到了分钟级,上千台神龙可在 5 分钟内完成申请,包括计算、网络、存储资源,并在 10 分钟完成创建并导入 Kubernetes 集群,集群创建效率大幅度提高,为未来常态化弹性资源池奠定基础。
对于大规模神龙集群运维,有三个非常核心的指标可以来衡量集群整体健康度,分别是宕机率、可调度率、在线率。云上神龙宕机原因通常分为硬件问题和内核问题。通过对日宕机率趋势统计和宕机根因分析,可量化集群的稳定性,避免出现潜在的大规模宕机风险出现。可调度率是衡量集群健康度的关键指标,集群机器会因为各种软硬件原因出现容器无法调度到这些异常机器上,例如 Load 大于 1000、磁盘出现压力、docker 进程不存在,kubelet 进程不存在等,在 Kubernetes 集群中,这批机器的状态会是 notReady。2019 年 双11,我们通过神龙宕机重启与冷迁移特性,极大提升了故障机轮转效率,使神龙集群的可调度率始终维持在 98% 以上,大促资源备容从容。而 双11 神龙的宕机率维持在 0.2‰ 以下,表现相当稳定。

随着集群规模的增加,管理难度也随之变大。例如如何能筛选出“cn-shanghai”Region 下生产环境,且实例规格为“ecs.ebmc6-inc.26xlarge”的所有机器。我们通过定义大量的预置标签来实现批量资源管理。在 Kubernetes 架构下,通过 定义Label 来管理机器。Label 是一个 Key-Value 健值对,可在神龙节点上使用标准Kubernetes的接口打Label。例如机器实例规格的label可定义"sigma.ali/machine-model":“ecs.ebmc6-inc.26xlarge”, 机器所在的 Region 可定义为"sigma.ali/ecs-region-id":“cn-shanghai”。通过完善的标签管理系统,可从几万台神龙节点中快速筛
选机器,执行诸如灰度分批次服务发布、批量重启、批量释放等常规运维操作。

对于超大规模集群,日常宕机是非常普遍的事情,对宕机的统计与分析非常关键,可以甄别出是否存在系统性风险。宕机的情况分为很多种,硬件故障会导致宕机,内核的 bug 等也会导致宕机,一旦宕机以后,业务就会中断,有些有状态应用就会受到影响。我们通过 ssh 与端口 ping 巡检对资源池的宕机情况进行了监控,统计宕机历史趋势,一旦有突增的宕机情况就会报警;同时对宕机的机器进行关联分析,如根据机房、环境、单元、分组 进行归类,看是否跟某个特定的机房有关;对机型、CPU 进行分
类统计,看是否跟特定的硬件有关系;同时 OS 版本,内核版本进行归类,看是否都发生在某些特定的内核上。对宕机的根因,也进行了综合的分析,看是硬件故障,还是有主动运维事件。内核的 kdump 机制会在发生 crash 的时候生成 vmcore,我们也对 vmcore 里面提取的信息进行归类,看某一类特定的 vmcore 关联的宕机数有多少。内核日志有些出错的信息,如 mce 日志soft lockup 的出错信息等,也能发现系统在宕机前后的是否有异常。通过这一系列的宕机分析工作,把相应的问题提交给内核团队,内核专家就会分析 vmcore,属于内核的缺陷的会给出 hotfix 解决这些导致宕机的问题。

运维大规模神龙集群不可避免遇到软硬件故障,而在云上技术栈更厚,出现问题会更为复杂。如果出问题单纯依靠人工来处理是不现实的,必须依赖自动化能力来解决。1-5-10 节点自愈可提供 1 分钟异常问题发现,5 分钟定位,10 分钟修复的能力。主要的神龙机器异常包括宕机、夯机、主机 load 高、磁盘空间满、too many openfiles、核心服务(Kubelet、Pouch、Star-Agent)不可用等。主要的修复动作包括宕机重启、业务容器驱逐、异常软件重启、磁盘自动清理,其中 80% 以上问题可通过重启宕机机器与将业务容器驱逐到其他节点完成节点自愈。另外我们通过监听神龙 Reboot 重启与 Redepoly 实例迁移二个系统事件来实现 NC 侧系统或硬件故障的自动化修复。

PouchContainer 容器技术演进助力阿里云原生升级


无论是 LXC 还是 runc 都是让所有容器共享 Linux 内核,利用 cgroup 和 namespace 来做隔离,对于强安全场景和强隔离场景是不适用的。为了容器这种开发和运维友好的交付形式能给更多场景带来收益,我们很早就开始探索这方面的技术,和集团 os 创新团队以及蚂蚁 os 虚拟化团队合作共建了 kata 安全容器和 gvisor 安全容器技术,在容器生态嫁接,磁盘网络系统调用性能优化等方面都做了很多的优化。在兼容性要求高的场景我们优先推广kata 安全容器,已经支持了 SAE 和 ACK 安全容器场景。在语言和运维习惯确定的场景我们也在 618 大促时上线了一些合适的电商使用了 gvisor 的运行时隔离技术,稳定性和性能都得到了验证。

镜像化以后必然会引入困难就是镜像分发的效率,一个是速度另一个是稳定性,让发布扩容流程不增加太多时间的情况下,还要保证中心节点不被压垮。
PouchContainer 在一开始就支持了使用 Dragonfly 来做 P2P 的镜像分发,就是为了应对这种问题,这是我们的第一代镜像分发方案。在研发域我们也对镜像分层的最佳实践做了推广,这样能最大程度的保证基础环境不变时每次下载的镜像层最小。镜像加速要解决的问题有:build 效率/push 效率/pull 效率/解压效率/组装效率。第一代镜像加速方案,结合 Dockerfile 的最佳设计解决了 build 效率和 pull 效率和中心压力。

第一代镜像分发的缺点是无论用户启动过程中用了多少镜像数据,在启动容器之前就需要把所有的镜像文件都拉到本地,在很多场景都是又浪费的,特别影响的是扩容场景,所以第二代的镜像加速方案,我们调研了阿里云的盘古,盘古的打快照、mount、再打快照完美匹配打镜像和分发的流程。能做到秒级镜像 pull,因为 pull 镜像时只需要鉴权,下载镜像 manifest,然后 mount 盘古。也能做到镜像内容按需读取。2018 年 双11,我们小规模上线了盘古远程镜像,也验证了我们的设计思路,这一代的镜像加速方案结合新的 overlay2 技术在第一代的基础上有解决了PouchContainer 效率/pull 效率/解压效率和组装效率。

但是也存在一些问题,首先镜像数据没有存储在中心镜像仓库中,只有 manifest 信息,这样镜像的分发范围就受限,在哪个盘古集群做的镜像,就必须在那个盘古集群所在的阿里云集群中使用这个镜像,其次没有 P2P 的能力,在大规模使用时对盘古后端的压力会很大,特别是离线场景下由于内存压力导致很多进程的可执行文件的 page cache 被清理然后需要重新 load 这种场景,会给盘古后端带来更大的压力。基于这两个原因,我们和 ContainerFS 团队合作共建了第三代镜像分发方案:DADI(基于块设备的按需p2p加载技术,后面有计划开源)。

daidi在构建阶段保留了镜像的多层结构,保证了镜像在多次构建过程中的可重用性,并索引了每个文件的在每层的offset 和 length,推送阶段还是把镜像推送到中心镜像仓库中,保证在每个机房都能拉取到这个镜像。在每个机房都设置了超级节点做缓存,每一块内容在特定的时间段内都只从镜像仓库下载一次。如果有时间做镜像预热,像双十一这种场景,预热阶段就是从中心仓库中把镜像预热到本地机房的超级节点,后面的同机房的数据传输会非常快。镜像 pull 阶段只需要下载镜像的 manifest 文件
(通常只有几 K大小),速度非常快,启动阶段大地会给每个容器生成一个快设备,这个块设备的 chunk 读取是按需从超级节点或临近节点 P2P 的读取内容。这样就保证了容器启动阶段节点上只读取了需要的部分内容。为了防止容器运行过程中出现 iohang,我们在容器启动后会在后台把整个镜像的内容全部拉到 node 节点,享受超快速启动的同时最大程度的避免后续可能出现的 iohang。

提供容器平台给应用使用,在容器启动之前必然有很多平台相关的逻辑需要处理,这也是我们以前用富
容器的原因。
1 安全相关:安全路由生成、安全脚本配置
2 cpushare 化相关配置:tsar 和 nginx 配置
3. 运维agent 更新相关:运维agent 更新相对频繁,基础镜像更新特别慢,不能依赖于基础镜像更新来更新运维agent
4. 配置相关逻辑:同步页头页尾,隔离环境支持, 强弱依赖插件部署
5. SN 相关:模拟写 SN 到/dev/mem,保证 dmidecode 能读到正确的 SN
6. 运维相关的的 agent 拉起,很多运维系统都依赖于在节点上面有一个 agent,不管这个节点是容器/ecs 还是物理机
7. 隔离相关的配置:比如 nproc 这个限制是在用户上面的,用统一个镜像的容器不能使用统一 uid 不然无法隔离 nproc

现在随着基于 K8s 的编排调度系统的推广,我们有了 Pod 能力,可以把一些预置逻辑放到前置 hook 中去执行,当然富容器可以瘦下来还要依赖于运维 agent 可以从主容器中拆出来,那些只依赖于 volume 共享就能跑起来的 agent 可以先移动到 sidecar 里面去,这样就可以把运维容器和业务主容器分到不同的容器里面去,一个 Pod 多个容器在资源隔离上面分开,主容器是 Guaranteed 的 QOS,运维容器是 Burstable 的 QOS。同时在 kubelet 上支持 Pod 级别的资源管控,保证这个 Pod 整体是 Guaranteed 的同时,限制了整个 pod 的资源使用量不超过应用单实例的申请资源。

还有一些 agent 不是只做 volume 共享就可以放到 sidecar 的运维容器中的,比如 monkeyking、arthas 需要能 attach 到主容器的进程上去,还要能 load 主容器中非 volume 路径上面的 jar 文件才能正常工作。对于这种场景 PouchContainer 容器也提供了能让同 Pod 多容器做一些 ns 共享的能力,同时配合 ns 穿越来让这些 agent 可以在部署方式和资源隔离上是和主容器分离的,但是在运行过程中还可以做它原来可以做的事情。

可插拔的插件化的架构和更精简的调用链路在容器生态里面还是主流方向,kubelet 可以直接去调用 containerd 的 CRI 接口,确实可以减少一调,不过 CRI 接口现在还不够完善,很多运维相关的指令都没有,logs 接口也要依赖于 container API 来实现。还有运行环境和构建环境分离,这样用户就不需要到宿主机上面执行 build。所有的运维系统也不再依赖于 container API。在这些约束下我们可以做到减少一跳,直接用 kubelet 去调用 containerd 的 CRI 接口。
现在每个应用都有很多的 Dockerifle,怎么让 Dockerfile 更有表达能力,减少 Dockerfile 数量。构建的时候并发构建也是一个优化方向,buildkit 在这方面是可选的方案,Dockerfile 表达能力的欠缺也需要新的解决方案,buildkit 中间态的 LLB 是 go 代码,是不是可以用 go 代码来代替 Dockerfile,定义更强表达能力的 Dockerfile 替代品。
容器化是云原生的关键路径,容器技术在运行时和镜像技术逐渐趋于稳定的情况下,热点和开发者的目光开始向上层转移,K8s 和基于其上的生态成为容器技术未来能产生更多创新的领域, PouchContainer 技术也在向着更云原生,更好适配 K8s 生态的方向发展,网络/diskquota/试图隔离等 PouchContainer 的插件在 K8s 生态系统中适配和优化也我们后面的方向之一。

更强,更稳,更高效:2019 年双11 etcd 技术升级分享

etcd 是一款开源的软件,集合了全世界优秀软件开发者的智慧。最近的一年在软件上有很多贡献者更新了很多性能优化,这里分别从几个方面介绍几个优化,最后介绍一个由阿里巴巴贡献的 etcd 存储优化。

  1. 内存索引层
    由于索引层大量使用锁机制同步对性能影响较大,通过优化锁使用,提升了读写性能具体参考:github pr;
  2. lease 规模化使用
    lease 是 etcd 支持 key 使用 ttl 过期的机制。在之前的版本中 scalability 较差,当有大量 lease 时性能下降的较为严重,通过优化 lease revoke 和过期失效的算法,解决了 lease 规模性的问题具体参考:github pr;
  3. 后端 boltdb 使用优化
    etcd 使用 boltdb 作为底层数据库存储 kv, 它的使用优化对整体性能影响很大。通过调节不同的 batch size 和 interval, 使我们可以根据不同硬件和工作负载优化性能具体参考:github pr。
    除此之外,新的完全并发读特性也优化了 boltdb tx 读写锁性能,大幅度的提升了读写性能

最后介绍一个由阿里巴巴自主研发并贡献开源社区的优化:基于 segregated hashmap 的 etcd 内部存储 freelist 分配回收算法

因此我们重新设计并实现了基于 segregated hashmap 的 etcd 内部存储 freelist 分配回收新算法,该优化算法将内部存储分配算法时间复杂度从 o(n) 降为 o(1), 回收从 o(nlgn) 也降为 o(1), 使 etcd 性能有了质的飞跃,极大地提高了 etcd 存储数据的能力,使得 etcd 存储容量从推荐的 2GB 提升到 100GB,提升 50 倍,读写性能提升 24 倍。CNCF 官方博客收录了此次更新,感兴趣的读者可以读一下。

性能优化除了服务端要做的事情外,还需要客户端的帮助。保持客户端使用最佳实践将保证 etcd 集群
稳定高效地运行,这里我们分享 3 个最佳实践:
1 put 数据时避免大的 value, 大的 value 会严重影响 etcd 性能,例如:需要注意 Kubernetes 下 crd 的使用;
2. 避免创建频繁变化的 key/value, 例如:Kubernetes 下 node 数据上传更新;
3. 避免创建大量 lease 对象,尽量选择复用过期时间接近的 lease, 例如 Kubernetes 下 event 数据的管理。

面对这些种种的问题,我们根据阿里巴巴内部场景,基于开源 etcd-operator 进行了一系列修改和加强,开发了 etcd 运维管理平台 Alpha。利用它,运维人员可以高效地运维管理 etcd,之前要前后操作多个工具完成的任务,现在只要操作它就可以完成,一个人就可以管理成百上千的 etcd 集群。下图展示了 Alpha 的基础功能。

如上图所示,Alpha 分为 etcd 生命周期管理和数据管理两大部分。
其中生命周期管理功能依托于 operator 中声明式的 CustomResource 定义,将 etcd 的集群创建、销毁的过程流程化、透明化,用户不再需要为每个 etcd 成员单独制定繁琐的配置,仅需要指定成员数量、成员版本、性能参数配置等几个简单字段。除此之外,我们还提供了 etcd 版本升级、故障节点替换、集群实例启停等功能,将 etcd 常用的运维操作自动化,同时也在一定程度上保证了 etcd 变更的稳定性。

其次,数据作为 etcd 的核心内容,我们也开发了一系列功能进行重点保障。在备份上,数据管理工具支持定期冷备及实时热备,且保持本地盘和云上 OSS 两类备份,同时也支持从备份上快速恢复出一个
新的 etcd 集群。此外,数据管理工具支持对 etcd 进行扫描分析,发现当前集群的热点数据键值数和存储量,弥补了业界无法提供数据管理的空白,同时该拓展也是 etcd 支持多租户的基础。最后,数据管理工具还支持对 etcd 进行垃圾数据清理、跨集群数据腾挪传输等功能。

这些丰富的功能为上层 Kubernetes 集群的管理提供了很多灵活的帮助,例如用户 A 原来在某云厂商或自建 Kubernetes 集群,我们可以通过迁移 etcd 内部的账本数据的功能,将用户的核心数据搬移至另外一个集群,方便地实现用户的k8s集群跨云迁移

etcd 常见的问题和风险分析如下图,主要分如下三个方面:
etcd 自身: 例如 OOM、代码 bug、panic 等;
宿主机环境: 例如宿主机故障,网络故障,同台宿主机其他进程干扰;
客户端: 例如客户端 bug、运维误操作、客户端滥用 ddos 等

针对这些风险点,我们从如下几个方面入手:
1.建立完善的监控告警机制,覆盖客户端输入,etcd 自身以及宿主机环境状态;
2. 客户操作审计,高危操作如删除数据做风控限流;
3. 数据治理,分析客户端滥用 引导最佳实践;
4. 定期数据冷备,通过热备实现异地多活,保证数据安全;
5. 常态化故障演练,做好故障恢复预案。

Service Mesh 带来的变化和发展机遇

Service Mesh 所带来的第一个变化体现于,服务治理手段从过去的框架思维向平台思维转变。这种转变并非后者否定前者,而是前后者相结合去更好地发挥各自的优势。两种思维的最大区别在于,平台思维不仅能实现应用与技术基础设施更好的解耦,也能通过平台的聚集效应让体系化的顶层设计有生发之地。

框架思维向平台思维转变在执行上集中体现于“轻量化”和“下沉”两个动作。轻量化是指将那些易变的功能从框架的 SDK 中移出,结果是使用了 SDK 的应用变得更轻,免除了因易变功能持续升级所带来的打扰而带来的低效,也因为彻底让应用的开发者无需关心这些功能而让他们能更好地聚焦于业务逻辑本身。从框架中移出的功能放到了 Service Mesh 的 Sidecar 中而实现了功能下沉。Service Mesh 作为平台性技术将由云厂商去运维和提供相应的产品,通过开源所构建的全球事实标准一旦被所有云厂商采纳并实现产品化输出,那时应用的可移植性问题就能水到渠成地解决。

功能下沉在阿里巴巴落地 Service Mesh 的过程中也看到了相应的价值。阿里巴巴的电商核心应用基本上都是用 Java 构建的,在 mesh 化之前,RPC 的服务发现与路由是在 SDK 中完成的,为了保证双11 这样的流量洪峰场景下的消费者用户体验,会通过预案对服务地址的变更推送做降级,避免因为频繁推送而造成应用进程出现 Full GC。Mesh 化之后,SDK 的那些功能被放到了 Sidecar(开发语言是 C++)这一独立进程中,这使得 Java 应用进程完全不会出现类似场景下的 Full GC 问题

从组织层面,这一转变意味着平台技术团队的人员技能需要多编程语言化。一个只有单一编程语言的团队是很难做好面向多编程语言的技术平台的,不只是因为视角单一,还因为无法“吃自己的狗食”而对多编程语言问题有切肤之痛。

由于插件是“长”在 Service Mesh 之上的,插件化的过程就是业务技术服务化的过程。另外,Ser-vice Mesh 需要提供一种选择能力,让业务的应用开发者或运维者选择自己的机器上需要哪些插件(可以理解为插件市场)。另一个值得关注的点是,插件的运维和管理能力以及一定的质量保证手段由 Service Mesh 平台提供,但运维、管理和质量保证的责任由各插件的提供者承担。这种划分将有效地独绝所由插件的质量由 Service Mesh 平台去承担而带来的低效,分而治之仍是改善很多工程效率的良方。

就我们与阿里云客户交流的经验来看,他们乐于尽最大可能采用非云厂商所特有的技术方案,以免被技术锁定而在未来的发展上出现掣肘。另外,他们只有采纳开源的事实标准软件才有可能达成企业的多云和混合云战略。基于客户的这一诉求,我们在Service Mesh的技术发展上特别重视参与开源事实标准的共建。在 Istio 和 Envoy 两个开源项目上,我们都会致力于将内部所做的那些优化反哺给开源社区。

阿里集团 双11 核心应用落地 Service Mesh 所克服的挑战


图中示例说明了 Service Mesh 所包含的三大平面,即数据平面(Data Plane)、控制平面(Con-trol Plane)和运维平面(Operation Plane)。数据平面我们采用的是开源的 Envoy(上图中的 Sidecar,请读者注意这两个词在本文中可以互换使用),控制平面采用的是开源的 Istio(目前只使用了其中的 Pilot 组件),运维平面则完全自研。
与半年前落地时不同,这次 双11 核心应用上落地我们采用了 Pilot 集群化部署的模式,也即 Pilot 不再与 Envoy 一起部署到业务容器中,而是搭建了一个独立的集群。这一变化使得控制平面的部署方式演进到了 Service Mesh 应有的终态。

熟悉 Istio 的读者想必清楚,Istio 是通过 iptables 的 NAT 表去做流量透明拦截的,通过流量透明拦截可在应用无感的情形下将流量劫持到 Envoy 中而实现 mesh 化。但很不幸,NAT 表所使用到的 nf_contrack 内核模块因为效率很低而在阿里巴巴的线上生产机器中被去除了,因此无法直接使用社区的方案。好在年初开始不久我们与阿里巴巴 OS 团队达成了合作共建,由他们负责承担 Service Mesh 所需的流量透明拦截和网络加速这两块的基础能力建设。经过两个团队的紧密合作,OS团队探索了通过基于 userid 和 mark 标识流量的透明拦截方案,基于 iptables 的 mangle 表实现了一个全新的透明拦截组件。
下图示例说明了存在透明拦截组件的情形下,RPC 服务调用的流量走向。其中,Inbound 流量是指调进来的流量(流量的接受者是 Provider 角色),而 Outbound 是指调出去的流量(流量的发出者是 Consumer 角色)。通常一个应用会同时承担两个角色,所以有 Inbound 和 Outbound 两股流量并存。

在阿里巴巴电商业务场景下的路由特性丰富多样,除了要支持单元化、环境隔离等路由策略,还得根据 RPC 请求的方法名、调用参数、应用名等完成服务路由。阿里巴巴内部的 Java RPC 框架是通过嵌入 Groovy 脚本来支持这些路由策略的,业务方在运维控制台上配置 Groovy 路由模板,SDK 发起调用时会执行该脚本完成路由策略的运用。
未来的 Service Mesh 并不打算提供 Groovy 脚本那么灵活的路由策略定制方案,避免因为过于灵活而给 Service Mesh 自身的演进带去掣肘。因此,我们决定借 mesh 化的机会去除 Groovy 脚本。通过落地应用所使用 Groovy 脚本的场景分析,我们抽象出了一套符合云原生的解决方案:扩展 Istio 原生的 CRD 中的 VirtualServiceDestinationRule,增加 RPC 协议所需的路由配置段去表达路由策略。

Envoy 诞生之初要解决的一个核心问题就是服务的可观测性,因此 Envoy 一开始就内置了大量的 stats(即统计信息)以便更好地对服务进行观测。Envoy 的 stats 粒度很细,甚至细到整个集群的IP 级别,在阿里巴巴环境下某些电商应用的 Consumer 和 Provider 服务加起来达到了几十万之多的 IP (每个 IP 在不同的服务下携带的元信息不同,所以不同的服务下的相同 IP 是各自独立的)。如此一来,Envoy 在这块的内存开销甚是巨大。为此,我们给 Envoy 增加了 stats 开关,用于关闭或打开 IP 级别的 stats,关闭 IP 级别的 stats 直接带来了内存节约 30% 成果。下一步我们将跟进社区的 stats symbol table 的方案来解决 stats 指标字符串重复的问题,那时的内存开销将进一步减少。

Service Mesh 落地的一项核心价值就是让基础设施与业务逻辑完全解耦,两者可以独立演进。为了实现这个核心价值,Sidecar 需要具备热升级能力,以便升级时不会造成业务流量中断,这对方案设计和技术实现的挑战还是蛮大的。
我们的热升级采用双进程方案,先拉起新的 Sidecar 容器,由它与旧的 Sidecar 进行运行时数据交接,在新的 Sidecar 准备发接管流量后,让旧的 Sidecar 等待一定时间后退出,最终实现业务流量无损。核心技术主要是运用了 Unix Domain SocketRPC 的节点优雅下线功能。下图大致示例了关键过程。

蚂蚁金服 双11 Service Mesh 超大规模落地揭秘


这里我们来详细回答一下,为什么不采用社区的流量劫持方案?
主要的原因是一方面 iptables 在规则配置较多时,性能下滑严重。另一个更为重要的方面是它的管控性和可观测性不好,出了问题比较难排查。而 Service Mesh 从初期就把蚂蚁金服现在线上的系统全量切换 Mesh 作为目标,并不是只是跑跑 demo,所以我们对性能和运维的要求是非常高的,毕竟,技术架构升级,如果是以业务有损或者资源利用率大幅度上升,这是无论如何都不能接受的。

在之前,我们做一些升级操作之类的,都是需要有一定的资源 Buffer,然后批量的进行操作,替换 Buffer 的不断移动,来完成升级的操作。这就要求 PaaS 层留有非常多的 Buffer,但是在 双11 的情况下,我们要求不增加机器,并且为了一个接入 SOFAMosn 的操作,反而需要更多的钱来买资源,这岂不是背离了我们的初衷。有人可能会问,不是还是增加了内存和 CPU 吗,这是提高了 CPU 利用率。以前业务的 CPU 利用率很低。并且这个是一个类似超卖的方案。看上去分配了。实际上基本没增加。
可以看到, 通过 Paas 层,我们的 Operator 操作,直接在现有容器中注入,并原地重启,在容器级别完成升级。升级完成后,这个 Pod 就具备了 SOFAMosn 的能力。

在这个方案中。SOFAMosn 会感知自己的状态,新的 SOFAMosn 启动会通过共享卷的 Domain Socket 来检测是否已有老的 SOFAMosn 在运行,如果有,则通知原有 SOFAMosn 进行平滑升级操作。

当需要比较大的资源调度的时候,我们推送一把开关,则资源限制打开,包活状态取消。资源域 B 瞬间
可以满血复活。而资源域 A 此时进入上一个状态,CPU 和内存被限制。在这里,SOFAMosn 以一个
极低的资源占用。完成流量保活的能力。使得资源的快速借调成为可能。

服务网格在“路口”的产品思考与实践

在 Service Mesh 之前,微服务体系的玩法都是由中间件团队提供一个 SDK 给业务应用使用,在
SDK 中会集成各种服务治理的能力,如:服务发现、负载均衡、熔断限流、服务路由等。

另一方面,目前 Istio 在整体性能上还存在一些有待解决的点,以下引述熬小剑老师在蚂蚁金服 Ser-
vice Mesh 深度实践中的观点):
Mixer
Mixer 的性能问题,一直都是 Istio 中最被人诟病的地方。
尤其在 Istio 1.1/1.2 版本之后引入了 Out-Of-Process Adapter,更是雪上加霜。
从落地的角度看,Mixer V1 糟糕至极的性能,已经是“生命无法承受之重”。对于一般规模的生
产级落地而言,Mixer 性能已经是难于接受,更不要提大规模落地……
Mixer V2 方案则给了社区希望:将 Mixer 合并进 Sidecar,引入 web assembly 进行
Adapter 扩展,这是我们期待的 Mixer 落地的正确姿势,是 Mixer 的未来,是 Mixer 的“诗和
远方”。然而社区望穿秋水,但Mixer V2 迟迟未能启动,长期处于 In Review 状态,远水解不了
近渴。
Pilot
Pilot 是一个被 Mixer 掩盖的重灾区:长期以来大家的性能关注点都在 Mixer,表现糟糕而且问题
明显的Mixer 一直在吸引火力。但是当选择放弃 Mixer(典型如官方在 Istio 新版本中提供的关闭
Mixer 的配置开关)之后,Pilot 的性能问题也就很快浮出水面。
我们实践下来发现 Pilot 目前主要有两大问题:
1)无法支撑海量数据
2)每次变化都会触发全量推送,性能较差

我们的服务网格产品名是 SOFAStack 双模微服务平台,这里的“双模微服务”是指传统微服务和
Service Mesh 双剑合璧,即“基于 SDK 的传统微服务”可以和“基于 Sidecar 的 Service Mesh
微服务”实现下列目标:

互联互通:两个体系中的应用可以相互访问;
平滑迁移:应用可以在两个体系中迁移,对于调用该应用的其他应用,做到透明无感知;
异构演进:在互联互通和平滑迁移实现之后,我们就可以根据实际情况进行灵活的应用改造和架构
演进;

CSE:Serverless 在阿里巴巴 双11 场景的落地

【笔记】不一样的 双11 技术,阿里巴巴经济体云原生实践(上)相关推荐

  1. 重磅下载 | 核心系统100%上云,揭秘双11背后的云原生实践

    2019 双11,订单创新峰值达到 54.4 万笔/秒,单日数据处理量达到 970PB,面对世界级的流量洪峰,今年的阿里交出了一份亮眼的云原生技术成绩单,并实现了100% 核心应用以云原生的方式上云: ...

  2. 重磅下载 | 核心系统 100% 上云,揭秘双11背后的云原生实践

    点击文末"阅读原文:,下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 2019 双11,订单创新峰值达到 54.4 万笔/秒,单日数据处理量达到 970PB,面对世界级 ...

  3. 天猫双11背后:阿里云全球最大混合云再创记录

    疯狂的双11结束了,天猫成交额最后定格在了1682亿元,又创新高. 疯狂增长数字背后折射的是一群群疯狂的人,有坚守深夜抢货的买家.提前很久备货的卖家.严阵以待的物流--当然还少不了可能连续几天都不能合 ...

  4. 【预告:直播回顾资料下载】2017阿里巴巴双11技术十二讲,历数双11精彩技术干货

    点击有惊喜 历届双11,阿里以其前瞻性的视角和创新技术一直致力于为大众递交诚意满满的答卷,大浪淘沙后最终沉淀下来的都是技术的烁金.叹为观止的数字中流转着这样的人.故事和技术,想要详细了解2017阿里双 ...

  5. 黑色星期五阿里云向海淘输出双11技术

    本文讲的是"黑色星期五"阿里云向海淘输出双11技术[IT168资讯]11月27日零点,"黑色星期五"正式到来,虽然远在中国的消费者无法参与海外的实体抢购,但电商 ...

  6. 重塑技术引擎 阿里落地全球最大规模云原生实践支撑双11

    4982亿,2020年天猫双11再创消费新纪录.58.3万笔/秒,双11交易峰值再创新高,阿里云又一次扛住全球最大规模流量洪峰.这一切背后支撑的"技术引擎"又是如何为近十亿全球购物 ...

  7. 开始报名!首次阿里巴巴经济体双 11 云原生实践展示

    2019 天猫双 11 再次刷新世界纪录,订单创新峰值达到 54.4 万笔/秒,单日数据处理量达到 970PB.今年阿里巴巴核心系统 100% 上云,撑住了双 11 的世界级流量洪峰. 双 11 云原 ...

  8. 人生是自己的选择,双11技术大队长的育女心经

    天下网商 王安忆 参与了2012年到2018年的六年天猫双11大促,在阿里巴巴光明顶技术作战中心,身为技术大队长的陈琴(花名:霜波)不苟言笑,她可能是最有计划性的女工程师,发号施令指挥百余名将员,为双 ...

  9. 大数据、人工智能、VR、Docker、前端,双11技术视频、讲义、文章一键get

    诚然,每届双11对阿里来说都是一次大考,然而,1207亿的背后,考校的绝不仅是阿里的系统支撑能力,比如: 17.5万笔/秒的交易订单数峰值,2015年是14.05万笔:12万笔/秒的支付峰值,2015 ...

最新文章

  1. Webform--LinQ 增、删、改、查
  2. 基于开源jabber(XMPP)架设内部即时通讯服务的解决方案
  3. 关于Java Collections的几个常见问题
  4. 能源动力与计算机科学交叉,深入落实学科交叉融合战略,能源与动力学院、计算机科学与技术学院、材料科学与技术学院研讨智能发动机技术...
  5. double float区别 java,float和double有什么区别?
  6. How——如何学习Win32汇编
  7. java hex to ascii_使用java实现hex和ascii码的转换
  8. 仿IOS通讯录效果,实现获取手机通讯录、字母排序显示、搜索联系人、拨打电话
  9. WinXP系统连接网络教程
  10. 关于linux打包以及解压到指定目录的简单操作demo
  11. DSD解码ES9038PRO和AK4497
  12. Linux下 文件或文件夹的复制(拷贝 cp)
  13. 高薪岗位云计算面试题,云计算运维工程师必备
  14. 在百度地图中获取当前点击 位置的 经纬度 和 地址信息
  15. 介词 by during for from
  16. [转]一个中高级PHP工程师所应该具备的能力
  17. 夏天最美丽的就应该是荷花了
  18. 关于html 背景图片的引用格式
  19. 甜叶菊提取物甜菊糖苷分离纯化吸附树脂
  20. mysql查询用户留存语法(用户留存和用户留存率问题)

热门文章

  1. JLINK烧写U-boot到NAND Flash中
  2. windows和android双系统平板,平板电脑双系统和安卓单系统,哪个好用?
  3. [UE] 软件界面(未完成)
  4. 大疆激光雷达livox avia 在ubuntu18.04+ROS中基本使用方法
  5. 网络基础知识之IP与子网掩码和网络地址
  6. 计算机辅助外语教学,【外语教学论文】计算机辅助外语教学浅述(共3543字)
  7. 初探DirectShow
  8. 天嵌i.mx6q--1
  9. 下列关于python运算符的使用描述正确的是_以下关于 Python 字符串的描述中,正确的是( )...
  10. [附源码]Nodejs计算机毕业设计京津冀畅游网设计Express(程序+LW)