如何将基础设施自动导入 Terraform ?

什么是 Terraform?

Terraform 是一个 CLI 工具,可基于现有的基础设施(逆向 Terraform)生成 tf/jsontfstate 文件。

Terraformer 使用 Terraform 提供程序,旨在轻松支持新添加的资源。要使用新字段升级资源,只需升级相关的 Terraform 提供程序即可。

我将回顾所经历过的完全相同的场景,这样,你就可以确切地看到使用 Terraform 导入是有多么简单。

为什么要导入现有基础设施?

在正文开始之前,我们需要先聊一下这个话题。就像生活中的其他事情一样,有时无法对未来进行规划。如果没有对基础设施的创建进行充分的规划,就可能会导致时间压力、紧急释放或需要手动创建基础设施,并且最初就从未使用过 Terraform。

示例:已定义资源,并希望告知状态该资源已存在。

想象一下,如果在生产中出现问题,就必须迅速进行更改以防止停机。在 route53 中手动添加更改以添加 DNS 记录。

一旦事情稳定,同样的记录将被定义为 Terraform 资源,但当应用运行时,将会返回一条消息,说明该资源已存在,这会导致应用阶段失败。

在这种情况下,需要做的就是导入现有资源的状态,以便下次运行 Terraform 应用时,Terraform 软件将考虑处于其状态的资源。在以后,这意味着所做的任何更改都将作为修改,而非添加。

在这种假设的情况下,让我们假设以下资源是从 AWS 控制台中创建的:

Route53 Record Set Name: www.mywebsite.com.
Route53 Record Set Type: CNAME
Route53 Record Set Value: mywebsite.com

现在,由于这三个资源都很简单,并且知道具体创建了什么,因此,可以将他们添加到 Terraform 项目中:

resource aws_route53_record www {
name = "www.mywebsite.com"
type = "CNAME"
zone_id = aws_route53_zone.zone.id
records = ["mywebsite.com"]
ttl = 300
}
resource aws_route53_zone zone {
name         = "mywebsite.com"
}

应用 Terraform 时的错误消息如下所示:

* aws_route53_record.www: 1 error(s) occurred:
* aws_route53_record.www: [ERR]: Error building changeset: InvalidChangeBatch: RRSet of type CNAME with DNS name www.mywebsite.com. is not permitted as it conflicts with other records with the same DNS name in zone mywebsite.com.
status code: 400

由于冲突,Terraform 将在此时退出。

要导入状态,甚至导入现有资源文件(如果你不再拥有它的话),可以运行一下 Terraformer CLI 命令:

AWS_PROFILE=craig terraformer import aws --resources=route53 --filter=aws_route53_record=mywebsite.com --regions=eu-west-2

Terraformer 的美妙之处在于使用了过滤器,而不是 Terraform 使用的命名约定。

你基本上可以根据给定的名称来猜测资源名称,而使用 Terraform 时,它必须采用特定的格式。

导入过程耗费几秒钟的时间,但窗口中的输出非常有用:

2020/06/28 21:50:14 aws importing default region
2020/06/28 21:50:14 aws importing... route53
2020/06/28 21:50:17 Refreshing state... aws_route53_zone.tfer--Z06212801O0AQL6BP58RC_mywebsite-002E-com
2020/06/28 21:50:19 aws Connecting....
2020/06/28 21:50:19 aws save route53
2020/06/28 21:50:19 aws save tfstate for route53

将创建一个目录结构,你可以从中获取所需的所有信息。

route53_zone 包含于我的资源类似的定义,terraform.tfstate 文件包含状态信息。

但你必须记住,terrform.tfstate 只包含已过滤资源的状态信息。如果使用它来代替现有的 Terraform 状态,那么你可能会删除已具有状态的资源。

这个状态文件的重点技术是现在可以从状态文件中获取所需的部分,并将其粘贴到现有文件中。

以下是可供参考的文件:

代码文件

resource "aws_route53_zone" "tfer--Z06212801O0AQL6BP58RC_mywebsite-002E-com" {
comment       = "Managed by Terraform"
force_destroy = "false"
name          = "mywebsite.com."
}

状态文件

{
"version": 3,
"terraform_version": "0.12.18",
"serial": 1,
"lineage": "17034a7a-eadd-b496-c4e3-0ca3639e33ee",
"modules": [
{
"path": ["root"],
"outputs": {
"aws_route53_zone_tfer--Z06212801O0AQL6BP58RC_mywebsite-002E-com_id": {
"sensitive": false,
"type": "string",
"value": "Z06212801O0AQL6BP58RC"
}
},
"resources": {
"aws_route53_zone.tfer--Z06212801O0AQL6BP58RC_mywebsite-002E-com": {
"type": "aws_route53_zone",
"depends_on": [],
"primary": {
"id": "Z06212801O0AQL6BP58RC",
"attributes": {
"comment": "Managed by Terraform",
"delegation_set_id": "",
"force_destroy": "false",
"id": "Z06212801O0AQL6BP58RC",
"name": "mywebsite.com.",
"name_servers.#": "4",
"name_servers.0": "ns-1428.awsdns-50.org",
"name_servers.1": "ns-1616.awsdns-10.co.uk",
"name_servers.2": "ns-307.awsdns-38.com",
"name_servers.3": "ns-944.awsdns-54.net",
"tags.%": "0",
"vpc.#": "0",
"zone_id": "Z06212801O0AQL6BP58RC"
},
"meta": {
"schema_version": 0
},
"tainted": false
},
"deposed": [],
"provider": "provider.aws"
}
},
"depends_on": []
}
]
}

结论

Terraform 肯定有它的用途,尽管对于日常单一资源的导入,替代方法使用起来可能会更快。但我认为,它的主要目的是为了导入更多的基础设施。我很有兴趣在更大的范围来验证这一点,下次若有机会需要导入多个资源时,我肯定会尝试一下的。


猜你喜欢

转载自blog.51cto.com/15060462/2674769