TL;博士
两种解决方案:
- 使用 Terraform 创建两个单独的模块
在创建 Kubernetes 集群的代码和 kubernetes 资源之间使用插值和depends_on:
resource "kubernetes_service" "example" {
metadata {
name = "my-service"
}
depends_on = ["aws_vpc.kubernetes"]
}
resource "aws_vpc" "kubernetes" {
...
}
破坏资源时
您遇到了依赖生命周期问题
PS:我不知道您用于创建/配置 Kubernetes 集群的代码,但我猜它看起来像这样
- 为 Kubernetes 集群编写代码(创建 VPC)
- 应用它
- 编写用于配置 Kubernetes 的代码(创建一个创建 ELB 的服务)
- 应用它
- 尝试摧毁一切 => 错误
正在发生的事情是,通过创建LoadBalancer 服务,Kubernetes 将在 AWS 上配置 ELB。但是 Terraform 不知道这一点,并且创建的 ELB 与 Terraform 管理的任何其他资源之间没有任何联系。所以当 terraform 试图销毁代码中的资源时,它会尝试销毁 VPC。但它不能,因为该 VPC 中有一个 terraform 不知道的 ELB。首先要确保 Terraform “取消配置” Kubernetes 集群,然后销毁集群本身。
这里有两个解决方案:
使用不同的模块,因此没有依赖生命周期。例如,第一个模块可能是k8s-infra
,另一个可能是k8s-resources
。第一个管理 Kubernetes 的所有 squeleton,并且是先应用/最后销毁。第二个管理集群内部的内容,并首先应用/销毁。
使用depends_on
参数显式编写依赖生命周期
创建资源时
terraform apply
即使尚未应用任何内容,您也可能会遇到无法创建资源的依赖问题。我将举一个 postgres 的另一个例子
- 编写代码创建 RDS PostgreSQL 服务器
- 用 Terraform 应用它
- 在同一模块中编写代码,以使用 postgres terraform 提供程序配置该 RDS 实例
- 用 Terraform 应用它
- 摧毁一切
- 尝试应用所有内容 => 错误
通过稍微调试 Terraform,我了解到所有提供程序都在plan
/的开头进行了初始化,apply
因此如果有一个无效的配置(错误的 API 密钥/无法访问的端点),那么 Terraform 将失败。
这里的解决方案是使用/命令的目标参数。Terraform 只会初始化与应用的资源相关的提供者。plan
apply
- 使用 AWS 提供商应用 RDS 代码:
terraform apply -target=aws_db_instance
- 应用一切
terraform apply
。因为 RDS 实例已经可达,所以 PostgreSQL 提供者也可以自己发起