Как создать 100 серверов в облаке за минуту? Работа с OpenStack клиентом
Как CLI-инструменты в связке с shell-автоматизацией помогают экономить время? Разбираемся на практике.
Для управления облачной инфраструктурой в индустрии накопилось достаточно много инструментов: Terraform, Pulumi, Ansible, управление через SDK или напрямую через REST API. При этом часто упускают из виду CLI инструменты в связке с shell-автоматизацией. А зря! Они помогают экономить время, которое тратится на ручное создание серверов или изучение сложных инструментов.
Привет! Я — Алексей, инженер в Selectel. Написал эту статью в форме небольшого воркшопа, чтобы можно было читать и повторять.
Задача
Итак, предположим, что нам нужно создать пачку серверов для каких-то тестов или калькуляций. Можно только предположить, сколько времени потратится на ручное создание серверов через панель управления и сколько будет допущено ошибок из-за человеческого фактора.
А с помощью CLI клиента OpenStack можно создать наши условные 100 серверов одной командой:
openstack server create --image "Ubuntu 22.04 LTS 64-bit" --network my_network --flavor SL1.1-2048-16 --max 100 my_server
Собственно, все. На этом можно закончить статью. Но для тех, кому интересно, что тут происходит и как работать с CLI, рассмотрим происходящее более подробно.
Знакомство с OpenStack CLI
Сразу оговорка — создание виртуальной машины (сервера, инстанса) с локальным диском отличается от создания ВМ с сетевым диском. В первом случае локальный диск является частью Flavor-а, а из образа диска сразу создается ВМ. Во втором — из образа диска делается вольюм, а он передается при создании ВМ.
Давайте представим исходную ситуацию: у вас есть пустой проект в облачной платформе Selectel. И работать мы будем с консольным инструментом OpenStack CLI.
Подготовительные этапы:
- установить OpenStack клиент,
- добавить сервисного пользователя с ролью администратора проекта,
- скачать RC-файл на компьютер с OpenStack клиентом.
Загружаем RC-файл с переменными окружения, необходимыми для авторизации OpenStack клиента. Работа с указанным выше RC-файлом предполагает введение пароля из консоли. Можно отредактировать файл и прописать пароль в файле, чтобы не вводить его каждый раз при инициализации переменных окружений. Но это не совсем безопасно.
Активируем переменные окружения:
source rc.sh
Базово создать один сервер с локальным диском можно следующей командой:
openstack server create --image 'Ubuntu 22.04 LTS 64-bit' --network my_network --flavor SL1.1-2048-16 my_server
Необходимые аргументы:
- image — исходный образ диска, из которого создаётся ВМ,
- flavor — объект, содержащий конфигурацию ВМ,
- network — сеть, в которой создается ВМ.
С сетевым диском алгоритм будет чуть другой — такой пример рассмотрим далее, а пока упростим себе задачу и будем работать с локальным диском.
OpenStack состоит из нескольких компонентов, отвечающих за свою часть работы и предоставляющих собственные эндпоинты. При работе с клиентом мы можем об этом не думать, т. к. он сделает все за нас. Но хочется выделить логические блоки для понимания концепций:
- Keystone — сервис авторизации и получения эндпоинтов компонентов и регионов,
- Nova (Compute) — сервис для создания ВМ (серверов, инстансов),
- Neutron (Network) — сервис по управлению сетевыми ресурсами,
- Glance (Images) — сервис для хранения образов (с ОС), из которых создаётся непосредственно сама ВМ или Volume,
- Cinder (Volume) — сетевые диски.
Практика
Перейдем к практике и через CLI поработаем с объектами образов, сети и Flavor-а.
Получаем список образов:
openstack image list
Пример использования (вывод обрезан для более удобного отображения):
openstack image list
+--------------------------------------+------------------------------------------+--------+
| ID | Name | Status |
+--------------------------------------+------------------------------------------+--------+
| 41383415-4c61-46e5-8cc4-ead5a6f78cf8 | CentOS 7 64-bit | active |
| 159f6bfa-d2fd-4d90-b2cc-e19d8aeafd22 | CentOS 7 Minimal 64-bit | active |
| 49653158-53a4-4cfe-95e0-b70509e6c1ac | CentOS 8 64-bit | active |
| 0b6fb188-0df5-46cf-9111-2840195df219 | CentOS 8 Stream 64-bit | active |
| a1b081d7-9eff-44b0-8d3f-85fabf2c88a6 | CentOS 9 Stream 64-bit | active |
| 7a827898-058b-4faf-bf8a-0d2311bef7c3 | Ubuntu 20.04 LTS 64-bit | active |
| 1fd341e8-82c2-4421-8a37-912cd5ee3ae3 | Ubuntu 22.04 LTS 64-bit | active |
......
+--------------------------------------+------------------------------------------+--------+
Получаем список Flavor-ов.
В OpenStack при создании ВМ необходимо передать идентификатор объекта Flavor. Можно считать это конфигурацией сервера — память, диск, количество CPU.
Смотрим доступные Flavor-ы.
openstack flavor list
Пример команды. Вывод обрезан.
openstack flavor list
+--------------------------------------+------------------------------------+--------+------+-----------+-------+-----------+
| ID | Name | RAM | Disk | Ephemeral | VCPUs | Is Public |
+--------------------------------------+------------------------------------+--------+------+-----------+-------+-----------+
| 1 | m1.tiny | 512 | 0 | 0 | 1 | True |
| 1011 | SL1.1-1024 | 1024 | 0 | 0 | 1 | True |
| 1012 | SL1.1-2048 | 2048 | 0 | 0 | 1 | True |
| 1013 | SL1.2-4096 | 4096 | 0 | 0 | 2 | True |
| 1014 | SL1.2-8192 | 8192 | 0 | 0 | 2 | True |
| 1015 | SL1.4-16384 | 16384 | 0 | 0 | 4 | True |
| 1016 | SL1.6-32768 | 32768 | 0 | 0 | 6 | True |
| 1017 | SL1.8-32768 | 32768 | 0 | 0 | 8 | True |
| 1018 | SL1.12-49152 | 49152 | 0 | 0 | 12 | True |
| 1019 | SL1.16-65536 | 65536 | 0 | 0 | 16 | True |
| 1020 | SL1.24-98304 | 98304 | 0 | 0 | 24 | True |
| 1311 | SL1.1-1024-8 | 1024 | 8 | 0 | 1 | True |
| 1312 | SL1.1-2048-16 | 2048 | 16 | 0 | 1 | True |
| 1313 | SL1.2-4096-32 | 4096 | 32 | 0 | 2 | True |
| 1314 | SL1.2-8192-64 | 8192 | 64 | 0 | 2 | True |
| 1315 | SL1.4-16384-128 | 16384 | 128 | 0 | 4 | True |
| 1316 | SL1.6-32768-256 | 32768 | 256 | 0 | 6 | True |
| 1317 | SL1.8-32768-384 | 32768 | 384 | 0 | 8 | True |
| 1318 | SL1.12-49152-512 | 49152 | 512 | 0 | 12 | True |
| 1319 | SL1.16-65536-768 | 65536 | 768 | 0 | 16 | True |
| 1320 | SL1.24-98304-1024 | 98304 | 1024 | 0 | 24 | True |
При необходимости можно создать Flavor командой openstack flavor create.
Обратите внимание, что у одних Flavor-ов поле Disc нулевое, а у других со значениями. Для использования flavor с нулевым диском нужно предварительно создать volume (сетевой диск). С ненулевым значением будет использоваться локальный диск.
Для начала создадим приватную сеть:
openstack network create my_network
Создадим в ресурс subnet в созданном network:
openstack subnet create --subnet-range 192.168.0.0/24 --network my_network my_subnet
Ремарка — сейчас не создается роутер и не настраивается маршрутизация. Таким образом, не будет работать «выход» в интернет. Об этом далее.
SSH Keypair
Если сейчас создать сервер, то заходить по SSH можно будет только по паролю. Это может быть неудобно и небезопасно, поэтому добавим публичную часть персонального ssh-ключа в хранилище. Затем можем указывать данный ключ при создании ВМ.
openstack keypair create --public-key ~/.ssh/id_rsa.pub my_keypair
Теперь можно создать наши условные 100 серверов:
openstack server create --image "Ubuntu 22.04 LTS 64-bit" --network my_network --flavor SL1.1-2048-16 --key-name my_keypair --max 100 my_server
Проверим созданные серверы с помощью команды openstack server list:
openstack server list
Пример команды, вывод обрезан.
openstack server list
+--------------------------------------+---------------+--------+--------------------------+-------------------------+---------------+
| ID | Name | Status | Networks | Image | Flavor |
+--------------------------------------+---------------+--------+--------------------------+-------------------------+---------------+
| 031080fa-3aa0-4848-8551-fd1e6f6ec65f | my_server-94 | ACTIVE | my_network=192.168.0.58 | Ubuntu 22.04 LTS 64-bit | SL1.1-2048-16 |
| 03864c9b-6b9b-4bea-8679-93367ca52250 | my_server-87 | ACTIVE | my_network=192.168.0.24 | Ubuntu 22.04 LTS 64-bit | SL1.1-2048-16 |
| 0efb6875-c481-4ec0-bc80-3392d84c89d6 | my_server-82 | ACTIVE | my_network=192.168.0.110 | Ubuntu 22.04 LTS 64-bit | SL1.1-2048-16 |
| 14c1677d-ef4c-4369-a64d-d4be73416eb9 | my_server-67 | ACTIVE | my_network=192.168.0.116 | Ubuntu 22.04 LTS 64-bit | SL1.1-2048-16 |
| 1619eaf7-c7ab-4db0-a875-38c39acabdac | my_server-76 | ACTIVE | my_network=192.168.0.52 | Ubuntu 22.04 LTS 64-bit | SL1.1-2048-16 |
| 1eadae93-f394-4301-a26f-b496f1e023ae | my_server-73 | ACTIVE | my_network=192.168.0.81 | Ubuntu 22.04 LTS 64-bit | SL1.1-2048-16 |
| 218bdd45-01a9-4b49-aa26-fb25ce7f7329 | my_server-80 | ACTIVE | my_network=192.168.0.76 | Ubuntu 22.04 LTS 64-bit | SL1.1-2048-16 |
| 24642e7f-b265-41a4-8d73-c29434655b30 | my_server-84 | ACTIVE | my_network=192.168.0.120 | Ubuntu 22.04 LTS 64-bit | SL1.1-2048-16 |
| 2e0c2dd3-8a07-421f-ba18-067e5fa320d9 | my_server-81 | ACTIVE | my_network=192.168.0.194 | Ubuntu 22.04 LTS 64-bit | SL1.1-2048-16 |
И посчитаем, что 100 серверов в активном состоянии:
openstack server list -f value | grep ACTIVE -c
100
Работа с сетевыми объектами
Мы получили 100 серверов, но как на них зайти и работать с ними? Можно использовать схему с дополнительным bastion-хостом, у которого будет выход в интернет. Заодно познакомимся поближе с сетевой частью.
В сетевую схему нужно добавить роутер, связать его с нашей приватной и внешней сетями, создать плавающий адрес (floating ip, внешний адрес) и привязать данный адрес к ВМ bastion:
openstack router create my_router
openstack router add subnet my_router my_subnet
Чтобы роутер позволял ВМ «выходить» в интернет из приватной сети (в данном случае из my_subnet) через NAT (для установки пакетов, обновления ПО и т.д.), нужно связать роутер с внешней сетью.
Получим имя внешней сети:
openstack network list --external -f value -c Name
external-network
Привяжем внешнюю сеть к роутеру:
openstack router set --external-gateway external-network my_router
Создадим floating IP, в выводе получим адрес:
openstack floating ip create external-network
Посмотреть созданные адреса можно командой:
openstack floating ip list
В моем случае адрес 31.129.42.122, и далее в тексте будет фигурировать именно он. У вас будет другой адрес.
Теперь применим подход с bastion на практике. Выберем, например, первую ВМ как bastion-хост (можно создать отдельно ВМ с более подходящей конфигурацией и хостнеймом, но для упрощения пропустим этот шаг). Через бастион можно будет подключиться ко всем остальным ВМ. В моем случае выберу ВМ 99.
Ассоциируем Floating IP и ВМ 1:
openstack server add floating ip my_server-1 31.129.42.122
Получаем внутренний адрес (адрес из приватной сети 192.168.0.0/24) ВМ 99:
openstack server show my_server-99 -f value -c addresses
{'my_network': ['192.168.0.111']}
В моем случае адрес 192.168.0.111.
Подключимся к ВМ-99 и проверим, что все работает, как и задумывалось:
ssh -J root@31.129.42.122 root@192.168.0.111
root@my-server-99:~#
Работа с сетевыми дисками
Мы уже работали с локальными дисками. Давайте чуть усложним задачу и создадим 100 хостов с сетевыми дисками.
Для начала удалим все текущие ВМ.
Важно: при выполнении следующей команды удалятся все ВМ в текущем проекте. Проверьте, что вы находитесь в нужном проекте.
openstack server list -f value -c ID | xargs -i -P 10 bash -c 'openstack server delete {}'
Сначала нужно создать volume (сетевой диск). В данном случае в API нет инструмента для создания 100 дисков, и нужно обернуть простые shell-команды в циклы.
Можно выполнить их в цикле for i in {1..100}; do COMMAND; done. В таком случае операции будут выполняться по одной. Процесс займет некоторое время, зато будет наглядным. Или можно использовать утилиту xargs для параллельного выполнения.
Для нашего примера используем сгенерированную последовательность от 1 до 100. И в 10 поток (-P 10) выполняем команду по созданию вольюма — {} раскроется xargs’ом в полученный аргумент от seq:
seq 1 100 | xargs -i -P 10 bash -c 'openstack volume create --size 10 --image "Ubuntu 22.04 LTS 64-bit" my_volume_{}'
Для примера давайте создадим свой Flavor:
openstack flavor create --private --disk 0 --vcpus 1 --ram 1024 my_flavor_net_hdd
И в финале создадим 100 ВМ с сетевым диском:
seq 1 100 | xargs -i -P 10 bash -c 'openstack server create --network my_network --key-name my_keypair --flavor my_flavor_net_hdd --volume volume_{} my_server_{}'
Итоги и шпаргалка
Мы рассмотрели, как управлять инфраструктурой, используя CLI инструменты при работе в терминале. А также, разобрали на базовые «кирпичики» автоматизацию более сложных процессов.
openstack keypair create
openstack keypair delete
openstack keypair list
openstack keypair show
openstack server create
openstack server delete
openstack server list
openstack server show
openstack server add floating ip
openstack server remove floating ip
openstack volume create
openstack volume delete
openstack volume list
openstack volume show
openstack router create
openstack router delete
openstack router list
openstack router show
openstack router add subnet
openstack router remove subnet
openstack router add route
openstack router remove route
openstack flavor list
openstack network create
openstack network list
openstack network show
openstack network delete
openstack subnet create
openstack subnet list
openstack subnet show
openstack subnet delete
openstack network list --external
openstack floating ip create
openstack floating ip list
openstack floating ip delete