devops
January 9, 2023

Облако в штанах - OpenStack на локалхосте.

В этой статье я покажу как перестать бояться облаков, начав с разворачивания MicroStack на своём рабочем месте.

Прелесть облака в возможности развернуть инфраструктуру, не отвлекаясь на инфраструктуру (бадум-тсс!). То есть мы не думаем о железе, коммутации и прочих проблемах датацентров. Просто рисуем виртуальную инфраструктуру - бах! - и через мгновение наши сети, сервера и приложения работают, а бизнес получает деньги. IaaS, SaaS, PaaS - вот это вот всё. Однако в чём проблема? В том, что мы персонально не бизнес и платить лишние деньги чтобы разобраться с инструментами иногда выходит накладно (на самом деле и бизнес не всегда может себе это позволить). Поэтому сегодня сэкономим и запустим OpenStack с помощью MicroStack, отточив свои навыки работы с ним.

Почему MicroStack, а не DevStack?

Потому что MicroStack поставляется в виде snap-пакета, который не гадит в систему так, как это делают другие варианты. Например, в руководстве по DevStack прямо сказано, что он вносит существенные изменения в систему, поэтому его лучше всего ставить на выделенную машину, что мне не очень нравится. У MicroStack, конечно, есть свои недостатки и ограничения, но когда до них дойдёт дело, нам, скорее всего, уже можно будет перейти на "взрослый" OpenStack в облаке.

Подготовка

Системные требования

Документация говорит, что нам нужен ноутбук или десктоп на актуальной версии Ubuntu с многоядерным процессором, 8 Гб оперативной памяти и 100 Гб места на диске. Я бы посоветовал иметь минимум 4 ядра, 16 Гб RAM и 250 Гб SSD. Моя система - Ubuntu 22.04.

Установка

Установка производится в две команды. Первая устанавливает snap-пакет, вторая - выполняет инициализацию OpenStack:

sudo snap install microstack --beta
sudo microstack init --auto --control

После неопределённого количества времени (минут 5-10), когда инициализация завершится, можно будет начать пользоваться своим локальным облаком.

Первые шаги

Проверка работоспособности

Первым делом проверяем что на консоль выводится что-нибудь красивое.

  • Посмотрим список доступных образов, с которых можно загрузиться. Их всего один - CirrOS:
microstack.openstack image list
+--------------------------------------+--------+--------+
| ID                                   | Name   | Status |
+--------------------------------------+--------+--------+
| cb8cb539-4659-4161-b158-a455e4653350 | cirros | active |
+--------------------------------------+--------+--------+
  • Посмотрим список доступных вычислительных шаблонов (наборов vCPU, RAM, Disk). Их, к счастью, побольше:
microstack.openstack flavor list
+----+-----------+-------+------+-----------+-------+-----------+
| ID | Name      |   RAM | Disk | Ephemeral | VCPUs | Is Public |
+----+-----------+-------+------+-----------+-------+-----------+
| 1  | m1.tiny   |   512 |    1 |         0 |     1 | True      |
| 2  | m1.small  |  2048 |   20 |         0 |     1 | True      |
| 3  | m1.medium |  4096 |   20 |         0 |     2 | True      |
| 4  | m1.large  |  8192 |   20 |         0 |     4 | True      |
| 5  | m1.xlarge | 16384 |   20 |         0 |     8 | True      |
+----+-----------+-------+------+-----------+-------+-----------+

Красиво, но для первого раза не впечатляет. Посмотрим на великолепный дашборд. Но сначала узнаем пароль администратора:

sudo snap get microstack config.credentials.keystone-password
123xxx123

С этим знанием пойдём изучать интерфейс Horizon по адресу https://10.20.20.1.

Интерфейс Horizon

Можно потыкать тут во все кнопочки и облазить все пункты меню. Собственно отсюда можно и поуправлять облаком, посоздавать инстансы и поделать всё, что мы дальше будем делать в консоли.

Настройка окружения

Пока мы не закрыли браузер, очень важно скачать RC-файл, который позволит настроить переменные окружения в консоли. Делается это через верхнее меню с именем нашего пользователя (admin), нажатием на пункт OpenStack RC file. Скачиваем его и сохраняем где-нибудь на видном месте в своей рабочей директории.

