使用 Golang 为亚马逊云科技开发 OpenAPI 日志分析云原生应用

SDK
OpenAPI
re:Invent
0
0
我们是开源日志分析工具 [APIcat](https://gitee.com/bjf-fhe/apicat?trk=cndc-detail) 的贡献者,APIcat 是一款基于 OpenAPI 描述文件对 HTTP 服务,特别是前后台分离之后的 API 服务进行日志分析的工具,因为 OpenAPI 对每个接口都进行了详细的输入输出定义,而且是一个全球标准,因此我们可以通过分析 OpenAPI 描述文件获得每个接口的要求,从而更细致的判定日志中每个访问的正确与否,从而提供不一样的日志分析能力。 亚马逊云科技是全球最全面、应用最广泛的云平台,我们的 OpenAPI 访问日志分析开源工具 APIcat 推出之后,不断的有朋友希望我们适配亚马逊云科技的日志分析功能,因此我们启动了亚马逊云科技的适配工作,在适配的过程中,对于亚马逊云科技强大而广泛的开放对接能力深有感触,迫不及待分享给大家。 # 完善的 API 支持能力 APIcat 是一款 Golang 编写的 CLI 工具,在适配伊始,我们首先学习的是亚马逊云科技的 Golang SDK 部分。亚马逊云科技的 Golang SDK 提供完全复合 [Golang 标准的帮助文档](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2?trk=cndc-detail),整体结构清晰,提供了很多指南和说明性文档,整体给开发者的感觉更亲切,让人有迹可循,如果平台只给了自动生成代码,但是代码中解释和引导的材料非常的少,也不愿意对接口和数据进行更多的文档化说明,这样的云平台让人上手就会非常困难。 ## 初始化客户端 初始化客户端的第一步是获得亚马逊云科技的授权,Amazon Golang SDK 的初始化大致分为创建 Config 和创建 Client 两步。 创建 Config 主要需要提供地域和认证信息,我们使用的方式如下: ```js //config是"github.com/aws/aws-sdk-go-v2/config"库 h.cfg, err = config.LoadDefaultConfig(context.Background(), config.WithCredentialsProvider(h), config.WithRegion(h.regionId)) ``` 左滑查看更多 亚马逊云科技的 Golang SDK 设计了很方便的扩展模式,比如上面的 LoadDefaultConfig 函数,通过 WithXXXX 的标准扩展模式可以支持不同的扩展功能,我们自定义了认证方式和 Region 获取方式,来兼容亚马逊云科技的认证信息初始化模式和我们自身软件的配置方式。通过传入两个不同的 Option 来达到自定义认证信息和地域信息的目的。 认证信息主要通过具有以下函数的接口类完成: ```js func (h *Config) Retrieve(ctx context.Context) (aws.Credentials, error) { return h.Credentials, nil } ``` 左滑查看更多 其中返回的认证信息至少包含 AccessKeyID 和 SecretAccessKey,这里提示一下大家,最好不要使用主账户的 AccessKeyID 和 SecretAccessKey,在使用对应功能的客户端或其他外部工具时,应该创建对应的 IAM 角色和用户,并使用这个 IAM 用户的认证信息来初始化客户端,这样才能最大化的保证账户安全。 亚马逊云科技这套 Golang SDK,在工具的使用方面,除了保证工具的广泛适用以外,在统一客户端规范上也做了很多工作,例如这个 Config 过程,深入代码,可以看到里面设计了多层次的配置读取加载逻辑,包含了很多标准化的流程,按标准要求初始化了客户端的很多部分。 这当然对用户是最好的,但一度让我们有些纠结。作为软件开发者,主要是纠结是使用通用的 LoadDefaultConfig 好呢,还是从更深的地方修改,以便我们对于亚马逊云科技的适配可以更好的符合我们自身软件的整体习惯。 期望所有配置改为遵循我们自己的逻辑,当然是最舒服的,但静下心从使用者的角度来想了想,统一配置对于一个使用多种亚马逊云科技工具的用户来讲,一定是更优的解决方案,因为用户使用云方案通常是使用一个服务商的多个服务,多种工具,采用亚马逊云科技的通用方案才可以使得单个用户所使用的所有亚马逊云科技的工具只需要一套配置即可。 自己作为软件开发者,当然还是应该以用户的便利为主,我想,这可能这也是亚马逊云科技设计这套配置逻辑的初心。 # 快速适配多种服务 完成基础的配置生成之后,我们就要开始适配整体的亚马逊云科技访问日志分析系统了。整体的逻辑如下: ![1.png](https://dev-media.amazoncloud.cn/4cedb44b74f34e6fa2e37f33b19045d2_1.png "1.png") 亚马逊云科技的负载均衡(英文名为 [Elastic Load Balancing](https://aws.amazon.com/cn/elasticloadbalancing/?trk=cndc-detail),下简称 ELB )提供了多种子产品覆盖多种负载均衡要求,因为我们处理的是 HTTP 负载均衡,因此选择了七层负载 Application Load Balancer 作为主要适配目标。 亚马逊云科技 ELB 的日志可以导出到 S3 进行存储,[Amazon Simple Storage Service](https://aws.amazon.com/cn/s3/?trk=cndc-detail)([Amazon S3](https://aws.amazon.com/cn/s3/?trk=cndc-detail))是一种对象存储服务,可以简单理解是一个分布式文件存储系统,就存储日志文件来说,日志文件存储的是以 gz 格式进行压缩的文本日志文件,需要注意的是 S3 的日志存储是一个默认关闭的可选服务,需要手动开启(会花费对应的 S3 存储费用,建议设置自动删除周期)。 亚马逊云科技的日志存储是一种类 Nginx 日志的单行文本,类似这样,点击查看[格式的详细说明](https://docs.aws.amazon.com/zh_cn/elasticloadbalancing/latest/application/load-balancer-access-logs.html?trk=cndc-detail), ```js https 2018-07-02T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 192.168.131.39:2817 10.0.0.1:80 0.086 0.048 0.037 200 200 0 57 "GET https://www.example.com:443/ HTTP/1.1" "curl/7.46.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 "Root=1-58337281-1d84f3d73c47ec4e58577259" "www.example.com" "arn:aws:acm:us-east-2:123456789012:certificate/12345678-1234-1234-1234-123456789012" 1 2018-07-02T22:22:48.364000Z "authenticate,forward" "-" "-" "10.0.0.1:80" "200" "-" "-" ``` 左滑查看更多 S3 存储的日志每5分钟更新一次,如果5分钟内访问多的话,会生成多个访问日志文件。因此,我们只需要按时刷新日志文件,并依次读取处理即可。 ## 获得相应服务的代码 从上面的流程图可以看出,如果要实现针对亚马逊云科技的访问日志分析,判定错误行为后,自动拦截的功能,实际我们需要调用的就是 S3 和 EC2 的服务接口。 得益于 Amazon Golang SDK 的标准化整合式文档,我们可以很方便地从文档下方的 Directories 中的 Service 中找到我们需要的服务: ![2.png](https://dev-media.amazoncloud.cn/b53c159f8a284ec896f3eebdb23a048d_2.png "2.png") ![3.png](https://dev-media.amazoncloud.cn/96456429d78c4c0f8a3b75613f2a4a4b_3.png "3.png") Service 的编程界面提供了一致的调用方式: ```js func NewFromConfig(cfg aws.Config, optFns ...func(*Options)) *Client ``` 通过将第一步中,我们初始化成功的 cfg,调用对应 Service 的 NewFromConfig 函数,我们可以快速的完成对应服务的客户端初始化,并进一步通过这个 client 完成对应的功能调用。 ### S3 主要对接流程 ![4.png](https://dev-media.amazoncloud.cn/e698578cf6c842bd8e68f4488b9e8573_4.png "4.png") S3 侧的主要流程如上图,我们完成初始化 client 之后,通过 ListObjectsV2 函数完成 Bucket 中文件的列表查询,ListObjectsV2 声明如下: ```js func (c *Client) ListObjectsV2(ctx context.Context, params *ListObjectsV2Input, optFns ...func(*Options)) (*ListObjectsV2Output, error) ``` 左滑查看更多 其中第二个参数中,有 StartAfter 属性,用来做递增查询。 ```js // ContinuationToken indicates Amazon S3 that the list is being continued on this // bucket with a token. ContinuationToken is obfuscated and is not a real key. // ContinuationToken 标记查询列表一次没有返回完全,使用这个 token 标记继续开始的地方 ContinuationToken *string ``` 左滑查看更多 然后,通过循环调用 GetObject 来获得详细日志内容,获得后,解压进行日志分析。 ```js func (c *Client) GetObject(ctx context.Context, params *GetObjectInput, optFns ...func(*Options)) (*GetObjectOutput, error) ``` 左滑查看更多 需要注意的是,S3 并不能直接对接,需要从配置面板中为 S3 配置 Access Point,并使用 access point 的 ARN 或者别名作为访问的 Bucket 名称才能进行 S3 的访问。 ![5.png](https://dev-media.amazoncloud.cn/92768ad2ed17404b9bb88ee524393691_5.png "5.png") ### EC2 主要对接流程 ![6.png](https://dev-media.amazoncloud.cn/568211a934fb4defa50d2e1278c20a5d_6.png "6.png") EC2 安全规则这边,则主要进行安全组的读取,完成条目比对后,进行实时更新,更新包括添加或者删除两种操作。对应调取的接口包括: ```js func (c *Client) DescribeSecurityGroupRules(ctx context.Context, params *DescribeSecurityGroupRulesInput, optFns ...func(*Options)) (*DescribeSecurityGroupRulesOutput, error) //Adds the specified inbound (ingress) rules to a security group. //将一条入网规则添加到安全组中。 func (c *Client) AuthorizeSecurityGroupIngress(ctx context.Context, params *AuthorizeSecurityGroupIngressInput, optFns ...func(*Options)) (*AuthorizeSecurityGroupIngressOutput, error) //Removes the specified inbound (ingress) rules from a security group. //从一个安全组中删除一条入网规则 func (c *Client) RevokeSecurityGroupIngress(ctx context.Context, params *RevokeSecurityGroupIngressInput, optFns ...func(*Options)) (*RevokeSecurityGroupIngressOutput, error) ``` # 更灵活的方案 上面的设计中,我们从 S3 直接读取了日志原始文件作为入口,进行日志分析,这其中必然涉及文件缓存、解压等复杂的文件操作,其实亚马逊云科技还提供了更为灵活的方案,对日志进行预处理,使得我们的后续读取和分析会更加简单,这就是 [Amazon Athena](https: //aws.amazon.com/cn/athena/?trk=cndc-detail) 服务。 [Amazon Athena](https: //aws.amazon.com/cn/athena/?trk=cndc-detail) 是一项基于开源框架的[无服务器](https://aws.amazon.com/cn/serverless/?trk=cndc-detail)交互式分析服务,支持开源表和文件格式。Athena 提供了一种简化、灵活的方法来分析包含它的 数据。从 [Amazon Simple Storage Service](https://aws.amazon.com/cn/s3/?trk=cndc-detail)(S3)数据湖和超过25个数据来源(包括本地数据来源,或使用 SQL 或 Python 的其他云系统)分析数据或构建应用程序。 这样,对于 S3 文件的直接操作可以转化为 Athena 的类 SQL 操作,这样,我们整体的 API 读取,就会更加的简单,整体逻辑关系变为: ![7.png](https://dev-media.amazoncloud.cn/3594459c0c87409fb1a8fc5ac902c5b9_7.png "7.png") # 使用 Golang 开发亚马逊云科技原生应用的体验总结 上述文章中,我们讲解了我们的 APIcat 应用适配亚马逊云科技中的一些体验过程,我认为亚马逊云科技为 Golang 开发者首先提供了一套很好的开发指南和类库支持,整体支持文档标准化做的很好,完全复合 Golang 要求的文档,使得从标准 Golang Dev 站点获得整套代码和帮助文件变得十分简单。 其次,包括一站式配置等一些设计体现了面向使用者的设计原则,也使得开发亚马逊云科技上的云原生应用变得十分的简易,从上面我们的例子也可以看出,从 Config 派生不同服务 client 的标准化做法简化了我们认知和理解亚马逊云科技的过程,使得我们对两个服务的对接都非常的容易。 最后,推荐在苦思冥想时,查看[亚马逊云科技的示例库](https://github.com/awsdocs/aws-doc-sdk-examples?trk=cndc-detail), 库里包含了多种语言的亚马逊云科技代码样例,值得参考。注意,本文中 Golang 采用的 v2 版本 sdk,因此,参考时,请阅读 gov2 版本的相关例子。 很高兴将我们的 APIcat 适配亚马逊云科技的工作可以如此顺利的开展,相信未来会有更多 Golang 开发的亚马逊云科技上的云原生应用让我们的云生活变得更简单! 文章审核:whb
0
目录
关闭