Terraform 面试问答(26 题)

本文整理了Terraform 面试问答(26 题)相关的 26 个高频面试问题,从基础到进阶再到生产实战层层递进,覆盖Terraform、面试等核心考点,每题附参考回答与追问,适合面试前系统复习。

适用岗位:运维工程师 / 技术支持工程师 / AI 运维工程师 / DevOps 工程师


一、岗位高频速查

岗位 必考问题 一句话要点
运维工程师 ① Terraform 和 Ansible 有什么区别?② init/plan/apply 完整流程?③ state 文件是什么、丢了怎么办?④ 常见坑:并发锁、资源误删、手动改动漂移 考基本功:工作流、state、与 Ansible 的分工边界必须讲清楚
技术支持工程师 ① plan/apply 报错怎么排查思路?② plan 输出里 + / - / ~ 怎么解读?③ 阿里云对接和密钥配置?④ 资源导不进/删不掉怎么处理 低频,了解即可:重点是”能看懂报错、有排查套路”,不追源码
AI 运维工程师 ① 怎么用 IaC 管理 GPU 服务器/训练环境的生命周期?② 训练集群(按需建、用完销毁)怎么编排?③ Terraform + Ansible + CI 怎么配合?④ 资源成本与闲置资源怎么控制 考”资源编排思路”:环境可复制、按需创建、自动回收、成本意识
DevOps 工程师 ① remote state 和后端怎么选?② 并发锁和 force-unlock?③ module 怎么设计复用?④ 状态漂移怎么检测修复?⑤ Terraform 怎么接 CI/CD 流水线? 考最佳实践:state 管理、模块化、漂移治理、流水线集成

二、基础篇

Q1. 什么是 IaC(基础设施即代码)?它解决了什么问题?

  • 【考察点】是否理解 IaC 的核心价值,而不是只会背名词
  • 【参考回答】IaC 就是用代码来管理基础设施。以前建服务器要么手动点控制台,要么写一次性脚本,资源建完就没人知道是怎么建的、改过什么。IaC 把服务器、网络、数据库这些资源用声明式配置文件描述出来,存进 Git,可以版本管理、Code Review、复用、一键重建。Terraform 就是干这个的,我在项目里主要用它建云资源,比如 ECS、VPC、安全组。它最大的价值是环境可复制——测试环境和生产环境用同一套代码建出来,杜绝”环境之间不一样”和手滑误操作。
  • 【追问】
    • 追问:声明式和命令式有什么区别?→ 声明式只描述”最终要什么状态”,工具自己算怎么达成,Terraform 就是声明式;命令式是写一步步怎么做的脚本,比如 Shell。声明式的好处是可预期、可对比差异。
    • 追问:IaC 不适合什么场景?→ 一次性、探索性的临时操作,代码成本高于手工成本;还有强依赖人工判断的变更,硬套 IaC 反而低效。
  • 【岗位标注】通用 / 运维 / AI 运维 / DevOps

Q2. Terraform 和 Ansible 定位有什么区别?(简历同时出现,必问)

  • 【考察点】两个工具的边界是否清晰——这是面试官看到”Linux、Ansible、Terraform”连排时最想验证的点
  • 【参考回答】Terraform 是资源编排工具,管”建和销毁”:云上的 ECS、VPC、数据库这些资源的生命周期。Ansible 是配置管理工具,管”装和配”:在已经存在的机器上装软件、改配置、起服务。我们项目里 Ansible 主导,负责服务器上的软件部署和环境配置;Terraform 配合负责云资源的创建,比如先建好 VPC 和 ECS,Ansible 再上去装环境。简单总结:Terraform 管”有什么机器”,Ansible 管”机器里装什么”,两者配合不重叠。
  • 【追问】
    • 追问:Terraform 能不能装软件?→ 技术上可以,用 provisioner(remote-exec/local-exec)在机器上执行命令,但官方和社区都不推荐,因为它不幂等、不好追踪,装软件是配置管理的活。
    • 追问:两者能互相替代吗?→ 不能,职责不同。Ansible 也能调云 API 建资源,但管理大量资源生命周期时没有 Terraform 的 state 和 plan 这套能力,实践上各干各的。
  • 【岗位标注】通用 / 运维 / AI 运维 / DevOps

