Скрестил Gogs, Drone и MinIO внутри k8s
Завязка
Я тут писал небольшую статейку (само собой, в org-mode
), для удобства хранил
её, само собой, в git'е, и решил сделать сборку в pdf для читателя на своём
домашнем Drone CI.
Инфраструктура
Мой Drone CI размещён на моём домашнем Kubernetes-«кластере», состоящем из сервера, который хостит, собственно Drone, Gogs, Grafana, и ещё всякое по-мелочи. Собрал я его просто для изучения этого самого k8s, и всё ещё поддерживаю, постепенно наращивая функциональность, но больше для изучения современных технологий и всякой кластеризации.
Drone CI у меня сконфигурирован на использование k8s в качестве runner'а, и оно неплохо работало до того момента, как мне потребовалось хранить артефакты. Оказалось, что Drone не умеет хранить артефакты, и Gogs тоже не умеет. Не то, чтобы меня это сильно удивило, в конце концов, я примерно по этому признаку их и выбирал — в них нет ничего лишнего.
Беглое гугление показало, что лучше всего Drone хранит всякое в S3. Ну что ж,сказано — сделано.
Домашний S3
Немножко погуглив, я обнаружил, что самый простой способ организовать дома S3 — это поставить MinIO. Почитал, какие образы они предоставляют, написал пяток ямлов, kubectl apply -f .
, и оно даже сходу почти заработало.
Из интересного: во-первых у них немножко другой API, они не используют хостнеймы для бакетов, а дают к ним доступ через URL, а во-вторых они разнесли работу на два порта, и часть клиентов поддерживает работу через дополнительный элемент в пути, а часть — нет. В итоге проще всего оказалось организовать доступ по двум портам изнутри кластера, доступ снаружи приподзакрыть, а для раздачи файлов сделать новый сервис.
Сервер раздачи
Соответственно, чтобы раздавать файлик без открытия доступа к хранилищу из внешнего контура, пришлось организовать сервер для раздачи файлов. Сначала я погуглил на тему раздачи просто через nginx, но потом я решил, что это неспортивно, и просто реверс-проксирование с кэшем, это не очень прикольно. Да и выставлять хранилище наружу без каких-либо ограничений мне не очень хотелось,в итоге я решил попробовать написать сервис для раздачи.
Сервис на Rust
Поскольку последнее время я осваиваю Rust, то решил посмотреть, как там обстоят дела с написанием веб-сервисов. Рассмотрев несколько возможных библиотек, я выбрал Axum, как довольно популярный, и вроде понятный с точки зрения документации.
В итоге за полтора часа экспериментов получился сервис на 150 строк на rust,который одной ногой умеет ходить в MinIO через rusoto_s3
, а другой — отдавать файлы по http через Axum. Получилось в целом неплохо, не разобрался только с юнит-тестированием: замокать весь мир оказалось непросто, и даже с помощью ChatGPT мне пока не удалось наладить тестирование, надо будет отдельно почитать, можно ли как-то малой кровью тестировать такие вот клиенты, без того,чтобы создавать тестовое окружение для S3 и вообще городить огород.
Выводы
В общем, традиционно потратил несколько часов на автоматизацию задачи, которая руками решалась за десять минут, и попутно:
- Разжился новым сервисом в домашнем k8s, в котором теперь буду хранить всякое
- Потренировался писать cloud-first веб-сервисы на расте
- Наладил хранение артефактов для Drone CI
Ну и задачку решил, поэтому доволен.