初探 Google 云原生的CICD - CloudBuild

大纲

Google Cloud Build 简介

Google Cloud Build(谷歌云构建)是谷歌云平台(Google Cloud Platform,GCP)提供的一项服务,可帮助开发人员以一致和自动化的方式构建、测试和部署应用程序或构件。它为构建和部署应用程序提供了一个完全托管、可扩展和灵活的环境。

使用Cloud Build,开发人员可以使用配置文件(如YAML或JSON)定义构建流水线,指定构建过程中要执行的步骤和操作。可以根据事件(如代码库提交或更改)自动触发这些流水线,也可以由开发人员手动触发。

Cloud Build支持各种构建工具和编程语言,允许开发人员使用他们喜欢的工具和框架。它与其他GCP服务(如Cloud Storage、Container Registry和Cloud Run)无缝集成,实现了平滑的部署和发布工作流程。

Cloud Build的主要功能包括并行构建以加快执行速度、可定制的构建步骤、缓存以提高构建性能以及与版本控制系统的集成,便于源代码管理。

总之,Cloud Build简化了构建和部署过程,促进了自动化和协作,并帮助开发人员在谷歌云平台上优化软件开发生命周期。

与Jenkins 对比的优缺点

可以认为Cloud build 就是jenkins 的简单替代品, 比起jenkins, cloud build 有如下的优缺点

优点1:

Cloud build是完全云原生和serverless 的, 而jenkins 需要额外部署, 单这一点,足以让部分人选择它。

优点2:

Cloud build的配置简单, 学习成本低

对比起Jenkins 那复杂的一堆配置。。。

Cloudbuild 的部署步骤用yaml 编写, 跟Ansible 类似, 而Jenkins 的groovy script 学习曲线相对更陡峭

缺点1:

只适用于部署GCP的服务, 对于on-prem service 的部署比较吃力

缺点2:

配置简单, 但是没有jenkins 部署那么灵活, groovy script 功能更加强大

缺点3:

由于cloud build 的每个step 都在一个单独的容器内完成, 导致一些文件共享的问题

例如 如果有两个步骤, 第1个步骤 , mvn test 下载了1堆依赖

下1个步骤 mvn package 还是要下载同样的依赖。。。

总之

Cloudbuild 适合POC 场景下的部署, 快速简单.

Jenkins 更适合复杂场景的部署, 例如如果你的部署pipeline 需要包含 代码漏洞扫描, approval 流程系统集成 等其他步骤, 还是Jenkins 更方便

clould build yaml - 定义部署的步骤

用1个简单的例子:

我有1个简单的springboot service

https://github.com/nvd11/demo_cloud_user

想部署到google 的cloud run平台中。

步骤无非就是

  1. 编译 并 执行Junit cases - command: mvn test
  2. 打包成jar package - command: mvn package
  3. 打包成 docker image - command: docker build
  4. push docker image 到 Google Artifact Repository (google 镜像仓库)- command : docker pull 《image-path》
  5. 把镜像deploy 到 google cloud run 平台 - command: gcloud run deploy 《service name》--image=《image-path》。。

而上面提到, 其实每1个步骤就是1个命令

其中 步骤1和2执行的是mvn 的命令, 所以步骤1和2我们需要引入 mvn 的docker 镜像

步骤3和4是docker 命令, 需要引入包含docker/kaniko 的docker 镜像

步骤5 是gcloud 命令, 则需要 google sdk的docker 镜像

所以我们需要在springboot service 的项目主目录下新建1个cloudbuild.yaml (如果需要docker部署, dockerfile也还是需要的)

cloudbuild.yaml

yaml 复制代码
steps:
  - id: check maven and jdk version
    name: maven:3.9-sapmachine-21 # https://hub.docker.com/_/maven
    entrypoint: mvn
    args: ['--version']

  - id: run maven test
    name: maven:3.9-sapmachine-21 # https://hub.docker.com/_/maven
    entrypoint: mvn
    args: ['test']

  - id: run maven package
    name: maven:3.9-sapmachine-21 # https://hub.docker.com/_/maven
    entrypoint: mvn
    args: ['package', '-Dmaven.test.skip=true']

  # https://cloud.google.com/build/docs/configuring-builds/substitute-variable-values
  - id: build docker image
    name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'europe-west2-docker.pkg.dev/$PROJECT_ID/my-docker-repo/demo-cloud-user', '.']

  - id: upload docker image to GAR
    name: 'gcr.io/cloud-builders/docker'
    args: [ 'push', 'europe-west2-docker.pkg.dev/$PROJECT_ID/my-docker-repo/demo-cloud-user']

  # deploy to Cloud run
  - id: deploy image to cloud run
    name: 'gcr.io/cloud-builders/gcloud'
    args: ['run', 'deploy', 'demo-cloud-user',
           '--image=europe-west2-docker.pkg.dev/$PROJECT_ID/my-docker-repo/demo-cloud-user',
           '--port=8080',
           '--platform=managed',
           '--region=europe-west2',
           '--no-allow-unauthenticated',
           '--service-account=vm-common@jason-hsbc.iam.gserviceaccount.com',
           '--key=projects/$PROJECT_ID/locations/europe-west2/keyRings/mykeyring/cryptoKeys/mycmek']
