使用 AWS 和 Kubernetes 提供商的 Terraform 循环

Posted

技术标签:

【中文标题】使用 AWS 和 Kubernetes 提供商的 Terraform 循环【英文标题】:Terraform cycle with AWS and Kubernetes provider 【发布时间】:2020-04-21 17:24:09 【问题描述】:

我的 Terraform 代码描述了一些用于构建 Kubernetes 集群的 AWS 基础设施,包括在集群中的一些部署。当我尝试使用terraform plan -destroy 破坏基础架构时,我得到了一个循环:

module.eks_control_plane.aws_eks_cluster.this[0] (destroy)
module.eks_control_plane.output.cluster
provider.kubernetes
module.aws_auth.kubernetes_config_map.this[0] (destroy)
data.aws_eks_cluster_auth.this[0] (destroy)

仅使用terraform destroy 手动破坏基础设施工作正常。不幸的是,Terraform Cloud 首先使用terraform plan -destroy 来计划销毁,这导致此操作失败。以下是相关代码:

eks_control_plane 模块的摘录:

resource "aws_eks_cluster" "this" 
  count = var.enabled ? 1 : 0

  name     = var.cluster_name
  role_arn = aws_iam_role.control_plane[0].arn
  version  = var.k8s_version

  # https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html
  enabled_cluster_log_types = var.control_plane_log_enabled ? var.control_plane_log_types : []

  vpc_config 
    security_group_ids = [aws_security_group.control_plane[0].id]
    subnet_ids         = [for subnet in var.control_plane_subnets : subnet.id]
  

  tags = merge(var.tags,
    
    
  )

  depends_on = [
    var.dependencies,
    aws_security_group.node,
    aws_iam_role_policy_attachment.control_plane_cluster_policy,
    aws_iam_role_policy_attachment.control_plane_service_policy,
    aws_iam_role_policy.eks_cluster_ingress_loadbalancer_creation,
  ]


output "cluster" 
  value = length(aws_eks_cluster.this) > 0 ? aws_eks_cluster.this[0] : null

来自 aws_auth 模块的 aws-auth Kubernetes 配置映射:

resource "kubernetes_config_map" "this" 
  count = var.enabled ? 1 : 0

  metadata 
    name      = "aws-auth"
    namespace = "kube-system"
  
  data = 
    mapRoles = jsonencode(
      concat(
        [
          
            rolearn  = var.node_iam_role.arn
            username = "system:node:EC2PrivateDNSName"
            groups = [
              "system:bootstrappers",
              "system:nodes",
            ]
          
        ],
        var.map_roles
      )
    )
  

  depends_on = [
    var.dependencies,
  ]


来自根模块的 Kubernetes 提供者:

data "aws_eks_cluster_auth" "this" 
  count = module.eks_control_plane.cluster != null ? 1 : 0
  name  = module.eks_control_plane.cluster.name


provider "kubernetes" 
  version = "~> 1.10"

  load_config_file       = false
  host                   = module.eks_control_plane.cluster != null ? module.eks_control_plane.cluster.endpoint : null
  cluster_ca_certificate = module.eks_control_plane.cluster != null ? base64decode(module.eks_control_plane.cluster.certificate_authority[0].data) : null
  token                  = length(data.aws_eks_cluster_auth.this) > 0 ? data.aws_eks_cluster_auth.this[0].token : null

这就是模块的调用方式:

module "eks_control_plane" 
  source  = "app.terraform.io/SDA-SE/eks-control-plane/aws"
  version = "0.0.1"
  enabled = local.k8s_enabled

  cluster_name          = var.name
  control_plane_subnets = module.vpc.private_subnets
  k8s_version           = var.k8s_version
  node_subnets          = module.vpc.private_subnets
  tags                  = var.tags
  vpc                   = module.vpc.vpc

  dependencies = concat(var.dependencies, [
    # Ensure that VPC including all security group rules, network ACL rules,
    # routing table entries, etc. is fully created
    module.vpc,
  ])



# aws-auth config map module. Creating this config map will allow nodes and
# Other users to join the cluster.
# CNI and CSI plugins must be set up before creating this config map.
# Enable or disable this via `aws_auth_enabled` variable.
# TODO: Add Developer and other roles.
module "aws_auth" 
  source  = "app.terraform.io/SDA-SE/aws-auth/kubernetes"
  version = "0.0.0"
  enabled = local.aws_auth_enabled

  node_iam_role = module.eks_control_plane.node_iam_role
  map_roles = [
    
      rolearn  = "arn:aws:iam::$var.aws_account_id:role/Administrator"
      username = "admin"
      groups = [
        "system:masters",
      ]
    ,
    
      rolearn  = "arn:aws:iam::$var.aws_account_id:role/Terraform"
      username = "terraform"
      groups = [
        "system:masters",
      ]
    
  ]

删除 aws_auth 配置映射(这意味着根本不使用 Kubernetes 提供程序)会中断循环。问题显然是 Terraform 试图破坏 Kubernetes 集群,这是 Kubernetes 提供者所必需的。使用多个terraform apply 步骤手动删除资源也可以正常工作。

有没有办法让 Terraform 先销毁所有 Kubernetes 资源,这样 Provider 就不再需要了,然后再销毁 EKS 集群?

【问题讨论】:

目前看来唯一的好方法是将其分成两个应用步骤。这甚至在 Terraform 文档中的某个地方推荐。真是个无赖 【参考方案1】:

您可以使用 depends_on 元参数来控制销毁顺序,就像您对某些 Terraform 代码所做的那样。

如果您将depends_on 参数添加到需要首先销毁的所有必需资源并使其依赖于eks-cluster,Terraform 将在集群之前销毁这些资源。

您还可以使用terraform graph 命令可视化您的配置和依赖关系,以帮助您决定需要创建哪些依赖关系。

https://www.terraform.io/docs/cli/commands/graph.html

【讨论】:

以上是关于使用 AWS 和 Kubernetes 提供商的 Terraform 循环的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes PVC 与 AWS 上的 ReadWriteMany

使用 AWS(ELB、Kubernetes Nginx 和 ACM)配置 HSTS

在 AWS 上使用 Kubernetes 部署 HTTP/2 Web 服务器

将 Kubernetes 应用程序从 AWS 迁移到 GCP

在 AWS EKS 和 Istio Ingress 上使用 GRPC 的 SSL 提供 StatusCode.UNAVAILABLE

Terraform 和 AWS ECS:类似于 Kubernetes 或 Docker swarm 的配置/秘密