Q3. Terraform 核心工作流:init / plan / apply / destroy 分别做什么?

  • 【考察点】基本命令流程是否真用过,而不是只看过文档
  • 【参考回答】init 是初始化:下载 provider 插件、初始化后端,新项目第一件事就是它。plan 是预演:对比代码和当前 state,生成执行计划,显示会新建、修改、删除哪些资源,不动真格。apply 是执行:把计划变成现实并更新 state。destroy 是销毁:把 state 里管理的资源全部删掉。我的日常流程是 init → plan 看变更 → apply 执行,destroy 只在测试环境用,生产基本不碰。
  • 【追问】
    • 追问:apply 之前必须手动跑 plan 吗?→ 不必须,apply 默认也会先自动跑一次 plan 再执行,但习惯上先手动 plan 是为了有意识地确认变更,特别是看到要删资源的场景。
    • 追问:只想销毁某一个资源怎么办?→ 可以用 terraform destroy -target=资源地址,或者 terraform state rm 把它从管理范围摘掉再销毁。
  • 【岗位标注】通用 / 运维 / 技术支持 / DevOps

Q4. HCL 语法基础:provider、resource、variable、output 怎么定义?

  • 【考察点】是否写过基础配置文件,语法是否门儿清
  • 【参考回答】HCL 是 Terraform 的声明式语言,核心是块(block)。provider 声明云厂商,比如阿里云是 provider "alicloud",里面配 region;resource 声明具体资源,比如 resource "alicloud_instance" "web" 就是一台 ECS,花括号里写实例规格、镜像、VPC 等参数;variable 定义输入变量,可以带默认值,用 var.xxx 引用;output 定义输出,比如实例的 IP,供其他模块或外部使用。键值对加缩进的结构很直观,跟 JSON/YAML 比可读性好很多。
  • 【追问】
    • 追问:variable 传值有哪几种方式?→ 命令行 -var、-var-file 指定 tfvars 文件、自动加载 terraform.tfvars、环境变量 TF_VAR_xxx,优先级是命令行最高。
    • 追问:密钥能直接写在 tfvars 里吗?→ 不行,那是明文。用环境变量或 CI 的密钥管理注入,代码仓库里不能留 access_key。
  • 【岗位标注】通用 / 运维 / 技术支持 / DevOps

Q5. 什么是 provider?怎么对接阿里云?

  • 【考察点】provider 概念,以及国内云厂商的实操对接
  • 【参考回答】provider 是 Terraform 和云平台之间的桥,每个云厂商有自己的插件,阿里云叫 alicloud。它负责把 HCL 里的声明翻译成云平台的 API 调用,也负责查询资源的真实状态,所以 plan 才能知道”云上现在是什么样”。对接阿里云就是在 provider 块里配 region 和凭据,凭据用环境变量 ALICLOUD_ACCESS_KEY / ALICLOUD_SECRET_KEY 传,不要写死在代码里。然后 init 会自动下载 alicloud provider 插件。
  • 【追问】
    • 追问:provider 版本怎么固定?→ 在 required_providers 里指定版本约束,配合 terraform.lock 文件锁定精确版本。
    • 追问:RAM 子账号可以用吗?→ 可以,阿里云建议用 RAM 子账号加最小权限的授权策略,别用主账号密钥。
  • 【岗位标注】通用 / 运维 / 技术支持 / AI 运维

Q6. state 文件是什么?为什么需要它?

  • 【考察点】是否理解 state 的核心作用,这是 Terraform 的灵魂
  • 【参考回答】state 是 Terraform 的账本,默认是本地文件 terraform.tfstate,记录每个资源在云上的真实 ID 和属性。Terraform 靠它把代码和真实资源对应起来,plan 的时候对比”代码声明、state 记录、云上真实状态”三方差异。没有 state,Terraform 就不知道哪些资源是自己建的,再 apply 会重复创建。所以 state 不能丢,生产环境要放远程后端。
  • 【追问】
    • 追问:state 能提交到 Git 吗?→ 不建议。一是 state 里可能有敏感信息(密码、密钥),二是多人同时改容易冲突,生产要用后端。
    • 追问:state 丢了会怎样?→ 云上资源还在,但 Terraform 失去对应关系,直接 apply 会按代码全部重建,产生一堆重复资源,这是最坏情况。
  • 【岗位标注】通用 / 运维 / DevOps

