我使用了 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}"
这仍然不能阻止 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
这导致 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']
现在 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"]
并出现此错误
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'
编辑2:
我曾尝试在 VPC 模块中添加来自 NAT 网关的 public_ip 输出作为 Jenkins 模块的输入。希望它能够保留 Jenkins 模块,直到 NAT 网关启动并准备就绪。这没有奏效。我观察到 Terraform 和模块的情况是,除非您在某个地方(例如在 Jenkins 用户数据中)使用该变量,否则该变量将被完全忽略。将其作为模块的输入是不够的,它必须是该模块中资源的输入。副作用是,作为计算值,它将每次都尝试重新创建您的资源。
答案1
感谢 jbardinhttps://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}"
}
}
确保将该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
答案2
您可能无法depends_on
在模块上使用,但我确信您仍然可以在模块创建的实际 NAT 网关资源上使用它。根据您的 Terraform 版本,获取它可能很简单,只需使用terraform state list
并深入研究它,或者手动搜索您的 Terraform 状态文件即可。
然而,似乎自 11.x 系列起,尚不支持该功能。Terraform 的未来版本可能会这样做,因为 HashiCorp 团队成员建议了一种方法来提供这里明确需要的东西。
问题的核心是depends_on
在模块扩展为资源之前的编译阶段运行,这使得它们不符合该参数的定位条件。