摆脱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 例子:

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的方案是可行的




部署到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

    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

[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:

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

# 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分钟多点

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/694030.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

张大哥笔记:经济下行,这5大行业反而越来越好

现在人们由于生活压力大,于是就干脆降低自己的欲望,只要不是必需品就不买了,自然而然消费也就降低了,消费降级未必是不好的现象! 人的生物本能是趋利避害,追求更好的生存和发展空间,回避对自己有…

C++使用thread_local实现每个线程下的单例

对于一个类,想要在每个线程种有且只有一个实例对象,且线程之间不共享该实例,可以按照单例模式的写法,同时使用C11提供的thread_local关键字实现。 在单例模式的基础上,使用thread_local关键字修饰单例的instance&…

Redis原理篇——哨兵机制

Redis原理篇——哨兵机制 1.Redis哨兵2.哨兵工作原理2.1.哨兵作用2.2.状态监控2.3.选举leader2.4.failover 1.Redis哨兵 主从结构中master节点的作用非常重要,一旦故障就会导致集群不可用。那么有什么办法能保证主从集群的高可用性呢? 2.哨兵工作原理 …

【Python】读取文件夹中所有excel文件拼接成一个excel表格 的方法

我们平常会遇到下载了一些Excel文件放在一个文件夹下,而这些Excel文件的格式都一样,这时候需要批量这些文件合并成一个excel 文件里。 在Python中,我们可以使用pandas库来读取文件夹中的所有Excel文件,并将它们拼接成一个Excel表…

AI助教时代:通义千问,让学习效率翻倍?

全文预计1100字左右,预计阅读需要5分钟。 关注AI的朋友知道,在今年5月份以及6月份的开端,AI行业可谓是风生水起,给了我们太多的惊喜和震撼!国内外各家公司纷纷拿出自己憋了一年的产品一决雌雄。 国内有文心一言、通义千…

大模型相关:ChatGPT的原理与架构

一、大模型面临的挑战 1.1 Transformer模型的缺陷: 与RNN相比Transformer面临以下挑战: 并行计算能力不足。RNN需要按序处理序列数据中的每个时间步,这限制了它在训练过程中充分利用现代GPU的并行计算能力,从而影响训练效率。长…

FastAPI给docs/配置自有域名的静态资源swagger-ui

如果只是要解决docs页面空白的问题,可先看我的这篇博客:FastAPI访问/docs接口文档显示空白、js/css无法加载_fastapi docs打不开-CSDN博客 以下内容适用于需要以自用域名访问swagger-ui的情况: 1. 准备好swagger-ui的链接,如&am…

STM32H750启动和内存优化(分散加载修改)

前些日子有个朋友一直给我推荐STM32H750这款芯片,说它的性价比,说它多么多么好。于是乎,这两天试了试,嚯,真香!我们先看看基本配置 这里简单总结下,cortex-m7内核,128k片内flash …

htb-linux-6-beep

nmap web渗透 目录扫描 漏洞关键词 shell py脚本执行 flag root 目前的权限 nmap root

Django 视图类

在Django框架中,视图类(Class-based views,简称CBVs)提供了一个面向对象的方式来定义视图。这种方式可以让你通过创建类来组织视图逻辑,而不是使用基于函数的视图(Function-based views,简称FBV…

109、python-第四阶段-6-多线程编程

单线程: import threading import timedef sing():while True:print("我在唱歌")time.sleep(1) def dance():while True:print("我在跳舞")time.sleep(1) if __name__"__main__":sing()dance()多线程: import threading…

嵌入式学习——Linux高级编程复习(进程)——day39

1. 进程 进程是计算机科学中的一个核心概念,它是操作系统进行资源分配和调度的基本单位,代表了一个正在执行中的程序实例。当一个程序被加载到内存并开始执行时,它就变成了一个进程。 1. 程序:存放在外存中的一段代码的集合 2. 进…

Java并发编程:线程生命周期

Java并发编程专栏 文章收录于Java并发编程专栏 线程生命周期 线程是Java并发编程的核心概念,理解线程生命周期对于编写高效的并发程序至关重要。本文将详细介绍 Java 线程的六种状态以及状态之间的转换关系,帮助读者更好地理解线程的行为。   在Java中…

mysql8.0中的mysql.ibd

mysql8.0版本中多了一个mysql.ibd的文件。5.7版本则没有这个文件。 MySQL5.7: .frm文件 存放表结构信息 .opt文件,记录了每个库的一些基本 信息,包括库的字符集等信息 .TRN,.TRG文件用于存放触发器的信 息内容。 在MySQL 8.0之前&#xff0…

2002NOIP普及组真题 4. 过河卒

线上OJ 地址: 【02NOIP普及组】过河卒 核心思想: 对于此类棋盘问题,一般可以考虑 dp动态规划、dfs深搜 和 bfs广搜。 解法一:dp动态规划 方法:从起点开始逐步计算到达每个位置的路径数。对于每个位置,它…

数 据 类 型

概述 Java 是强类型语言。 每一种数据都定义了明确的数据类型,在内存中分配了不同大小的内存空间(字节)。 Java 中一共有 8 种基本类型(primitive type),包括 4 种整型、2 种浮点型、1 种字符类型&#…

HikariCP连接池初识

HikariCP的简单介绍 hikari-光,hikariCP取义:像光一样轻和快的Connetion Pool。这个几乎只用java写的中间件连接池,极其轻量并注重性能,HikariCP目前已是SpringBoot默认的连接池,伴随着SpringBoot和微服务的普及&…

【ai】pycharm远程ssh开发

方式1: gateway的方式是远程放一个pycharm 专业版,经常下载失败 方式2: 类似vs,源码本地,同步到远程进行运行。 参考大神的分享: Pycharm远程连接服务器(2023-11-9) Pycharm远程连接服务器(windows下远程修改服务器代码)[通俗易懂] cpolar 建议同时内网穿透 选 远程开…

详解 Flink 的状态管理

一、Flink 状态介绍 1. 流处理的无状态和有状态 无状态的流处理:根据每一次当前输入的数据直接转换输出结果的过程,在处理中只需要观察每个输入的独立事件。例如, 将一个字符串类型的数据拆分开作为元组输出或将每个输入的数值加 1 后输出。…

Pycharm中import torch报错解决方案(Python+Pycharm+Pytorch cpu版)

pycharm环境搭建完毕后,编写一个py文件demo,import torch报错,提示没有。设置python解释器: 选择conda环境,使用现有环境,conda执行文件找到Anaconda安装路径下Scripts文件夹内的conda.exe,最后…