Q7. 什么是资源依赖?depends_on 什么时候用?

  • 【考察点】隐式依赖和显式依赖的理解,以及会不会滥用 depends_on
  • 【参考回答】Terraform 会分析资源之间的引用关系自动排序,比如安全组里引用了 VPC 的 ID,VPC 就一定先建,这叫隐式依赖,绝大多数情况靠它就够了。depends_on 是显式声明,用在两个资源没有直接引用、但先后顺序有要求的时候,比如先建数据库再建应用,但应用的配置里没有直接引用数据库资源。我不太滥用它,能靠引用解决的就不用 depends_on,因为隐式依赖还能帮 Terraform 避免循环依赖。
  • 【追问】
    • 追问:depends_on 用多了有什么坏处?→ 会掩盖真实的依赖关系、破坏资源创建的并行度,plan 也看不出”为什么这么排序”。
    • 追问:遇到循环依赖怎么办?→ 拆模块或者用数据源(data source)把某个信息变成查询而非创建,绕开成环。
  • 【岗位标注】通用 / 运维 / DevOps

Q8. terraform plan 输出里的 + / - / ~ 符号是什么意思?

  • 【考察点】是否真正看过 plan 输出并理解含义——“看过”和”用过”的分水岭
  • 【参考回答】plan 输出里 + 表示新建,- 表示删除,~ 表示原地修改,-/+ 连在一起表示先删后建,也就是这个资源会被替换重建。我每次 apply 前都会扫一遍这些符号,特别警惕 -/+ 和整块资源被删,确认是不是改了什么触发重建的属性。plan 还会列出每个资源具体哪些属性变了,比如 ~ security_group 下面的规则变更,能精确到字段。
  • 【追问】
    • 追问:看到 ~ 能知道具体改了哪一项吗?→ 能,plan 会显示 属性名: 旧值 => 新值 的 diff 格式,逐字段列出来。
    • 追问:什么情况下会出现 -/+?→ 改了一些创建时决定、云平台不允许原地改的属性,比如 ECS 的镜像、磁盘类型,会触发 force replacement。
  • 【岗位标注】通用 / 运维 / 技术支持 / DevOps

Q9. variable 和 output 怎么用?敏感信息怎么处理?

  • 【考察点】输入输出机制,以及敏感信息的安全意识
  • 【参考回答】variable 定义输入参数,output 定义输出结果。比如我在模块里把 VPC ID 定义成 output,别处就能用 module.xxx.vpc_id 引用。output 里如果含密码这类敏感值,可以标 sensitive = true,apply 时控制台会打码显示。变量值我一般用 terraform.tfvars 传,生产环境用 CI 的变量注入,避免明文进仓库。
  • 【追问】
    • 追问:sensitive = true 之后值还会进 state 吗?→ 会!它只是控制台显示时打码,state 里仍然是明文,所以真正的风险点是 state 的存放,生产必须放后端并加密。
    • 追问:output 能被别的模块引用吗?→ 可以,模块输出是模块复用的关键接口,module.模块名.输出名。
  • 【岗位标注】通用 / 运维 / DevOps

三、进阶篇

Q1. remote state(后端)是什么?为什么生产必须用?

  • 【考察点】state 管理的最佳实践,是否知道”单人本地玩”和”团队生产用”的差别
  • 【参考回答】remote state 就是把 state 从本地文件挪到远程后端,比如阿里云 OSS、AWS S3、Terraform Cloud。好处有三个:一是多人协作,大家读写同一份 state,不会各改各的;二是安全,后端可以开版本管理和加密;三是防丢,本地文件删了云上还有备份。我们生产是把 state 放 OSS,backend 配置写在代码里,init 的时候自动拉取。
  • 【追问】
    • 追问:remote state 解决了并发问题吗?→ 没有,它只解决共享,并发写入还得靠后端锁(比如 S3 配 DynamoDB 锁表、OSS 后端的锁机制)。
    • 追问:从本地 state 切到 OSS 后端怎么迁移?→ 改 backend 配置后执行 terraform init -migrate-state,它会自动把本地 state 上传到后端。
  • 【岗位标注】运维 / DevOps

