Skip to content

ZfauX/bingo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Схема

Задание

Мы запускаем наш новый сервис - API хранилища истории сессий нашего онлайн кинотеатра «Фильмопоиск». Дату запуска сдвинуть нельзя, наш PR уже активно продвигает этот запуск. От тебя потребуется развернуть продуктовую инсталляцию этого сервиса. Наш подрядчик "Horns&Hooves Soft inc" пишет для нас этот новый сервис. Неделю назад подрядчик провёл демонстрационную презентацию. На ней он показал почти корректно работающее приложение, и презентовал HTTP эндпоинт, который отвечает на GET /ping кодом 200, если приложение работает корректно и кодом 500, если нет. Мы попросили внести небольшие изменения: нужно, чтобы запрос GET /long_dummy в 75% случаев работал быстрее секунды, при этом нас устроит закешированный ответ не старше минуты. На презентации он работал дольше. Кроме того, подрядчик сообщил, что потребуется внести некоторые технологические изменения для повышения удобства эксплуатации, а так же починить несколько некритичных багов для повышения стабильности в работе. Вчера должна была состояться приёмка, но подрядчик на связь не вышел и перестал отвечать на письма, сообщения и звонки. Нам удалось выяснить, что у подрядчика возникли серьёзные форс-мажорные обстоятельства. Скорее всего получится возобновить взаимодействие не раньше согласованной даты запуска. Подрядчик не успел предоставить документацию к приложению, и не смог развернуть у нас своё приложение в срок, как ранее обещал. Тот стенд, на котором проводилась демонстрация, уже успели разобрать. К счастью, у нашего менеджера остался email с бинарником приложения, который использовали на демо. https://storage.yandexcloud.net/final-homework/bingo – вот ссылка на этот бинарник.

Твоя задача развернуть отказоустойчивую инсталляцию приложения из имеющегося бинарника до даты запуска продукта. Планируется стабильная нагрузка в 60 RPS, пиковая в 120 RPS. В эту пятницу выходит из отпуска наш тестировщик Петя, который работал с подрядчиком и умеет тестировать это приложение. Он сможет проверить твою и инсталляцию и подсказать, что с ней не так, чтобы тебе было удобнее готовиться к финальному запуску. Петя интроверт, не любит живое общение, поэтому он обещал сделать автоматику и помогать тебе с помощью специального сервиса - https://devops.yactf.ru Посредством этого сервиса он и будет принимать решение о том, насколько тебе удалось справиться с требованиями технического задания.

Требования (в порядке убывания важности):

  • Отказоустойчивость: сервис должен быть развернут на двух нодах, отказ любой из них должен быть незаметен пользователю. Допускается просадка по RPS до стабильного значения в момент отказа любой из нод. При живости обеих нод, инсталяция обязана выдерживать пиковую нагрузку. Так же нужно обеспечить восстановление работоспособности любой отказавшей ноды быстрее, чем за минуту.
  • Сервис должен переживать пиковую нагрузку в 120 RPS в течение 1 минуты, стабильную в 60 RPS.
  • Запросы POST /operation {"operation": <operation_id: integer>} должны возвращать незакешированный ответ. Сервер должен обрабатывать такие запросы и отдавать результат быстрее, чем за 400 миллисекунд в 90% случаев при 120 RPS, гарантируя не более 1% ошибок.
  • Запросы GET /db_dummy должны возвращать незакешированный ответ. Сервер должен обрабатывать такие запросы и отдавать результат быстрее, чем за 400 миллисекунд в 90% случаев при 120 RPS, гарантируя не более 1% ошибок.
  • Запросы GET /api/movie/{id} должны возвращать незакешированный ответ. Сервер должен обрабатывать такие запросы и отдавать результат быстрее, чем за 400 миллисекунд в 90% случаев при 120 RPS, гарантируя не более 1% ошибок.
  • Запросы GET /api/customer/{id} должны возвращать незакешированный ответ. Сервер должен обрабатывать такие запросы и отдавать результат быстрее, чем за 400 миллисекунд в 90% случаев при 120 RPS, гарантируя не более 1% ошибок.
  • Запросы GET /api/session/{id} должны возвращать незакешированный ответ. Сервер должен обрабатывать такие запросы и отдавать результат быстрее, чем за 400 миллисекунд в 90% случаев при 120 RPS, гарантируя не более 1% ошибок.
  • Запросы GET /api/movie должны возвращать незакешированный ответ. Сервер должен обрабатывать такие запросы и отдавать результат гарантируя не более 1% ошибок. Требований по времени ответа нет, планируем делать не более одного такого запроса одновременно.
  • Запросы GET /api/customer должны возвращать незакешированный ответ. Сервер должен обрабатывать такие запросы и отдавать результат гарантируя не более 1% ошибок. Требований по времени ответа нет, планируем делать не более одного такого запроса одновременно.
  • Запросы GET /api/session должны возвращать незакешированный ответ. Сервер должен обрабатывать такие запросы и отдавать результат гарантируя не более 5% ошибок. Требований по времени ответа нет, планируем делать не более одного такого запроса одновременно.
  • Запросы POST /api/session должны возвращать незакешированный ответ. Сервер должен обрабатывать такие запросы и отдавать результат гарантируя не более 1% ошибок. Требований по времени ответа и RPS нет.
  • Запросы DELETE /api/session/{id} должны возвращать незакешированный ответ. Сервер должен обрабатывать такие запросы и отдавать результат гарантируя не более 1% ошибок. Требований по времени ответа и RPS нет.
  • Задача со звёздочкой: сделать так, чтобы сервис работал на отдельном домене по https протоколу, и по http без редиректа на https (допускается самоподписанный сертификат).
  • Задача со звёздочкой: сделать http3.
  • Задача со звёздочкой: сделать так, чтобы запросы GET /long_dummy возвращали ответ не старше 1 минуты и отвечали быстрее, чем за 1 секунду в 75% случаев.
  • Задача со звёздочкой: желательно обеспечить наблюдаемость приложения: графики RPS и ошибок по каждому эндпоинту.
  • Задача со звёздочкой: автоматизировать развёртывание при помощи devops инструментов, с которыми вы успели познакомиться ранее.

