Від "стартапу" до тисяч серверів у десятці ЦОД. Як ми гналися за зростанням Linux інфраструктури

Якщо ваша IT інфраструктура росте надто швидко, ви рано чи пізно зіткнетеся з вибором – лінійно збільшувати людські ресурси на її підтримку чи починати автоматизацію. До якогось моменту ми жили у першій парадигмі, а потім почався довгий шлях до Infrastructure-as-Code.

Від "стартапу" до тисяч серверів у десятці ЦОД. Як ми гналися за зростанням Linux інфраструктури

Зрозуміло, НСПК – не стартап, але така атмосфера панувала у компанії у перші роки існування, і це були дуже цікаві роки. Мене звати Корняков Дмитро, більш ніж 10 років я підтримую інфраструктуру Linux з високими вимогами доступності. До команди НСПК приєднався у січні 2016 року і, на жаль, не застав самого початку існування компанії, але прийшов на етапі великих змін.

Загалом можна сказати, що наша команда постачає для компанії 2 продукти. Перший – це інфраструктура. Пошта має ходити, DNS працювати, а контролери домену – пускати вас на сервери, які не повинні падати. IT ландшафт компанії величезний! Це business&mission critical системи, вимоги щодо доступності деяких – 99,999. Другий продукт – самі сервери, фізичні та віртуальні. За існуючими потрібно стежити, а нові регулярно постачати замовникам із багатьох підрозділів. У цій статті я хочу наголосити на тому, як ми розвивали інфраструктуру, яка відповідає за життєвий цикл серверів.

Початок шляху

На початку шляху наш стек технологій виглядав так:
ОС CentOS 7
Контролери домену FreeIPA
Автоматизація — Ansible(+Tower), Cobbler

Все це розташовувалося в 3-х доменах, розмазаних на кількох ЦОДах. В одному ЦОД – офісні системи та тестові полігони, в інших ПРОД.

Створення серверів у якийсь момент виглядало так:

Від "стартапу" до тисяч серверів у десятці ЦОД. Як ми гналися за зростанням Linux інфраструктури

У шаблоні VM CentOS minimal і необхідний мінімум як коректний /etc/resolv.conf, решта приїжджає через Ansible.

CMDB - Excel.

Якщо сервер фізичний, то замість копіювання віртуальної машини на нього встановлювалася ОС за допомогою Cobbler – у конфіг Cobbler додаються MAC адреси цільового сервера, сервер DHCP отримує IP адресу, а далі наливається ОС.

Спочатку ми навіть намагалися робити якийсь configuration management у Cobbler. Але з часом це стало приносити проблеми з переносимістю конфігурацій як в інші ЦОД, так і Ansible код для підготовки VM.

Ansible в той час багато хто з нас сприймав як зручне розширення Bash і не скупився на конструкції з використанням shell, sed. Загалом Bashsible. Це призводило до того, що, якщо плейбук з якоїсь причини не відпрацьовував на сервері, простіше було видалити сервер, поправити плейбук і прокатати заново. Ніякого версіонування скриптів насправді був, переносимості змін теж.

Наприклад, ми захотіли змінити якийсь конфіг на всіх серверах:

  1. Змінюємо конфігурацію на існуючих серверах у логічному сегменті/ЦОД. Іноді не за один день – вимоги до доступності та закон великих чисел не дозволяє застосовувати всі зміни разом. А деякі зміни потенційно деструктивні і вимагають перезапуску чогось – від служб до самої ОС.
  2. Виправляємо в Ansible
  3. Виправляємо у Cobbler
  4. Повторюємо N разів для кожного логічного сегмента/ЦОД

Щоб всі зміни проходили гладко, необхідно було враховувати безліч чинників, а зміни відбуваються постійно.

  • Рефакторинг ansible коду конфігураційних файлів
  • Зміна внутрішніх best practice
  • Зміни за підсумками аналізу інцидентів/аварій
  • Зміна стандартів безпеки як внутрішніх, так і зовнішніх. Наприклад, PCI DSS щороку доповнюється новими вимогами.

Зростання інфраструктури та початок шляху

Кількість серверів/логічних доменів/ЦОД зростала, а з ними кількість помилок у конфігураціях. У якийсь момент ми дійшли трьох напрямків, у бік яких потрібно розвивати configuration management:

  1. Автоматизація. Наскільки можливо, потрібно уникати людського фактора в операціях, що повторюються.
  2. Повторюваність. Керувати інфраструктурою набагато простіше, коли вона передбачувана. Конфігурація серверів та інструментів для їх підготовки має бути скрізь однаковою. Це також важливо для продуктових команд – додаток повинен гарантовано після тестування потрапляти в продуктивне середовище, налаштоване аналогічно тестовому.
  3. Простота та прозорість внесення змін до configuration management.

Залишилося додати кілька інструментів.

Як сховище коду ми вибрали GitLab CE, не в останню чергу за наявність вбудованих модулів CI/CD.

Сховище секретів – Hashicorp Vault, в т.ч. за чудове API.

