Terraform:如何在创建 NAT 网关之前防止 ASG ec2 实例出现

Lev*_*evi 6 terraform

我正在使用 2 个模块。一个是自定义 VPC 模块,另一个是用于启动 jenkins ec2 实例的模块。

您不能使用depends_on模块,但 Jenkins 模块确实依赖 VPC 模块的某些输出,就像这样......

  jenkins_elb_subnets_ids                 = ["${module.vpc.public_subnets_ids[0]}", "${module.vpc.public_subnets_ids[1]}"]
  jenkins_instance_subnets_ids            = ["${module.vpc.private_subnets_ids[0]}", "${module.vpc.private_subnets_ids[1]}"]
  vpc_id                                  = "${module.vpc.vpc_id}"
  vpc_cidr                                = "${var.vpc_cidr}"
Run Code Online (Sandbox Code Playgroud)

这仍然不能阻止 jenkins Ec2 实例在 NAT 网关创建之前启动。

?[0m?[1mmodule.jenkins.aws_launch_configuration.jenkins_lc: Creation complete after 5s (ID: devops-jenkins-lc-20180309131935169800000002)?[0m?[0m
?[0m?[1mmodule.jenkins.aws_autoscaling_group.jenkins_asg: Creating...?[0m
  arn:                            "" => "<computed>"
  default_cooldown:               "" => "<computed>"
  desired_capacity:               "" => "1"
  force_delete:                   "" => "false"
  health_check_grace_period:      "" => "300"
  health_check_type:              "" => "EC2"
  launch_configuration:           "" => "devops-jenkins-lc-20180309131935169800000002"
  load_balancers.#:               "" => "1"
  load_balancers.2235174564:      "" => "devops-jenkins-elb"
  max_size:                       "" => "1"
  metrics_granularity:            "" => "1Minute"
  min_size:                       "" => "1"
  name:                           "" => "devops-jenkins-lc-20180309131935169800000002"
  protect_from_scale_in:          "" => "false"
  tags.#:                         "" => "4"
  tags.0.%:                       "" => "3"
  tags.0.key:                     "" => "Name"
  tags.0.propagate_at_launch:     "" => "1"
  tags.0.value:                   "" => "devops-jenkins"
  tags.1.%:                       "" => "3"
  tags.1.key:                     "" => "BackupDisable"
  tags.1.propagate_at_launch:     "" => "1"
  tags.1.value:                   "" => "No"
  tags.2.%:                       "" => "3"
  tags.2.key:                     "" => "Environment"
  tags.2.propagate_at_launch:     "" => "1"
  tags.2.value:                   "" => "dev"
  tags.3.%:                       "" => "3"
  tags.3.key:                     "" => "AppComponent"
  tags.3.propagate_at_launch:     "" => "1"
  tags.3.value:                   "" => "Jenkins-master"
  target_group_arns.#:            "" => "<computed>"
  vpc_zone_identifier.#:          "" => "2"
  vpc_zone_identifier.3355635847: "" => "subnet-4f13e705"
  vpc_zone_identifier.3554579391: "" => "subnet-8e92b2d3"
  wait_for_capacity_timeout:      "" => "0"?[0m
?[0m?[1mmodule.jenkins.aws_autoscaling_group.jenkins_asg: Creation complete after 1s (ID: devops-jenkins-lc-20180309131935169800000002)?[0m?[0m
?[0m?[1mmodule.vpc.aws_vpn_gateway.transit_vgw: Still creating... (10s elapsed)?[0m?[0m
?[0m?[1mmodule.vpc.aws_route53_zone.main: Still creating... (10s elapsed)?[0m?[0m
?[0m?[1mmodule.vpc.aws_nat_gateway.private_nat_gw.1: Still creating... (10s elapsed)?[0m?[0m
?[0m?[1mmodule.vpc.aws_nat_gateway.private_nat_gw.0: Still creating... (10s elapsed)?[0m?[0m
Run Code Online (Sandbox Code Playgroud)

这导致 Jenkins 无法正常启动。

Cannot find a valid baseurl for repo: amzn-main/latest
Could not retrieve mirrorlist http://repo.us-east-1.amazonaws.com/latest/main/mirror.list error was
12: Timeout on http://repo.us-east-1.amazonaws.com/latest/main/mirror.list: (28, 'Connection timed out after 5001 milliseconds')
Mar 09 13:19:55 cloud-init[2581]: util.py[WARNING]: Failed to install packages: ['git', 'aws-cfn-bootstrap', 'docker', 'jq-libs', 'jq', 'perl-Test-Simple.noarch', 'perl-YAML.noarch', 'gcc', 'amazon-ssm-agent.rpm', 'perl-Switch', 'perl-DateTime', 'perl-Sys-Syslog', 'perl-LWP-Protocol-https', 'perl-Test-Simple.noarch', 'perl-YAML.noarch']
Run Code Online (Sandbox Code Playgroud)

现在,Terraform 确实有来自 AWS 团队的“官方”VPC 模块。我看过它的代码,但它似乎没有做任何事情来减轻这种情况?但是有了 90k 部署和只有 36 个问题......看起来不像他们有问题。我没有自己测试过它,因为使用它不是一种选择,但这可能意味着问题出在我的模块上。

编辑:那不起作用@sysadmin1138 我试过这个......

resource "aws_autoscaling_group" "jenkins_asg" {
  depends_on                = ["module.vpc.aws_nat_gateway.private_nat_gw.1", "module.vpc.aws_nat_gateway.private_nat_gw.0"]
Run Code Online (Sandbox Code Playgroud)

并得到这个错误

Initializing the backend...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.

Error: aws_autoscaling_group.jenkins_asg: resource depends on non-existent module 'vpc.aws_nat_gateway.private_nat_gw.1'



Error: aws_autoscaling_group.jenkins_asg: resource depends on non-existent module 'vpc.aws_nat_gateway.private_nat_gw.0'
Run Code Online (Sandbox Code Playgroud)

编辑2:

我尝试在 VPC 模块中添加来自 NAT Gatway 的 public_ip 输出作为 Jenkins 模块的输入。希望它能够在 NAT 网关启动并准备好之前阻止 Jenkins 模块。这没有用。我对 Terraform 和模块的观察是,除非您在某处使用该变量,例如在 Jenkins 用户数据中,否则该变量将被完全忽略。将它作为模块的输入是不够的,它必须是该模块中资源的输入。副作用是作为计算值,它每次都会尝试重新创建您的资源。

Lev*_*evi 2

感谢 jbardin https://github.com/hashicorp/terraform/issues/14056

为了解决此问题,您需要使用 VPC 模块的输出。您可以使用该aws_nat_gateway属性public_ip,但由于我在之后创建了一条路线,所以aws_nat_gateway我使用了该属性。然后我在 Jenkins 模块中创建了一个虚拟变量和虚拟资源。

resource "null_resource" "dummy" {
  provisioner "local-exec" {
    command = "echo ${var.dummy}"
  }
}
Run Code Online (Sandbox Code Playgroud)

确保将该dummy变量分配给您选择的输出。它还需要是一个字符串。dummy = "${join(",", module.vpc.private_nat_gw_routes)}"

之后我使用了depends_on = ["null_resource.dummy"]我的 ASG 资源。这使得该资源等到创建 NAT 网关 + 路由之后,但不会产生每次重新创建资源的令人讨厌的副作用。

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed
Run Code Online (Sandbox Code Playgroud)