Гостьовий пост: управляємо "Віртуальним приватним хмарою" за допомогою Terraform

  1. Що таке Terraform
  2. підготовка
  3. Приступаємо до роботи
  4. зміна конфігурації
  5. Сценарії використання Terraform
  6. висновок

Сьогодні ми публікуємо гостьовий пост, написаний нашим клієнтом. Олексій - технічний директор компанії. Компанія займається розробкою однойменної освітньої платформи, а також проводить інтерактивні олімпіади для школярів. Вся інфраструктура Учі.Ру побудована на базі нашого сервісу « Віртуальне приватне хмара ».
Олексій Вахов докладно розповідає про те, як він і його колеги використовують утиліту для автоматизації налаштування і підтримки віртуальної інфраструктури. Сподіваємося, що його досвід буде цікавий і іншим користувачам нашого хмари.

Ось уже більше чотирьох років ми створюємо онлайн-платформу для шкільної освіти. Сотні тисяч учнів зі всієї Росії вирішують інтерактивні завдання, беруть участь в регулярних олімпіадах, і все це відбувається в рамках нашої платформи. Зараз система складається з більш десяти продакшенів, частина яких обслуговує зовнішніх відвідувачів з навантаженнями 500-800 запитів в секунду, на інших працюють додатки для внутрішнього використання.

Наш флагманський продукт - це сайт. Крім роботи над сайтом ми проводимо онлайн-олімпіади з математики, підприємництву і російській мові. Продакшени олімпіад, як і будь-яких заходів з чіткими датами проведення, відрізняються сильно нерівномірним трафіком. Під час основного туру сайт навантажений сильно, і на нас лежить висока відповідальність і важливо, щоб технічно сталося все гладко. А після нагородження та підбиття підсумків продакшен олімпіади працює в спокійному режимі.

Близько року тому ми перевели майже всю нашу інфраструктуру з виділених серверів в хмару і дуже задоволені. Можливість швидко докупити будь-яку кількість серверів особливо актуальна для олімпіад, так як там пікове навантаження тримається всього пару тижнів, і на цей час ми піднімаємо ферму з пари десятків серверів, а потім її розформовуємо. Однак і для всіх інших продакшенів можливість швидко підкрутити ресурси дуже цінна.

В хмарі помінялися навіть принципи організації інфраструктури. На залізних серверах доводилося комбінувати по кілька ролей на бокс, так як вони великі і досить дорогі, до того ж підключення нового сервера завжди займає кілька днів. Система з часом ставала крихкою і не гнучкою. Зараз ми виділяємо кожен продакшен в окремий ізольований проект зі своєю підмережею і під кожну роль заводимо окремий сервер. Наприклад, під VPN доступ беремо найменші, на одне ядро ​​і 512 мегабайт пам'яті, а під сервери додатків і бази даних найчастіше купуємо сервер максимального розміру.

Коли кількість серверів зросла до декількох десятків, ми зіткнулися з новою проблемою: управляти конфігурацією через графічний інтерфейс стало некомфортно.
Коли з графічної панеллю працюють кілька людей, починає проявлятися людський фактор: уявімо собі, наприклад, ситуацію, коли хтось щось поміняв і не повідомив про це колегам (та й як про це повідомити?).

Скажімо з 8 серверів, які повинні бути однакові, один може мати іншу версію операційної системи або трохи інша кількість оперативної пам'яті. Завдання клонування або підняття нового продакшена з нуля також мала на увазі багато ручної роботи. Тому ми вирішили автоматизувати роботу з налаштування та підтримки нашої інфраструктури за допомогою утиліти Terraform ..

У цій статті я розповім для чого потрібен Terraform, покажу, як налаштувати оточення і створити тестовий сервер в будь-якому OpenStack-хмарі на прикладі хмари Селектел. Також ми обговоримо особливості використання утиліти на живому продакшені.

Що таке Terraform

- це чудова утиліта від компанії (творці Vagrant, Consul і деяких інших широко відомих у вузьких колах інструментів). З її допомогою можна моделювати, зберігати і змінювати хмарну інфраструктуру у вигляді простих шаблонів мовою HCL (HashiCorp Configuration Language). Хоча створення своєї мови - зазвичай дуже погана ідея, HCL мені подобається. Він являє собою надбудову над JSON, яку легко і приємно читати.

Наведу спрощений приклад (в реальності потрібно вказати трохи більше атрибутів) для створення сервера в хмарі «Селектел», практично повністю пояснює всі тонкощі синтаксису, які нам знадобляться:

resource "openstack_blockstorage_volume_v1" "disk" {name = "disk" region = "ru-1" size = 10} resource "openstack_compute_instance_v2" "server" {name = "server" flavor_name = "flavor-1024-1" region = "ru -1 "block_device {uuid =" $ {openstack_blockstorage_volume_v1.disk.id} "}}