Q2. 什么是 module?怎么封装和复用?

  • 【考察点】模块化思维,能不能讲出”为什么封装”而不只是”会写”
  • 【参考回答】module 就是可复用的资源包,把一组相关资源封装成黑盒,只暴露变量和输出。比如我把”一套 Web 环境”封装成一个 module,里面是 VPC、ECS、安全组、SLB,外部只需要传环境名、实例规格这些参数。好处是多环境复用同一套逻辑,改一处所有环境都生效,也方便团队沉淀标准。我用过开源 module,也自己写过,就是一个普通目录加 variables.tf、outputs.tf,main.tf 里放资源定义。
  • 【追问】
    • 追问:module 的版本怎么管理?→ source 可以指向 registry、Git 仓库带 tag,配合 version 参数锁定版本,跟依赖管理一样。
    • 追问:module 写得不好会有什么坑?→ 参数暴露太多就失去封装意义,参数太少又不够灵活;还有 module 内循环依赖难解,所以设计时要先定好输入输出接口。
  • 【岗位标注】运维 / DevOps

Q3. terraform.lock 文件是干什么的?

  • 【考察点】依赖锁定意识,类比 package-lock.json
  • 【参考回答】lock 文件类似 package-lock.json,锁定 provider 插件的精确版本和校验和。init 的时候生成,之后每次 init 都会校验,防止某天 provider 悄悄升级导致行为变化。生产上我们把它提交到 Git,保证所有人、所有 CI 用的 provider 版本完全一致。需要升级 provider 时执行 terraform init -upgrade,lock 会随之更新。
  • 【追问】
    • 追问:什么时候会想升级 provider?→ 云平台 API 变更、要用的新资源类型只在新版本支持、或者修了影响我们的 bug。
    • 追问:lock 文件能手工改吗?→ 能但不建议,手工改容易和真实下载的插件校验和不符,init 会报错,应该用 -upgrade 让它自己更新。
  • 【岗位标注】运维 / DevOps

Q4. 什么是状态漂移(drift)?怎么检测和修复?

  • 【考察点】是否理解”代码声明 vs 云上真实状态”不一致的真实生产场景
  • 【参考回答】漂移就是真实云资源和代码声明不一致了,最常见的原因是有人手动在控制台改了东西,比如手动加了一条安全组规则、改了实例规格,Terraform 不知道。检测方式就是跑 plan,它会对比并显示差异;自动化一点就是定时跑 plan 把 diff 发告警。修复有两个方向:要么改代码去对齐现实,要么 apply 把资源改回代码声明,也可以 terraform import 把手动建的资源纳管进来,让一切回到”代码是唯一真相”。
  • 【追问】
    • 追问:有没有现成的漂移检测工具?→ 有,driftctl(已并入 Snyk IaC)这类工具,或者 Terraform Cloud 的 drift detection 定时检测,本质都是跑 plan 做 diff。
    • 追问:手动改动一定不好吗?→ 紧急故障时手动改可以理解,但事后必须同步回代码,否则下次 apply 会把紧急修复覆盖掉,或者产生不可预期的重建。
  • 【岗位标注】运维 / AI 运维 / DevOps

Q5. terraform state 系列命令有什么用?

  • 【考察点】state 操作的熟练度,这是区分”用过”和”玩过”的重要指标
  • 【参考回答】terraform state list 列出 state 里所有资源;state show 看某个资源的详细属性;state mv 把资源移动到新地址,常用于资源改名或拆分模块后重新映射;state rm 把资源从 state 摘除,摘除后 Terraform 不再管它,但云上资源还在;state pull 把后端 state 拉到本地查看。我用到最多的是 rm 和 mv,比如发现某个资源不该由 Terraform 管,就 rm 掉。
  • 【追问】
    • 追问:state rm 和 terraform destroy 有什么区别?→ destroy 是删云上资源也删 state;rm 只删 state,云上资源留着但变成”没人管”。
    • 追问:state mv 用错会怎样?→ 资源地址对不上,plan 会认为旧地址的资源要删、新地址要建,看起来就是一次”删了又建”,实际上云上资源没动,把关系理对再 plan 就好了。
  • 【岗位标注】运维 / DevOps

