11 月 19 - 20 日 Apache Pulsar 社区年度盛会来啦,立即报名! 了解详情
写点什么

干货 | 如何构建系统优化成本,携程出海云原生实践

  • 2021-03-11
  • 本文字数:4666 字

    阅读完需:约 15 分钟

干货 | 如何构建系统优化成本,携程出海云原生实践

一、背景

随着携程国际化战略的开展,为了给海外用户提供更好的服务,携程国际机票有很大一部分数据来源于世界各地的海外供应商和平台,在美国、德国、新加坡等全球众多的海外站点部署业务服务。相比自建私有云,购买设备和组建运维团队,公有云是企业出海的一个更好选择。


但该怎么上云,如何充分利用云原生的能力,是每个企业服务上云前面临的问题,其实我们可以遵循在业界已有的成熟云原生标准。所谓的云原生是一组最佳实践和方法论,指导我们在云环境下构建可伸缩、高可用、松耦合的应用,更快速和低成本运行服务,享受它带来的红利。


云原生本身是一个非常宽泛的概念,本文主要分享携程国际机票在上云实践中关于构建系统和成本优化的一些经验。

二、上云经验

2.1 基础设施即代码



要让我们的应用能够在云上部署,首先需要构建基于云原生的基础设施。传统的手工构建费时费力,虽然可以通过一些自动化脚本取代手工操作实现构建,但是如果整个基础设施的构建过程逻辑复杂,会带来脚本的维护工作量和排查调试等新的问题。


在云原生背景下,我们遵循 Infrastructure as Code(基础设施即代码),应用除了自有的代码仓库外,还有对应的基础设施 IAC 仓库,包含了应用依赖的基础设施和周边系统的配置文件。引入版本仓库控制后,团队可以像管理自己的代码一样管理基础设施,包括追溯到任意版本分支复现问题,一致性的环境配置,所有对基础设施的变更也更容易追踪和 review。


另外我们还需要类似 Terraform 的自动化编排构建基础设施的工具帮助管理基础设施的生命周期。Terraform 对基础设施编码的声明式配置思想和 Kubernetes 如出一辙,我们只需要在配置文件里描述期望的基础设施配置,避免了复杂的过程命令式脚本开发维护,剩下的编排构建工作就交给 Terraform 实现。此外声明式的配置文件有更好的可读性,简单的最终结果一目了然。


对于基础设施系统,秉承让工程师专注于自己最擅长的任务 —— 为客户提供业务创新和可行的解决方案,摆脱繁重的运维工作,我们会倾向于尽可能选择托管版的 Kubernetes 服务。根据我们的实际经验,搭建一个生产级别可用的 Kubernetes 集群整个耗时在分钟级别。

 

基础设施作为代码后,就可以集成在 CI/CD 流水线里,实现自动化持续部署。无论是基础设施还是业务应用的 CI/CD 流水线,出于公司安全合规的考虑,从工程师提交变更,编译,自动化测试,打包镜像这些和 CI 相关的步骤在公司内网执行;之后的镜像会通过代理推送到相应云平台的私有仓库,通过类似 kubectl、Terraform 等一些编排工具的客户端发送请求到云端,远程执行 CD 部分的工作。


业务代码的 CI/CD 流水线

2.2 日志

基础设施之上除了运行业务应用外,还有支撑业务服务的周边系统,例如日志和监控。


日志系统同样使用了托管版的 Elastic Search,简化诸如硬件预置、软件安装和修补、故障恢复、备份和监控等管理任务,同时提供了多个可用区的高可用性。


上云后,应用可能会由于弹性伸缩经常会调度到不同的计算节点,伴随着调度的切换,本地的日志也会被销毁,因此需要实时把日志采集到统一的存储服务中,同时要求日志采集功能具备扩展性和适配性。


业务应用内部直接推送日志的方案虽然简单,但应用和日志收集功能互相耦合,对日志功能的维护带来不便,同时日志的采集开销也会影响到应用自身的运行。我们采用以 Daemon Set 方式在每个计算节点上部署日志采集代理,收集该节点上所有应用日志,随后按自定义的规则加工处理日志数据,输出到 Elastic Search,在前端 Kibana 展现。应用只需要简单地将日志发送到 stdout 和 stderr,完全解耦日志功能和业务应用。

2.3 监控