Тестування конфігурацій та ansible ролей – Molecule+Testinfra. Тести йдуть набагато швидше, якщо підключаєтеся до ansible mitogen. Паралельно ми почали писати власну CMDB та оркестратор для автоматичного деплою (на картинці над Cobbler), але це вже зовсім інша історія, про яку в майбутньому розповість мій колега та головний розробник цих систем.

Наш вибір:

Molecule + Testinfra
Ansible + Tower + AWX
Світ Серверів + DITNET (Власна розробка)
Шкіряник
Gitlab + GitLab runner
Сховище Hashicorp

Від "стартапу" до тисяч серверів у десятці ЦОД. Як ми гналися за зростанням Linux інфраструктури

До речі про ansible ролі. Спочатку вона була одна, після кількох рефакторингів їх стало 17. Категорично рекомендую розбивати моноліт на ідемпотентні ролі, які можна запускати потім окремо, додатково можна додати теги. Ми розбили ролі по функціоналу – network, logging, packages, hardware, molecule etc. А загалом дотримувалися стратегії нижче. Не наполягаю, що це істина в єдиній інстанції, але в нас спрацювало.

  • Копіювання серверів із “золотого образу” – зло!З основних недоліків – ви точно не знаєте, в якому стані зараз образи, і що всі зміни прийдуть у всі образи у всі ферми віртуалізації.
  • Використовуйте дефолтні файли конфігурації щонайменше і домовтеся з іншими підрозділами, що за основні системні файли відповідаєте ви, Наприклад:
    1. Залишіть /etc/sysctl.conf порожнім, налаштування повинні лежати лише в /etc/sysctl.d/. Ваш дефолт в один файл, кастом для застосування в інший.
    2. Використовуйте override файли для редагування systemd юнітів.
  • Шаблонізуйте всі конфіги та підкладайте повністю, по можливості ніяких sed та його аналогів у плейбуках
  • Рефактор код системи управління конфігураціями:
    1. Розбийте завдання на логічні сутності та перепишіть моноліт на ролі
    2. Використовуйте лінтери! Ansible-lint, yaml-lint, etc
    3. Змінюйте підхід! Ніякого bashsible. Потрібно описувати стан системи
  • Під всі Ansible ролі потрібно написати тести в molecule і щодня генерувати звіти.
  • У нашому випадку після підготовки тестів (яких більше 100) знайшлося близько 70000 помилок. Виправляли кілька місяців.Від "стартапу" до тисяч серверів у десятці ЦОД. Як ми гналися за зростанням Linux інфраструктури

Наша реалізація

Отже, незаймані ролі були готові, шаблонізовані і перевірені лінтерами. І навіть гіти скрізь піднято. Але питання надійної доставки коду в різні сегменти залишилося відкритим. Вирішили синхронізувати скриптами. Виглядає так:

Від "стартапу" до тисяч серверів у десятці ЦОД. Як ми гналися за зростанням Linux інфраструктури

Після того як приїхала зміна, запускається CI, створюється тестовий сервер, прокочуються ролі, тестуються молекулою. Якщо все ок, код йде в прод гілку. Але ми не застосовуємо новий код на наявні сервери в автоматі. Це своєрідний стопор, необхідний високої доступності наших систем. А коли інфраструктура стає величезною, у справу йде ще закон великих чисел – навіть якщо ви впевнені, що зміна нешкідлива, вона може призвести до сумних наслідків.

Варіантів створення серверів також багато. Ми вибрали кастомні скрипти на пітоні. А для CI ansible:

- name: create1.yml - Create a VM from a template
  vmware_guest:
    hostname: "{{datacenter}}".domain.ru
    username: "{{ username_vc }}"
    password: "{{ password_vc }}"
    validate_certs: no
    cluster: "{{cluster}}"
    datacenter: "{{datacenter}}"
    name: "{{ name }}"
    state: poweredon
    folder: "/{{folder}}"
    template: "{{template}}"
    customization:
      hostname: "{{ name }}"
      domain: domain.ru
      dns_servers:
        - "{{ ipa1_dns }}"
        - "{{ ipa2_dns }}"
    networks:
      - name: "{{ network }}"
        type: static
        ip: "{{ip}}"
        netmask: "{{netmask}}"
        gateway: "{{gateway}}"
        wake_on_lan: True
        start_connected: True
        allow_guest_control: True
    wait_for_ip_address: yes
    disk:
      - size_gb: 1
        type: thin
        datastore: "{{datastore}}"
      - size_gb: 20
        type: thin
        datastore: "{{datastore}}"

Ось до чого ми прийшли, система продовжує жити та розвиватися.

  • 17 ansible-ролей для налаштування сервера. Кожна з ролей призначена для вирішення окремого логічного завдання (логування, аудит, авторизація користувачів, моніторинг тощо).
  • Тестування ролей. Molecule + TestInfra.
  • Власна технологія: CMDB + Оркестратор.
  • Час створення сервера ~30 хвилин автоматизовано і практично не залежить від черги завдань.
  • Однакове стан/найменування інфраструктури в усіх сегментах – плейбуки, репозиторії, елементи віртуалізації.
  • Щоденна перевірка стану серверів із генерацією звітів про розбіжності з стандартом.

Сподіваюся моє оповідання буде корисним тим, хто на початку шляху. А який стек автоматизації використовуєте ви?

Джерело: habr.com