Q6. terraform import 是什么?什么场景用?

  • 【考察点】存量资源纳管,很典型的真实迁移场景
  • 【参考回答】import 是把已经存在的云资源导入 state,让 Terraform 接管,不重建资源。典型场景:公司原来手动建的服务器,现在要纳入 Terraform 管理,就用 terraform import 资源地址 资源ID 把它的 ID 关联到代码里的 resource 块。注意 import 只写 state 不写代码,所以导入后还要补对应的代码块,再 plan 对比看有没有差异。
  • 【追问】
    • 追问:import 之后 plan 出来一堆 diff 怎么办?→ 正常,说明代码参数和实际配置有差距,要么改代码对齐现实,要么让资源被 apply 修正,二选一,但先确认哪些差异是真实业务需要的。
    • 追问:把资源从管理范围退出来怎么做?→ state rm 摘掉,或者删掉代码里的 resource 块再 terraform apply -target 精准销毁。
  • 【岗位标注】运维 / DevOps

Q7. count 和 for_each 有什么区别?

  • 【考察点】批量创建资源的两种方式及选型
  • 【参考回答】count 按数量创建,用 count.index 区分,适合”N 台同构的机器”;for_each 按集合或 map 创建,用 each.key / each.value 区分,适合”每台机器参数不一样”,比如三台机器名字、规格都不同。关键区别是 count 依赖列表下标,列表中间删掉一项,后面的资源会整体重建(索引错位);for_each 按稳定 key 管理,删一项不影响其他。所以现在官方也更推荐 for_each。
  • 【追问】
    • 追问:count 索引错位具体是什么场景?→ 比如 list = [“a”,”b”,”c”] 建了三台机器,把 b 删了变成 [“a”,”c”],原来 c 的机器下标从 2 变 1,Terraform 会认为它不是原来的资源,先删后建。
    • 追问:for_each 的 key 用什么好?→ 用稳定不变的标识,比如实例名、可用区名,别用会变的字段,否则也会引起资源重建。
  • 【岗位标注】运维 / DevOps

Q8. refresh 和 -target 参数是什么?

  • 【考察点】plan/apply 的高级参数,考”什么时候用、有什么坑”
  • 【参考回答】refresh 是 plan/apply 前重新读取云上真实状态、对齐后再算计划的步骤;terraform plan -refresh-only 是只刷新 state 不改资源,常用于手动改动多、想先校准账本的时候。-target 是指定只针对某个资源或模块做 plan/apply,比如紧急只改一个安全组。但 -target 有坑:它可能让依赖它的资源没被处理,state 里出现”半新半旧”的状态,所以只适合临时用,长期还是要全量 apply。
  • 【追问】
    • 追问:-target 具体有什么隐患?→ 它只处理目标资源,不处理依赖链上其他资源,可能导致部分应用后状态混乱;用多了还会掩盖真实的变更范围。
    • 追问:什么时候必须用 refresh-only?→ 云上被手动改过、或者想确认 state 和现实是否一致又不想动资源时。
  • 【岗位标注】运维 / DevOps

Q9. 多人同时 apply,Terraform 怎么防止互相覆盖?

  • 【考察点】并发锁机制
  • 【参考回答】远程后端一般都带锁能力,比如 S3 后端配 DynamoDB 锁表、阿里云 OSS 后端也有锁机制。apply 开始前先拿锁,拿不到就阻塞等待或直接报错,防止两个人同时写 state 互相覆盖。锁的原理是后端建一条锁记录,谁拿到谁干活,干完释放。如果进程被 kill 或网络断了,锁可能残留,需要确认没有其他任务在跑后手动 terraform force-unlock 释放。
  • 【追问】
    • 追问:force-unlock 有什么风险?→ 如果真有其他人在 apply,强杀锁会导致两个人同时写 state,state 直接损坏,所以解锁前必须先确认没有并发任务。
    • 追问:本地 state 有锁吗?→ 有,会生成 terraform.tfstate.lock.info 文件,但只防同一台机器上的并发,防不了多台机器,这也是为什么团队要用后端。
  • 【岗位标注】运维 / DevOps

四、生产实战·刁钻篇

