eks-fargate服务最佳实践
需求来源
-
项目在线上运行的时候,偶尔会遇到一些难缠的客户端问题。这些问题没有
traceback
,但是业务逻辑明显不对。我们很想收集客户端的log的信息来辅助我们查找问题,但是由于没有traceback
,所以不会触发常规的错误和日志上传。因此我们想要做一个web服务。我们可以把要收集日志的客户端设备ID登记到这台服上,然后客户端启动时会访问这个web服务,如果发现自己需要提交历史日志,则打包将日志发送到appdump上。我们将这个web
服务取名为controltower
。 -
之所以使用一个额外的web服务来通知客户端上传日志,而不是通过服务端来通知,主要有两个原因:
1
21. 我们需要登记哪些问题或者哪些设备需要上传日志,在一个web服务上进行登记操作比在服务端上做类似的操作更简单、更安全。
2. 客户端可能在连接服务器之前就已经报错了,独立的web服务器在这种情况下仍然可以工作。 -
controltower
的开发和部署有以下几个需求:1
2
31. 开发效率高。显然controltower不是一个游戏的业务系统,这也意味着我们不可能花很多时间在这个web服务上。因此要求有很高的开发效率。
2. 部署效率高。同上,我们也不可能花费很多精力在这个web服务的部署和维护上,所以越简单越好。
3. 自动扩缩容。这个web服务通常只会在客户端启动的时候访问一次。QPS比较低,但是对于维护后开服的这种特殊时段,或者某个活动开启的时段,可能有集中的大量访问,因此我们希望这个web服务能够自动扩缩容。
技术选型
-
在最开始的时候我们考虑的是
FaaS
来实现。理论上只用写function
,部署也非常简单。由于项目目前是在海外运营,所以我们首先考虑了AWS lambda
。但是考虑到未来项目也会在国内运营,我们希望相同的服务在国内也能部署,因此最终放弃了AWS lambda
。 -
去掉
lambda
选项之后,docker
部署成为了下一个选项。这也是我们最终选择的方案。AWS的EKS+fargate
。具体的EKS+fargate
方案将在后面介绍。 -
在Web框架的选择上,由于项目内的语言栈主要以
python
为主,因此我们在python web
框架中进行了选择。考虑到controltower
是一个API web
服务,而非html web
服务,因此我们选择了最近风头正盛的fastapi
框架。主要看重的是:1
21. 原生异步提供的高性能
2. 通过type hint原生支持swagger文档,方便调试 -
数据库上我们使用了
mongodb
,这是公司内部使用比较多的数据库,无论是开发还是运维同学都比较熟悉。在fastapi
内使用基于asyncio
的motor做为mongodb client
。 -
在部署上,我们使用了uvicorn-gunicorn-fastapi-docker 做为基础镜像。这个镜像内部的主要结构为:
1
2
31. 前端使用Gunicorn接收http请求,根据pod的CPU核心数量生成对应的worker进程,默认1:1,即一个CPU核心一个worker进程
2. Worker进程内使用[uvicorn](http://undefined/) 做为ASGI server,这个也是fastapi推荐使用的ASGI server
3. 每个uvicorn进程里运行一个fastapi应用 -
举例来说,如果我们启动一个4核心的pod,则该pod内会启动4个uvicorn进程,和mongodb建立4个连接。由于所有的状态都在mongodb里,所以服务本身是可以轻松水平扩展的,只要最终不超过mongodb的承载能力即可。
EKS的特性说明
托管方式
- EKS一共有三种托管方式,产品详情可查看官网:
- EKS on AWS EC2。拉起一堆EC2作为node,用户得自己维护EC2(也包括SOPT实例)。
- EKS on 自己的机器。支持把自己准备的机器 使用eks来做调度。
- EKS on AWS Fargate。控制面和NODE均托管,serverless特性的KaaS产品。
收费方式
- 控制面不收费,一个pod一个node,只按pod的资源收费。
扩缩容方式
- EKS fargate并不支持node级别的纵向扩容,只支持pod级别的纵向扩容,pod级别的纵向扩容的方式,都需要在pod重启时完成(分为手动重启和自动重启)。
- EKS本身提供横向的auto scalling,当一个pod支持不住的时候会拉起一个新的pod。
部署流程
准备环境
控制机器
- 创建一台EC2机器用作控制机,如果接入了
gitlab-runner
,其实可以省去控制机的安装,控制机器上安装的工具如下:
1 | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" |
配置IAM
- 参考参考官网。
配置service-account
- 配置
aws-load-balancer-controller
组件所需的service-account
,在控制机器上kubectl apply
。
1 | apiVersion: v1 |
部署流程
镜像认证
- 创建镜像认证凭据。
1 | kubectl create secret docker-registry ${IMAGE_PULL_SECRETS} --docker-server=${仓库地址} --docker-username=${仓库用户名} --docker-password=${仓库密码} --namespace=${NS名称} |
部署LB控制器
- 参考这里部署 部署
aws-load-balancer-controller
,注意需安装在kube-system
这个namespace
下。
部署服务端
- 创建ns,为了适配gitlab的cicd发布,ns的名称需符合规范: {project_name}-{project_id},比如:
1 | kubectl create ns mini-hunter-9391 |
- 部署
min-hunter-server
服务,其deployment
的yaml如下:
1 | apiVersion: apps/v1 |
- 通过Service和Ingress暴露7层应用服务。
1 | apiVersion: v1 |
- 通过创建
service
资源暴露4层应用服务:
1 | apiVersion: v1 |
部署web控制台
- 部署
min-hunter-web
服务,其deployment
的yaml如下:
1 | apiVersion: apps/v1 |
- 通过Service和Ingress暴露7层应用服务。
1 | apiVersion: v1 |
扩缩容服务
- 使用
horizontal-pod-autoscaler
组件对web平台进行水平的自动扩缩容,通过修改deployment
的replica
值来自动扩缩容pod个数。
部署Metrics Server
- 需要部署Metrics Server,用于采集pod的负载数据。
1 | kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.3.7/components.yaml |
- 通过如下命令查看是否成功。
1 | kubectl get deployment metrics-server -n kube-system |
部署HPA
- 设置web服务的hpa服务。
1 | kubectl autoscale deployment mini-hunter-web --cpu-percent=50 --min=1 --max=10 --namespace=mini-hunter-9391 |
Gitlab的CICD发布
-
EKS默认可以集成Gitlab的
CICD
发布。关于如何集成EKS到Gitlab请参考这篇文章,这里主要介绍集成之后如何配置CICD。 -
由于Gitlab集成EKS后,会注入环境变量到gitlab的runner,所以runner可以通过kubectl命令控制EKS集群。
-
controltower
的pipeline
的流水线效果如下,可自助在Gitlab
推送代码后进行CICD
发布。
-
mini-hunter
的pipeline
的流水线效果如下,可自助在Gitlab
推送代码后进行CICD
发布。
赞赏一下