FC - Custom Container 运行环境下的 Gin 自动部署

又是没找到工作的一天,所以又开始尝试一些新东西,这篇文章讲在阿里云 Serverless 架构的 FC 产品,Custom Container 环境下如何跑起 Gin 应用。

Serverless 架构一开始是在腾讯云的 SCF 先接触的,我的博客涉及到 Serverless 的文章应该说是非常多的,近年来也越来越多的人开始进行更多的接触,把更多的业务放上来。一开始我们更多是依赖厂商对特定语言预制好了的环境,比如 Node 、 PHP 这些热门的,但这些版本是固定的,而且你要是想增加一些底层依赖库其实是很麻烦的。

然后又出现了 Custom Runtime 来更好解决这个问题,但是阿里云提供的 Funcraft 工具,我是没跑通官方迁移文档中的 Laravel 、 ThinkPHP 迁移流程,后面排查是 FC 语言提供的默认环境和用 Funcraft 的不一样,少了很多底层依赖库,要自己加进去也麻烦,所以我就放弃了,哈哈哈。阿里云现在又抛弃了这个 Funcraft 工具,开始推 Serverless Devs,然后这个工具的压测功能我也是没跑起来,继续使用 wrk,哈哈哈。

Custom Runtime 其实可以让我们更好去做一些业务,比如我最近做的 反代 ,部署在香港地域,nginx 代理到指定的网站,比如 GitHub 、GitHub API 等,现在支持了很多常用域名。其实做这个是非常简单的,nginx 判断二级目录是不是支持的域名,然后 proxy_pass 过去,写一个 Dockerfile + nginx.conf 就可以了。

我之前这方面也写过一篇 文章 的,因为我要借助 Funcraft 来生成 nginx 环境的那些文件,所以整体流程其实是非常麻烦的,而且最重要的是,那个方法现在已经不行了,没仔细去排查,应该是后面版本迭代升级了然后影响到了,我自身没有去控制好版本号。

用 Custom Runtime 来完成反代需求,呈现的效果是非常棒的,让我对这块有了不一样的期望,那就是能不能把整一个应用更便捷部署上来。

Custom Runtime 有什么优势呢?

  1. 容器镜像,可以更好的实现我们业务的运行环境,不过 FC 不支持多阶段构建,go 的 Dockerfile 都是编译后,就放在 scratch 中去跑,但测试后发现是不行的。
  2. 低成本迁移,因为我们可以用 Dockerfile 来构建环境。
  3. 镜像加速,实例的镜像拉取可能是通过已启动的实例,不是每次都走源站,相当于启动速度会快很多,毕竟不支持多阶段构建,编译后基本都 200M+ 了。
  4. 自动部署,在控制台配置好后,监听到代码仓库的变化,自动进行构建后部署到 FC。
  5. 权限,不需要向之前打包一样,还是在 linux 下加上执行权限然后再打包。

业务的灰度是实现不了的,但可以做测试环境、生产环境的区分,相当于两个函数去监听两个不同的分支。


接着我们来简单的部署一个,Gin 官方的 Demo 稍微改一下,我们在代码中要写死监听端口的,经过打印 env 的排查,这边 FC 是没有在环境变量中提供 FC_SERVER_PORT 的。

main.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"github.com/gin-gonic/gin"
"net/http"
)

func main() {
r := gin.Default()

r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})

err := r.Run(":9000")

if err != nil {
return
}
}

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
FROM golang:1.18-alpine as build

# 时区
RUN apk --no-cache add tzdata

ENV TZ=Asia/Shanghai

WORKDIR /code

COPY go.mod go.sum ./

# 下载依赖
RUN go mod download && go mod verify

COPY . .

# 编译
RUN env GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o main main.go

# 清除缓存
RUN go clean --modcache

EXPOSE 9000

# 执行
CMD ["./main"]

部署流程:

页面最底部我放了完整的源码,可以先去下载。下载完成后,上传到代码托管平台。

到阿里云的容器镜像服务,有个人免费版的,创建一个镜像仓库。

填写基本的信息。

设置代码的来源。

进入镜像仓库,配置下触发编译的分支。

填写触发信息。

手动进行一个触发。

好家伙,报错了,可以上代理或者使用海外编译,dddd。

开启海外编译模式。

编译完成了,共花费 82 秒。

开始进入 FC 流程,创建一个容器镜像类型的,接着选择我们的容器镜像仓库。

可以看到,因为不支持多阶段构建,所以还是比较大的。

来触发器看一下请求的链接。

发起个请求看看,成功了。

如果你的程序涉及一些静态文件,比如 HTML 模板,可以了解下 embed。


其实 Serverless 或者上云,其实还是有很多需要注意的,那就是不要对某一个云厂商的某一个产品依赖太严重,要考虑下如果后期换云会怎么样。

南极哥:厂商提供的 MySQL ✔,厂商提供的 AliSQL/TDSQL ✘

厂商提供的这些产品是非常棒的,但最怕如果它 GG 了,或者我们要换一个云,没有替代品,那我们的重构成本是多少了。

比如最近微信群传的,微信小程序云开发的费用可能会提升很多,但云开发对特供提供的分发依赖是非常强的,相当于你抛弃云开发,你只能重新重构,所以我一直很抗拒这种,包括后面出的云托管。

可能在有些方面,我们不是当前最流行的,但企业应用,我们不是要让我们的业务存在更多的可控性嘛,不能意味的追求牛逼、高大上、最先进的架构,而忽略了出现故障之类的时候,我们有没有能力及时处置、及时降低我们的业务损失。


源码

往上