Мы запускаем наш новый сервис - 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
--------------------------------------------------
Выбираю прокси. Выбирал между 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
--------------------------------------------------
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/make_ssl
Для автоматизации процесса были созданы плейбуки для ansible и инструкция для terraform. Для использования плейбуков необходимо изменить адреса в инвентарном файле ansible на адреса из вывода terraform. Так же предполагается, что выполнение инструкций ansible и terraform производятся на одном ПК.