Q1. state 文件丢了,云上资源还在,怎么办?

  • 【考察点】灾难恢复能力,最狠的”实战题”
  • 【参考回答】先别慌,资源在云上就还在,只是 Terraform 失去了对应关系。恢复思路是把存量资源重新纳管:如果 remote state 后端开了版本管理(OSS/S3 版本控制),直接回滚到旧版本是最快的;没有备份就只能逐个 terraform import 把资源导回 state。最坏情况是 state 没了直接 apply,Terraform 会把代码里的资源当新的全部重建,云上冒出一堆重复资源。所以生产 state 必须放后端 + 开版本控制,就是防这个的。
  • 【追问】
    • 追问:state 没了直接 apply 会发生什么?→ 每台机器都按代码”新建”,云上重复资源堆积,还可能因为重名直接 apply 失败,总之是灾难,所以第一反应是恢复/回滚 state 而不是 apply。
    • 追问:OSS 版本控制能恢复多久?→ 取决于版本保留策略,建议生产开生命周期规则长期保留 state 的版本历史。
  • 【岗位标注】运维 / DevOps

Q2. 有人手动在控制台把 ECS 删了,再 apply 会发生什么?

  • 【考察点】漂移场景的真实推演,考”代码声明还在,资源没了”的处理
  • 【参考回答】plan 会发现真实资源不存在但 state 还记着,输出会显示这个资源被”替换”或重建——因为 Terraform 认为”资源从有到无”是它自己的职责,实际上云上已经没了,apply 就会重新创建一台。对无状态应用这是好事,代码声明还在,拉回来就行。但如果这台机器是数据库、有数据,重建就出大事了。所以生产关键资源要么加 prevent_destroy,要么团队立规矩:手动操作必须事后同步到代码,并用定时 plan 提前发现漂移。
  • 【追问】
    • 追问:机器上的数据呢?→ Terraform 不保证实例内数据,数据在云盘上,实例销毁后云盘是否保留取决于释放策略和 provider 配置,数据安全靠备份和云厂商快照。
    • 追问:怎么提前发现这种漂移?→ 定时跑 plan 对 diff 告警,把”资源消失”这类变更第一时间暴露出来,而不是等上线时才发现。
  • 【岗位标注】运维 / AI 运维 / DevOps

Q3. apply 中途进程被杀,锁卡住了怎么办?

  • 【考察点】锁故障处理,真实生产事故
  • 【参考回答】锁卡住通常是 apply 被 kill 或网络中断,state 里残留了锁记录。处理步骤:先确认当前没有其他人或 CI 任务在跑 apply(查后端锁记录、查 CI 队列),确认安全后执行 terraform force-unlock <锁ID> 手动释放。关键前提是”先确认没有并发”,否则强杀锁会导致两个人同时写 state。解锁后重新 apply,Terraform 会基于上次的 state 继续,已经建好的资源会被识别出来,不会重复建。
  • 【追问】
    • 追问:怎么判断锁是不是残留?→ 看锁记录的时间戳和来源:很久没更新、对应进程已不存在、CI 任务列表里没有对应任务,基本就是残留。
    • 追问:force-unlock 之后 state 会不一致吗?→ 一般不会,apply 失败时 state 通常保持事务性(要么更新成功要么不动),但保险起见解锁后先 plan 看差异再 apply。
  • 【岗位标注】运维 / DevOps

Q4. 改了一个参数,导致整个资源要重建,为什么?怎么避免?

  • 【考察点】force replacement 机制,考”哪些属性会触发重建”
  • 【参考回答】有些属性是资源创建时决定的,云平台 API 不允许原地改,比如 ECS 的镜像、磁盘类型,改了之后 Terraform 只能 -/+ 先删后建。避免的办法:plan 阶段盯紧 -/+ 符号,看到重建先停下来确认;把容易变的配置放 user_data 或参数文件里,而不是放在会触发重建的属性上;实在要换就接受重建,但确保数据在外置磁盘或有备份。最重要的习惯是:apply 前必看 plan 有没有 -/+,有就确认为什么。
  • 【追问】
    • 追问:怎么知道哪个属性触发了重建?→ plan 输出里该属性旁边会标注 forces replacement,一眼能看出来。
    • 追问:user_data 变了会重建吗?→ 一般不会触发重建(它属于可更新属性),但不同 provider 实现可能不同,还是要看 plan 确认。
  • 【岗位标注】运维 / DevOps