Теперь скачаем openstack-клиент и проверим его работоспособность (обратите внимание на rc-файл)

sudo apt install python3-openstackclient
source ./admin-openrc.sh

openstack --insecure project list
+----------------------------------+---------+
| ID                               | Name    |
+----------------------------------+---------+
| 0f84aee1cf8249978fa551bc403569b5 | admin   |
| 254cec0e7ee8429489e44c445d1352e5 | service |
+----------------------------------+---------+

Из некрасивого - надо вводить пароль администратора при первом запуске admin-openrc.sh и использовать опцию --insecure в openstack-клиенте, чтобы игнорировать самоподписанный сертификат API. Всё это можно поправить.

  • В файле admin-openrc.sh правим строку с export OS_PASSWORD=$OS_PASSWORD_INPUT на export OS_PASSWORD="<пароль администратора>". Не забываем сделать chmod 600 admin-openrc.sh, если вас гложит паранойя на тему светящихся паролей.
  • Импортируем сертификат microstack к себе. Сначала найдём где лежат файлы сертификата
sudo snap get microstack config.tls | awk /pem/'{print $2}'

/var/snap/microstack/common/etc/ssl/certs/cacert.pem
/var/snap/microstack/common/etc/ssl/certs/cert.pem
/var/snap/microstack/common/etc/ssl/private/key.pem
  • Копируем эти файлы к себе в рабочую директорию, не забыв выставить нужные права и владельца, затем добавляем в admin-openrc.sh следующие строки:
export OS_CACERT="./certs/cacert.pem"
export OS_CERT="./certs/cert.pem"
export OS_KEY="./certs/key.pem"

Теперь, если мы снова сделаем source ./admin-openrs.sh, openstack-клиент можно будет запускать без опции --insecure и ввода пароля администратора. У - удобство.

Первый сервер

Наконец, когда комфортной работе с openstack ничего не мешает, можно приступать к утилизации ресурсов. То есть попробовать создать Compute Instance или по-простому - облачную виртуалку, ведь в качестве бэкэнда OpenStack использует гипервизор Qemu KVM.

Сначала создадим новенький проект в котором будем работать. Это сущность, с которой себя будут идентифицировать ресурсы (инстансы, сети, группы безопасности, ролевой доступ и т.п.):

openstack project create MyTest

+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description |                                  |
| domain_id   | default                          |
| enabled     | True                             |
| id          | 5aee210a06d0413983610b543e359d70 |
| is_domain   | False                            |
| name        | MyTest                           |
| options     | {}                               |
| parent_id   | default                          |
| tags        | []                               |
+-------------+----------------------------------+

Разрешим пользователю admin, под которым мы работаем, доступ к созданному проекту, чтобы он мог управлять его ресурсами:

openstack role add --user admin --project MyTest admin
openstack user list --project MyTest

+----------------------------------+-------+
| ID                               | Name  |
+----------------------------------+-------+
| 003928000bad4f88a21110ea1df794bc | admin |
+----------------------------------+-------+

Переключимся в созданный нами проект. Это вообще одна из самых важных частей нашей работы, потому что если создавать ресурсы в одном проекте, а потом на них ссылаться в другом, жизнь сразу же превратится в debug hell. Самый простой способ переключения - экспорт переменных окружения:

export OS_PROJECT_ID=5aee210a06d0413983610b543e359d70
export OS_PROJECT_NAME="MyTest"

Вот теперь можно создать инстанс на базе стандартного образа cirros:

openstack server create --flavor m1.tiny --image cirros --wait MyServer

+-------------------------------------+----------------------------------------------------------+
| Field                               | Value                                                    |
+-------------------------------------+----------------------------------------------------------+
| OS-DCF:diskConfig                   | MANUAL                                                   |
| OS-EXT-AZ:availability_zone         | nova                                                     |
| OS-EXT-SRV-ATTR:host                | ionice                                                   |
| OS-EXT-SRV-ATTR:hypervisor_hostname | ionice                                                   |
| OS-EXT-SRV-ATTR:instance_name       | instance-00000001                                        |
| OS-EXT-STS:power_state              | Running                                                  |
| OS-EXT-STS:task_state               | None                                                     |
| OS-EXT-STS:vm_state                 | active                                                   |
| OS-SRV-USG:launched_at              | 2023-01-07T14:23:27.000000                               |
| OS-SRV-USG:terminated_at            | None                                                     |
| accessIPv4                          |                                                          |
| accessIPv6                          |                                                          |
| addresses                           |                                                          |
| adminPass                           | c5V2vik8HDWC                                             |
| config_drive                        |                                                          |
| created                             | 2023-01-07T14:23:15Z                                     |
| flavor                              | m1.tiny (1)                                              |
| hostId                              | 13de0f11093b0df1a2f7dc5f321ab4787b447b89b1404e1daba695df |
| id                                  | 51eb6610-efb2-49f2-86be-12ce5f7c5355                     |
| image                               | cirros (cb8cb539-4659-4161-b158-a455e4653350)            |
| key_name                            | None                                                     |
| name                                | MyServer                                                 |
| progress                            | 0                                                        |
| project_id                          | 5aee210a06d0413983610b543e359d70                         |
| properties                          |                                                          |
| security_groups                     | name='default'                                           |
| status                              | ACTIVE                                                   |
| updated                             | 2023-01-07T14:23:27Z                                     |
| user_id                             | 003928000bad4f88a21110ea1df794bc                         |
| volumes_attached                    |                                                          |
+-------------------------------------+----------------------------------------------------------+

openstack server list 
+--------------------------------------+----------+--------+----------+--------+---------+
| ID                                   | Name     | Status | Networks | Image  | Flavor  |
+--------------------------------------+----------+--------+----------+--------+---------+
| 51eb6610-efb2-49f2-86be-12ce5f7c5355 | MyServer | ACTIVE |          | cirros | m1.tiny |
+--------------------------------------+----------+--------+----------+--------+---------+

Видим, что сервер создан, но беда - у него нет IP-адреса. Зачем нам нужна такая машина в облаке? Собственно откуда-то отсюда приходит понимание что вся эта облачная магия сама ничего не делает и надо будет использовать руки. Тем не менее, сейчас мы можем посмотреть, точно ли сервер поднялся, для этого посмотрим логи с tty:

openstack console log show MyServer

...
  ____               ____  ____
 / __/ __ ____ ____ / __ \/ __/
/ /__ / // __// __// /_/ /\ \ 
\___//_//_/  /_/   \____/___/ 
   http://cirros-cloud.net


login as 'cirros' user. default password: 'gocubsgo'. use 'sudo' for root.
cirros login: [  260.495873] random: nonblocking pool is initialized

Ну вроде ок. Переходим к более сложной работе - получаем доступ к серверу по сети. Создадим сеть - эта сущность не имеет адресации и предназначена для логического разделения пространства. То есть внутри неё будет строиться топология.

openstack network create MyNet

+---------------------------+--------------------------------------+
| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | UP                                   |
| availability_zone_hints   |                                      |
| availability_zones        |                                      |
| created_at                | 2023-01-07T14:45:38Z                 |
| description               |                                      |
| dns_domain                | None                                 |
| id                        | 0dcd7434-204a-4f0c-ad98-879ae87b782f |
| ipv4_address_scope        | None                                 |
| ipv6_address_scope        | None                                 |
| is_default                | False                                |
| is_vlan_transparent       | None                                 |
| mtu                       | 1442                                 |
| name                      | MyNet                                |
| port_security_enabled     | True                                 |
| project_id                | 5aee210a06d0413983610b543e359d70     |
| provider:network_type     | geneve                               |
| provider:physical_network | None                                 |
| provider:segmentation_id  | 49174                                |
| qos_policy_id             | None                                 |
| revision_number           | 1                                    |
| router:external           | Internal                             |
| segments                  | None                                 |
| shared                    | False                                |
| status                    | ACTIVE                               |
| subnets                   |                                      |
| tags                      |                                      |
| updated_at                | 2023-01-07T14:45:39Z                 |
+---------------------------+--------------------------------------+

Создадим в сети подсеть. Вот тут уже будут циферки:

openstack subnet create --network MyNet --subnet-range 192.168.0.0/24 --allocation-pool start=192.168.0.101,end=192.168.0.200 --dns-nameserver 8.8.8.8 MySubnet