Якщо зберегти наведений вище код в файл з розширенням .tf, налаштувати необхідні токени для доступу і викликати в консолі команду `terraform apply`, то станеться рівно те, що очікується: Terraform створить диск і тільки після цього створить сервер, на основі цього свіжого диска .

Якщо запустити `terraform apply` ще раз, то утиліта побачить, що такий диск і сервер вже є, і нічого робити не буде. Також легко додати пам'яті на сервер, помінявши `flavor_name` на` flavor-2048-1` і знову викликавши `terraform apply`. Terraform передбачувано оновить тільки пам'ять, а диск чіпати не буде. Команда `terraform destroy` видалить всі створені ресурси (і можна забути про висять в порожнечу DNS-записи тестових серверів, забуті диски та інші артефакти, які дратують будь-якого перфекціоніста).

Перш ніж приступати до роботи з Terraform, уважно вивчіть офіційну документацію (вона дуже хороша і зрозуміла, читається на одному диханні) і кілька днів поекспериментуйте з тестовими інфраструктурами, бажано на окремих акаунтах. Це дуже важливо: нерозуміння тонкощів роботи з Terraform може привести до непоправних наслідків. Експерименти якраз і допоможуть вам розібратися, як Terraform працює станом.

Розглянемо сценарії роботи з Terraform більш докладно.

підготовка

Для початку необхідно налаштувати оточення. Я розповім, як це робимо ми, але, думаю, якщо ви вже скріптуете свою інфраструктуру, то напевно знаєте які моменти вимагають автоматизації. Рекомендую вивчити, там є дуже несподівані представники - Grafana, PostgreSQL, Heroku і багато інших. Може бути, щось стане в нагоді при моделюванні вашої інфраструктури.
Ми поки управляємо тільки серверами і DNS-записами.

Для роботи нам знадобляться:

  • проект з необхідною кількістю квот;
  • користувач з доступом до даного проекту;
  • консольні утиліти OpenStack;
  • ідентифікатор образу операційної системи;
  • підготовлений набір змінних оточення.

Новий проект, користувача і квоти налаштуйте через GUI (хоча це теж можна скріптовать, але вже не через Terraform). Збережіть ID проекту: він буде використовуватися під час налаштування доступу OpenStack-провайдера. Зайдіть в проект і створіть локальну мережу, якщо вона ще не створена (в хмарі Selectel локальна мережа створюється автоматично, якщо ви замовите плаваючий IP-адреса).

Далі встановіть консольні утиліти для отримання деяких внутрішніх ідентифікаторів, які недоступні через GUI. У статті " Робота з API віртуального приватного хмари: консольні клієнти »Докладно написано, як їх встановити і використовувати. Для зручності ми завернули їх в контейнер і використовуємо в такий спосіб:

docker run --rm \ -e OS_AUTH_URL = https: //api.selvpc.ru/identity/v3 \ -e OS_PROJECT_ID = # {...} \ -e OS_USER_DOMAIN_NAME = # {...} \ -e OS_USERNAME = # {...} \ -e OS_PASSWORD = # {...} \ -e OS_REGION_NAME = # {...} \ uchiru / ostack: v2 команда, яку необхідно запустити

Де OS_USER_DOMAIN_NAME - логін в панелі «Селектел» (номер договору), PROJECT_ID - ідентифікатор проекту, OS_REGION_NAME - регіон (ru-1 для Санкт-Петербурга, ru-2 - Москва), OS_USERNAME / OS_PASSWORD - логін / пароль користувача (не забувайте, що у нього повинен бути доступ до проекту).

Щоб отримати ідентифікатор способу, запустіть команду glance image-list і знайдіть потрібний вам образ:

root @ 2118c4e58238: / # glance image-list | grep 16.04 eecd3d0f-6968-40ea-bed6-4c2949bbac3d | Ubuntu-16.04 LTS 32-bit ce532860-acef-40cd-b3c7-699c22b4dfd6 | Ubuntu-16.04 LTS 64-bit

Тепер залишилося створити потрібні Флавор. Зазвичай OpenStack-провайдери надають фіксований набір конфігурацій, проте «Селектел» в цьому плані більш гнучкий, так як дозволяє зібрати довільну конфігурацію для кожного сервера (при роботі в UI Флавор створюється автоматично на кожен новий сервер). Ми ж будемо створювати Флавор за допомогою команди nova. Відразу ж прийміть схему іменування, якій будете слідувати. Розумно вибрати щось типу flavor-1024-2 -двухядерний сервер з гігабайтом пам'яті.
Формат команди:

