摆脱Jenkins - 使用google cloudbuild 部署 java service 到 compute engine VM

在之前 介绍 cloud build 的文章中

初探 Google 云原生的CICD - CloudBuild

已经介绍过, 用cloud build 去部署1个 spring boot service 到 cloud run 是很简单的, 因为部署cloud run 无非就是用gcloud 去部署1个 GAR 上的docker image 到cloud run 容器

yaml file 例子:

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

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

  - id: run maven package
    name: maven:3.9.6-sapmachine-17 # 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-config#logging

部署到GCE的问题

但是cloud build 本身是1个non-vpc product, 是无法直接通过 GCE vm的subnet ip address 去连接vm的.

但是

gcloud compute ssh 本身是可以直接用 ssh key file 验证的

而且

gcloud compute ssh 后面可以带 -- 参数执行1段 指定的命令

所以实际上不同过内网ip 连接. 那就是讲用cloud build 部署service 到 vm的方案是可行的

java 复制代码

部署到GCE的思路

  1. 首先 准备1对ssh key pair, 并把public key安装在对应的vm中, 确保可以用private key登陆

  2. 把这对key pari 放在 google security manager 中

  3. 在 cloudbuild yaml 中把 这对key pari 引入, 虽然理论上只需要私钥就可以, 但是cloudbuild 也需要校验public key 奇怪了

  4. 编写cloudbuild yaml

    java 复制代码
    a. mvn build
    b. build docker image
    c. push docker image to GAR
    d. 利用 gcloud compute ssh 连接vm
    	执行:
    	1. docker stop current container
    	2. docker pull latest image
    	3. docker run container
  5. 创建1个cloud build trigger, 当有新的代码push 到指定branch的时候自动出发cloud build, 有1个前提, 这个 code repository 必须是github, github Enterprise, GitLab, BitBucket 之一, 国内的一些代码仓库就算了

实现

1. 准备一对key pair

具体步骤忽略

确保可以用ssh key 登陆 对应的vm

yaml 复制代码
[gateman@manjaro-x13 keys]$ gcloud compute ssh tf-vpc0-subnet0-vm0 --ssh-key-file=/home/gateman/.ssh/id_rsa
No zone specified. Using zone [europe-west2-c] for instance: [tf-vpc0-subnet0-vm0].
External IP address was not found; defaulting to using IAP tunneling.
WARNING: 

To increase the performance of the tunnel, consider installing NumPy. For instructions,
please see https://cloud.google.com/iap/docs/using-tcp-forwarding#increasing_the_tcp_upload_bandwidth

Linux tf-vpc0-subnet0-vm0 5.10.0-30-cloud-amd64 #1 SMP Debian 5.10.218-1 (2024-06-01) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat Jun  8 16:15:23 2024 from 35.235.242.17
gateman@tf-vpc0-subnet0-vm0:~$ 
2. 把这对key pari 放在 google security manager 中

key pair 是敏感数据, 建议不要用terraform, 避免敏感数据check in 到代码仓库

3. 编写cloudbuild.yaml

注意这里的第一个步是多余的并不起作用, 因为在

deploy image to GCE 这个step中

会利用gcloud 命令重新下载key file pairs

只是简单介绍下引入 secret manager item的方法

至于为何不用第一步的方法, 因为遇到了1个奇怪的错误, prviate key format is not valid.

我已经raised 1个ticket 给google support, 等下文

cloudbuild-gce.yaml:

