试用Terraform的Ansible提供商
Terraform的Ansible提供者已经发布。
通过这样做,我们可以动态地从tfstate文件生成Ansible inventory,非常方便。为了测试方便,我会在Sakura Cloud上试一试。
以下是对给出链接的简要描述:
1. https://www.ansible.com/blog/providing-terraform-with-that-ansible-magic
提供 Terraform 与 Ansible 等魔力的博客文章。
2. https://github.com/ansible/terraform-provider-ansible
Ansible Terraform 提供者的 GitHub 仓库。
3. https://registry.terraform.io/providers/ansible/ansible/latest/docs
Ansible 最新版本的 Terraform 提供者文档。
本次以在Ubuntu服务器上搭建Web服务器的场景为例进行。
预先准备
准备土地开垦
请根据以下链接提供的指示进行准备。
作者将使用以下版本。
$ terraform version
Terraform v1.4.0
确认Python的版本
我使用的Python版本是3.8或更高版本。
我将使用以下版本。
$ python -V
Python 3.10.11
安装Ansible和模块。
pip install ansible
ansible-galaxy collection install cloud.terraform
用于使用Ansible进行SSH连接的密钥生成
$ ssh-keygen -f ./id_rsa
1. 准备所需文件
准备以下四个文件。
我把它放在这个代码库中。
$ ls -1
ansible.cfg
inventory.yml
main.tf
playbook.yml
ansible.cfg文件
为了避免ansible在执行时出现与SSH连接相关的警告和确认信息。
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
存货.yml
使用Ansible来参考tfstate文件中的值。
plugin: cloud.terraform.terraform_provider
主要.tf
以下是用于在Sakura Cloud 上创建服务器的 tf 文件。此外,我们还定义了 ansible_host 资源,以便从 tfstate 生成 ansible inventory。
terraform {
required_providers {
ansible = {
source = "ansible/ansible"
version = "~> 1.0.0"
}
sakuracloud = {
source = "sacloud/sakuracloud"
version = "2.17.0"
}
}
}
provider "sakuracloud" {
token = "YOUR_TOKEN"
secret = "YOUR_TOKEN_SECRET"
zone = "tk1a"
}
variable "password" {
default = "P@ssw0rd"
}
data "sakuracloud_archive" "ubuntu" {
os_type = "ubuntu2004"
}
resource "sakuracloud_disk" "web_server" {
name = "Web Server"
source_archive_id = data.sakuracloud_archive.ubuntu.id
}
resource "sakuracloud_server" "web_server" {
name = "Web Server"
disks = [sakuracloud_disk.web_server.id]
core = 1
memory = 2
description = "nginx"
network_interface {
upstream = "shared"
}
disk_edit_parameter {
hostname = "web-server"
password = var.password
ssh_key_ids = [sakuracloud_ssh_key.key.id]
disable_pw_auth = true
}
}
resource "sakuracloud_ssh_key" "key" {
name = "key"
public_key = file("./id_rsa.pub")
}
resource "ansible_host" "web_server" {
name = sakuracloud_server.web_server.ip_address
groups = ["web"]
variables = {
ansible_user = "ubuntu",
ansible_ssh_private_key_file = "./id_rsa",
ansible_python_interpreter = "/usr/bin/python3"
ansible_become = "yes"
ansible_become_method = "sudo"
ansible_become_pass = var.password
}
}
剧本.yml
安装Web服务器。
- hosts: web
tasks:
- name: apt update
apt:
update_cache: yes
- name: install nginx
apt:
name: nginx
state: present
2.执行terraform init
将会安装SakuraCloud和Ansible供应商。
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding sacloud/sakuracloud versions matching "2.17.0"...
- Finding ansible/ansible versions matching "~> 1.0.0"...
- Installing sacloud/sakuracloud v2.17.0...
- Installed sacloud/sakuracloud v2.17.0 (self-signed, key ID 96CEB4B93D86849D)
- Installing ansible/ansible v1.0.0...
- Installed ansible/ansible v1.0.0 (self-signed, key ID 7664CDD95312BDBD)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
- 确认执行terraform plan后会添加4个计划。
$ terraform plan
data.sakuracloud_archive.ubuntu: Reading...
data.sakuracloud_archive.ubuntu: Read complete after 1s [id=************]
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:
# ansible_host.web_server will be created
+ resource "ansible_host" "web_server" {
+ groups = [
+ "web",
]
+ id = (known after apply)
+ name = (known after apply)
+ variables = {
+ "ansible_become" = "yes"
+ "ansible_become_method" = "sudo"
+ "ansible_become_pass" = "P@ssw0rd"
+ "ansible_python_interpreter" = "/usr/bin/python3"
+ "ansible_ssh_private_key_file" = "./id_rsa"
+ "ansible_user" = "ubuntu"
}
}
# sakuracloud_disk.web_server will be created
+ resource "sakuracloud_disk" "web_server" {
+ connector = "virtio"
+ id = (known after apply)
+ name = "Web Server"
+ plan = "ssd"
+ server_id = (known after apply)
+ size = 20
+ source_archive_id = "************"
+ zone = (known after apply)
}
# sakuracloud_server.web_server will be created
+ resource "sakuracloud_server" "web_server" {
+ commitment = "standard"
+ core = 1
+ description = "nginx"
+ disks = (known after apply)
+ dns_servers = (known after apply)
+ gateway = (known after apply)
+ hostname = (known after apply)
+ id = (known after apply)
+ interface_driver = "virtio"
+ ip_address = (known after apply)
+ memory = 2
+ name = "Web Server"
+ netmask = (known after apply)
+ network_address = (known after apply)
+ private_host_name = (known after apply)
+ zone = (known after apply)
+ disk_edit_parameter {
+ disable_pw_auth = true
+ hostname = "web-server"
+ password = (sensitive value)
+ ssh_key_ids = (known after apply)
}
+ network_interface {
+ mac_address = (known after apply)
+ upstream = "shared"
+ user_ip_address = (known after apply)
}
}
# sakuracloud_ssh_key.key will be created
+ resource "sakuracloud_ssh_key" "key" {
+ fingerprint = (known after apply)
+ id = (known after apply)
+ name = "key"
+ public_key = <<-EOT
ssh-rsa ****
EOT
}
Plan: 4 to add, 0 to change, 0 to destroy.
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
3. 执行 terraform apply
输入并执行”yes”。
等待显示”Apply complete!”。
可以试着从tfstate生成清单来确认吗?
请使用以下命令查看tfstate中的清单信息
$ ansible-inventory -i inventory.yml --graph --vars
可以根据tfstate的内容进行生成。
$ ansible-inventory -i inventory.yml --graph --vars
@all:
|--@ungrouped:
|--@web:
| |--59.106.214.22
| | |--{ansible_become = yes}
| | |--{ansible_become_method = sudo}
| | |--{ansible_become_pass = P@ssw0rd}
| | |--{ansible_python_interpreter = /usr/bin/python3}
| | |--{ansible_ssh_private_key_file = ./id_rsa}
| | |--{ansible_user = ubuntu}
执行playbook
可以使用以下命令来执行Ansible playbook。
$ ansible-playbook -i inventory.yml playbook.yml
$ ansible-playbook -i inventory.yml playbook.yml
PLAY [web] *****************************************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [59.106.214.22]
TASK [apt update] **********************************************************************************************************************************************************************************************
changed: [59.106.214.22]
TASK [install nginx] *******************************************************************************************************************************************************************************************
changed: [59.106.214.22]
PLAY RECAP *****************************************************************************************************************************************************************************************************
59.106.214.22 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
我确认了Web服务器正在运行。
$ curl 59.106.214.22
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
印象
使用tfstate轻松生成了清晰的库存,效果非常好。
旧时我写了一个从tfstate生成清单的脚本,所以这样的麻烦就消失了,很方便。
我希望未来在工作中能够充分利用这一点。
補充
如果使用旧版的Python,那么将使用旧版的Ansible,因为它不支持该版本,会出现警告并无法使用。
$ ansible-inventory -i inventory.yml --graph --vars
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 16:52:21) [Clang 6.0 (clang-600.0.57)].
This feature will be removed from ansible-core in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
[WARNING]: Collection cloud.terraform does not support Ansible version 2.11.12
...
@all:
|--@ungrouped: