2

在我的 terraform 基础架构中,我根据参数启动了几个 Kubernetes 集群,然后使用 kubernetes 提供程序将一些标准内容安装到这些 Kubernetes 集群中。

当我更改参数并且不再需要其中一个集群时,terraform 无法将其拆除,因为提供程序和资源都在模块中。但是,我没有看到替代方案,因为我在同一个模块中创建了 kubernetes 集群,并且 kubernetes 对象都是每个 kubernetes 集群。

我能想到的所有解决方案都涉及在我的 terraform 配置中添加一堆样板。我应该考虑从脚本生成我的 terraform 配置吗?


我做了一个 git repo,它准确地显示了我遇到的问题:

https://github.com/bukzor/terraform-gke-k8s-demo

4

1 回答 1

5

TL;博士

两种解决方案:

  1. 使用 Terraform 创建两个单独的模块
  2. 在创建 Kubernetes 集群的代码和 kubernetes 资源之间使用插值和depends_on:

    resource "kubernetes_service" "example" {
      metadata {
        name = "my-service"
      }
    
      depends_on = ["aws_vpc.kubernetes"]
    }
    
    resource "aws_vpc" "kubernetes" {
      ...
    }
    

破坏资源时

您遇到了依赖生命周期问题

PS:我不知道您用于创建/配置 Kubernetes 集群的代码,但我猜它看起来像这样

  1. 为 Kubernetes 集群编写代码(创建 VPC)
  2. 应用它
  3. 编写用于配置 Kubernetes 的代码(创建一个创建 ELB 的服务)
  4. 应用它
  5. 尝试摧毁一切 => 错误

正在发生的事情是,通过创建LoadBalancer 服务,Kubernetes 将在 AWS 上配置 ELB。但是 Terraform 不知道这一点,并且创建的 ELB 与 Terraform 管理的任何其他资源之间没有任何联系。所以当 terraform 试图销毁代码中的资源时,它会尝试销毁 VPC。但它不能,因为该 VPC 中有一个 terraform 不知道的 ELB。首先要确保 Terraform “取消配置” Kubernetes 集群,然后销毁集群本身。

这里有两个解决方案:

  1. 使用不同的模块,因此没有依赖生命周期。例如,第一个模块可能是k8s-infra,另一个可能是k8s-resources。第一个管理 Kubernetes 的所有 squeleton,并且是先应用/最后销毁。第二个管理集群内部的内容,并首先应用/销毁。

  2. 使用depends_on参数显式编写依赖生命周期

创建资源时

terraform apply即使尚未应用任何内容,您也可能会遇到无法创建资源的依赖问题。我将举一个 postgres 的另一个例子

  1. 编写代码创建 RDS PostgreSQL 服务器
  2. 用 Terraform 应用它
  3. 在同一模块中编写代码,以使用 postgres terraform 提供程序配置该 RDS 实例
  4. 用 Terraform 应用它
  5. 摧毁一切
  6. 尝试应用所有内容 => 错误

通过稍微调试 Terraform,我了解到所有提供程序都在plan/的开头进行了初始化,apply因此如果有一个无效的配置(错误的 API 密钥/无法访问的端点),那么 Terraform 将失败。

这里的解决方案是使用/命令的目标参数。Terraform 只会初始化与应用的资源相关的提供者。planapply

  1. 使用 AWS 提供商应用 RDS 代码:terraform apply -target=aws_db_instance
  2. 应用一切terraform apply。因为 RDS 实例已经可达,所以 PostgreSQL 提供者也可以自己发起
于 2019-01-13T16:53:10.287 回答