Я хотел изучить Kubernetes и DevOps. Для построения кластера Kubernetes требуется не менее 3 виртуальных машин, чтобы автоматизировать процесс развертки VDS я решил воспользоваться Terraform. В своем последнем посте я писал о том, как создать шаблон cloud-init Ubuntu для Proxmox. В этом посте мы возьмем этот шаблон и используем его для развертывания пары виртуальных машин с помощью автоматизации Terraform. Если у вас нет шаблона, он понадобится вам, прежде чем продолжить.
Обзор
- Установить Terraform
- Определите метод аутентификации для Terraform для взаимодействия с Proxmox (ключи user / pass vs API)
- Базовая инициализация Terraform и установка провайдера
- Разработать план Terraform
- План терраформирования
- Запустите Terraform plan и наблюдайте за появлением виртуальных машин!
Ссылка на видео на Youtube
Если вы предпочитаете видео-версии, пожалуйста, перейдите по ссылке https://youtu.be/UXXIl421W8g, чтобы посмотреть видео в реальном времени о том, как я развертываю виртуальные машины в Proxmox с использованием Terraform, и почему мы выполняем каждую команду.
1 – Установить Terraform
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=$(dpkg --print-architecture)] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt update
sudo apt install terraform
2 – Определение метода аутентификации (использование ключей API)
Здесь у вас есть два варианта:
- Имя пользователя / пароль – вы можете использовать существующего пользователя root по умолчанию и пароль root здесь, чтобы упростить задачу … или
- Ключи API – это включает в себя настройку нового пользователя, предоставление этому новому пользователю необходимых разрешений, а затем настройку ключей API, чтобы пользователю не приходилось вводить пароль для выполнения действий
Я выбрал метод API key, поскольку нежелательно, чтобы ваш пароль root хранился в файлах Terraform (даже в качестве переменной окружения — не лучшая идея). Я действительно не знал, что делаю, и в любом случае фактически предоставил новому пользователю полные права администратора. Должен ли я заблокировать его? Конечно. Знаю ли я, какие минимально необходимые разрешения для этого? Нет. Если кто-нибудь в комментариях или на Reddit сможет просветить меня, я был бы очень признателен!
Итак, нам нужно создать нового пользователя. Мы назовем его ‘blog_example’. Чтобы добавить нового пользователя, перейдите в Datacenter на левой вкладке, затем Permissions -> Users -> Нажмите add (Разрешения -> Пользователи -> Добавить), назовите пользователя и нажмите Добавить.
Далее нам нужно добавить токены API. Щелкните токены API под пользователями в категории разрешений и нажмите Добавить. Выберите пользователя, которого вы только что создали, и присвоите токену идентификатор, а также снимите флажок разделение привилегий (это означает, что мы хотим, чтобы токен имел те же разрешения, что и пользователь):
Когда вы нажмете Добавить, вам будет показан ключ. Сохраните этот ключ. Он больше никогда не будет отображаться!
Далее нам нужно добавить роль новому пользователю. Permissions -> Add -> Path = ‘/’ (Разрешения -> Добавить -> Путь = ‘/’), Пользователь — это тот, которого вы только что создали, роль = ‘PVEVMAdmin’. Это дает пользователю (и связанный с ним токен API!) права на все узлы (путь / for) для выполнения действий VMAdmin:
Вам также необходимо добавить разрешения для хранилища, используемого виртуальными машинами, которые вы хотите развернуть (как из, так и в), для меня это /storage/local-zfs (для вас может быть /storage / local-lvm). Добавьте это тоже в раздел path . Используйте здесь роль администратора, потому что пользователю также нужна возможность выделять место в хранилище данных (вы могли бы использовать PVEVMAdmin + роль хранилища данных, но я еще не определился, какую именно):
На этом мы закончили с разрешениями:
Пришло время обратиться к Terraform.
3 – Основная информация о Terraform и установке провайдера
Terraform состоит из трех основных этапов: инициализация, планирование и применение. Мы начнем с описания планов, которые можно представить как тип файла конфигурации для того, что вы хотите сделать. Планы — это файлы, хранящиеся в каталогах. Создайте новый каталог (terraform-блог) и создайте два файла: main.tf и vars.tf:
cd ~
mkdir terraform-blog && cd terraform-blog
touch main.tf vars.tf
Мы надеемся, что у двух файлов разумные названия. Основное содержимое будет в main.tf и мы добавим несколько переменных в vars.tf. Все может войти в систему main.tf но хорошей практикой является раннее разделение функций. На самом деле у меня не так много информации, как следовало бы vars.tf но все мы должны с чего-то начинать
Хорошо, итак, в main.tf давайте добавим минимум. Нам нужно сообщить Terraform, чтобы она использовала провайдера, этот термин они используют для обозначения соединителя с объектом, с которым Terraform будет взаимодействовать. Поскольку мы используем Proxmox, нам нужно использовать провайдера Proxmox. На самом деле это очень просто – нам просто нужно указать имя и версию, и Terraform берет их с github и устанавливает. Я использовал провайдера Telmate Proxmox.
main.tf:
terraform {
required_providers {
proxmox = {
source = "telmate/proxmox"
version = "2.7.4"
}
}
}
Сохраните файл. Теперь мы инициализируем Terraform нашим базовым планом (terraform init), который заставит его выйти и захватить провайдера. Если все пройдет хорошо, нам сообщат, что провайдер установлен и Terraform инициализирован. Terraform также действительно хорош тем, что сообщает вам следующий шаг в нижней части выходных данных (“попробуйте запустить ‘terraform plan’ next”).
austin@EARTH:/mnt/c/Users/Austin/terraform-blog$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding telmate/proxmox versions matching "2.7.4"...
- Installing telmate/proxmox v2.7.4...
- Installed telmate/proxmox v2.7.4 (self-signed, key ID A9EBBE091B35AFCE)
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.
4 – Разработка плана Terraform
Хорошо, когда провайдер установлен, пришло время использовать его для развертывания виртуальной машины. Мы будем использовать шаблон, созданный в предыдущем посте (Как создать Proxmox Ubuntu cloud-init image). Измените ваш main.tf файл следующим образом. Я разбиваю это внутри файла с комментариями
terraform {
required_providers {
proxmox = {
source = "telmate/proxmox"
version = "2.7.4"
}
}
}
provider "proxmox" {
# url is the hostname (FQDN if you have one) for the proxmox host you'd like to connect to to issue the commands. my proxmox host is 'prox-1u'. Add /api2/json at the end for the API
pm_api_url = "https://prox-1u:8006/api2/json"
# api token id is in the form of: <username>@pam!<tokenId>
pm_api_token_id = "blog_example@pam!new_token_id"
# this is the full secret wrapped in quotes. don't worry, I've already deleted this from my proxmox cluster by the time you read this post
pm_api_token_secret = "9ec8e608-d834-4ce5-91d2-15dd59f9a8c1"
# leave tls_insecure set to true unless you have your proxmox SSL certificate situation fully sorted out (if you do, you will know)
pm_tls_insecure = true
}
# resource is formatted to be "[type]" "[entity_name]" so in this case
# we are looking to create a proxmox_vm_qemu entity named test_server
resource "proxmox_vm_qemu" "test_server" {
count = 1 # just want 1 for now, set to 0 and apply to destroy VM
name = "test-vm-${count.index + 1}" #count.index starts at 0, so + 1 means this VM will be named test-vm-1 in proxmox
# this now reaches out to the vars file. I could've also used this var above in the pm_api_url setting but wanted to spell it out up there. target_node is different than api_url. target_node is which node hosts the template and thus also which node will host the new VM. it can be different than the host you use to communicate with the API. the variable contains the contents "prox-1u"
target_node = var.proxmox_host
# another variable with contents "ubuntu-2004-cloudinit-template"
clone = var.template_name
# basic VM settings here. agent refers to guest agent
agent = 1
os_type = "cloud-init"
cores = 2
sockets = 1
cpu = "host"
memory = 2048
scsihw = "virtio-scsi-pci"
bootdisk = "scsi0"
disk {
slot = 0
# set disk size here. leave it small for testing because expanding the disk takes time.
size = "10G"
type = "scsi"
storage = "local-zfs"
iothread = 1
}
# if you want two NICs, just copy this whole network section and duplicate it
network {
model = "virtio"
bridge = "vmbr0"
}
# not sure exactly what this is for. presumably something about MAC addresses and ignore network changes during the life of the VM
lifecycle {
ignore_changes = [
network,
]
}
# the ${count.index + 1} thing appends text to the end of the ip address
# in this case, since we are only adding a single VM, the IP will
# be 10.98.1.91 since count.index starts at 0. this is how you can create
# multiple VMs and have an IP assigned to each (.91, .92, .93, etc.)
ipconfig0 = "ip=10.98.1.9${count.index + 1}/24,gw=10.98.1.1"
# sshkeys set using variables. the variable contains the text of the key.
sshkeys = <<EOF
${var.ssh_key}
EOF
}
Здесь много чего происходит. Надеюсь, встроенные комментарии все объяснят. Если нет, дайте мне знать в комментариях или на Reddit (u / Nerdy-Austin).
Теперь перейдем к файлу vars.tf. Это немного проще для понимания. Просто объявите переменную, дайте ей имя и значение по умолчанию. Это все, что я знаю на данный момент, и это работает.
variable "ssh_key" {
default = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcwZAOfqf6E6p8IkrurF2vR3NccPbMlXFPaFe2+Eh/8QnQCJVTL6PKduXjXynuLziC9cubXIDzQA+4OpFYUV2u0fAkXLOXRIwgEmOrnsGAqJTqIsMC3XwGRhR9M84c4XPAX5sYpOsvZX/qwFE95GAdExCUkS3H39rpmSCnZG9AY4nPsVRlIIDP+/6YSy9KWp2YVYe5bDaMKRtwKSq3EOUhl3Mm8Ykzd35Z0Cysgm2hR2poN+EB7GD67fyi+6ohpdJHVhinHi7cQI4DUp+37nVZG4ofYFL9yRdULlHcFa9MocESvFVlVW0FCvwFKXDty6askpg9yf4FnM0OSbhgqXzD austin@EARTH"
}
variable "proxmox_host" {
default = "prox-1u"
}
variable "template_name" {
default = "ubuntu-2004-cloudinit-template"
}
5 – План терраформирования (официальный термин, обозначающий “что Terraform будет делать дальше”)
Теперь, когда файлы .tf завершены, мы можем запустить план (terraform plan). Мы определили ресурс count = 1, поэтому мы ожидаем, что Terraform создаст единственную виртуальную машину. Пусть Terraform ознакомится с планом и расскажет нам, что она намерена делать. Это говорит нам о многом.
austin@EARTH:/mnt/c/Users/Austin/terraform-blog$ terraform plan
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:
# proxmox_vm_qemu.test_server[0] will be created
+ resource "proxmox_vm_qemu" "test_server" {
+ additional_wait = 15
+ agent = 1
+ balloon = 0
+ bios = "seabios"
+ boot = "cdn"
+ bootdisk = "scsi0"
+ clone = "ubuntu-2004-cloudinit-template"
+ clone_wait = 15
+ cores = 2
+ cpu = "host"
+ default_ipv4_address = (known after apply)
+ define_connection_info = true
+ force_create = false
+ full_clone = true
+ guest_agent_ready_timeout = 600
+ hotplug = "network,disk,usb"
+ id = (known after apply)
+ ipconfig0 = "ip=10.98.1.91/24,gw=10.98.1.1"
+ kvm = true
+ memory = 2048
+ name = "test-vm-1"
+ nameserver = (known after apply)
+ numa = false
+ onboot = true
+ os_type = "cloud-init"
+ preprovision = true
+ reboot_required = (known after apply)
+ scsihw = "virtio-scsi-pci"
+ searchdomain = (known after apply)
+ sockets = 1
+ ssh_host = (known after apply)
+ ssh_port = (known after apply)
+ sshkeys = <<-EOT
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcwZAOfqf6E6p8IkrurF2vR3NccPbMlXFPaFe2+Eh/8QnQCJVTL6PKduXjXynuLziC9cubXIDzQA+4OpFYUV2u0fAkXLOXRIwgEmOrnsGAqJTqIsMC3XwGRhR9M84c4XPAX5sYpOsvZX/qwFE95GAdExCUkS3H39rpmSCnZG9AY4nPsVRlIIDP+/6YSy9KWp2YVYe5bDaMKRtwKSq3EOUhl3Mm8Ykzd35Z0Cysgm2hR2poN+EB7GD67fyi+6ohpdJHVhinHi7cQI4DUp+37nVZG4ofYFL9yRdULlHcFa9MocESvFVlVW0FCvwFKXDty6askpg9yf4FnM0OSbhgqXzD austin@EARTH
EOT
+ target_node = "prox-1u"
+ unused_disk = (known after apply)
+ vcpus = 0
+ vlan = -1
+ vmid = (known after apply)
+ disk {
+ backup = 0
+ cache = "none"
+ file = (known after apply)
+ format = (known after apply)
+ iothread = 1
+ mbps = 0
+ mbps_rd = 0
+ mbps_rd_max = 0
+ mbps_wr = 0
+ mbps_wr_max = 0
+ media = (known after apply)
+ replicate = 0
+ size = "10G"
+ slot = 0
+ ssd = 0
+ storage = "local-zfs"
+ storage_type = (known after apply)
+ type = "scsi"
+ volume = (known after apply)
}
+ network {
+ bridge = "vmbr0"
+ firewall = false
+ link_down = false
+ macaddr = (known after apply)
+ model = "virtio"
+ queues = (known after apply)
+ rate = (known after apply)
+ tag = -1
}
}
Plan: 1 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.
Вы можете увидеть результаты этапа планирования Terraform. В нем сообщается, что будет создан proxmox_vm_qemu.test_server[0] со списком параметров. Здесь вы можете перепроверить IP-адрес, а также остальные базовые настройки. Внизу краткое описание – “План: 1 добавить, 0 изменить, 0 уничтожить”. Также обратите внимание, что это снова говорит нам, какой шаг выполнить следующим – “terraform apply”.
6 – Выполните план Terraform и наблюдайте за появлением виртуальных машин!
Получив краткое изложение того, что мы хотим, теперь мы можем применить план (terraform apply). Обратите внимание, что после определения характера изменений вам будет предложено ввести «да», чтобы применить изменения. Обычно для создания моих виртуальных машин требуется 1 15 секунд + / -15 секунд.
Если все пройдет хорошо, вам сообщат, что добавлен 1 ресурс!
Команда и полный вывод:
austin@EARTH:/mnt/c/Users/Austin/terraform-blog$ terraform apply
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:
# proxmox_vm_qemu.test_server[0] will be created
+ resource "proxmox_vm_qemu" "test_server" {
+ additional_wait = 15
+ agent = 1
+ balloon = 0
+ bios = "seabios"
+ boot = "cdn"
+ bootdisk = "scsi0"
+ clone = "ubuntu-2004-cloudinit-template"
+ clone_wait = 15
+ cores = 2
+ cpu = "host"
+ default_ipv4_address = (known after apply)
+ define_connection_info = true
+ force_create = false
+ full_clone = true
+ guest_agent_ready_timeout = 600
+ hotplug = "network,disk,usb"
+ id = (known after apply)
+ ipconfig0 = "ip=10.98.1.91/24,gw=10.98.1.1"
+ kvm = true
+ memory = 2048
+ name = "test-vm-1"
+ nameserver = (known after apply)
+ numa = false
+ onboot = true
+ os_type = "cloud-init"
+ preprovision = true
+ reboot_required = (known after apply)
+ scsihw = "virtio-scsi-pci"
+ searchdomain = (known after apply)
+ sockets = 1
+ ssh_host = (known after apply)
+ ssh_port = (known after apply)
+ sshkeys = <<-EOT
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcwZAOfqf6E6p8IkrurF2vR3NccPbMlXFPaFe2+Eh/8QnQCJVTL6PKduXjXynuLziC9cubXIDzQA+4OpFYUV2u0fAkXLOXRIwgEmOrnsGAqJTqIsMC3XwGRhR9M84c4XPAX5sYpOsvZX/qwFE95GAdExCUkS3H39rpmSCnZG9AY4nPsVRlIIDP+/6YSy9KWp2YVYe5bDaMKRtwKSq3EOUhl3Mm8Ykzd35Z0Cysgm2hR2poN+EB7GD67fyi+6ohpdJHVhinHi7cQI4DUp+37nVZG4ofYFL9yRdULlHcFa9MocESvFVlVW0FCvwFKXDty6askpg9yf4FnM0OSbhgqXzD austin@EARTH
EOT
+ target_node = "prox-1u"
+ unused_disk = (known after apply)
+ vcpus = 0
+ vlan = -1
+ vmid = (known after apply)
+ disk {
+ backup = 0
+ cache = "none"
+ file = (known after apply)
+ format = (known after apply)
+ iothread = 1
+ mbps = 0
+ mbps_rd = 0
+ mbps_rd_max = 0
+ mbps_wr = 0
+ mbps_wr_max = 0
+ media = (known after apply)
+ replicate = 0
+ size = "10G"
+ slot = 0
+ ssd = 0
+ storage = "local-zfs"
+ storage_type = (known after apply)
+ type = "scsi"
+ volume = (known after apply)
}
+ network {
+ bridge = "vmbr0"
+ firewall = false
+ link_down = false
+ macaddr = (known after apply)
+ model = "virtio"
+ queues = (known after apply)
+ rate = (known after apply)
+ tag = -1
}
}
Plan: 1 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
proxmox_vm_qemu.test_server[0]: Creating...
proxmox_vm_qemu.test_server[0]: Still creating... [10s elapsed]
proxmox_vm_qemu.test_server[0]: Still creating... [20s elapsed]
proxmox_vm_qemu.test_server[0]: Still creating... [30s elapsed]
proxmox_vm_qemu.test_server[0]: Still creating... [40s elapsed]
proxmox_vm_qemu.test_server[0]: Still creating... [50s elapsed]
proxmox_vm_qemu.test_server[0]: Still creating... [1m0s elapsed]
proxmox_vm_qemu.test_server[0]: Creation complete after 1m9s [id=prox-1u/qemu/142]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Теперь проверьте Proxmox и посмотрите, была ли создана ваша виртуальная машина:
Успех! Теперь вы должны иметь возможность подключаться к новой виртуальной машине по SSH с помощью уже предоставленного вами ключа (примечание: имя пользователя будет «ubuntu», а не то, что вы указали в своем ключе).
Удаление тестовой виртуальной машины
Я просто устанавливаю значение 0 для ресурса в файле main.tf и применяю, и виртуальная машина останавливается и уничтожается.
Заключение
Это краткое руководство по использованию Terraform для развертывания виртуальных машин в Proxmox, но, оглядываясь назад, можно сказать, что в нем достаточно много деталей. Мне потребовалось довольно много времени, чтобы разобраться с проблемами разрешений, недопустимостью имен хостов (оказывается, в именах хостов нельзя использовать символы подчеркивания (_), на поиск которых ушел час), назначением ролей пользователям в сравнении с соответствующими ключами API и т.д. но я рад, что проработал все и могу передать это дальше. Скоро увидите мой следующий пост о использовании Terraform для развертывания полного набора машин Kubernetes в кластере Proxmox (и захватывающее продолжение этого поста, использование Ansible для начальной загрузки кластера Kubernetes)!