由于之前公有云平台并没有提供托管的监控系统,所以我们只能自己来搭建。监控系统选型几乎没有什么纠结,使用了几乎是云原生领域监控事实标准的 Prometheus + Grafana。但是原生的 Prometheus 本身只支持单机部署,存在单点故障,同时存储空间受限于本地磁盘,随着时间的推移,监控数据的增加,单机 Prometheus 的性能终究会达到瓶颈。


Prometheus 官方建议根据服务维度拆分,携程本身在上云前已经实现了微服务架构,单个 Prometheus 实例配置成仅采集指定的几个微服务指标,在一定程度上实现了水平扩容。虽然这个方案具备可行性,但是需要配置多个不同的 yaml 文件搭建多个 Prometheus 去发现多个不同服务的监控数据,增加了工程师的运维负担。


我们使用 Kubernetes Operator 来简化这部分工作。在 Kubernetes 的支持下,管理无状态的微服务已经变得比较简单,内置组件 Deployment 可以在无需附加操作的情况下,就可以管理应用的生命周期。


而对于数据库、监控系统等有状态的服务,就需要做一些额外的管理工作,这部分的工作又牵涉到具体应用相关的运维知识,具有资深经验的大牛可以把这些运维技术知识编写成自动化的 Operator,借助 Kubernetes 的能力,像操作 Kubernetes 内置资源一样简单地运行和管理这些复杂的有状态应用,减少工程师的运维成本。


Prometheus operator 通过自定义资源类型 CRD 来简化 Prometheus 部署,使用了 namespace selector 简化了监控目标服务的发现,每个 Prometheus 负责收集特定 namespace 里服务的监控数据。

 


Prometheus operator

虽然 Prometheus 可以多实例部署,但视图层 Grafana 查询数据需要配置多个数据源,这些数据源相互独立,不能聚合统一到全局视图。另外,我们希望能长期存放至少 3 个月的历史数据,数据全部放在本地磁盘存在高昂的存储成本和灾备迁移成本问题。我们引入了 Thanos 组件,解决以下几个核心需求:


1)Thanos Sidecar 定期 2 小时从 Prometheus 服务收集数据上传到远程对象存储(AWS 的 S3),降低丢失数据的风险和历史数据存储成本。而且像 S3 这样的对象存储本身有多副本高可用特性,降低了容灾成本。


2)Grafana 只需要查询 Thanos 的全局接口,Thanos 从多个 Prometheus 实例和对象存储拉取数据去重聚合。


3)此外 Thanos Compact 组件可以对特别久的历史数据 downsample 和压缩,进一步减少存储成本。

同时,Prometheus operator 也封装了 Thanos 相关的集成运维工作,简单修改几个配置就能把 Thanos 作为 sidecar 组件接入。


通过 Grafana + Prometheus Operator + Thanos,一个高可用和高扩展的监控系统就搭建好了。



Thanos 架构

 

三、成本优化

上云的成本也是重要考量的标准。很多人会问,从 IDC 迁移到公有云后,成本会减低吗?如果只是直接把 IDC 使用方式照搬到公有云上,对资源依赖的总量没有变化,那自然成本也不会有多大的改善。

每个上云团队都会面临成本管理的挑战,从技术的角度看,我们可以优化应用提高资源利用率避免浪费,同时利用公有云的按需付费、不用补付费的弹性特性。

3.1 优化计算资源成本

3.1.1 弹性伸缩

以计算资源成本为例:计算实例成本 = 实例运行时长 * 实例价格。如果只是简单粗暴把本地机房的运行模式套用到云上计算,云服务计算资源的费用是高于本地机房的。所以我们需要充分利用云上按需收费的特性,减少闲置资源成本。实例的运行时长和 Kubernetes 集群内的服务数量,以及分配给这些服务的计算资源成正比。同时服务的数量又是和流量成正比。


机票业务场景存在突发的业务流量,比如临近节假日颁布的旅游政策,营销直播活动甚至是最近的疫情。云原生的弹性特性很好地利用合理的资源应对突发的流量。Kubernetes 的 HPA 弹性架构会实时采集集群整体的负载指标,判断是否满足弹性伸缩条件和执行 pod 的伸缩。仅仅是 pod 的伸缩还不够,我们还需要在集群中使用 Cluster Autoscaler 组件,监控集群中由于资源分配不足无法被正常调度的 pod,自动从云平台的实例池中申请增加节点。同时在业务流量下降后,Cluster Autoscaler 组件也会检测集群中资源利用率较低的节点,将其中的 pod 调度到其他可用节点上,回收这部分闲置节点。


