Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rolling upgrades на примере OpenStack Keystone

Rolling upgrades на примере OpenStack Keystone

Борис Бобров (ведущий программист Mail.Ru Group) @ MoscowPython Meetup 47

"Большинству разработчиков сервисов на Python приходилось менять схему базы данных в какой-то момент жизни сервиса. Эта задача настолько типична, что для неё есть отдельный подмодуль для Django. Всё становится сложнее, если приложение, как типичный микросервис, работает в нескольких экземплярах. И ещё сложнее, если допускать даунтайма сервиса нельзя. В докладе будет рассказано, как эта проблема была решена в Keystone -- сервисе аутентификации и авторизации в OpenStack".

Видео: http://www.moscowpython.ru/meetup/47/rolling-upgrades/

Moscow Python Meetup

July 27, 2017
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. Кто я? • Борис Бобров • Работаю в Mail.Ru Group

    над infra.mail.ru • Питоню с 2010 • Занимаюсь опенстеком с 2014 • Core reviewer в Keystone
  2. В чём задача? • Сделать так, чтобы REST-приложение на Python

    можно было обновить с релиза X на релиз X+1 – Например, X.a.b → (X+1).c.d – За время разработки менялась схема базы данных
  3. Решение задачи • Разработчик: – django-admin makemigrations – python manage.py

    script # (sqlalchemy-migrate) – alembic revision • Деплоер – systemctl stop <service> – Получить обновленный код – Мигрировать: • django-admin migrate • migrate (sqlalchemy- migrate) • alembic upgrade head – systemctl start <service>
  4. Решение задачи • Разработчик: – django-admin makemigrations – python manage.py

    script # (sqlalchemy-migrate) – alembic revision – RPM/Docker/Puppet/... • Деплоер – systemctl stop <service> – Получить обновленный код – Мигрировать: • django-admin migrate • migrate (sqlalchemy- migrate) • alembic upgrade head – systemctl start <service>
  5. В чём задача? • Сделать так, чтобы REST-приложение на Python

    можно было обновить с релиза X на релиз X+1 – Например, X.a.b → (X+1).c.d – За время разработки менялась схема базы данных • High Availability
  6. Решение задачи 1)Выключить сервис на всех серверах 2)Обновить сервис на

    сервере №1 • Обновить код • Обновить базу данных 3)Обновить код на серверах №2, №3, …
  7. В чём задача? • Сделать так, чтобы REST-приложение на Python

    можно было обновить с релиза X на релиз X+1 – Например, X.a.b → (X+1).c.d – За время разработки менялась схема базы данных • High Availability • Обновление без даунтайма
  8. Почему без даунтайма (на примере OpenStack Keystone) • Keystone -

    сервис аутентификации и авторизации • Центральный компонент в OpenStack • Используется в 98% инсталляций
  9. Решение задачи 1)Выключить сервис на всех серверах 2)Обновить сервис на

    сервере №1 • Обновить код • Обновить базу данных 3)Обновить код на серверах №2, №3, …
  10. Решение задачи 1)Выключить сервис на всех серверах 2)Обновить сервис на

    сервере №1 • Код • Базу данных ----- здесь всё ломается ----- 3)Обновить код на серверах №2, №3, …
  11. Решение задачи 1)Выключить сервис на всех серверах 2)Обновить сервис на

    сервере №1 • Код • Базу данных ----- здесь всё ломается ----- ----- http://bit.ly/2eOJGTG ----- 3)Обновить код на серверах №2, №3, ...
  12. Слой совместимости в приложении • Только добавление колонок и таблиц

    • Конвертация из старого формата в новый • Конвертация из нового формата в старый • Версионирование моделей • Пример: oslo.versionedobjects
  13. Слой совместимости в приложении: минусы • Очень сложно написать для

    сложных проектов • Не покрывает все случаи (Fk, NOT NULL) id name 1 Vasya 2 Anya 3 Petya id name domain 1 Vasya 2 Anya 3 Petya id name 1 Test.ru 2 a.com
  14. Вариант 2 – в базе данных • Keystone - сервис

    аутентификации и авторизации • Центральный компонент в OpenStack • Используется в 98% инсталляций
  15. Вариант 2 – в базе данных • Keystone - сервис

    аутентификации и авторизации • Центральный компонент в OpenStack • Используется в 98% инсталляций • Использует MySQL (через sqlalchemy)
  16. Триггеры CREATE TRIGGER local_user_after_update_trigger AFTER UPDATE ON local_user FOR EACH

    ROW BEGIN UPDATE user SET domain_id = NEW.domain_id WHERE id = NEW.user_id and domain_id <> NEW.domain_id; END;
  17. Триггеры CREATE TRIGGER local_user_after_update_trigger AFTER UPDATE ON local_user FOR EACH

    ROW BEGIN UPDATE user SET domain_id = NEW.domain_id WHERE id = NEW.user_id and domain_id <> NEW.domain_id; END; “Для каждой записи, обновлённой в таблице local_user, выполнить UPDATE user SET ...”
  18. Триггеры • Стандартизированы • Более-менее • https://ru.wikipedia.org/wiki/Триггер_(базы_данных) • Поддерживаются нужными

    СУБД • MySQL • PostgreSQL • Даже SQLite! • Де-факто стандарт для живых обновлений • Известны операторам
  19. Expand $ tree expand_repo expand_repo ├── __init__.py ├── manage.py ├──

    migrate.cfg ├── README └── versions ├── 001_expand_initial_null_migration.py ├── 002_password_created_at_not_nullable.py ├── 003_add_key_hash_and_encrypted_blob_to_credential.py ├── 004_reset_password_created_at.py
  20. Миграция данных $ tree data_migration_repo data_migration_repo ├── __init__.py ├── manage.py

    ├── migrate.cfg ├── README └── versions ├── 001_data_initial_null_migration.py ├── 002_password_created_at_not_nullable.py ├── 003_migrate_unencrypted_credentials.py ├── 004_reset_password_created_at.py
  21. Contract $ tree contract_repo contract_repo ├── __init__.py ├── manage.py ├──

    migrate.cfg ├── README └── versions ├── 001_contract_initial_null_migration.py ├── 002_password_created_at_not_nullable.py ├── 003_remove_unencrypted_blob_column_from_credential.py ├── 004_reset_password_created_at.py
  22. Contract • Удаление старых данных • Удаление старых колонок •

    Удаление старых таблицы • Удаление триггеров • Другие операции запрещены
  23. Фазы обновления 1) Обновление кода на сервере №1 2) Expand

    (keystone-manage db_sync --expand) 3) Migrate (keystone-manage db_sync --migrate)
  24. Фазы обновления 1) Обновление кода на сервере №1 2) Expand

    (keystone-manage db_sync --expand) 3) Migrate (keystone-manage db_sync --migrate) 4) Обновление кода остальных серверах
  25. Фазы обновления 1) Обновление кода на сервере №1 2) Expand

    (keystone-manage db_sync --expand) 3) Migrate (keystone-manage db_sync --migrate) 4) Обновление кода остальных серверах 5) Contract (keystone-manage db_sync --contract)
  26. Ссылки • Спецификация в Keystone: https://specs.openstack.org/openstack/keystone-specs/specs/keystone/newton/manag e-migration.html • 170 патчей

    в Neutron https://review.openstack.org/#/q/topic:bp/adopt-oslo-versioned-objects-for-db • Существующие миграции в Keystone: https://git.openstack.org/cgit/openstack/keystone/tree/keystone/common/sql • Вопросы можно задать сюда: [email protected]