# https://stackoverflow.com/questions/68779751/error-publishing-source-code-from-cloud-build-to-a-bucket-using-triggers
logsBucket: gs://jason-hsbc_cloudbuild/logs/
options: # https://cloud.google.com/cloud-build/docs/build-config#options
  logging: GCS_ONLY # or CLOUD_LOGGING_ONLY https://cloud.google.com/cloud-build/docs/build-co

十分简单易懂:

其中Google 已经允许在Cloudbuild 使用built-in的默认参数, 例如$PROJECT_ID 代替真实的gcp project id

参考:

https://cloud.google.com/build/docs/configuring-builds/substitute-variable-values

值得注意的是options- logging 如果配置了CLOUD_LOGGING_ONLY则cloud build 日志会发送到google 日子平台

日志格式:

如果是选择GCS_ONLY 则需要配置logsBucket

日志格式:

个人更喜欢更简介的第2种。

用Cloud build trigger 触发部署

当写好cloudbuild.yaml写好后, 有两种方法出发部署

第一种是使用cloud build trigger

所谓cloud build trigger 就是让你的代码仓库的更新事件(commit/pull request) 去触发一个部署

而目前代码仓库只支持github 和 bitbucket, 置于国内的gitee, coding之类或者gitlab 私有化部署的代码仓库不支持

新建1个trigger 的详细步骤

1.打开trigger 的google console 页面, 点击新建trigger button
填写trigger 参数

有几个关键参数

region: 建议和您的其他resource 的region保持一致,减少网络传输距离

Name: cloudbuild的名字, 必填

Repository: 就是你的代码仓库, 第一次使用,需要配置google cloud 到github Oauth2 授权

branch: 就是制定某个branch的时间, 可以用.*代替全部branch, 建议只写某几个release branch

Event:有3个选项, 这里不解释了

1.push to a new branch

2.push new tag

3.pull request

Cloud Build configuration file location:

默认是 /cloudbuild.yaml 当然可以改成其他的, 让1个项目可以多种部署参数。

Service account: 部署所以用的service account, 如果不填, 则用cloud build 本身的agent service account 去部署, 权限问题是个坑。

注意上面的步骤也可以用terraform管理

触发Trigger

有两种方式, 1就是真的去修改代码, 利用commit/pull request/tag 事件出发

2是在ui上按run

查看build 状态和历史

部署历史的dashboard 能在UI上查看

点进去某个item 就能看详细的日志

当然用命令行也是可以的, 但是不太方便, 主要是查看具体日志的部分, 暂时我只能基于bucket 里的日志来查看:

bash 复制代码
Service URL: https://demo-cloud-user-7hq3m4pdya-nw.a.run.app
[gateman@manjaro-x13 demo_cloud_user]$ gcloud builds list --region=europe-west2
ID                                    CREATE_TIME                DURATION  SOURCE  IMAGES  STATUS
499f567c-10c9-4ae3-9456-d29bbc02168a  2024-05-01T18:21:10+00:00  3M21S     -       -       SUCCESS
6eec19d7-d7dc-4b51-8c5a-57a00879f044  2024-05-01T18:00:28+00:00  3M16S     -       -       SUCCESS
678554d2-b56b-4c5b-a81a-61addde1bc46  2024-05-01T15:03:33+00:00  3M19S     -       -       SUCCESS
d9ef5b26-52c6-4278-b1b1-e42ec5d456ad  2024-04-23T15:31:07+00:00  2M46S     -       -       SUCCESS
85946729-b839-4d42-9fda-e610f4333ba2  2024-04-23T15:02:02+00:00  2M37S     -       -       FAILURE
d636308d-2c19-4c59-9943-6371b185a022  2024-04-22T19:16:26+00:00  2M35S     -       -       SUCCESS
114660c2-6c23-410e-8bf9-76877dcd3bb0  2024-04-22T19:02:52+00:00  17S       -       -       SUCCESS
8d21277c-51c5-4f59-8a00-6db5d1dbd837  2024-04-22T18:34:56+00:00  35S       -       -       FAILURE
b3221243-5ada-4ccb-958e-c06ce127e788  2024-04-22T18:28:51+00:00  -         -       -       FAILURE
e1fde2bf-b7a1-47aa-9629-b3561c2dcca0  2023-11-04T20:54:29+00:00  1M38S     -       -       SUCCESS
[gateman@manjaro-x13 demo_cloud_user]$ gsutil cat gs://jason-hsbc_cloudbuild/logs/log-499f567c-10c9-4ae3-9456-d29bbc02168a-step-5.txt
Already have image (with digest): gcr.io/cloud-builders/gcloud
Deploying container to Cloud Run service [demo-cloud-user] in project [jason-hsbc] region [europe-west2]
Deploying...
Setting IAM Policy.............done
Creating Revision..........................................................................................................................................................................................................done
Routing traffic.....done
Done.
Service [demo-cloud-user] revision [demo-cloud-user-00006-v9c] has been deployed and is serving 100 percent of traffic.
Service URL: https://demo-cloud-user-7hq3m4pdya-nw.a.run.app