下图是我们对资源节点数(黄色曲线)的监控,黄色曲线因为流量增加出现过一段尖刺,如果不使用弹性伸缩,我们要保证集群能在峰值流量时稳定可用,至少要把集群的总节点数维持在红色虚线这个位置;使用弹性伸缩后,集群节点的平均数量就可以保持在更低的绿色曲线位置。

 


弹性伸缩案例

云原生的弹性特性不仅帮助减少资源使用成本,也提高服务对基础架构故障的容错率,在基础设施部分可用区中断不可用期间,其他可用区域会增加相应数量的节点继续保持整个集群的可用。

 

Kubernetes 支持对 pod 容器所需的 CPU 和内存调整,找到一个合理的配额以合理的成本达到最佳的性能。所以我们在服务上云前会做一些接近真实环境的负载测试,观察业务流量的变化对集群性能的影响(业务周期性高峰和低峰的资源使用率,服务的资源瓶颈,合适的余量资源 buffer 应对尖刺流量等等)。既不会因为实际利用率过高导致稳定性问题,比如 OOM 或者频繁的 CPU throttling,也不会因为过低浪费资源(毕竟,即使你的应用只使用了实例的 1%,也要支付该实例 100%的费用)。

3.1.2 竞价实例

某些云平台会把一些闲置计算资源作为竞价实例,比按需实例更低的定价出租,顾名思义,竞价实例的最终费用是按市场供需出价决定的。按照我们实际使用的体验,如果不是特别热门的机型,定价基本在按需实例费用的 30%左右。低价的竞价实例自然有它的限制,云平台会因为按需实例池的资源不足会回收部分竞价实例,当然在回收前会提前通知到这些实例。例如 AWS 会提供 Terminal handler 组件在收到回收通知后提前把容器调度到其他可用的实例上。



此外配置了多种机型和不同可用区域的竞价实例池,进一步降低了竞价资源被回收概率,最后会有保底的按需实例池避免竞价实例完全不可用导致服务中断。


携程国际机票使用按需实例和竞价实例的混合部署,保证低成本和高可用。一些系统关键组件(比如 Cluster Autoscaler),中断就会丢失数据的有状态服务(比如 Prometheus)运行在按需实例。而对错误容忍度高,使用灵活无状态的业务应用运行在竞价实例上。通过 Kubernetes 的节点亲和性控制不同类型的服务调度到对应类型标签的实例上。


 节点亲和性

3.2 数据存储成本优化

 


日志和监控的历史数据,我们会定期备份转移到更低成本的对象存储。


Thanos 的 Sidecar 会定期 2 小时备份监控数据到对象存储。


我们创建周期性的定时脚本任务,把 Elastic Search 的日志数据打成快照文件,迁移到低成本的对象存储。通过 Serverless 方式运行定时任务。以 AWS 的 Lambda 为例,按照任务实际运行时长和请求次数计费,缺点是只能运行生命周期短的函数,但运行低频周期性且简单的定时脚本是非常合适的。



3.3 网络传输成本优化

网络部分的优化依赖实际业务场景。以携程国际机票业务为例,主要的数据传输量集中在查询场景(根据用户实际的搜索条件从海外各个供应商平台拉取机票相关的业务数据),和外部下游服务的流量比例是出少进多。一般服务和外网接口交互走的是云平台提供托管的 NAT 网关,对出网和入网流量收取相同的费用。但国际机票查询业务的场景更适用于只收取出网流量费用的收费模型,所以我们自建部署透明代理 squid 在能访问外网的子网段,运行在私有子网段的业务应用通过代理 squid 转发请求到外网供应商平台服务。

四、总结

本文通过携程国际机票在云原生的实践,分享了如何快速在云上搭建一套稳定高效的生产环境实现快速交付、智能弹性,以及在云上的一些成本优化经验。借助云原生体系实现了基础设施自动化,释放一部分的运维工作就可以更多地投入到业务迭代,更敏捷地响应业务需求迭代,通过监控和日志实现快速试错和反馈。


整体而言,上云涉及的方方面面实在太多了,限于篇幅很难全部讲清,希望本文的一些小分享能帮助到更多想上云的团队,少走弯路,拥抱云原生。


作者简介:

马孟起,携程后端开发专家,对操作系统和网络技术有浓厚兴趣。