Немножко комментариев и рекомендаций:

  • Для нас важно получить работающую инсталляцию, и менее важно как эта работоспособность была обеспечена. Мы засчитываем только рабочие решения. В качестве решения помимо эндпоинта мы хотим увидеть, как эта инсталляция была развернута. В минимальном варианте это должно быть сочинение на тему "как я это развернул руками". В идеале же, это должен быть репозиторий, который при помощи различных devops инструментов способен развернуть всю инсталляцию по одной команде. Мы не ожидаем от всех участников идеального варианта, но автоматизированные решения при прочих равных, мы оценим выше неавтоматизированных. При этом работающее неавтоматизированное решение будет засчитано, а неработающее автоматизированное - нет;
  • Бинарник умеет в развернутой базе данных создавать необходимые для работы таблицы и наполнять их тестовыми данными. Нужно его только об этом правильно попросить, уверен вы сможете разобраться как. Наличие в базе этих тестовых данных - одно из необходимых условий успешного выполнения задания. Вы можете в рамках тестов создавать некоторые сущности в базе и их же удалять. Однако не стоит удалять ничего из изначально там заведённого - это может не понравиться автоматике, которая будет считать Ваш рейтинг;
  • Важно убедиться в том, что на сервере настроено корректно точное время. Таймзона не имеет значения. В противном случае некоторые наши проверки решат, что вы считерили, добавив кеширование там, где его быть не должно;
  • В конфигурации есть параметр student_email - тут должен быть ваш email, который вы использовали при регистрации на тренировки - это важно для проверки задания;
  • Хэлсчек в приложении есть, живёт на GET /ping и свою функцию выполняет;
  • Можешь на своё усмотрение упаковать бинарник в docker image, либо этого не делать;
  • Для тех, кто разворачивается в Яндекс.Облаке - разворачивайтесь в одной АЗ;
  • Для самостоятельной проверки RPS и времени ответа своей инсталяции можете пользовать wrk / ab;
  • Для SSL, http3 и кеширования мы рекомендуем использовать reverse proxy, которые это поддерживают, например nginx;
  • Некоторый софт не умеет отдавать метрики в формате prometheus, для такого софта сбоку разворачивают что-то, что умеет собрать и отдать за него эти метрики. Гуглить по запросу "<название софта> export metrics".

Исследование и решения

Запуск приложения

curl -O https://storage.yandexcloud.net/final-homework/bingo
file bingo
_bingo: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, with debug_info, not stripped_
chmod +x bingo
./bingo
_Hello world_
./bingo --help
_bingo
Usage:
   [flags]
   [command]
Available Commands:
  completion           Generate the autocompletion script for the specified shell
  help                 Help about any command
  prepare_db           prepare_db
  print_current_config print_current_config
  print_default_config print_default_config
  run_server           run_server
  version              version
Flags:
  -h, --help   help for this command
Use " [command] --help" for more information about a command._
./bingo version
_20231121T1537_
./bingo print_current_config
_Error_
./bingo print_default_config
_postgres_cluster:
  hosts:
  - address: localhost
	port: 5432
  user: postgres
  password: postgres
  db_name: postgres
  ssl_mode: disable
  use_closest_node: false_
./bingo print_default_config > bingo.conf
./bingo run_server --help
_run_server
Usage:
   run_server [flags]
Flags:
  -h, --help   help for run_server_
./bingo run_server 
_Error_
sudo ./bingo run_server
_Didn't your mom teach you not to run anything incomprehensible from root?_
strace ./bingo
strace ./bingo print_current_config 
_found failed access to file /opt/bingo/config.yaml_
sudo mkdir /opt/bingo
./bingo print_default_config > config.yaml
sudo cp config.yaml /opt/bingo/
./bingo print_current_config
strace ./bingo run_server
edit config.yaml
sudo apt instlall postgresql
./bingo prepare_db 
./bingo run_server 
_Error_
strace ./bingo run_server 
_found failed access to file /opt/bongo/logs/416265556f/main.log_
sudo mkdir -p /opt/bongo/logs/416265556f/
sudo touch /opt/bongo/logs/416265556f/main.log
./bingo run_server
_Error_
strace ./bingo run_server 
_Found insufficient rights on file_
sudo chmod 0666 /opt/bongo/logs/416265556f /main.log
./bingo run_server
_30sec startup_
./bingo run_server &
tail -f /opt/bongo/logs/416265556f /main.log

Получен код:

My congratulations.
You were able to start the server.
Here's a secret code that confirms that you did it.
--------------------------------------------------
code:         yoohoo_server_launched
--------------------------------------------------

Поход в корень

Смотрим открытые порты:

ss -tunlp # --> ipv4 30164/tcp

Открываем http://localhost:30164

Нашёл код:

Hi. Accept my congratulations. You were able to launch this app.
In the text of the task, you were given a list of urls and requirements for their work.
Get on with it. You can do it, you'll do it.
--------------------------------------------------
code:         index_page_is_awesome
--------------------------------------------------

Web-proxy

Выбираю прокси. Выбирал между nginx и caddy. У nginx экспериментальная поддержка https/3. Принял решение установить и настроить caddy. Реализовал настройки через Caddyfile. Чтобы запускался по умолчанию лежит в /etc/caddy. Кэширование из коробки нет. Реализовано с помощью планировщика.

sudo echo "* * * * * root curl http://localhost:30164/long_dummy -o ~/bingo/caddy/cache_html/index.html"; sleep 30; curl http://localhost:30164/long_dummy -o ~/bingo/caddy/cache_html/index.html" >> /etc/crontab

Тесты

Ставлю и пробую wrk. Ранее, кажется при просмотре логов от bingo замечаю наличие библиотеки троттлинга для golang. На тестах замечаю, что RPS от одного сервиса bingo ограничен ~100. Нужно минимум 2 экземпляра для выполнения требований ТЗ по производительности.

Пишу тесты для wrk

  • tests/api-customer-id.lua
  • tests/api-customer.lua
  • tests/api-movie-id.lua
  • tests/api-movie.lua
  • tests/api-session-id.lua
  • tests/db_dummy.lua
  • tests/operation.lua

Замечаю, что bingo:

  • падает по OOM
  • I feel bad вместо pong на healthcheck

Решил реализовывать проект на машинах из 2 лекции. Сервис буду запускать с помощью systemd. Пишу unit и healthcheck для сервиса.

Целевая платформа

Развертывание ВМ, сети, подсети c помощью Terraform.

Ускорение старта

Сначала я думал, что долгий старт — это норма. При просмотре пакетов через tcpdump. Обнаружил запросы к http://8.8.8.8.

ip route add blackhole 8.8.8.8

Для сохранения правила маршрутизации после перезагрузки. Редактирование файла: /etc/netplan/00-installer-config.yaml

netplan generate
netplan apply

Приложение начало запускаться значительно быстрее. Получен код:

Congratulations.
You were able to figure out why
the application is slow to start and fix it.
Here's a secret code that confirms that you did it.
--------------------------------------------------
code:         google_dns_is_not_http
--------------------------------------------------

Avahi - zeroconf локальное разрешение имён (*.local)

sudo apt install avahi-daemon

Оптимизация запросов БД

Просматриваю логи базы данных и собираю запросы. Запускаю вручную с профилировкой.

sql
explain (analyze,verbose on)

Смотрю планы выполнения запросов, добавляю индексы и/или первичные ключи.

Результат

В итоге оптимизировал исходную таблицу, чтобы повторные запросы не отваливались по таймауту.

Все оптимизации:

-- PK
ALTER TABLE public.sessions ADD CONSTRAINT sessions_pk PRIMARY KEY (id);
ALTER TABLE public.customers ADD CONSTRAINT customers_pk PRIMARY KEY (id);
ALTER TABLE public.movies ADD CONSTRAINT movies_pk PRIMARY KEY (id);
-- Indexes
CREATE INDEX sessions_movie_id_idx ON public.sessions (movie_id);
CREATE INDEX movies_year_name_idx ON public.movies (year DESC, name);
CREATE INDEX customers_surname_idx ON public.customers (surname,name ,birthday DESC,id DESC);
CREATE INDEX movies_year_idx ON public.movies ("year" DESC, name, id DESC);

Мониторинг

  • Yandex Monitoring для VM (диски, CPU), NLB (пакеты)
  • Grafana+Prometheus для caddy (на домашнем ПК), чтобы следить за RPS, длительностью запросов и ошибками HTTP

SSL

Реализую подключение приложения к базе данных через ssl.

  • ssl/make_ssl

Автоматизация

Для автоматизации процесса были созданы плейбуки для ansible и инструкция для terraform. Для использования плейбуков необходимо изменить адреса в инвентарном файле ansible на адреса из вывода terraform. Так же предполагается, что выполнение инструкций ansible и terraform производятся на одном ПК.

Итоговые тесты

итоги

About

The final project of the Young&&Yandex DevOps trainings

Resources

License

Stars

Watchers

Forks

Packages

No packages published