+----------------------+--------------------------------------+
| Field                | Value                                |
+----------------------+--------------------------------------+
| allocation_pools     | 192.168.0.101-192.168.0.200          |
| cidr                 | 192.168.0.0/24                       |
| created_at           | 2023-01-07T14:49:09Z                 |
| description          |                                      |
| dns_nameservers      | 8.8.8.8                              |
| dns_publish_fixed_ip | None                                 |
| enable_dhcp          | True                                 |
| gateway_ip           | 192.168.0.1                          |
| host_routes          |                                      |
| id                   | 4e370f25-c5dd-4c2b-8b13-8b58be1c2536 |
| ip_version           | 4                                    |
| ipv6_address_mode    | None                                 |
| ipv6_ra_mode         | None                                 |
| name                 | MySubnet                             |
| network_id           | 0dcd7434-204a-4f0c-ad98-879ae87b782f |
| project_id           | 5aee210a06d0413983610b543e359d70     |
| revision_number      | 0                                    |
| segment_id           | None                                 |
| service_types        |                                      |
| subnetpool_id        | None                                 |
| tags                 |                                      |
| updated_at           | 2023-01-07T14:49:09Z                 |
+----------------------+--------------------------------------+

Чтобы сеть была похожа на настоящую, добавим ей роутер:

openstack router create MyRtr
+-------------------------+--------------------------------------+
| Field                   | Value                                |
+-------------------------+--------------------------------------+
| admin_state_up          | UP                                   |
| availability_zone_hints |                                      |
| availability_zones      |                                      |
| created_at              | 2023-01-07T15:16:51Z                 |
| description             |                                      |
| external_gateway_info   | null                                 |
| flavor_id               | None                                 |
| id                      | 4db0e235-edc1-4db5-8abe-11bbe0c9a82a |
| name                    | MyRtr                                |
| project_id              | 5aee210a06d0413983610b543e359d70     |
| revision_number         | 1                                    |
| routes                  |                                      |
| status                  | ACTIVE                               |
| tags                    |                                      |
| updated_at              | 2023-01-07T15:16:51Z                 |
+-------------------------+--------------------------------------+

И самая малость - создадим порт, то есть выделим в подсети IP-адрес как объект. Дальше этот объект мы присвоим нашему серверу:

openstack port create --network MyNet MyServerPort

+-------------------------+------------------------------------------------------------------------------+
| Field                   | Value                                                                        |
+-------------------------+------------------------------------------------------------------------------+
| admin_state_up          | UP                                                                           |
| allowed_address_pairs   |                                                                              |
| binding_host_id         |                                                                              |
| binding_profile         |                                                                              |
| binding_vif_details     |                                                                              |
| binding_vif_type        | unbound                                                                      |
| binding_vnic_type       | normal                                                                       |
| created_at              | 2023-01-08T09:30:33Z                                                         |
| data_plane_status       | None                                                                         |
| description             |                                                                              |
| device_id               |                                                                              |
| device_owner            |                                                                              |
| device_profile          | None                                                                         |
| dns_assignment          | None                                                                         |
| dns_domain              | None                                                                         |
| dns_name                | None                                                                         |
| extra_dhcp_opts         |                                                                              |
| fixed_ips               | ip_address='192.168.0.184', subnet_id='4e370f25-c5dd-4c2b-8b13-8b58be1c2536' |
| id                      | 66390e75-23c9-4ce6-8e13-54766849e835                                         |
| ip_allocation           | None                                                                         |
| mac_address             | fa:16:3e:f7:72:a6                                                            |
| name                    | MyServerPort                                                                 |
| network_id              | 0dcd7434-204a-4f0c-ad98-879ae87b782f                                         |
| numa_affinity_policy    | None                                                                         |
| port_security_enabled   | True                                                                         |
| project_id              | 5aee210a06d0413983610b543e359d70                                             |
| propagate_uplink_status | None                                                                         |
| qos_network_policy_id   | None                                                                         |
| qos_policy_id           | None                                                                         |
| resource_request        | None                                                                         |
| revision_number         | 1                                                                            |
| security_group_ids      | d4b314ae-85b7-400c-9cea-4f1edf9c12e2                                         |
| status                  | DOWN                                                                         |
| tags                    |                                                                              |
| trunk_details           | None                                                                         |
| updated_at              | 2023-01-08T09:30:33Z                                                         |
+-------------------------+------------------------------------------------------------------------------+

