惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 叶小钗
O
OpenAI News
V
V2EX
大猫的无限游戏
大猫的无限游戏
博客园 - 聂微东
S
Schneier on Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
小众软件
小众软件
L
LINUX DO - 热门话题
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - Franky
Security Latest
Security Latest
S
SegmentFault 最新的问题
Project Zero
Project Zero
Spread Privacy
Spread Privacy
K
Kaspersky official blog
J
Java Code Geeks
V
Vulnerabilities – Threatpost
C
Cisco Blogs
C
CERT Recently Published Vulnerability Notes
月光博客
月光博客
T
The Exploit Database - CXSecurity.com
L
Lohrmann on Cybersecurity
人人都是产品经理
人人都是产品经理
博客园 - 三生石上(FineUI控件)
Scott Helme
Scott Helme
WordPress大学
WordPress大学
量子位
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
宝玉的分享
宝玉的分享
Hugging Face - Blog
Hugging Face - Blog
AWS News Blog
AWS News Blog
Help Net Security
Help Net Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Simon Willison's Weblog
Simon Willison's Weblog
S
Secure Thoughts
博客园 - 【当耐特】
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
V
Visual Studio Blog
Last Week in AI
Last Week in AI
T
Tailwind CSS Blog
腾讯CDC
Cyberwarzone
Cyberwarzone
IT之家
IT之家
GbyAI
GbyAI
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
云风的 BLOG
云风的 BLOG
T
Troy Hunt's Blog
D
Docker

czp's blog

Ubuntu 下使用 zsh · HonKit 使用 VNC 来远程管理服务器 · HonKit Linux 下无限试用 JetBrains · HonKit 使用 KMS 激活 Windows · HonKit 为 KVM 中的 Windows 虚拟机启用 VirtIO · HonKit 在 Spring Boot 中处理 MissingKotlinParameterException · HonKit 用 Spring Native 拯救微服务 · HonKit 正确调试 PHP · HonKit Ubuntu 增加最大文件打开数量限制 · HonKit 将 Minecraft 服务端编译到 native · HonKit 用凝聚力购买 P 社游戏 DLC · HonKit 模拟超星网课 Android 客户端 · HonKit 模拟 Bilibili Android 客户端 · HonKit 模拟哔咔 Android 客户端 · HonKit 异步是什么 · HonKit GCP Pub/Sub push 至 IAP 保护的 Endpoint · HonKit 部署 Spring Native 到 GCP App Engine · HonKit 多个 Gradle SubProject 同时编译导致 CI/CD 内存耗尽 · HonKit Google Cloud Build 运行 DIND · HonKit 在 Google Storage 中部署 SPA · HonKit Telegram Bot 收不到普通群聊消息的问题 · HonKit 加密货币交易 · HonKit 挖掘以太坊 · HonKit 挖掘门罗币 · HonKit 小明学英语 · HonKit 卖程序的小女孩 · HonKit 一个测试工程师走进一家酒吧 · HonKit 我给你们讲个 TCP 笑话吧! · HonKit 我给你们讲个 UDP 笑话吧! · HonKit 格局打开 · HonKit c 语言常见未定义行为 · HonKit 在 Kotlin 使用 SpaceEngineers Remote API · HonKit Kotlin 协程 · HonKit 在 Spring Boot 中正确注册 Jackson Module · HonKit Spring Boot Jpa 使用 Google Cloud SQL · HonKit Spring Boot 中配置单页应用 · HonKit Spring Boot 无法加载 ClasspathResource 问题 · HonKit 正确打包 Spring Boot 到 war · HonKit czp's blog · HonKit 鸣谢列表 · HonKit 友链 · HonKit
Terraform 不自动更新 CloudRun service · HonKit
2026-04-11 · via czp's blog

本文撰写时的年份: 2024-05

当使用 Terraform 来管理容器服务的时候, 第一次部署没有任何问题, 但是第二次部署的时候, 就会发现由于 docker image 的名字没有变, 所以 Terraform 不会自动更新容器服务

相关的 issue 有很多: https://github.com/hashicorp/terraform-provider-google/issues/6706

以 GoogleCloud CloudRun service 举例:

resource "google_cloud_run_v2_service" "default_service" {
  name     = "default-service"
  location = "asia-east2"
  template {
    containers {
      image = "asia-east2-docker.pkg.dev/projectId/repositoryName/default-service"
    }
  }
}

在 CI 中构建出新版本的微服务镜像之后, 那肯定是以 latest 标签推送到 docker repository 的, 所以在 Terraform 中使用的镜像名不会改变

于是问题就来了, 正因为镜像名没有变, 导致这个 Terraform resource 没有改动, 所以 Terraform 会认为此资源不需要更新, 执行 terraform plan 命令的时候这个资源会被跳过

这个问题应该在其他服务商的类似的容器服务里也会遇到. 查了很多 StackOverflow 问答之后, 主流解决方案大多是在镜像构建之后以变量形式传入镜像的 hash 给 Terraform, 又或者是从 docker repository 里读取最新镜像的 hash, 然后把 hash 拼到镜像名后面. 但是这些方式太恶心了

在研究了 gcloud 命令行是如何部署 CloudRun 之后, 得到了启发

CloudRun 底层使用的是 knative, 所以可以在 CloudRun 的 revision 页面看到最终使用的 knative 的 yaml, 而在命令行部署出来的 revision 会有一条特别的 label:

apiVersion: serving.knative.dev/v1
kind: Revision
metadata:
  xxx: xxx
  labels:
    xxx: xxx
    client.knative.dev/nonce: tnffyvylsw

注意看其中的 client.knative.dev/nonce , 这是 gcloud 命令行自动生成出来的随机字符串, 每个 revision 的一定都不一样

同样的, 我们可以在 Terraform 中也使用随机字符串使每一次执行时的资源描述都不一样

resource "random_string" "nonce" {
  length  = 10
  numeric = false
  special = false
  lower   = true
  upper   = false
  keepers = {
    timestamp = timestamp()
  }
}

resource "google_cloud_run_v2_service" "default_service" {
  name     = "default-service"
  location = "asia-east2"
  template {
    labels = {
      "terraform-deployment" : random_string.nonce.result
    }
    containers {
      image = "asia-east2-docker.pkg.dev/projectId/repositoryName/default-service"
    }
  }
}

用当前时间戳来做随机字符串的 keeper, 所以每次部署随机字符串都会改变. 而用随机字符串做 "default_service" 的 label, 所以每一次部署时 "default_service" 这个资源一定会改变

这样就能让 Terraform 每一次都重新部署 CloudRun service

另外顺便一提, CloudRun job 是没有这个问题的, CloudRun job 会在每次执行时重新拉取一遍镜像, 所以只要 docker image 的某个 tag (比如说 latest)的内容物被更新了, CloudRun job 的执行内容就会自动改变, 不需要重新部署

但是 CloudRun service 会在部署时将 docker tag 转换为其 hash 来"固化"版本, 所以不论 docker 有没有更新, 都不会影响已经部署了的 service, 想要执行新的镜像就必须重新部署. 而 tag 不变的情况下 Terraform 又不会重新部署, 这才引出上述问题