写点什么

Custom Container 的 CI/CD 最佳实践案例

作者:刘宇
  • 2021 年 12 月 15 日
  • 本文字数:2997 字

    阅读完需:约 10 分钟

Custom Container的CI/CD最佳实践案例

在实际生产过程中,我们往往会遇到这样一个通用的项目持续发布的流程:


Git Clone -> Docker Build -> Docker Push -> Deploy Function


这样一个简单的流程,却在很多工具中难以实现,或者过于复杂,那么在 Serverless 架构下,通过 Serverless devs 如果来解决这个流程呢?

准备一个 Github 仓库

这个仓库包括了以下的内容:


  • 用户的代码

  • 构建镜像所需要的 Dockerfile

  • 部署所需要的资源描述文件

  • 一些流程脚本


以仓库anycodes/CustomContainerDemo 为例,可以看到这是一个 Node.js 的项目,其中:


  • 用户的代码

  • server.js

  • package.json

  • 构建镜像所需要的 Dockerfile

  • Dockerfile

  • 部署所需要的资源描述文件

  • s.yaml

  • 一些流程脚本

  • setup.sh

  • 其他文件

  • Github Action 文件

  • version(描述景象 tag 的文件)

关于一些流程

在整个项目中,包括两个流程:


  • Github Action 的流程

  • 自定义 Setup.sh 流程

Github Action 的流程

这个流程主要是一些环境的初始化等:


name: Publish
on: push: branches: [ main ]
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: node-version: 12 registry-url: https://registry.npmjs.org/ - run: npm install -g @serverless-devs/s - run: s config add --AccountID ${{secrets.AccountID}} --AccessKeyID ${{secrets.AccessKeyID}} --AccessKeySecret ${{secrets.AccessKeySecret}} -a publish_access - run: chmod +x ./setup.sh - run: ./setup.sh
复制代码


整个过程为确定 nodejs 环境,安装 Serverless Devs,配置密钥信息(可以参考如何通过Github Action使用Serverless Devs做CI/CD - 账号信息配置


完成上述的初始化和密钥配置之后,可以直接执行我们的流程./setup.sh

自定义 Setup.sh 流程

该流程也是比较简单的,主要做了几个事情:


  1. 明确我的镜像 registry 地址和 tag(此处 tag 是从 version 文件读取的)

  2. 通过 serverless devs fc 组件提供的 build 能力,进行构建操作

  3. 通过 deploy 方法进行项目部署


#!/usr/bin/env bash
# git clone && cd repo
version=$(cat version)registry='registry.cn-shanghai.aliyuncs.com/custom-container/test:'
export image=$registry$versions build --use-dockers deploy --push-registry acr-internet --use-local -y
复制代码


这里有一个问题:谁给我进行的 docker build 以及谁给我进行的 docker push?


  • 在本例子中docker build行为是由 serverless devs 帮做的,但是此出也可以不选择s build,可以选择更为原生的docker build

  • 在本例子中,在进行s deploy的时候,会有一个参数叫做--push-registry acr-internet,此时可以注意该参数有两个可选:


Deploy
Deploy a serverless application.
Usage
$ s deploy <options>
Options
--use-remote Deploy resource using remote config. --use-local Deploy resource using local config. --push-registry <registry> Specify registry or registry type of the image when use custom container runtime. Registry type includes 'acr-internet' and 'acr-vpc'
Global Options
-y, --assume-yes Assume that the answer to any question which would be asked is yes. -h, --help Display help for command.
Examples with Yaml
$ s deploy $ s <ProjectName> deploy $ s deploy --use-remote $ s exec -- deploy --use-remote $ s exec <ProjectName> -- deploy --use-remote
Examples with CLI
You can refer to the usage of fc-api and execute [s cli fc-api -h] for help
复制代码


可以根据自己需求,选择:


  • 'acr-internet': 目标 registry 地址设为公网地址。

  • 'acr-vpc': 目标 registry 地址设为专有网络(vpc)地址。

  • '${registry url}': 自定义 registry 地址。


关于上述整个操作的基本流程:


整个流程基本是:


项目测试

由于我在 Github Action 中声明的是:


on:  push:    branches: [ main ]
复制代码


所以,此时我只需要 push 代码,即可触发发布流程:



部署后的地址效果:


案例总结与注意事项

在上面的步骤中,我们进行了密钥的配置:


s config add --AccountID ${{secrets.AccountID}} --AccessKeyID ${{secrets.AccessKeyID}} --AccessKeySecret ${{secrets.AccessKeySecret}} -a publish_access
复制代码


这里面其实最后有一个参数是-a publish_access,它的含义是为当前密钥指定一个别名,因为 Serverless Devs 支持多密钥的,所以为当前密钥配置一个别名,在以后的使用过程中可以指定,例如在当前的 Yaml 中,第三行有:


access: publish_access
复制代码


用来指定使用该密钥,测试的 Yaml 配置如下:


edition: 1.0.0name: fcDeployAppaccess: publish_access
services: HelloWorld: component: fc props: region: cn-shanghai service: name: custom-container-test description: demo for custom-container-test function: name: custom-container-function runtime: custom-container caPort: 8080 codeUri: ./ timeout: 60 customContainerConfig: image: ${env(image)} command: '["node"]' args: '["server.js"]' triggers: - name: httpTrigger type: http config: authType: anonymous methods: - GET - POST customDomains: - domainName: auto protocol: HTTP routeConfigs: - path: /*
复制代码


完整的 Yaml 配置可以参考:https://github.com/devsapp/fc/blob/main/docs/Others/yaml.md


在上面的 Yaml 中,其实可以看到image: ${env(image)},其实 Serverless Devs 的 Yaml 支持多种形式的变量:


  • 获取当前机器中的环境变量:{env(secretId)}

  • 获取外部文档的变量:{file(./path)}

  • 获取全局变量:${vars.*}

  • 获取其他项目的变量:${projectName.props.*}

  • 获取 Yaml 中其他项目的结果变量:${projectName.output.*}


实战举例,例如当我需要访问数据库等,此时我并不想把密钥明文配置到 Yaml 中,此时可以考虑,将密钥配置到环境变量中,进行直接使用。


关于 构建 问题:


如果使用 s build --use-docker 构建镜像,则需要确保 s.yml 中的 codeUri 字段指向的目录中包含 Dockerfile


关于 权限 问题:


如果配置的密钥权限不够(例如是子账号),则可能会导致用户无法创建某些权限,进而导致部署不成功,这个时候可以考虑让主账号创建好相关的 Role,并且在此处指定:



关于密钥最小权限:


  • AliyunFCFullAccess

  • AliyunContainerRegistryFullAccess


关于所绑定的 Role 的最小权限:


  • AliyunContainerRegistryReadOnlyAccess

发布于: 4 小时前阅读数: 5
用户头像

刘宇

关注

阿里云Serverless云布道师 2020.01.04 加入

阿里云Serverless产品经理,国防科大在读博士,《Serverless架构》、《Serverless实践》、《人人都能学会的Serverless架构》等书籍作者,Serverless Devs发起人,Anycodes在线编程负责人。

评论

发布
暂无评论
Custom Container的CI/CD最佳实践案例