openstack server add MyServer MyServerPort

openstack server list
+--------------------------------------+----------+--------+---------------------+--------+---------+
| ID                                   | Name     | Status | Networks            | Image  | Flavor  |
+--------------------------------------+----------+--------+---------------------+--------+---------+
| 51eb6610-efb2-49f2-86be-12ce5f7c5355 | MyServer | ACTIVE | MyNet=192.168.0.184 | cirros | m1.tiny |
+--------------------------------------+----------+--------+---------------------+--------+---------+

Попробуем подключиться к серверу по ssh?

ssh cirros@192.168.0.184
ssh: connect to host 192.168.0.184 port 22: No route to host

Ожидаемый фэйл. Потому что подсеть, в которой находится наш сервер, изолирована и наш локалхост не знает о ней (кстати, убедитесь, что у вас не пересекаются подсети, иначе чуда не произойдёт, а времени на дебаг уйдёт уйма). Поэтому нам надо выдать серверу IP-адрес, доступный снаружи. У microstack уже создана external-подсеть, доступная с локалхоста. Ранее мы уже подключались к дашборду Horizon (10.20.20.1), то есть подсеть 10.20.20.0/24 - это пул адресов, из которого мы можем выдать нашему серверу адрес, чтобы иметь возможность прямого подключения.

Зачем вообще всё так сложно? Всё потому, что наша виртуальная инфраструктура ничем не отличается от обычной - сети, как и наши локальные, изолируются для экономии адресов и безопасности (NAT). То есть, если мы создаём инфраструктуру, в которой будут сервера БД и приложений, то нам бы не хотелось светить наружу лишние порты, чтобы всякие мамкины хакеры не стучались на них и не сливали драгоценные данные в сеть. Мы за это по шапке получать не хотим, поэтому, как взрослые люди, создадим отдельно jump-хост, выдадим ему доступ по ssh, с него получим доступ к серверам БД и приложений, а само приложение опубликуем только по портам 80 и 443 (на самом деле всё будет немножко сложнее, но базовая архитектура именно такая). В этой статье извращаться так не будем, но просто следует уяснить - попасть внутрь сети проекта, если она не выведена наружу настройками маршрутизации, нельзя.

Посмотрим как выглядит наша внешняя сеть и подсеть

openstack network list
+--------------------------------------+----------+--------------------------------------+
| ID                                   | Name     | Subnets                              |
+--------------------------------------+----------+--------------------------------------+
| 0dcd7434-204a-4f0c-ad98-879ae87b782f | MyNet    | 4e370f25-c5dd-4c2b-8b13-8b58be1c2536 |
| 28cf292a-c5ea-4982-9608-259e5292cd53 | test     | c2e793bd-ef81-4489-a2cd-ba7a6313432f |
| 364baed9-3b1c-45a6-9856-91248d1914be | external | 8d42b2c8-91ac-4293-b390-5463cece2324 | <--- (!)
+--------------------------------------+----------+--------------------------------------+

openstack subnet list 
+--------------------------------------+-----------------+--------------------------------------+------------------+
| ID                                   | Name            | Network                              | Subnet           |
+--------------------------------------+-----------------+--------------------------------------+------------------+
| 4e370f25-c5dd-4c2b-8b13-8b58be1c2536 | MySubnet        | 0dcd7434-204a-4f0c-ad98-879ae87b782f | 192.168.0.0/24   |
| 8d42b2c8-91ac-4293-b390-5463cece2324 | external-subnet | 364baed9-3b1c-45a6-9856-91248d1914be | 10.20.20.0/24    | <--- (!)
| c2e793bd-ef81-4489-a2cd-ba7a6313432f | test-subnet     | 28cf292a-c5ea-4982-9608-259e5292cd53 | 192.168.222.0/24 |
+--------------------------------------+-----------------+--------------------------------------+------------------+

Сейчас нам надо сделать так, чтобы сети MyNet и external могли "видеть" друг друга:

openstack router set MyRtr --external-gateway external
openstack router add subnet MyRtr MySubnet

Создадим ip-адрес в сети external методом floating

