一些基本解释:
terraform plan 基本上根据 terraform azurerm provider 验证您的代码,以检查您的代码是否正确,是否满足 Azure API 的要求(例如,使用正确的属性、类型等)。如果一切正常,它会进行试运行,并向您展示当您执行terraform apply 时会发生什么。在这一点上,terraform 不知道 Azure 中存在或不存在什么,它只是进行试运行以给您一个想法。这意味着即使您的terraform plan 成功,您的terraform apply 也不一定会成功。
请记住,azurerm provider 更像是 Azure API 之上的包装器。它根据 Azure API 的要求进行自己的验证。
现在回答您的问题:
它如何知道清单文件中的所需状态与 azure 门户中资源的当前状态相同?是直接用azurerm api检查还是参考状态文件?
对于 Terraform 创建的任何资源,Terraform 将 always 验证状态文件。它与 Azure API 进行检查的唯一时间是它必须与资源交互时。
如果它引用状态文件,第一次计划如何验证 terraform 计划,而它还没有状态文件(因为它只是会生成状态文件的 terraform 应用?
参考基本解释。它可以追溯到terraform plan 的工作方式。因为它是一个执行计划,所以它还不需要状态文件。状态文件仅包含在 Azure 中创建的内容或从 Azure 导入的内容的信息。它是关于实际现有资源的信息。 terraform plan 仅进行空运行/测试/简单验证,以让您知道您的代码是否足以进行下一步:terraform apply。
其次,terraform destroy 命令是否引用了我们的清单文件(所需的配置文件),还是仅使用当前状态(Azure 门户中的资源实际状态)验证状态文件
当 Terraform 对象保存在状态文件中时,它们会使用 Azure 资源 ID 耦合到 Azure 对象。类似于plan 或apply 的terraform destroy 仍将使用状态文件作为其对现实世界的理解(Azure 中的当前状态)。如果从 Terraform 代码中删除 Terraform 对象,destroy 将与状态文件进行交叉检查,并注意到此资源存在于状态文件中。由于它存在于状态文件中但正在从您的代码中删除,因此 Terraform 将发送一个请求以销毁该资源。
看看下面你可以尝试的一些场景,这可能有助于你更好地理解。
场景 1
- 假设您创建了一个名为
ststorageaccount 的存储帐户,来自 Azure 门户。
- 然后您继续编写 Terraform 代码以创建相同的存储帐户并执行
terraform plan。您会注意到执行计划不知道此存储帐户已存在,并且执行计划显示尝试再次创建它。
- 由于计划“成功”,您可以继续执行
terraform apply。您现在收到一条错误消息,指出存储帐户ststorageaccount 已经存在,需要在状态文件中导入。 terraform apply 阶段是 Terraform 的 azurerm provider 开始与 Azure API 交互以创建资源的时候。 Azure API 知道 Azure 中的状态,是向 Terraform 以及随后向您抛出错误的那个。
- 由于 Terraform 无法成功创建存储帐户,它不会将其添加到状态文件中,而是要求您手动导入。
场景 2
- 您编写 Terraform 代码以在
South East Asia 区域中创建特定资源。
- 您再次执行
terraform plan,因为 Terraform 仅根据 Terraform 的 azurerm provider 验证您的代码,它向您展示了一个成功的执行计划。
- 您继续使用
terraform apply,但现在收到一条错误消息,指出该区域错误,必须改为SouthEastAsia(不带空格)。
- 发生这种情况是因为 Terraform
azurerm provider 接受 South East Asia 而该特定资源的 Azure API 要求以不同方式编写区域。
因此,您可以看到这两个案例显示了 terraform plan 和 terraform apply 的行为方式不同,因为它们在两个不同的“平面”上工作。