如何使用Terraform在KVM上提供VM
在这篇文章中,我将通过安装Terraform KVM提供程序,并使用它来管理在KVM虚拟机管理程序上运行的实例。
Terraform是一种开源基础架构,作为Hashicorp创建的代码软件工具。
它允许我们安全和可预测地创建,改变和改进基础架构。
所有基础架构代码都可以保存在Git存储库和版本中。
Terraform提供商负责资源的生命周期:创建,读取,更新,删除。
Hashicorp拥有许多正式支持的提供商可供使用。
不幸的是,KVM不在列表中。
第1步:安装KVM虚拟机管理程序
此设置的主要准备工作是KVM虚拟机管理程序。
通过从下面的列表中引用相关文章,在Linux系统中安装KVM。
如何在Rhel/CentOS 8上安装KVM
如何在Fedora上安装KVM
在CentOS 7/Ubuntu/Debian/Sles上安装KVM
在Arch Linux/Manjaro上安装KVM
KVM服务(libvird)应运行并启用以在启动时启动。
sudo systemctl start libvirtd sudo systemctl enable libvirtd
使能够 vhost-net
Ubuntu/Debian上的内核模块。
sudo modprobe vhost_net echo vhost_net | sudo tee -a /etc/modules
如果要生成KVM VM模板,请参阅如何在KVM上创建CentOS/Fedora/Rhel VM模板
第2步:安装Terraform
安装和启动KVM后,请执行Terraform安装。
如何在Ubuntu/debian/centos/arch/fedora上安装Terraform
Terraform安装更容易。
我们只需下载二进制存档,提取并将二进制文件放在目录中 $PATH
。
第3步:安装Terraform KVM提供程序
Terraform KVM提供商将使用Linux的KVM使用LibVirt提供基础架构。
它由Duncan Mac-Vicar P与其他贡献者保持。
初始化Terraform Working目录。
$cd ~ $terraform init Terraform initialized in an empty directory!
为存储Terraform插件创建目录。
cd ~/.terraform.d mkdir plugins
检查GitHub发布页面是否可用下载。
在Ubuntu/Linux Mint上安装Terraform KVM提供程序
sudo apt -y install wget wget https://github.com/dmacvicar/terraform-provider-libvirt/releases/download/v0.6.0/terraform-provider-libvirt-0.6.0+git.1569597268.1c8597df.Ubuntu_18.04.amd64.tar.gz tar xvf terraform-provider-libvirt-0.6.0+git.1569597268.1c8597df.Ubuntu_18.04.amd64.tar.gz
移动 terraform-provider-libvirt
二进制文件到 ~/.terraform.d/plugins
目录。
mv terraform-provider-libvirt ~/.terraform.d/plugins/
在CentOS 7/Fedora/OpenSuse上安装Terraform KVM提供程序
如果我们在工作站中运行Fedora或者CentOS,请运行下面的命令。
# CentOS 7/Fedora sudo yum -y install wget wget https://github.com/dmacvicar/terraform-provider-libvirt/releases/download/v0.6.0/terraform-provider-libvirt-0.6.0+git.1569597268.1c8597df.Fedora_28.x86_64.tar.gz tar xvf terraform-provider-libvirt-0.6.0+git.1569597268.1c8597df.Fedora_28.x86_64.tar.gz mv terraform-provider-libvirt ~/.terraform.d/plugins/
从源安装Terraform KVM提供程序
对于其他系统,我们可以从源中构建Terraform LibVirt提供程序。
为此,我们需要.1.2.14或者较新版本的超级可用士最新版本的golangmkisofs需要使用CloudInit Feature.cgo是labvirt-go包所需的。
导出cgo_enabled ="1"
在帮助下安装继续使用Linux系统:
如何在Linux Mint19上安装Go(golang)
如何安装rhel 8
如何在Ubuntu 18.04/CentOS 7上安装
通过运行,可以在Arch Linux/Manjaro上安装:
sudo pacman -S go cdrkit
确保你有 $GOPATH
配置在Linux系统中。
然后继续下载并安装提供程序。
go get github.com/dmacvicar/terraform-provider-libvirt go install github.com/dmacvicar/terraform-provider-libvirt
二进制文件将位于 $GOPATH/bin/terraform-provider-libvirt
。
将其复制到插件目录。
cp $GOPATH/bin/terraform-provider-libvirt ~/.terraform.d/plugins
使用Terraform KVM提供商
一旦我们在插件目录内有提供者。
创建Terraform Projects文件夹。
mkdir ~/projects/terraform cd ~/projects/terraform
创建 libvirt.tf
在KVM上为VM部署的文件。
provider "libvirt" { uri = "qemu:///system" } #provider "libvirt" { # alias = "server2" # uri = "qemu+ssh://Hyman@theitroad/system" #} resource "libvirt_volume" "centos7-qcow2" { name = "centos7.qcow2" pool = "default" source = "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2" #source = "./CentOS-7-x86_64-GenericCloud.qcow2" format = "qcow2" } # Define KVM domain to create resource "libvirt_domain" "db1" { name = "db1" memory = "1024" vcpu = 1 network_interface { network_name = "default" } disk { volume_id = "${libvirt_volume.centos7-qcow2.id}" } console { type = "pty" target_type = "serial" target_port = "0" } graphics { type = "spice" listen_type = "address" autoport = true } }
初始化Terraform Working目录:
$terraform init Initializing provider plugins… Terraform has been successfully initialized! You Jan 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执行计划
$terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ----------------------------------------------------------------------- An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: + libvirt_domain.db1 id: <computed> arch: <computed> console.#: "1" console.0.target_port: "0" console.0.target_type: "serial" console.0.type: "pty" disk.#: "1" disk.0.scsi: "false" disk.0.volume_id: "${libvirt_volume.centos7-qcow2.id}" emulator: <computed> graphics.#: "1" graphics.0.autoport: "true" graphics.0.listen_address: "127.0.0.1" graphics.0.listen_type: "address" graphics.0.type: "spice" machine: <computed> memory: "1024" name: "db1" network_interface.#: "1" network_interface.0.addresses.#: <computed> network_interface.0.hostname: <computed> network_interface.0.mac: <computed> network_interface.0.network_id: <computed> network_interface.0.network_name: "default" qemu_agent: "false" running: "true" vcpu: "1" + libvirt_volume.centos7-qcow2 id: <computed> format: "qcow2" name: "centos7.qcow2" pool: "default" size: <computed> source: "./CentOS-7-x86_64-GenericCloud.qcow2" Plan: 2 to add, 0 to change, 0 to destroy. ----------------------------------------------------------------------- Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.
然后,如果确认需要正确的状态,则构建Terraform基础架构。
$terraform apply An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: + libvirt_domain.db1 id: <computed> arch: <computed> console.#: "1" console.0.target_port: "0" console.0.target_type: "serial" console.0.type: "pty" disk.#: "1" disk.0.scsi: "false" disk.0.volume_id: "${libvirt_volume.centos7-qcow2.id}" emulator: <computed> graphics.#: "1" graphics.0.autoport: "true" graphics.0.listen_address: "127.0.0.1" graphics.0.listen_type: "address" graphics.0.type: "spice" machine: <computed> memory: "1024" name: "db1" network_interface.#: "1" network_interface.0.addresses.#: <computed> network_interface.0.hostname: <computed> network_interface.0.mac: <computed> network_interface.0.network_id: <computed> network_interface.0.network_name: "default" qemu_agent: "false" running: "true" vcpu: "1" + libvirt_volume.centos7-qcow2 id: <computed> format: "qcow2" name: "centos7.qcow2" pool: "default" size: <computed> source: "./CentOS-7-x86_64-GenericCloud.qcow2" Plan: 2 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes
按"是"确认执行。
以下是我的Terraform执行输出。
libvirt_volume.centos7-qcow2: Creating... format: "" => "qcow2" name: "" => "db.qcow2" pool: "" => "default" size: "" => "<computed>" source: "" => "./CentOS-7-x86_64-GenericCloud.qcow2" libvirt_volume.centos7-qcow2: Creation complete after 8s (ID: /var/lib/libvirt/images/db.qcow2) libvirt_domain.db1: Creating... arch: "" => "<computed>" console.#: "" => "1" console.0.target_port: "" => "0" console.0.target_type: "" => "serial" console.0.type: "" => "pty" disk.#: "" => "1" disk.0.scsi: "" => "false" disk.0.volume_id: "" => "/var/lib/libvirt/images/db.qcow2" emulator: "" => "<computed>" graphics.#: "" => "1" graphics.0.autoport: "" => "true" graphics.0.listen_address: "" => "127.0.0.1" graphics.0.listen_type: "" => "address" graphics.0.type: "" => "spice" machine: "" => "<computed>" memory: "" => "1024" name: "" => "db1" network_interface.#: "" => "1" network_interface.0.addresses.#: "" => "<computed>" network_interface.0.hostname: "" => "<computed>" network_interface.0.mac: "" => "<computed>" network_interface.0.network_id: "" => "<computed>" network_interface.0.network_name: "" => "default" qemu_agent: "" => "false" running: "" => "true" vcpu: "" => "1" libvirt_domain.db1: Creation complete after 0s (ID: e5ee28b9-e1da-4945-9eb0-0cda95255937) Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
确认VM创建 virsh
命令。
$sudo virsh list Id Name State --------------------- 7 db1 running
获取实例IP地址。
$sudo virsh net-dhcp-leases default Expiry Time MAC address Protocol IP address Hostname Client ID or DUID ----------------------------------------------------------------------------------------------------------------------------------------------- 2019-03-24 16:11:18 52:54:00:3e:15:9e ipv4 192.168.122.61/24 - 2019-03-24 15:30:18 52:54:00:8f:8c:86 ipv4 192.168.122.198/24 rhel8 ff:61:69:21:bd:00:02:00:00:ab:11:0e:9c:c6:63:ee:7d:c8:d1
我的实例IP是 192.168.122.61
。
我可以ping实例。
$ ping -c 1 192.168.122.61 PING 192.168.122.61 (192.168.122.61) 56(84) bytes of data. 64 bytes from 192.168.122.61: icmp_seq=1 ttl=64 time=0.517 ms --- 192.168.122.61 ping statistics -- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.517/0.517/0.517/0.000 ms
要摧毁基础架构,请运行:
terraform destroy
使用带有Terraform LibVirt提供程序的Cloud-Init
我们使用的实例资源没有通过用户密码的选项。
因此,如果我们使用不支持密码身份验证的云模板,则无法登录。
幸运的是,我们可以使用libvirt_cloudinit_disk资源将用户数据传递给实例。
创建Cloud Init配置文件。
$cat cloud_init.cfg #cloud-config # vim: syntax=yaml ## ** **** **** **** **** ***** # ---- for more examples look at: ----- # ---> https://cloudinit.readthedocs.io/en/latest/topics/examples.html # ** **** **** **** **** **** **** **** ## This is the configuration syntax that the write_files module # will know how to understand. encoding can be given b64 or gzip or (gz+b64). # The content will be decoded accordingly and then written to the path that is # provided. ## Note: Content strings here are truncated for example purposes. ssh_pwauth: True chpasswd: list: | root: StrongPassword expire: False users: - name: jmutai # Change me ssh_authorized_keys: - ssh-rsa AAAAXX #Chageme sudo: ['ALL=(ALL) NOPASSWD:ALL'] shell: /bin/bash groups: wheel
这将设置root密码 StrongPassword
添加用户名为 jmutai
使用指定的公共SSH键键将用户添加到Whee组,并允许在没有密码的情况下运行sudo命令。
编辑 libvirt.tf
使用Cloud Init配置文件。
provider "libvirt" { uri = "qemu:///system" } #provider "libvirt" { # alias = "server2" # uri = "qemu+ssh://Hyman@theitroad/system" #} resource "libvirt_volume" "centos7-qcow2" { name = "db.qcow2" pool = "default" #source = "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2" source = "./CentOS-7-x86_64-GenericCloud.qcow2" format = "qcow2" } data "template_file" "user_data" { template = "${file("${path.module}/cloud_init.cfg")}" } # Use CloudInit to add the instance resource "libvirt_cloudinit_disk" "commoninit" { name = "commoninit.iso" user_data = "${data.template_file.user_data.rendered}" } # Define KVM domain to create resource "libvirt_domain" "db1" { name = "db1" memory = "1024" vcpu = 1 network_interface { network_name = "default" } disk { volume_id = "${libvirt_volume.centos7-qcow2.id}" } cloudinit = "${libvirt_cloudinit_disk.commoninit.id}" console { type = "pty" target_type = "serial" target_port = "0" } graphics { type = "spice" listen_type = "address" autoport = true } } # Output Server IP output "ip" { value = "${libvirt_domain.db1.network_interface.0.addresses.0}" }
重新初始化Terraform Working目录。
$terraform init Initializing provider plugins... - Checking for available provider plugins on https://releases.hashicorp.com... - Downloading plugin for provider "template" (2.1.0)... The following providers do not have any version constraints in configuration, so the latest version was installed. To prevent automatic upgrades to new major versions that Jan contain breaking changes, it is recommended to add version = "..." constraints to the corresponding provider blocks in configuration, with the constraint strings suggested below. * provider.template: version = "~> 2.1" Terraform has been successfully initialized! You Jan 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 terraform apply
注意屏幕上打印的服务器IP。
或者使用 virsh
命令以获取服务器IP地址。
$sudo virsh net-dhcp-leases default Expiry Time MAC address Protocol IP address Hostname Client ID or DUID -------------------------------------------------------------------------------------------------------- 2019-03-24 16:41:32 52:54:00:22:45:57 ipv4 192.168.122.219/24 -
尝试以root用户和密码设置登录实例。
检查是否创建的SSH用户可以使用ssh键登录并在没有密码的情况下运行sudo。
$ssh Hyman@theitroad The authenticity of host '192.168.122.219 (192.168.122.219)' can't be established. ECDSA key fingerprint is SHA256:G8ByhT4+FXBzh/MabB67rcS6JpTUn1TcrusXhiy8ke0. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.122.219' (ECDSA) to the list of known hosts. [Hyman@theitroad ~]$sudo su Last login: Sun Mar 24 13:16:46 UTC 2019 on tty1 [Hyman@theitroad ~]#