openstack floating ip create external
+---------------------+--------------------------------------+
| Field               | Value                                |
+---------------------+--------------------------------------+
| created_at          | 2023-01-08T19:04:24Z                 |
| description         |                                      |
| dns_domain          | None                                 |
| dns_name            | None                                 |
| fixed_ip_address    | None                                 |
| floating_ip_address | 10.20.20.59                          |
| floating_network_id | 364baed9-3b1c-45a6-9856-91248d1914be |
| id                  | 411d8e7a-7f78-4a81-bde9-848af52acb9b |
| name                | 10.20.20.59                          |
| port_details        | None                                 |
| port_id             | None                                 |
| project_id          | 5aee210a06d0413983610b543e359d70     |
| qos_policy_id       | None                                 |
| revision_number     | 0                                    |
| router_id           | None                                 |
| status              | DOWN                                 |
| subnet_id           | None                                 |
| tags                | []                                   |
| updated_at          | 2023-01-08T19:04:24Z                 |
+---------------------+--------------------------------------+

Проассоциируем полученный IP с нашим сервером

openstack server add floating ip MyServer 411d8e7a-7f78-4a81-bde9-848af52acb9b

openstack server list 
+--------------------------------------+----------+--------+----------------------------------+--------+---------+
| ID                                   | Name     | Status | Networks                         | Image  | Flavor  |
+--------------------------------------+----------+--------+----------------------------------+--------+---------+
| 51eb6610-efb2-49f2-86be-12ce5f7c5355 | MyServer | ACTIVE | MyNet=10.20.20.59, 192.168.0.184 | cirros | m1.tiny |
+--------------------------------------+----------+--------+----------------------------------+--------+---------+

В интерфейсе Horizon уже можно посмотреть на красивую карту

Сетевая карта проекта

Можем теперь подключиться к серверу. Иии... нет, ещё не всё готово (звуки рыдания). Сетевая связность получена, но есть такая штука, как группы безопасности. С их помощью определяются правила поведения трафика - кому и по каким портам и протоколам разрешать или запрещать ходить. Как правила на файрволле.

Создадим группу безопасности и добавим в неё правило, разрешающее всем доступ по SSH:

openstack security group create MySecGrp
openstack security group rule create --remote-ip 0.0.0.0/0 --dst-port 22:22 --protocol tcp --ingress MySecGrp

Проассоциируем наш настрадавшийся сервер с созданной группой безопасности:

openstack server add security group MyServer MySecGrp

Ну а теперь можно попробовать попасть на сервер. Однако, скорее всего, опять ничего не выйдет - сам Cirros не понял что у него появился ip-адрес, поэтому сервер надо перезагрузить (в копилку опыта по траблшутингу). Этого могло не произойти, если бы мы создавали инстанс не в самом начале, а когда у нас была бы сеть.

openstack server reboot

Теперь можно и SSH (Кстати, креды можно подсмотреть выше, где мы изучили логи с tty):

ssh cirros@10.20.20.59
The authenticity of host '10.20.20.59 (10.20.20.59)' can't be established.
ECDSA key fingerprint is SHA256:Ss6Rv+15YrTGxdHdperb1sQFBw9Z0zFB4idXmDzKcUc.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
cirros@10.20.20.59's password: 
$ whoami 
cirros

Теперь можно сказать что мы молодцы и умеем делать HelloWorld на OpenStack, не заплатив при этом ни копейки облачным провайдерам.

Полезные команды

  • Выключение/включение MicroStack
sudo snap disable microstack
sudo snap enable microstack
  • Перезапуск служб MicroStack
sudo systemctl restart snap.microstack.*
  • Путь, по которому установлен microstack - /var/snap/microstack/*

Что дальше?

Мы убедились, что на Microstack можно научиться навыкам работы с OpenStack, остаётся только развивать эти навыки и пробовать что-то существенное. Начать я бы рекомендовал с двух туториалов:

  1. Официальная документация по MicroStack
  2. Обучающая база по OpenStack от Canonical

После этого, конечно же, следует хотя бы бегло погулять по официальной документации OpenStack. Ну а дальше начинать творить - создавать свои инфраструктуры, загружать образы, играться с cloud-init, писать код Terraform, пробовать мультитенантность, тыкаться в API и ковырять компоненты OpenStack.

Важно лишь помнить, что хоть MicroStack и позволяет иметь своё облако, это, в первую очередь, лишь песочница. Не стоит использовать инструмент в продакшне.