yaml 复制代码
steps:

  # to prepare ssh private key file
  - id: prepare ssh private key file
    name: 'ubuntu'
    entrypoint: bash
    args:
      - '-c'
      - |
        echo $$SSH_PRIVATE_KEY | cut -c 1-30
        echo $$SSH_PRIVATE_KEY > /workspace/ssh_key_file
        echo $$SSH_PUBLIC_KEY > /workspace/ssh_key_file.pub
        chmod 600 /workspace/ssh_key_file
        chmod 600 /workspace/ssh_key_file.pub
    secretEnv:
      - 'SSH_PRIVATE_KEY'
      - 'SSH_PUBLIC_KEY'



  - id: run maven package
    name: maven:3.9.6-sapmachine-17 # https://hub.docker.com/_/maven
    entrypoint: mvn
    args: [ 'package' ]

  # https://cloud.google.com/build/docs/configuring-builds/substitute-variable-values
  # i guess I should combine the two steps into one
  - id: build docker image
    name: 'gcr.io/cloud-builders/docker'
    args: [ 'build', '-t', 'europe-west2-docker.pkg.dev/$PROJECT_ID/my-docker-repo/${_APP_NAME}', '.' ]

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


  - id: deploy image to GCE
    name: 'gcr.io/cloud-builders/gcloud'
    entrypoint: bash
    args:
      - '-c'
      - |
        whoami
        set -x
        mkdir -p /root/.ssh
        gcloud secrets versions access latest --secret=gateman-private-ssh-key > /root/.ssh/id_rsa
        gcloud secrets versions access latest --secret=gateman-public-ssh-key > /root/.ssh/id_rsa.pub
        chmod 600 /root/.ssh/id_rsa
        chmod 600 /root/.ssh/id_rsa.pub
        gcloud compute ssh gateman@${_VM_HOST} --zone=europe-west2-c --quiet --ssh-key-file=/root/.ssh/id_rsa -- "whoami" 
        gcloud compute ssh gateman@${_VM_HOST} --zone=europe-west2-c --quiet --ssh-key-file=/root/.ssh/id_rsa -- "sudo docker container prune -f; sudo docker ps -a"  
        gcloud compute ssh gateman@${_VM_HOST} --zone=europe-west2-c --quiet --ssh-key-file=/root/.ssh/id_rsa -- "sudo docker stop ${_APP_NAME} && sudo docker rm ${_APP_NAME}" 
        gcloud compute ssh gateman@${_VM_HOST} --zone=europe-west2-c --quiet --ssh-key-file=/root/.ssh/id_rsa -- "sudo docker pull europe-west2-docker.pkg.dev/$PROJECT_ID/my-docker-repo/${_APP_NAME}:${_APP_TAG}"
        gcloud compute ssh gateman@${_VM_HOST} --zone=europe-west2-c --quiet --ssh-key-file=/root/.ssh/id_rsa -- "sudo docker run -d -p ${_PORT}:8080 --name ${_APP_NAME} europe-west2-docker.pkg.dev/$PROJECT_ID/my-docker-repo/${_APP_NAME}:${_APP_TAG}"
        echo ok
        
 
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-config#logging

# to define
availableSecrets:
  secretManager:
    - versionName: projects/$PROJECT_ID/secrets/gateman-private-ssh-key/versions/latest
      env: 'SSH_PRIVATE_KEY'
    - versionName: projects/$PROJECT_ID/secrets/gateman-public-ssh-key/versions/latest
      env: 'SSH_PUBLIC_KEY'

substitutions:
  _APP_NAME: demo-cloud-user
  _APP_TAG: latest
  _PORT: "8081"
4. 创建1个cloudbuild trigger
python 复制代码
# difference between data and resource: data is read only, resource is read and write
data google_service_account "cloudbuild_sa" {
  project = var.project_id
  account_id = "terraform"
}


# referring https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/cloudbuild_trigger
resource "google_cloudbuild_trigger" "demo_cloud_user-gce-trigger" {
  name = "demo-cloud-user-gce-trigger" # could not contains underscore

  location = var.region_id

  # when use github then should use trigger_template
  github {
    name = "demo_cloud_user"
    owner = "nvd11"
    push {
      branch = "main"
      invert_regex = false # means trigger on branch
    }
  }

  # the
  substitutions = {
    _VM_HOST = "tf-vpc0-subnet0-vm0"
  }

  filename = "cloudbuild-gce.yaml"
  # projects/jason-hsbc/serviceAccounts/terraform@jason-hsbc.iam.gserviceaccount.com
  service_account = data.google_service_account.cloudbuild_sa.id 
}

测试

创建1个commit 并push 到github 的main branch

测试通过, 耗时2分钟多点

相关推荐
nvd112 天前
Auth0 /userinfo 速率限制问题解决方案
googlecloud·authing
jumu2023 天前
探索非线性电液伺服系统:从PID到反步控制的奇妙之旅
googlecloud
nvd113 天前
# 指南:从零开始为 GKE 应用启用 Google 账号登录 (IAP)
googlecloud
@YDWLCloud9 天前
谷歌云 Compute Engine 实操手册:虚拟机配置与负载均衡全流程
java·运维·服务器·云计算·负载均衡·googlecloud
TG:@yunlaoda360 云老大12 天前
谷歌云AI 时代的算力革命:CPU、GPU 到 TPU 的架构与定位解析
人工智能·架构·googlecloud
酷尔。14 天前
Gemini学生认证、订阅方法和常见问题的解决方法
ai·googlecloud·使用教程·gemini
攻城狮杰森16 天前
AI·重启思维:Gemini 3 带你走进智能的下一个维度
人工智能·语言模型·ai作画·aigc·googlecloud
这儿有一堆花18 天前
重磅推出!Google Antigravity:一次 “以 Agent 为中心 (agent-first)” 的 IDE 革命
vscode·ai·ai编程·googlecloud
TG:@yunlaoda360 云老大1 个月前
AI 电影制作迈入新阶段:谷歌云Veo 3.1模型发布,实现音频全覆盖与精细化创意剪辑
人工智能·云计算·音视频·googlecloud
TG:@yunlaoda360 云老大1 个月前
谷歌云Flink 核心组成及生态发展:实时数据处理的下一代引擎
大数据·flink·googlecloud