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
PRO

July 27, 2017
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. Обновление без даунтайма на
    примере OpenStack Keystone

    View Slide

  2. Кто я?

    Борис Бобров

    Работаю в Mail.Ru Group над infra.mail.ru

    Питоню с 2010

    Занимаюсь опенстеком с 2014

    Core reviewer в Keystone

    View Slide

  3. В чём задача?

    Сделать так, чтобы REST-приложение на Python
    можно было обновить с релиза X на релиз X+1
    – Например, X.a.b → (X+1).c.d
    – За время разработки менялась схема базы данных

    View Slide

  4. Решение задачи

    Разработчик:
    – django-admin makemigrations
    – python manage.py script #
    (sqlalchemy-migrate)
    – alembic revision

    Деплоер
    – systemctl stop
    – Получить обновленный код
    – Мигрировать:

    django-admin migrate

    migrate (sqlalchemy-
    migrate)

    alembic upgrade head
    – systemctl start

    View Slide

  5. Решение задачи

    Разработчик:
    – django-admin makemigrations
    – python manage.py script #
    (sqlalchemy-migrate)
    – alembic revision
    – RPM/Docker/Puppet/...

    Деплоер
    – systemctl stop
    – Получить обновленный код
    – Мигрировать:

    django-admin migrate

    migrate (sqlalchemy-
    migrate)

    alembic upgrade head
    – systemctl start

    View Slide

  6. В чём задача?

    Сделать так, чтобы REST-приложение на Python
    можно было обновить с релиза X на релиз X+1
    – Например, X.a.b → (X+1).c.d
    – За время разработки менялась схема базы данных

    High Availability

    View Slide

  7. Пример конфигурации с HA
    keepalived + haproxy

    View Slide

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

    Обновить код

    Обновить базу данных
    3)Обновить код на серверах №2, №3, …

    View Slide

  9. В чём задача?

    Сделать так, чтобы REST-приложение на Python
    можно было обновить с релиза X на релиз X+1
    – Например, X.a.b → (X+1).c.d
    – За время разработки менялась схема базы данных

    High Availability

    Обновление без даунтайма

    View Slide

  10. Почему без даунтайма
    (на примере OpenStack Keystone)

    Keystone - сервис аутентификации и
    авторизации

    Центральный компонент в OpenStack

    Используется в 98% инсталляций

    View Slide

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

    Обновить код

    Обновить базу данных
    3)Обновить код на серверах №2, №3, …

    View Slide

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

    Код

    Базу данных
    ----- здесь всё ломается -----
    3)Обновить код на серверах №2, №3, …

    View Slide

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

    Код

    Базу данных
    ----- здесь всё ломается -----
    ----- http://bit.ly/2eOJGTG -----
    3)Обновить код на
    серверах №2, №3, ...

    View Slide

  14. Как обеспечить совместимость

    View Slide

  15. Как обеспечить совместимость
    Вариант 1 – в приложении

    View Slide

  16. Слой совместимости в приложении

    Только добавление колонок и таблиц

    Конвертация из старого формата в новый

    Конвертация из нового формата в старый

    Версионирование моделей

    Пример: oslo.versionedobjects

    View Slide

  17. Слой совместимости в приложении: минусы

    Очень сложно написать для сложных
    проектов

    Не покрывает все случаи (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

    View Slide

  18. Слой совместимости в приложении: плюсы

    Простота написания в простых проектах

    Не специфично для бэкенда

    View Slide

  19. Как обеспечить совместимость
    Вариант 2

    View Slide

  20. Вариант 2 – в базе данных

    Keystone - сервис аутентификации и
    авторизации

    Центральный компонент в OpenStack

    Используется в 98% инсталляций

    View Slide

  21. Вариант 2 – в базе данных

    Keystone - сервис аутентификации и
    авторизации

    Центральный компонент в OpenStack

    Используется в 98% инсталляций

    Использует MySQL (через sqlalchemy)

    View Slide

  22. Триггеры

    View Slide

  23. Триггеры

    View Slide

  24. View Slide

  25. Триггеры
    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;

    View Slide

  26. Триггеры
    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 ...”

    View Slide

  27. Триггеры

    Хранимые процедура

    Обеспечивают совместимость старых
    записей с новыми

    И новых со старыми

    Транзакционны

    View Slide

  28. Триггеры

    Их не знают питонисты

    Нет ORM

    Тяжело отлаживать

    View Slide

  29. Триггеры

    Стандартизированы

    Более-менее

    https://ru.wikipedia.org/wiki/Триггер_(базы_данных)

    Поддерживаются нужными СУБД

    MySQL

    PostgreSQL

    Даже SQLite!

    Де-факто стандарт для живых обновлений

    Известны операторам

    View Slide

  30. Репозитории миграции: до
    └── versions
    ├── 106_allow_password_column_to_be_nullable.py
    ├── 107_add_user_date_columns.py
    ├── 108_add_failed_auth_columns.py
    └── 109_add_password_self_service_column.py

    View Slide

  31. Репозитории миграции: после
    migrate_repo/
    expand_repo/
    data_migration_repo/
    contract_repo/

    View Slide

  32. 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

    View Slide

  33. Expand

    Новые колонки

    Новые таблицы

    Триггеры

    Остальные операции запрещены

    View Slide

  34. Миграция данных
    $ 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

    View Slide

  35. 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

    View Slide

  36. Contract

    Удаление старых данных

    Удаление старых колонок

    Удаление старых таблицы

    Удаление триггеров

    Другие операции запрещены

    View Slide

  37. Миграция схемы: до

    108_add_failed_auth_columns.py

    View Slide

  38. Миграция схемы: после

    108_add_failed_auth_columns.py

    003_add_key_hash_and_encrypted_blob_to_credential.py

    003_migrate_unencrypted_credentials.py

    003_remove_unencrypted_blob_column_from_credential.py

    View Slide

  39. Файлы миграции

    108_add_failed_auth_columns.py

    003_add_key_hash_and_encrypted_blob_to_credential.py

    003_migrate_unencrypted_credentials.py

    003_remove_unencrypted_blob_column_from_credential.py

    View Slide

  40. Фазы обновления

    View Slide

  41. Фазы обновления
    1) Обновление кода на сервере №1

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  46. Итоги

    Триггеры – стандарт, используйте их

    Для простого приложения – совместимость в
    коде

    View Slide

  47. Ссылки

    Спецификация в 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]

    View Slide

  48. Ещё мы хайрим

    Заниматься чем-то подобным

    Чинить опенстек

    Писать прочие штуки на Python

    [email protected]

    [email protected]

    View Slide