Q5. Terraform 和 Ansible 都管同一台机器,会不会打架?

  • 【考察点】工具边界和团队分工的真实理解——简历两个技能都有,这道题几乎必被追问
  • 【参考回答】会,如果边界不清。我们项目里定的规矩:Terraform 只管资源创建和销毁——ECS、VPC、安全组、磁盘这些基础设施;机器起来之后,装什么软件、配什么服务全是 Ansible 管,Terraform 绝不碰实例内部。两边 state 各管各的,互不干扰。最忌讳的是两边改同一件事,比如 Terraform 的 user_data 里装了 Nginx,Ansible 又去改 Nginx 配置,谁 apply 都会把对方的改动覆盖掉,两个工具的 state 都对不上。
  • 【追问】
    • 追问:user_data 里到底能不能放部署逻辑?→ 技术上可以,但违反分层原则,最好只放开机引导(拉取配置、通知 Ansible 接管),部署逻辑交给配置管理工具。
    • 追问:Ansible 改了实例内部,Terraform 会感知吗?→ 不会,实例内部状态不在 Terraform 视野里,除非 user_data 变化触发重建才会”重装”。
  • 【岗位标注】通用 / 运维 / AI 运维 / DevOps

Q6. 生产环境误执行 destroy,有没有保险措施?

  • 【考察点】生产保护意识,考”出事之前的防护”
  • 【参考回答】有几道防线。一是 lifecycle 里加 prevent_destroy = true,误删时直接报错拒绝;二是生产用单独的目录和单独的 state,跟测试环境物理隔离,CI 里生产 apply/destroy 必须人工审批;三是 state 后端开版本管理,万一真删了还能从备份恢复。我们的流程是生产从不直接跑 destroy,销毁走审批。另外提醒:terraform destroy 只删 state 里的资源,手动建的不会动,所以所有该管的资源都要纳管,否则”管不到的”才是风险。
  • 【追问】
    • 追问:加了 prevent_destroy 之后怎么正常销毁?→ 先删掉这个配置再 destroy,故意两步操作,等于让销毁必须经过一次显式的配置变更。
    • 追问:真删了还能救吗?→ 云厂商的快照、回收站(如 ECS 实例回收站)是最后手段,所以关键资源提前开快照策略比事后抢救重要。
  • 【岗位标注】运维 / AI 运维 / DevOps

Q7. apply 明明成功了,但服务就是不通,为什么?

  • 【考察点】”apply 成功 ≠ 服务就绪”的反直觉认知
  • 【参考回答】这是新手最容易踩的坑:apply 成功只代表”云平台接受了创建请求”,不代表服务已经就绪。比如 ECS 创建成功但系统还在初始化,安全组规则配了但没生效,数据库状态是 creating 但 apply 已经返回。所以生产上我会在 apply 之后加验证:用 Ansible 或脚本去探活端口、查服务状态。Terraform 部分资源有 timeouts 配置可以等待,但根本上 apply 完不等于一切正常,这一点和代码部署差别很大。
  • 【追问】
    • 追问:有没有办法让 apply 等资源就绪?→ 可以用 provisioner 的 remote-exec 探活,或数据源轮询,但更推荐的是”Terraform 只保证资源被创建,就绪交给 Ansible/监控探活”,各司其职。
    • 追问:timeouts 配置怎么用?→ 在 resource 块里写 timeouts { create = "10m" },控制创建操作的等待上限,超时报错而不是无限等。
  • 【岗位标注】通用 / 运维 / AI 运维

Q8. 反直觉:plan 显示一堆资源要删,但云上资源明明好好的?

  • 【考察点】对”代码 / state / 真实状态”三方对比机制的理解深度
  • 【参考回答】plan 显示删除,最可能的原因是 state 里根本没有这些资源——它们从没被纳管,或者 state 记录和真实 ID 对不上(比如机器被手动重建过、从快照恢复的)。Terraform 只认 state,state 里没有就认为不存在,就会按代码”重建”。还有一种常见情况:模块被拆分后资源地址变了但 state mv 没做,plan 就认为旧地址的资源要删。所以遇到 plan 里大片删除,第一反应是先看 state 再决定,千万别直接 apply。
  • 【追问】
    • 追问:怎么看 state 里到底有什么?→ terraform state list 列出全部托管资源,和云控制台对一遍就清楚了。
    • 追问:反过来,plan 显示新建但资源其实已存在会怎样?→ 同样因为 state 缺失,apply 会尝试创建,云平台会报”资源已存在”冲突,此时应该 import 纳管而不是硬创建。
  • 【岗位标注】运维 / DevOps