用google SDK 命令行去触发

这种方法无需配置trigger, 只需要在local 本地或者安装有google sdk 的环境下

进入代码项目的folder

执行

bash 复制代码
gcloud builds submit --config=path/to/custom-build-config.yaml

config 参数可以不写, 默认的config 位置就是./cloudbuild.yaml

这种trigger 方式还有这些好处

  1. 无需关心git remote 的地址, 支持任何项目, 甚至没有交给git管理的项目
  2. 无需commit 代码就可以触发build, 随改随部署

例子:

复制代码
[gateman@manjaro-x13 demo_cloud_user]$ gcloud builds submit
Creating temporary tarball archive of 24 file(s) totalling 108.2 KiB before compression.
Some files were not included in the source upload.

Check the gcloud log [/home/gateman/.config/gcloud/logs/2024.05.02/03.17.04.250214.log] to see which files and the contents of the
default gcloudignore file used (see `$ gcloud topic gcloudignore` to learn
more).

Uploading tarball of [.] to [gs://jason-hsbc_cloudbuild/source/1714591025.18917-5d48d906138b4c9d906c9ceb47c62898.tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/jason-hsbc/locations/global/builds/8bf33682-33a3-452c-9653-5966a35e1611].
Logs are available at [ https://console.cloud.google.com/cloud-build/builds/8bf33682-33a3-452c-9653-5966a35e1611?project=912156613264 ].
ID                                    CREATE_TIME                DURATION  SOURCE                                                                                   IMAGES  STATUS
8bf33682-33a3-452c-9653-5966a35e1611  2024-05-01T19:16:48+00:00  2M57S     gs://jason-hsbc_cloudbuild/source/1714591025.18917-5d48d906138b4c9d906c9ceb47c62898.tgz  -       SUCCESS

至于具体日志,还是建议去console 上查看

cloud build 的一些坑

1. gcloud SDK 执行的cloud build 的region 是global (non-region)

这个是google 暂时的limitation

导致两个问题:

  1. 在gcp console 上我们必须用global region 去filter google sdk出发的cloudbuild 历史和看日志, 这代表 用trigger 出发和google sdk出发的cloudbuild 历史不在同1页上

  2. gcloud builds submit command 默认下会尝试在 us region(人类希望的大本营) 创建bucket, 如果你的gcp project 所在的organization policy限制了us region的权限, 则你会遇到这个错误:

bash 复制代码
ERROR: (gcloud.builds.submit) HTTPError 412: 'us' violates constraint 'constraints/gcp.resourceLocations'	

原因: cloud build 无法在us region 创建staging folder

https://cloud.google.com/sdk/gcloud/reference/builds/submit#--gcs-source-staging-dir

解决方法1:

bash 复制代码
    ERROR: (gcloud.builds.submit) HTTPError 412: 'us' violates constraint 'constraints/gcp.resourceLocations'

解决方法2:

创建bucket gs://_cloudbuild/ bucket

我采用了第二种

glcoud builds build 所以的service account 是cloud build 默认的agent account

即使你用admin account 执行 gcloud build 命令, 默认下它用的是 cloud build 的agent account

最好预先分配好权限, 否则部署cloud run/ GKE 时很可能会失败

当然用下面页面分配也是可以的

还有一种方法,

可以用 glcoud builds build --account=emailaddr 来强制使用某个service account来部署, 前提是这个service account 已经在当前环境用gcloud auth 登陆

相关推荐
csdn_aspnet3 小时前
GitOps宣言:Kubernetes配置的版本化革命
云原生·容器·kubernetes·gitops
xmlhcxr5 小时前
Docker容器常用操作与私有仓库部署实验笔记
docker·云原生·eureka
白胡子6 小时前
Kubernetes NFS 接入方案
云原生
河码匠9 小时前
Kubernetes YAML 详解之网络服务二( Ingress、IngressClasses)
云原生·容器·kubernetes
blackorbird9 小时前
一个来自法国的基于K8s的规模化扫描集群
云原生·容器·kubernetes
掘根9 小时前
【微服务即时通讯】消息存储子服务2
微服务·云原生·架构
风向决定发型丶10 小时前
浅谈K8S的Label和Annotation
云原生·容器·kubernetes
培小新10 小时前
【Docker安全优化】
云原生·eureka
easy_coder10 小时前
从 ManifestRender 到 Certificate:一次 Kubernetes 应用发布故障的深度排障实录
云原生·云计算