背景
从2013年以Docker为首的容器技术的成功,再到2019年kubernetes容器编排技术的迅速崛起,云计算越来越被广大用户所熟悉认可,今天云原生几乎“包罗万象”般的无处不在,越来越多的企业将自己的核心业务迁移到云上,越来越多的业务使用云原生的方式部署、呈现,企业开始享受云时代的利好。那么作为云能力的输出者,我们如何能够将自己的能力以优质的服务提供给客户,如何高效、安全、便捷地管理这些云资产成为了我们最为高度关注的问题。
其中 OpenAPI 是云计算中最重要的一环,是连接客户与阿里云产品的桥梁,根据阿里云 OpenAPI 团队的数据,超过50%的调用量是以OpenAPI的方式与阿里云产品进行交互的,可见API质量的好坏直接影响着云产品使用体验,也决定着云产品的价值。一个标准、规范、易用的API可以很大程度上提升云产品的能力。ACK 产品作为阿里云容器服务的入口,服务着大量的用户,在 2021 我们对ACK(阿里云容器服务Kubernetes版,下统一简称:ACK)产品的 OpenAPI 进行了系统性的梳理,改进;探索出来了一条ROA API之路,将ACK 的打造成了阿里云第一个完全使用ROA风格API的云产品。
过去面临的问题
首先,从2015年阿里云容器服务诞生到2019年将容器市场做到国内Top1,ACK 经历了长达4年的快跑,实现了从追赶到超越;在这期间,ACK 在 OpenAPI 的建设上却远远落后于国内外其他厂商,常常被用户吐槽,给客户带来不好的体验。
其次,由于阿里云的产品提供的API都是PRC风格的,而ACK 是ROA风格的,并不适合这套规范,在这种背景下,ACK面临着许多问题和挑战。
API 定义
由于没有ROA风格的规范,ACK的API采用完全透传的方式,没有统一的资源规范、资源定义,API与资源的关系描述不够清晰,也未对数据结构进行拆分,这导致API文档以及SDK没有元数据支撑,变得难以维护,客户理解门槛高。
在API是透传模式,API网关不会对用户输入的字段进行检验,能够在网关层规避的错误要透到ACK服务端才能被发现,不仅增加了服务端的压力,同时也严重影响用户的使用体验。
API 文档
API 文档描述不清、甚至描述错误。文档与OpenAPI描述对不上,同一个产品的OpenAPI里相同概念采用不同名词,信息对不上。因为ACK的API采用透传方式,API的字段都未被API网关管理起来,推送出去的文档,只有API的简单描述,该API具体的字段以及说明并没有。其次,OpenAPI的隐藏行为未做描述,如果此时错误信息也很模糊,用户只能抓狂。最后,文档示例不足,ACK场景比较多(例如:创建集群就多达5中场景),旧文档中的示例非常单一。
SDK/CLI
更多的用户会使用SDK和CLI来与ACK进行交互,我们SDK存在下面几个问题:
-
由于公开的API有限,用户不能够通过SDK完对所有功能的操作。
-
由于API文档的问题,用户往往不知道该怎么使用SDK。
-
SDK缺乏文档说明和示例说明。
错误码
错误码不统一,错误信息不规范,客户通过错误信息不能有效排查问题,提工单响应速度极慢。
所以,定义一套ROA风格规范,沉淀完整、准确的资源和API元数据,有利于服务产品的开发,从而提升ACK的质量。
规范建立
由于没有符合我们产品的规范(ROA API规范),那么我们边走出一条属于ACK的特色之路来,在2021年我们和OpenAPI团队进行深度交流、合作,终于构建出来了阿里云ROA风格API的规范
下面详细描述一下我们是如何一步步走来的。
API 规范
API 规范的建立,是我们团队(ACK)和 OpenAPI团队 共同建设完成的,特别感谢文档团队对我们的支持。这里我重点描述一下,做为云产品一侧,我们自身建立了哪些API规范,希望能对其产品在ROA上的使用上带来帮助。
接口版本
一个云产品,通常有两类API,OpenAPI和InnerAPI,OpenAPI提供给外部客户使用, InnerAPI实现内部系统、服务之间的调用,提高API的安全性,降低风险。为了更好的API区分以及API维护,我们对接口的POP产品和版本都进行了区分。其中:
- [Product=xx Version=xx]:所有对外公开的API都维护在CS这个产品下,且固定版本。接口直接对外提供,用户可以在官网获取到虽有OpenAPI的接口文档,可以直接在SDK中找到接口定义。
- [Product=xx Version=xx]:不对外开放的API。接口不对外提供,用户不可见,从内部域名调用,接口文档在内部平台维护,SDK专门提供在另一个版本。用于给控制台或者二方产品提供的内部API。
接口设计
参考Restful的设计理念,并且结合我们自己的一些实践来对Web Api进行设计。
-
基于“资源”:数据也好、服务也好,在 RESTFul 设计里一切都是资源。
-
无状态。一次调用一般就会返回结果,不存在类似于“打开连接-访问数据-关闭连接”这种依赖于上一次调用的情况。
-
URL中通常不出现动词,只有名词。
-
URL语义清晰、明确,使用HTTP的GET、POST、DELETE、PUT来表示对于资源的增删改查。
-
返回结果使用JSON不使用XML。
-
所有路径path全部小写,以下划线分隔,所有参数,包括POST里面的body,以及header。
例如: GET /clusters/cluster_id/logs
参数设计
ACK是容器服务的入口,依赖很多底层产品,所以在参数(请求参数和返回参数两种)上通常分为下面几种:
-
IAAS 参数:IAAS参数尽量跟底层产品的API参数保持一致,包括:命名、类型、default值、枚举值、校验等。方便用户理解一些底层概念。
-
Kubernetes 参数:k8s相关参数需和社区或者友商保持一致。
-
ACK 业务参数:言简意赅,参数设计要完全精确,一旦上线的业务参数,不允许修改和删除,因为修改会存在API/SDK/CLI的兼容性问题。
IAAS 和Kubernetes 参数基本都已经固定成型,这里重点描述一下我们在业务参数定义上总结出来的规范:
-
参数名必须严格按照蛇形方式命名。
-
如果其他有相同含义的参数,要复用已有的参数名,比如:cluster_type、type
-
查询修改等接口要注意互相兼容,入参和出参要做到对应,目标必须是查询出参可以直接拿来作为修改的入参,用户理解无障碍。创建或者修改的参数,一定能在查询API中返回。
-
返回结构中Key必须是固定值,而不是动态值,方便调用方反序列化。
-
返回结构必须是Json结构,不能是纯List,不方便扩展。
-
失败调用必须返回error结构告知用户问题所在,例如:{"code":404,"message":"Resource Not Found"}
-
如果是异步API,必须返回task_id,供用户对任务进行状态查询。
API 接口限流
所有API必须配置合理的流量阈值,保证我们的服务在遇到不会因为流量攻击导致服务中断的情况,具体的限流阈值需要根据各产品自身的调用量以及平台压测数据为准。根据OpenAPI平台的提供的能力,建议为API同时设置两个维度的限流阈值:
- API维度:API层面最大允许请求数。
- 用户维度:单用户最大允许请求数。
错误码设计
错误码信息是最好的反馈我们API在出现异常是的工具,良好的错误设计能够在调用失败的时候准确的反映出系统的错误,也便于接入监控系统,用于产品自身对服务质量的监控。错误码设计时必须包含以下几个方面,
-
错误码定义:服务HTTP协议对错误码段的划分,2xx:正确,3xx:重定向,4xx:客户端,5xx:服务段
-
错误信息:言简意赅且能反映出错的原因,最好是根因,避免二次定位。
-
字段映射:如果前后端字段有不一致的地方,需要明确映射关系,便于在OpenAPI平台维护。
操作规范
操作规范主要是指:在完成API定义和开发之后,将API元数据录入到API网关时需要注意的事情。
-
平台操作权限收敛:API在平台上的编辑权限必须收敛到API维护负责人手中,作为唯一修改入口,避免上线未经严格Review的API。API开发人员有权查看API内容。
-
上线前Review:一旦上线,就会有用户开始使用,上线前必须做最后一次Review。这将是接口上线变为固定版本前的最后一次审核。这次Review的前提是已经完成了"需求阶段评审"的所有内容,Review通过后会直接上线。这个Review的内容必须包含前面提到的4项规范,有一条不满足,都不能上线
-
API上线后,需在最短时间内提供文档,并更新SDK、CLI、TF等工具的支持,保持联动。
文档规范
上面讲述了我们在API接口定义上总结出来的规范,我们在来说说文档规范。文档相当于API的眼睛,完备的文档才能让用户使用起OpenAPI来如庖丁解牛般游刃有余。文档规范的建立是我们团队(ACK)和 文档团队 共同完成的,特别感谢文档团队对我们的支持。
基本阿里云所有的产品都是使用的RPC,鲜少有使用ROA的,而RPC是没有明确区分Path、Query、Body这些参数的,所以你看到其他云产品(例如:ECS),所有的请求参数都罗列在一个表格中。这对ROA风格API就很难区分了,在ROA中Path、Query、Body都有明确的划分,参数必须传递正确,而RPC的这种文档风格,显然不能够满足我们的需求。于是在2020年我们联合文档团队重新定义了文档模板结构,认真评估分析友商和社区的规范,构建属于阿里云的新文档模板。主要内容包括:
-
请求语法:符合ROA API的描述。
-
请求参数:请求参数由一张表拆分为:请求Path参数、请求Query参数,请求Body参数三部分。
-
响应体语法:符合ROA API的描述。
-
响应示例:支持多示例
-
开发者资源:新增开发者资源,为用户使用SDK、ApiExplore等提供指引。
新旧模板对比:
OpenAPI治理
在ROA风格API的规范建立完成后,我们重点针对我们之前API上的不合规进行了专项治理,
API拆分
之前我们所有的API都在一个版本中维护,其中私有、公开、控制台调用的API都混在一起,大大增加了对API的归类和维护的成本。内部调用的API本来走内网即可,也走了公网,增加了产品的风险。
并且,随着产品的升级,有很多老产品的API(Swarm)这部分API现在大部分已经没有用户在调用了,这类API我们也不应该在维护到现有的OpenAPI中,提供给客户,应该单独版本维护,或者按规范走下线流程。
面对这些问题,我们对已有的API进行了拆分。拆分原则:
-
该下线的走标准流程下线
-
所有OpenAPI用一个版本来维护
-
将所有内部调用的API全部拆分出去,单独维护;控制台将调用链路切到 Inner。
最终,我们将256个API进行梳理、拆分。其中OpenAPI 68个,Swarm的部分下线,剩下的都完成了Inner改造,待所有Swarm用户都升级到Kubernetes后,全面下线。
资源抽象
我们对我们API进行了资源抽象,用户使用API来访问云服务,本质上是想通过对某种云资源执行特定的操作来完成一个业务动作。例如ACK产品中,集群、节点、节点池等等都可以抽象成一种资源,用户可以单独对该资源进行相关操作(增/删/改/查)。做了资源抽象之后,我们产品在支持Terraform上, 几乎是开发零成本。
数据结构抽象
数据结构我相信每一个搞开发的同学都非常清楚,数据结构(data structure)是带有结构特性的数据元素的集合,简而言之,数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合。
在我们ACK产品中,集群,节点池,节点中有很多结构都是一致的,我们可以把这些结构单独提取出来维护,
- 对内:方便其他乃至后面新增的API进行直接引用,而不需要在多次反复的定义。
- 对外:便于用户理解
文档完善
文档了有新模板做支持,后续的事情就变得愈发的简单了。既然框架已经定了,那么接下来的事情就是为这具身躯一共血肉。
-
API字段录入AMP平台,提供API元数据唯一入口。
-
补充、校准字段描述信息。并让文档同学逐篇进行Review。非常感谢文档团队的大力支持。
-
API使用的隐藏"坑"在文档中做重点说明。
-
完善API示例。
SLO治理
借助API团队提供的[治理平台], 我们能够快速有效的发现当前API所存在的问题,以便快速制定对应的优化和改进策略。
一个产品的服务质量,一个最简单的衡量指标便是SLO。根据[治理平台]的数据,我们深挖可用率不达5个9的API,分析整个API的调用链路,最大可能消除了调用链路上的异常。经过一段时间的治理,ACK API的SLO从80+提升到了99~100。
开发者工具治理
用过ACK开发者工具的同学都知道,不是太友好。我自己用过也觉得难用,也难怪用户诟病。我们在做了资源拆分,数据结构提炼之后,联合SDK团队同学,对我们的开发者工具也进行了大换血,新的SDK是基于 [TeaDSL]解决方案生成的,发布功能目前已支持的程序语言:Node.js / PHP / Go / Java / C# / Python3 / Python2 / C++。这将是全新的使用体验,运行更加稳定。非常感谢SDK团队的支持。
-
ApiExplore:更加人性化,和API文档一起联动,完美的将API呈现给开发者。容器服务Kubernetes版。
-
SDK:基于TeaDSL生成的SDK。alibabacloud-go/cs-20151215。
-
ARC:新版本CLI,支持结构化参数。ARC,新版阿里云CLI工具ARC使用说明。
全新的开发者工具已经上线多时,欢迎大家前去体验。
取得的成果
经过小半年的治理,我们产品在OpenAPI的质量以及使用体验上都得到了很大的提升。下面列举了目前可量化出来的指标,还有部分指标还在统计中,例如:用户满意度。
开放API SLO:平均可用率从<99.910%提升到99.991%
文档覆盖率:从50%提升到了100%
开放度达标率:从85%提升到100%
最后
随着上云进程的不断加速,客户对产品的使用体验要求越来越高,同时云产品对提升企业IT治理能力也变得越来越重要。OpenAPI是云产品对外暴露的门户,OpenAPI的好坏直接影响了阿里云被集成能力。OpenAPI的治理并非一朝一夕就完成,它和稳定性一样,也是一个持续投入的过程,我们将持续致力于产品稳定性和用户体验等方面的优化,同时也期望能有更多的产品加入到OpenAPI的治理中来,一起将产品做的更好。