nova --is-public False flavor-create & amp; amp; amp; amp; lt; flavor-name & amp; amp; amp; amp; gt; auto & amp; amp; amp; amp; lt; mem-in-mb & amp; amp; amp; amp; gt; 0 & amp; amp; amp; amp; lt; cpu-n & amp; amp; amp; amp; gt ;.

Нарешті, для коректної роботи Terraform знадобиться експортувати кілька змінних оточення:

export TF_VAR_SELECTEL_ACCOUNT = 112233 # ваш логін від облікового запису Selectel export TF_VAR_PROJ_ID = 5b1b496 .. # ідентифікатор проекту export TF_VAR_USER = ... # логін користувача export TF_VAR_PASSWORD = ... # пароль цього користувача

От і все! Тепер у вас є всі компоненти для того, щоб створити свій перший сервер.

Приступаємо до роботи

Створіть файл provider.tf (ім'я файлу, природно, може бути будь-яким) з доступом до хмари:

provider "openstack" {domain_name = "$ {var.SELECTEL_ACCOUNT}" auth_url = "https://api.selvpc.ru/identity/v3" tenant_name = "$ {var.PROJ_ID}" tenant_id = "$ {var.PROJ_ID } "user_name =" $ {var.USER} "password =" $ {var.PASSWORD} "}

Додайте файл variables.tf:

variable "image_list" {type = "map" default = { "ubuntu-x64-1604" = "2de94623-a2a2-49e3-984d-3e6ca85e2b84"}} # змінні необхідно оголосити variable "PROJ_ID" {} variable "SELECTEL_ACCOUNT" {} variable "USER" {} variable "PASSWORD" {} # плаваючий IP і ідентифікатор мережі можна скопіювати з UI variable "box01-floating-ip" {default = "..."} variable "network-id" {default = ". .. "} variable" box01-ip "{default =" 192.168.0.4 "}

І, нарешті, файл box01.tf з описом сервера:

resource "openstack_blockstorage_volume_v1" "disk-for-box01" {name = "disk-for-box01" region = "ru-1" size = 10 image_id = "# $ {var.image_list [" ubuntu-x64-1604 "]} "volume_type =" basic.ru-1a "} resource" openstack_compute_instance_v2 "" box01 "{name =" box01 "flavor_name =" flavor-1024-1 "region =" ru-1 "network {uuid =" $ {var.network -id} "fixed_ip_v4 =" $ {var.box01-ip} "floating_ip =" $ {var.box01-floating-ip} "} metadata = {" x_sel_server_default_addr "=" {\ "ipv4 \": \ "\" } "} block_device {uuid =" $ {openstack_blockstorage_volume_v1.disk-for-box01.id} "source_type =" volume "boot_index = 0 destination_type =" volume "}}

Потім виконайте команду `terraform apply` - і через кілька секунд ваш перший сервер готовий! Ми роздаємо IP-адреси вручну для більшої контрольованості, плюс при зміні ресурсів OpenStack видасть нову адресу, якщо він не вказаний явно, що не завжди зручно.

Синтаксис Terraform досить самодокументірованний. Ви з цеглинок-ресурсів складаєте ті конструкції, які вам потрібні. Утиліта сама прораховує залежності і, наприклад, створить сервер тільки після того, як створений диск. Однак те, що можна зробити паралельно - буде робити паралельно.

Звичайно, один-єдиний сервер набагато швидше і зручніше створити через GUI. Я думаю, що реальна користь від Terraform починається від пари десятків серверів, особливо якщо також скріптовать DNS-записи, Бакета S3 і інші сервіси.

зміна конфігурації

Додати або прибрати згадку (або диски) дуже просто: змініть Флавор і викличте команду `terraform apply`. Зверніть увагу: в результаті виконання цієї команди сервер перезавантажиться!

Розмір диска слід міняти акуратно, так як Terraform пересоздаст його з нуля, якщо робити через скрипти. Але вихід є: збільште розмір через UI і в відповідному tf-скрипті. Terraform вас зрозуміє правильно і чіпати диск не буде.

Додати сервер найпростіше, скопіювавши файл box01.tf і оновивши соответсnвующіе змінні. Для наших проектів в 10-20 серверів ми зберігаємо tf-файли плоско (Не формуючи ієрархію з файлів по будь-якою ознакою): скільки серверів - стільки файлів.

Сценарії використання Terraform

Повторюся ще раз: за рівнем бід, які можна накоїти на живому продакшені (причому, дуже, дуже швидко) Terraform залишить далеко позаду навіть `truncate table`. Мабуть, це самий небезпечний інструмент, з яким я коли-небудь працював. Тому дуже важливо добре розуміти принципи його роботи.

З технічної точки зору Terraform є один-єдиний бінарний файл на Go, його можна скомпілювати, розібратися, налагодити. Вся магія реалізована через файл стану і різноманіття провайдерів для роботи з різними сервісами.

Типовий сценарій виглядає так. Ви задаєте бажану конфігурацію в tf-скриптах. Файл стану в цей момент порожній. Набираєте команду `terraform plan`.Ето найприємніша і безпечна команда: вона нічого не змінює, просто пише, які зміни утиліта внесе, якщо запустити команду` terraform apply`.
Далі ви запускаєте `terraform apply` і тільки тоді будуть створені реальні сервери, диски, записи в DNS і так далі. Інформація про ці ресурси буде збережена в файл стану (JSON-файл з досить простим синтаксисом). При подальшій роботі утиліта буде використовувати файл стану, також збирати інформацію з реального світу і порівнювати її з вашими скриптами.

Причиною всіх непорозумінь є те, що Terraform працює з трьома об'єктами одночасно:

  • tf-скрипти - це те, що ви хочете бачити;
  • файл стану - це те, як виглядає інфраструктура на думку Terraform;
  • реальний стан справ - як насправді виглядає інфраструктура.

У момент планування запиту (а apply команда відрізняється від plan тільки тим, що зміни реально застосовуються), Terraform зчитує файл стану, оновлює властивості кожного об'єкта по його ID (в будь-якому сервісі у кожного ресурсу є унікальний ідентифікатор, саме його використовує Terraform для ідентифікації) і порівнює отримані атрибути.

Грубо кажучи, можна вважати, що стан - це перелік ідентифікаторів ресурсів, якими управляє даний проект. Якщо ви додасте сервер або DNS-запис руками, то Terraform про неї не дізнається. Необхідно буде помістити її в стан явно. Якщо видаліть сервер через GUI, то Terraformу також потрібно буде оновити стан за допомогою команди `terraform state rm <віддалені ресурси>`.

У попередньому розділі я рекомендував збільшувати диск через UI і в tf-скрипті. Як це працює? Припустимо, спочатку в tf-скрипті вказаний диск 10ГБ. Terraform створив його і записав id свіжого диска, а також його розмір у файл стану. Ви поміняли розмір через UI на 20ГБ. Якщо запустити `terraform plan` зараз, то Terraform дізнається у OpenStack, що розмір диска 20ГБ, а в tf-файлі - 10ГБ, і запропонує його перебудувати. Якщо ви поміняєте розмір диска на 20ГБ, то Terraform переконається, що диск реально 20ГБ і в скриптах - 20ГБ і нічого робити не буде. Може здатися, що зберігати в стані факт, що колись диск був 10ГБ і не потрібно, так як Terraform не використовує цей атрибут. Насправді, це так і є, але особливість реалізації деяких провайдерів вимагає збереження деяких додаткових атрибутів (наприклад, регіон для всіх OpenStack-ресурсів), підозрюю, що саме тому автори вирішили зберігати в стані останні значення всіх властивостей кожного ресурсу.

Щоб Terraform працював коректно, необхідно зберігати файл стану централізовано. Ми зберігаємо прямо в репозиторії, також можна зберігати на S3, в комерційному сервісі Atlas, в Consul і деяких інших сховищах, повний список яких також є в.

висновок

У цій статті ми розглянули особливості роботи з Terraform дуже коротко. На жаль, за рамками нашого розгляду залишилася цікава тема з імпорту вже існуючої інфраструктури. Скажу коротко. Можна скористатися командою `terraform import`, яка, правда, з'явилася недавно, реалізована далеко не для всіх провайдерів і поки відверто сирувата. Робочий варіант на сьогодні - додати ресурс з правильним типом і ідентифікатором прямо в файл стану і викликати `terraform refresh`.

Отже, якщо ви активно користуєтеся хмарними сервісами, часто створюєте і видаляєте різні сутності через GUI, рекомендую спробувати. ви знайдете повний комплект скриптів зі статті, достатній для закладу свого сервера за допомогою Terraform. Хоча утиліта молода, з досить високим порогом входу, після впровадження відчуття порядку і контролю сильно зросте. Буду радий відповісти на будь-які питання і зауваження в коментарях і поштою [email protected] .

Дякую команду «Селектелa» за пропозицію написати гостьовий пост. Також запрошую всіх читачів відвідати. Кожен робочий день публікую маленьку історію про розробку, думки, інструменти і все таке.

Дякую за увагу!

А й як про це повідомити?
Як це працює?

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

Или позвоните нам по телефонам: (048) 823-25-64

Организация (обязательно) *

Адрес доставки

Объем

Как с вами связаться:

Имя

Телефон (обязательно) *

Мобильный телефон

Ваш E-Mail

Дополнительная информация: