$30 off During Our Annual Pro Sale. View Details »

Как проверить систему, не запуская её (Гейзенбаг 2017)

Как проверить систему, не запуская её (Гейзенбаг 2017)

https://asatarin.github.io/talks/how-to-check-a-system-without-running-it/

Системы, которые мы разрабатываем, становятся сложнее с каждым днём. И кажется, нет спасения от вездесущей сложности, которая проникает во всё. Один из аспектов этой сложности — конфигурация. С одной стороны, конфигурация сильно влияет на стабильность и доступность системы, с другой — проверке её корректности уделяется очень мало внимания. В докладе расскажем, как мы тестируем конфигурацию и насколько это было полезно в нашем проекте.

Этот доклад будет интересен всем, кто хочет узнать простой способ увеличения стабильности и доступности системы в продакшне.

Andrey Satarin

December 08, 2017
Tweet

More Decks by Andrey Satarin

Other Decks in Programming

Transcript

  1. View Slide

  2. Андрей Сатарин, @asatarin
    Как проверить систему,
    не запуская её

    View Slide

  3. Вы отвечаете за uptime
    в вашем проекте?

    View Slide

  4. Да — вы в правильном
    месте
    Нет — еще можно уйти

    View Slide

  5. Проблема

    View Slide

  6. Сервис
    6
    Клиент
    Клиент
    Клиент
    Клиент

    View Slide

  7. Как не зафакапить наш
    сервис?

    View Slide

  8. 〉модульные тесты
    〉функциональные тесты
    〉тесты производительности
    〉еще немного тестов
    〉и еще тесты
    Как не зафакапить наш сервис?
    8

    Functionality

    Usability

    Reliability

    Performance

    Supportability

    +


    View Slide

  9. 9
    Сервис = код

    View Slide

  10. 10
    Сервис = код + конфигурация

    View Slide

  11. 11
    Сервис = код + конфигурация

    View Slide

  12. Как (не) убить сервис
    конфигурацией?

    View Slide

  13. Пример 1
    Одноклассники 2013

    View Slide

  14. View Slide

  15. «Однажды вечером система мониторинга зафиксировала
    незначительную проблему с одним из серверов. Для её
    устранения нужно было поправить шаблон конфигурации.»
    Три дня в Одноклассниках — начало
    15

    View Slide

  16. «Но дежурный администратор правил файл шаблона в другом
    редакторе, который поместил этот символ в конец файла»
    Три дня в Одноклассниках — кульминация
    16

    View Slide

  17. «В Одноклассниках, как и во многих других проектах,
    применяется инцидент-менеджмент. То есть все нештатные
    ситуации фиксируются и делятся по категориям:
    〉баг в нашем коде,
    〉ошибки конфигурации,
    …»
    Три дня в Одноклассниках — развязка
    17

    View Slide

  18. Пример 2
    Google Chubby

    View Slide

  19. View Slide

  20. «By their very nature, fault-tolerant systems try to mask problems»
    Chubby — обычная работа
    20
    Для консенсуса нужно большинство — 3 из 5 нод

    View Slide

  21. «By their very nature, fault-tolerant systems try to mask problems»
    Chubby — работа со сбоями
    21
    Для консенсуса нужно большинство — 3 из 5 нод

    View Slide

  22. «We once started a system with five replicas, but misspelled the
    name of one of the replicas in the initial group»
    Chubby — ошибка в конфигурации
    22
    Для консенсуса нужно большинство — 3 из 5 нод

    View Slide

  23. «We once started a system with five replicas, but misspelled the
    name of one of the replicas in the initial group»
    Chubby — ошибка в конфигурации + сбои
    23
    Невозможно собрать большинство из 5 нод

    View Slide

  24. 〉Не могут быть найдены модульными/функциональными/и т.д.
    тестами
    〉Могут очень дорого стоить
    〉Могут быть незаметны долгое время
    〉Им уделяют мало внимания
    Вывод: ошибки конфигурации
    24

    View Slide

  25. Код vs конфигурация
    25
    Код Конфигурация
    Java/C++/Python/etc Protobuf/XML/JSON/YAML/etc
    Строгий синтаксис Строгий синтаксис
    Строгая семантика Семантика не специфицирована
    Ревью/тесты/еще тесты/и т.д. ???

    View Slide

  26. Что делать?
    — Мы очень внимательно
    проверим конфигурацию!

    View Slide

  27. 〉Хранится в 18 protobuf файлах
    〉Спецификация этих файлов — 400
    строк кода
    〉Множество внутренних связей
    〉Больше нод — больше
    конфигурация
    Конфигурация «Проект К»
    27
    Нод в кластере
    Строк
    конфигурации
    8 нод 700+
    32 ноды 1600+
    300 нод 10000+

    View Slide

  28. Что делать?

    View Slide

  29. Теория

    View Slide

  30. https://twitter.com/allspaw/status/922494066620796928
    30

    View Slide

  31. View Slide

  32. View Slide

  33. View Slide

  34. «Our study shows that many of today’s mature, widely-used
    software systems are subject to latent configuration errors
    (referred to as LC errors) in their critically important 

    configurations—those related to the system’s reliability,
    availability, and serviceability.»
    Latent Errors
    34

    View Slide

  35. «LC [latent configuration] errors contribute to 75% of the high-
    severity issues and take much longer to diagnose, indicating their
    high impact and damage.»
    Latent Errors => серьезные инциденты
    35

    View Slide

  36. «Finding 3: 

    Resulting from Findings 1 and 2, 4.7%– 38.6% of the studied
    RAS [reliability availability serviceability] parameters do not have any
    early checks and are thereby subject to LC [latent configuration]
    errors which can cause severe impact on the system’s
    dependability.»
    Нет никаких проверок
    36

    View Slide

  37. «Such prevalence of LC [latent configuration] errors indicates the
    need for tool support to systematically rule out the threats.»
    «Another option to invoking the early checkers is to create
    a standalone checking program comprised of the checkers, and
    run it when the configuration file changes.»
    Нам нужны инструменты!
    37

    View Slide

  38. «This paper advocates early detection of configuration errors
    to minimize failure damage, especially in cloud and datacenter
    systems.»
    Мораль
    38

    View Slide

  39. В теории разницы
    между теорией
    и практикой нет,
    а на практике есть
    Приписывается разным людям

    View Slide

  40. Практика

    View Slide

  41. 〉Нужны тесты на конфигурацию продакшена
    〉Как написать такие тесты?
    Что делать?
    41

    View Slide

  42. — Надо проверить, что банковские переводы работают!
    — Как ты себе это представляешь? Отправили 10 миллиардов
    и ждем?
    — ???
    Основано на реальных событиях
    Типичные тесты в продакшене
    42

    View Slide

  43. Мы не будет запускать
    систему

    View Slide

  44. Пример 3
    Тривиальные проверки

    View Slide

  45. @pytest.mark.parametrize(
    ['path_to_config'],
    all_production_config_paths()
    )
    def test_config_is_loadable(path_to_config):
    config = load_config(path_to_config)
    assert_that(config, not_(none()))
    45
    Проверяем, что конфигурация загружается

    View Slide

  46. @pytest.mark.parametrize(
    ['path_to_config'],
    all_production_config_paths()
    )
    def test_config_is_loadable(path_to_config):
    config = load_config(path_to_config)
    assert_that(config, not_(none()))
    46
    Проверяем, что конфигурация загружается

    View Slide

  47. CONFIG_FOLDER = ‘path/to/config/folder’
    CONFIG_FILE_PATTERN = 'config.txt'
    def all_production_config_paths():
    return map(
    os.path.dirname,
    list_all_files_for_pattern(
    CONFIG_FOLDER,
    CONFIG_FILE_PATTERN
    )
    )
    47

    View Slide

  48. @pytest.mark.parametrize(
    ['config'],
    all_production_configs()
    )
    def test_unique_node_ids(config):
    assert_that(
    config.NodeIds,
    sequence_has_unique_elements()
    )
    48
    Простая проверка инвариантов

    View Slide

  49. Пример 4
    «Проект R» и порты

    View Slide

  50. «Проект R» и порты
    50
    Primary

    host1:port1
    Secondary

    host2:port2
    Клиент

    host1:port1

    host2:port2

    View Slide

  51. «Проект R» и порты
    51
    Primary

    host1:port1
    Secondary

    host2:port2
    Клиент

    host1:port1

    host2:port3

    View Slide

  52. «Проект R» и порты
    52
    Primary

    host1:port1
    Secondary

    host2:port2
    Клиент

    host1:port1

    host2:port3

    View Slide

  53. @pytest.mark.parametrize(…)
    def test_ports_are_valid(client, server_pri, server_sec):
    client_primary = client['primary']['connection']
    client_secondary = client['secondary']['connection']
    server_primary = server_pri[‘connection']
    server_secondary = server_sec['connection']
    assert_that(client_primary, equal_to(server_primary))
    assert_that(client_secondary, equal_to(server_secondary))
    53

    View Slide

  54. 〉Не все клиенты смотрели на правильный secondary
    〉Проблема была не видна до фактического отказа primary
    〉Поиск проблемы в продакшне чрезвычайно дорог
    〉Тесты на конфигурацию легко масштабируются на новых
    клиентов
    Мораль «Проект R»
    54

    View Slide

  55. Пример 5
    «Проект K»
    и отказоустойчивость

    View Slide

  56. «Проект К» — отказоустойчивость
    56
    Стойка 1 Стойка 2 Стойка 3
    Каждая нода в отдельной стойке

    View Slide

  57. «Проект К» — отказоустойчивость
    57
    Стойка 1 Стойка 2 Стойка 3
    Отказала стойка — полет нормальный

    View Slide

  58. «Проект К» — отказоустойчивость
    58
    Стойка 1 Стойка 3
    Ошибка конфигурации — две ноды в одной стойке

    View Slide

  59. «Проект К» — отказоустойчивость
    59
    Стойка 1 Стойка 3
    Отказала стойка — часть системы стала недоступной

    View Slide

  60. @pytest.mark.parametrize(…)
    def test_every_node_is_in_a_separate_rack(config):
    hostname_to_rack_id = {
    hostname: get_rack_id(h) 

    for h in config.hostnames
    }
    rack_ids = hostname_to_rack_id.values()
    assert_that(rack_ids, sequence_has_unique_elements())
    60

    View Slide

  61. @pytest.mark.parametrize(…)
    def test_every_node_is_in_a_separate_rack(config):
    hostname_to_rack_id = {
    hostname: get_rack_id(h) 

    for h in config.hostnames
    }
    rack_ids = hostname_to_rack_id.values()
    assert_that(rack_ids, sequence_has_unique_elements())
    61

    View Slide

  62. Как написать метод get_rack_id()?
    〉Разметить руками — подходит, если нод мало (< 10)
    〉Получить информацию из внешней системы (если она у вас
    есть)
    Где узнать как ноды в стойках стоят?
    62

    View Slide

  63. 〉Система не знает про расположение серверов в стойках
    〉Но мы то знаем, как сервера расположены в стойках
    〉«Внешние» проверки на основе этого знания легко нашли
    проблему
    〉Такой тест легко масштабируется на новые инсталляции
    Мораль «Проект K»
    63

    View Slide

  64. Выводы

    View Slide

  65. 〉Конфигурация это как код, только хуже
    〉Конфигурацию можно и нужно тестировать
    〉Тесты на конфигурацию легко масштабируются на множество
    инсталляций/клиентов/и т.д.
    〉Тесты на конфигурацию просто написать и получить много
    пользы
    Выводы
    65

    View Slide

  66. Напиши свой первый
    тест на конфигурацию,
    username@

    View Slide

  67. Андрей Сатарин
    Ведущий инженер по автоматизации тестирования
    https://twitter.com/asatarin
    [email protected]

    View Slide

  68. 〉Три дня, которые потрясли нас в 2013
    〉«Paxos Made Live – An Engineering Perspective»
    〉«Early detection of configuration errors to reduce failure damage»
    〉Gixy — open source от Яндекса, который сделает
    конфигурирование Nginx безопасным
    Ссылки
    68

    View Slide