Предположим уже есть некий настроенный хост с libvirt и 2мя сетевыми интерфейсами.
Первая br0 смотрит в интернет, вторая br1 в локальную сеть.
На внутреннем интерфейсе статичный ип-адрес 10.0.0.1
.
По мануалке
создадим файлик main.tf
и напишем в него так:
terraform {
required_providers {
libvirt = {
source = "dmacvicar/libvirt"
version = "~> 0.6.14"
}
}
}
provider "libvirt" {
uri = "qemu+ssh://root@10.0.0.1/system"
}
Если во время terraform init
будет “подвисать”, то можно настроить
зеркало
в ~/.terraformrc
.
Далее нужно узнать id
сетевых интерфейсов и хранилищ в libvirt. Пусть нам libvirt об этом расскажет.
Для сетевых интерфейсов:
virsh net-info br0;
virsh net-info br1;
Для пулов:
virsh pool-info default
Нужно запомнить строки Name
и UUID
.
Далее создадим файлик сетевых ресурсов libvirt_network.tf
с содержимым:
resource "libvirt_network" "br0" {
}
resource "libvirt_network" "br1" {
}
И для ресурсов дискового пространства libvirt_pool.tf
:
resource "libvirt_pool" "default" {
}
Теперь можно импортировать ресурсы. UUID берем из предыдущих virsh-команд:
terraform import libvirt_network.br0 <UUID>
terraform import libvirt_network.br1 <UUID>
terraform import libvirt_pool.default <UUID>
Чтож, теперь существующие ресурсы libvirt импортированы в статус terraform.
Теперь нужно записать их в конфигурационные файлы.
Команда terraform state list
покажет существующие в terraform ресурсы.
Команда terraform state show libvirt_network.br0
покажет содержимое ресурса.
Перенести можно примерно такой командой:
terraform state show libvirt_network.br0 | sed 's/id/#id/' > libvirt_network.tf
terraform state show libvirt_network.br1 | sed 's/id/#id/' >> libvirt_network.tf
id комментируется, так как оно не может хранится в конфиг-файле. Аналгично перенесем pool:
terraform state show libvirt_pool.default | sed 's/id/#id/' > libvirt_pool.tf
Ура. Ресурсы в конфиг-файлах. Настало время объявить свои ресурсы, создать виртуальные машины в libvirt при помощи terraform.
То достаточно посмотреть список при помощи:
terraform state list
libvirt_network.br0
libvirt_network.br1
libvirt_pool.default
и удалить ненужный
terraform state rm <name>
и затем удалить/переименовать/закоментировать соответсвующие файлы. Эта команда удалит именно из terraform.
Далее берется некий cloud
-образ, образ диска с уже установленным дистрибутивом.
Запишем в файлик upstream_debian_volume.tf
такое:
resource "libvirt_volume" "debian-11-upstream" {
name = "debian-11-upstream.qcow2"
pool = "default"
source = "https://cloud.debian.org/images/cloud/bullseye/20221020-1174/debian-11-genericcloud-amd64-20221020-1174.qcow2"
format = "qcow2"
}
Тут лучше использовать ссылку на конкретный образ нежели чем latest
.
Со временем можно обновлять по необходимости. terraform apply
выкачает образ.
Далее настроим виртуальную машину. Роутер для маршрутизации в докер. В вашем случае такое может не понадобится. Всё нижеследующее просто для примера
Напишем файл swarmgw.tf
. Ниже я разберу его по частям.
# resize hdd
resource "libvirt_volume" "swarmgw" {
name = "swarmgw.qcow2"
base_volume_id = libvirt_volume.debian-11-upstream.id
pool = "default"
size = 3221225472 # 3GB
}
Объявляется ресурс libvirt_volume
swarmgw
(это в контексте terraform).
Физически же он ляжет в пул default
под именем swarmgw.qcow2
.
Для этого апстримный образ и увеличится размер диска до 3GB (размер указывается в байтах).
Размер не может быть уменьшен.
Далее идут команды после старта системы
resource "libvirt_cloudinit_disk" "init-swarmgw" {
name = "init-swarmgw.iso"
pool = "iso"
user_data = <<EOF
#cloud-config
growpart:
mode: auto
device: ['/']
users:
- name: <user_name>
lock_passwd: true
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
write_files:
- path: /etc/systemd/network/ens3.network
content: |
[Match]
Name=ens3
[Network]
DHCP=ipv4
- path: /etc/systemd/network/ens4.network
content: |
[Match]
Name=ens4
[Network]
Address=10.0.0.120/24
- path: /home/alex/.ssh/authorized_keys
content: |
ssh-rsa <user_public_key>
package_update: true
hostname: swarmgw
runcmd:
- DEBIAN_FRONTEND=noninteractive apt install -y qemu-guest-agent iptables-persistent
- systemctl disable ifup@ens3 ifup@ens4
- systemctl disable ifupdown-pre
- DEBIAN_FRONTEND=noninteractive apt remove -y ifupdown resolvconf
- systemctl disable networking
- systemctl disable cloud-init-local cloud-init cloud-config cloud-final
- systemctl enable systemd-networkd
- systemctl enable systemd-resolved
- ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
- sed -i /etc/systemd/resolved.conf -e 's/#DNSSEC=no/DNSSEC=yes/' -e 's/#MulticastDNS=yes/MulticastDNS=no/' -e 's/#LLMNR=yes/LLMNR=no/'
- sed -i /etc/ssh/sshd_config -e 's/#AddressFamily any/AddressFamily inet/' -e 's/#ListenAddress 0.0.0.0/ListenAddress 10.0.0.120/'
- sed -i /etc/default/chrony -e 's/DAEMON_OPTS="-F 1"/DAEMON_OPTS="-4 -F 1"/'
- echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
- iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
- iptables -A FORWARD -i ens3 -o ens4 -m state --state ESTABLISHED,RELATED -j ACCEPT
- iptables-save > /etc/iptables/rules.v4
- reboot
EOF
}
Для полного понимая нужно посмотреть на
документацию
Основное - заменить всё что внутри <>
(узернэйм и его публичный ключ),
growpart
- расширяет файловую систему после увеличения диска,
users
- создает пользователя,
а lock_passwd
блокирует логин по паролю (у рут пользователя так же заблокирован пароль).
Далее я просто делаю минимальные настройки операционной системы и настраиваю простой nat.
Ниже объявление самой виртуальной машины (ну то что мы обычно кликаем в интерфейсе пользователя - память, цпу, …).
resource "libvirt_domain" "swarmgw" {
name = "swarmgw"
memory = "456"
vcpu = 1
qemu_agent = true
running = true
cloudinit = libvirt_cloudinit_disk.init-swarmgw.id
cpu {
mode = "host-passthrough"
}
video {
type = "qxl"
}
network_interface {
network_id = libvirt_network.br0.id
}
network_interface {
network_id = libvirt_network.br1.id
}
boot_device {
dev = [ "hd" ]
}
console {
type = "pty"
target_port = "0"
target_type = "serial"
}
disk {
volume_id = libvirt_volume.swarmgw.id
}
}
После terraform apply создастся 3 ресурса, виртуальная машина, диск, и iso-образ.
Посмотреть их можно как обычно в terraform state list
:
libvirt_cloudinit_disk.init-swarmgw
libvirt_domain.swarmgw
libvirt_volume.swarmgw
Удалить виртуальную машину можно через terraform destroy --target <ресурс>
.
Эта команда удалит из терраформ и из libvirt.
На этом всё. Продолжение следует…