本文转载自:携程技术(ID:ctriptech)

原文链接:干货 | 如何构建系统优化成本,携程出海云原生实践

2021-03-11 07:001551

评论 1 条评论

发布
用户头像
好文章啊. 基于实际需求, 平衡收入产出, 得出的最佳实践. 赞
2021-03-11 14:21
回复
没有更多了
发现更多内容

企评家,企业评价助力新三板企业健康发展

企评家

企评家|河南豫能控股股份有限公司的企业成长性报告简述

企评家

时序数据库 vs OLAP

CnosDB

IoT 时序数据库 开源社区 CnosDB infra

易捷行云EasyStack 加入龙蜥社区,共同打造多样化算力创新云平台

OpenAnolis小助手

云计算 开源 龙蜥社区 CLA 易捷行云

微服务架构设计实践

Arvin

微服务架构

中关村e谷为产业搭台:中关村论坛(空天专场)黑科技亮相现场

联营汇聚

【深入理解TcaplusDB技术】扫描数据示例代码——[List表]

tcaplus

数据库 nosql TcaplusDB 腾讯游戏

【深入理解TcaplusDB技术】删除列表指定位置数据示例代码——[List表]

tcaplus

数据库 nosql TcaplusDB 腾讯游戏

【深入理解TcaplusDB技术】TcaplusDB Go SDK手册(二)

tcaplus

数据库 nosql TcaplusDB 腾讯游戏

LAXCUS分布式操作系统如何保障系统安全

LAXCUS分布式操作系统

软件系统安全 量子攻击 分布式软件系统

使用任务管理软件有哪些好处,好用的任务管理软件有哪些?

PingCode

【深入理解TcaplusDB技术】替换列表指定位置数据示例代码——[List表]

tcaplus

数据库 nosql TcaplusDB 腾讯游戏

面由 AI 生|虚拟偶像“捏脸”技术解析

ZEGO即构

计算机视觉 虚拟偶像 Avatar AI捏脸

KubeVela 1.3 发布:开箱即用的可视化应用交付平台,引入插件生态、权限认证、版本化等企业级新特性

阿里巴巴云原生

阿里云 开源 云原生 KubeVela

开发、运维、业务都说好的全栈云原生长这样!

York

云原生 系统架构 全栈

【深入理解TcaplusDB技术】删除列表所有数据示例代码——[List表]

tcaplus

数据库 nosql TcaplusDB 腾讯游戏

企评家企业大数据,实现6种应用的场景

企评家

【深入理解TcaplusDB技术】TDR表GO SDK示例代码——删除数据

tcaplus

数据库 nosql TcaplusDB 腾讯游戏

企业知识管理平台的作用及功能

小炮

企业知识管理

浅谈MatrixOne如何用Go语言设计与实现高性能哈希表

MatrixOrigin

golang 哈希表 MatrixOrigin MatrixOne 矩阵起源

阿里云发布企业云原生IT成本治理方案:五大能力加速企业 FinOps 进程

阿里巴巴云原生

阿里云 云原生 FinOps

微信小程序开发系列 (二) :微信小程序的单步调试和控制器实现步骤概述

Jerry Wang

微信小程序 前端开发 MVVM 微信开发 4月月更

轻量级 Kubernetes 多租户方案的探索与实践

火山引擎开发者社区

Kubernetes 云原生

【深入理解TcaplusDB技术】插入数据到列表指定位置示例代码——[List表]

tcaplus

数据库 nosql TcaplusDB 腾讯游戏

【深入理解TcaplusDB技术】批量删除列表指定位置数据示例代码——[List表]

tcaplus

数据库 nosql TcaplusDB 腾讯游戏

ArrayList和SubList的坑面试题

芝士味的椒盐

Java 面试题 Java 开发

大咖说 X 对话开源|论数据库人才发展战略

大咖说

数据库 阿里云 科技

【深入理解TcaplusDB技术】异步扫描数据示例代码——[List表]

tcaplus

数据库 nosql TcaplusDB 腾讯游戏

【深入理解TcaplusDB技术】TcaplusDB Go SDK手册(一)

tcaplus

数据库 nosql TcaplusDB 腾讯游戏

组织能力建设为啥这么难

凌晞

组织活力 组织建设

干货 | 如何构建系统优化成本,携程出海云原生实践_云计算_携程技术_InfoQ精选文章