问题描述
在使用 Terraform 创建新的域记录时,首先需要找到适合托管它的区域(hosted zone)。例如,如果要为mysite.example.com
创建DNS记录,需要找到example.com
区域,并在其中为mysite
创建记录,操作类似下面这样的代码:
variable zone {
type = string
}
variable subdomain {
type = string
}
variable targets {
type = list(string)
default = ["devops.stackexchange.com"]
}
data aws_route53_zone this {
name = var.zone
}
resource aws_route53_record this {
zone_id = data.aws_route53_zone.this.zone_id
name = "${var.subdomain}.${var.zone}"
type = "CNAME"
ttl = 100
records = var.targets
}
output fqdn {
value = aws_route53_record.this.fqdn
}
如果要创建devops.mysite.example.com
,可以通过以下两种方式之一调用此模块:
zone = "example.com"
subdomain = "devops.mysite"
或者,如果已经有了mysite.example.com
的托管区域,可以使用如下方式:
zone = "mysite.example.com"
subdomain = "devops"
然而,可能会出现这样的情况:一开始可能只有example.com
作为唯一的托管区域,但后来可能会为mysite
子域添加一个新的托管区域。如果发生这种情况,我不想改变我的代码,因为需求仍然保持不变。我只希望 Terraform 能够察觉到仍然有可能满足我的需求(即在devops.mysite.example.com
和devops.stackexchange.com
之间创建一个 DNS CName 记录),并相应地进行调整。
解决方案
请注意以下操作注意版本差异及修改前做好备份。
Terraform 本身并没有直接提供递归查找适合托管的域的功能。但是,你可以采用一些策略来解决这个问题。
方案1:合理管理托管区域
在使用 Terraform 进行资源管理时,建议将区域(hosted zone)也纳入 Terraform 管理。这样可以确保你的区域和记录都处于 Terraform 的管辖之下。这意味着,你可以在 Terraform 的计划(terraform plan
)中清晰地看到任何可能的变更。即使托管区域在不同的远程状态文件中,像 runatlantis.io 这样的工具也能在 GitHub Pull Request 中显示变更差异。
方案2:使用自定义脚本
如果你的域和区域管理不在 Terraform 的管辖之下,你可以编写自定义脚本来解决这个问题。以下是一个示例的 Python 脚本,它使用 boto3 库来逐层查找适合的托管区域并创建记录:
import boto3
def find_hosted_zone(domain):
client = boto3.client('route53')
response = client.list_hosted_zones()
for zone in response['HostedZones']:
if domain.endswith(zone['Name'][:-1]):
return zone['Id']
return None
def create_dns_record(zone_id, subdomain, targets):
client = boto3.client('route53')
record_name = f'{subdomain}.{zone_id}'
response = client.change_resource_record_sets(
HostedZoneId=zone_id,
ChangeBatch={
'Changes': [{
'Action': 'CREATE',
'ResourceRecordSet': {
'Name': record_name,
'Type': 'CNAME',
'TTL': 100,
'ResourceRecords': [{'Value': target} for target in targets]
}
}]
}
)
return response
def main():
domain = 'example.com'
subdomain = 'devops.mysite'
targets = ['devops.stackexchange.com']
zone_id = find_hosted_zone(domain)
if zone_id:
create_dns_record(zone_id, subdomain, targets)
print(f'DNS record created for {subdomain}.{domain}')
else:
print(f'No suitable hosted zone found for {domain}')
if __name__ == '__main__':
main()
在这个示例中,find_hosted_zone
函数会列出所有托管区域,然后逐一检查域名是否以这些区域名结尾。如果找到适合的托管区域,create_dns_record
函数将创建相应的 DNS 记录。
请根据你的实际情况和需求,适当修改这个脚本。
通过合理管理托管区域或使用自定义脚本,你可以更好地控制域名和记录的管理,并根据需求动态地创建适当的记录。