使用Terraform来管理现有的用于ACM证书验证的Route53记录
在使用Terraform进行资源管理时,通过import命令可以将现有资源纳入管理。然而,当使用ACM获取证书并创建用于DNS验证的Route53记录(CNAME)时,如果导入后执行terraform plan命令,会输出”将销毁并重新创建现有资源”的信息。虽然如果证书的DNS验证记录已经完成验证,重新创建可能没有问题,但是我考虑到目标证书是用于ECS的ALB上,如果证书出现问题,恢复可能会很麻烦。因此,我尝试验证了一种方法,以确保Terraform不会重新创建现有记录。
继续记录
在验证过程中,由于在ACM上创建证书的时间已经过去了一段时间,因此证书和其验证记录之间的关系不明确。我担心重新创建验证记录可能会影响证书的失效或验证状态的更改。然而,仔细考虑后,我发现在创建证书时并没有相应的验证记录存在。而且在完成验证后的一段时间内,验证记录似乎没有被使用。所以即使运行destroy/create操作,应该也不会有问题。
实际上,读取证书验证与当前使用的ALB关联的记录的目的是一个敏感的问题,但单纯地将Route53记录导入到Terraform中,可以使用(allow_overwrite=true)参数而无需使用import命令。这就是我认为的。
另外补充
我明白原因了。由于使用了for_each创建的资源,在这种情况下,必须指定aws_route53_record.cert_validation[“*.xxx.example.com”]。
验证
现有证书的状态如下。
-
- ドメイン名: *.xxx.example.com ※ワイルドカード証明書
-
- 状況: 発行済み
-
- 使用中?: はい
-
- 状況の詳細: 証明書は 2021-XX-XXTXX:XX:XXUTC に発行されました
- 検証状態: 成功
Terraform的定义以acm_certificate_validation的参考资料中的以下方式呈现。它会自动执行一系列的操作(包括在ACM中颁发证书并进行DNS验证的操作),并帮助我们创建证书和对应的Route53记录。
resource "aws_acm_certificate" "example" {
domain_name = "*.xxx.example.com"
validation_method = "DNS"
}
data "aws_route53_zone" "example" {
name = "xxx.example.com"
private_zone = false
}
resource "aws_route53_record" "example" {
for_each = {
for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = data.aws_route53_zone.example.zone_id
}
resource "aws_acm_certificate_validation" "example" {
certificate_arn = aws_acm_certificate.example.arn
validation_record_fqdns = [for record in aws_route53_record.example : record.fqdn]
}
假设现有的ACM证书已经被成功导入(资源指定使用ARN方式有点特殊)。
创建定义后,首先使用常规方法导入资源,然后在计划中进行差异确认。执行导入操作。
(请注意,资源指定格式为区域ID_记录_记录类型。ACM证书DNS验证的Route53记录以下划线开头,因此在区域ID和记录之间使用连续的下划线进行分隔)
> terraform import aws_route53_record.cert_validation XXXXXXXXXX__XXXXXXXXXX.xxx.example.com_CNAME
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
取得成功。
随后按照上述定义执行计划。
> terraform plan
actions are indicated with the following symbols:
+ create
- destroy
Terraform will perform the following actions:
# module.common.aws_route53_record.cert_validation will be destroyed
- fqdn = "_XXXXXXXXXX.xxx.example.com" -> null
om_CNAME" -> null
- name = "_XXXXXXXXXX.xxx.example.com" -> null
d
+ resource "aws_route53_record" "cert_validation" {
+ allow_overwrite = true
+ fqdn = (known after apply)
+ id = (known after apply)
+ name = "_XXXXXXXXXX.xxx.example.com"
+ records = [
+ "_XXXXXXXXXX.XXXXXXXXXX.acm-validations.aws.",
]
+ ttl = 300
+ type = "CNAME"
+ zone_id = "XXXXXXXXXX"
}
Plan: 1 to add, 0 to change, 1 to destroy.
由于在过程中添加了关于aws_acm_certificate_validation的描述,因此此处没有输出。
已经输出了一个销毁现有记录并创建新记录的计划。
由于希望避免这种情况,暂时回滚。
> terraform state rm aws_route53_record.cert_validation
Removed aws_route53_record.cert_validation
Successfully removed 1 resource instance(s).
不使用import的情况下制定计划。
> terraform plan
Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_acm_certificate_validation.cert will be created
+ resource "aws_acm_certificate_validation" "cert" {
+ certificate_arn = "arn:aws:acm:ap-northeast-1:XXXXXXXXXX:certificate/XXXXXXXXXX"
+ id = (known after apply)
+ validation_record_fqdns = (known after apply)
}
# aws_route53_record.cert_validation["*.xxx.example.com"] will be created
+ resource "aws_route53_record" "cert_validation" {
+ allow_overwrite = true
+ fqdn = (known after apply)
+ id = (known after apply)
+ name = "_XXXXXXXXXX.xxx.example.com"
+ records = [
+ "_XXXXXXXXXX.XXXXXXXXXX.acm-validations.aws.",
]
+ ttl = 300
+ type = "CNAME"
+ zone_id = "XXXXXXXXXX"
}
Plan: 2 to add, 0 to change, 0 to destroy.
在Route53记录的参考资料中,如果allow_overwrite设置为true,那么如果已经存在相同的记录,就会进行覆盖。但是即使是覆盖,只要在terraform上不被视为destroy,资源应该会继续运行而不被删除(至少我希望如此)。
允许覆盖 -(可选)如果有的话,允许在Terraform中覆盖现有记录以创建此记录。这不会影响在Terraform中更新记录的能力,也不会阻止Terraform内的其他资源或在Terraform之外手动进行的Route 53更改覆盖此记录。默认为false。不建议在大多数环境中使用此配置。
我申请。
> terraform apply
Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
+ create
+ certificate_arn = "arn:aws:acm:ap-northeast-1:XXXXXXXXXX:certificate/XXXXXXXXXX"
+ id = (known after apply)
+ validation_record_fqdns = (known after apply)
}
# aws_route53_record.cert_validation["*.xxx.example.com"] will be created
+ resource "aws_route53_record" "cert_validation" {
+ allow_overwrite = true
+ fqdn = (known after apply)
+ id = (known after apply)
+ name = "_XXXXXXXXXX.xxx.example.com"
+ records = [
+ "_eacbe743751c2f4f3d1aff8c466acc27.jddtvkljgg.acm-validations.aws.",
]
+ ttl = 300
+ type = "CNAME"
+ zone_id = "XXXXXXXXXX"
}
Plan: 2 to add, 0 to change, 0 to destroy.
aws_route53_record.cert_validation["*.xxx.example.com"]: Creating...
aws_route53_record.cert_validation["*.xxx.example.com"]: Still creating... [10s elapsed]
aws_route53_record.cert_validation["*.xxx.example.com"]: Still creating... [20s elapsed]
aws_route53_record.cert_validation["*.xxx.example.com"]: Still creating... [30s elapsed]
aws_route53_record.cert_validation["*.xxx.example.com"]: Still creating... [40s elapsed]
aws_route53_record.cert_validation["*.xxx.example.com"]: Creation complete after 46s [id=XXXXXXXXXX__XXXXXXXXXX.xxx.example.com._CNAME]
aws_acm_certificate_validation.cert: Creating...
aws_acm_certificate_validation.cert: Creation complete after 1s [id=2021-05-21 00:34:19 +0000 UTC]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
在这种情况下,确认了申请之前和之后证书的状态,完全没有进行任何更改。
-
- ドメイン名: *.xxx.example.com ※ワイルドカード証明書
-
- 状況: 発行済み
-
- 使用中?: はい
-
- 状況の詳細: 証明書は 2021-XX-XXTXX:XX:XXUTC に発行されました
- 検証状態: 成功
为了安全起见,我们会执行这个计划。
> terraform plan
Note: Objects have changed outside of Terraform
Terraform detected the following changes made outside of Terraform since the last "terraform
apply":
# aws_route53_record.cert_validation["*.xxx.example.com"] has been chang id = "XXXXXXXXXX__XXXXXXXXXX.xxx.example.com name = "_XXXXXXXXXX.xxx.example.com"
# (6 unchanged attributes hidden)
}
Unless you have made equivalent changes to your configuration, or ignored the relevant
attributes using ignore_changes, the following plan may include actions to undo or respond
to these changes.
────────────────────────────────────────────────────────────────────────────────────────────
Your configuration already matches the changes detected above. If you'd like to update the
Terraform state to match, create and apply a refresh-only plan:
terraform apply -refresh-only
因为设置没有差异,但在tfstate中存在差异,所以输出了要执行刷新操作。
> terraform apply -refresh-only
Note: Objects have changed outside of Terraform
Terraform detected the following changes made outside of Terraform since the last "terraform
apply":
# aws_route53_record.cert_validation["*.xxx.example.com"] has been changed
~ resource "aws_route53_record" "cert_validation" {
id = "XXXXXXXXXX__XXXXXXXXXX.xxx.example.com._CNAME"
name = "_XXXXXXXXXX.xxx.example.com"
# (6 unchanged attributes hidden)
}
This is a refresh-only plan, so Terraform will not take any actions to undo these. If you
were expecting these changes then you can apply this plan to record the updated values in
the Terraform state without changing any remote objects.
Would you like to update the Terraform state to reflect these detected changes?
Terraform will write these changes to the state without modifying any real infrastructure.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
我們將再次執行計劃。
> terraform plan
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no
differences, so no changes are needed.
没有任何改变。这样就可以了。
我们了解到,可以不导入Route53的记录,而是使用allow_overwrite=true来覆盖现有记录。
但请注意,由于我们只是针对ACM验证使用的CNAME记录进行了测试,其他记录类型尚未确认。
请提供更多的上下文或者句子,以便我能准确地把它翻译成中文。
根据Route53记录的参考资料,创建区域时不需要进行NS/SOA记录的terraform导入。