如何确定适合托管子域的相关域/托管区

124次阅读
没有评论

问题描述

在使用 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.comdevops.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 记录。

请根据你的实际情况和需求,适当修改这个脚本。

通过合理管理托管区域或使用自定义脚本,你可以更好地控制域名和记录的管理,并根据需求动态地创建适当的记录。

正文完