Как желание написать простой CRUD привело к созданию целой видеоплатформы

от автора

  • Введение

  • Подготовка к работе

  • Начало работы

  • Когда одного CRUD’а мало

  • Начинаем делать реальный проект

  • Перед разделением на микросервисы

  • Разделение на микросервисы

  • Создание клиентских приложений

  • Добавление мониторинга

  • Перевод проекта в Kubernetes: dev- и cloud-стенды

  • Cloud Deploymen

  • Итоги

Введение

Статья о том, как безобидная инициатива постепенно приобрела эффект снежного кома и со временем превратилась в видеоплатформу, которая в последствии стала DevOps-проектом.

Захотелось мне как-то узнать, — а на сколько это сложно написать своё API, которое может обладать базовым работающим функционалом, — читать записи из БД и вносить их туда. Хотелось просто понимать, как пишется самое простое рабочее API, как работает бэкенд, как он взаимодействует с базами данных.

Из языков программирования я был наиболее знаком с Python, поэтому следовало выбрать фрэймворк под этот язык. Выбор стоял между Django и FastAPI. Django чаще используется для создания монолитных приложений, которое уже изначально идет с БД и админкой. Нам же нужно было настроить и понять работу с базами данных самостоятельно, а так же работать не строго в рамках границ одного монолита, — а с возможностью выхода за эти рамки при необходимости. Таким образом выбор пал на FastAPI.

Подготовка к работе

Заниматься работой над этим проектом я решил в наиболее удобной для этого среде, — на свободный SSD-диск на 256 ГБ установил Linux Ububntu, и в ней настроил все, что необходимо для работы, — установил среду разработки и сам FastAPI. Изучать фреймворк решил по книге «FastAPI веб-разработка на Python», автор Билл Любанович.

Начало работы

Изначально я просто делал всё по книге, — списывал оттуда код, вникал, устранял проблемы. Некоторые примеры, используемые в книге заметно отличались от актуального Python-стека, поэтому часть кода приходилось адаптировать под современные версии Python и библиотек. Практически сразу — с момента создания своего первого эндпоинта я начал использовать Git, и сразу же решил обернуть код в Docker. Потому, что не было ни одной причины этого не сделать. Позднее на примерах кода из книги по созданию списка исследований и работы с ним — был сделан полноценный CRUD, на что программа книги и была рассчитана. Так я впервые познакомился с разделением приложения на уровни: web-уровень принимает HTTP-запросы и возвращает ответы, service-уровень содержит бизнес-логику, а data-уровень отвечает за взаимодействие с базами данных.

В исходном варианте данные хранились в SQLite. И я подумал, что будет перспективным перейти с SQLite на PostgreSQL, таким образом я познакомился с SQLAlchemy, — ORM-библиотекой, позволяющей работать с различными СУБД через единый интерфейс. Так как проект у меня был в Docker, а PostgreSQL запускался в отдельном контейнере, — с этого момента я начал работать с docker-compose. Признаюсь, что переход с SQLite на PostgreSQL дался мне не совсем легко. Это было связано с тем, что пришлось существенно перерабатывать data-уровень: если раньше там использовались raw SQL-запросы, то теперь появились ORM-модели и работа через session SQLAlchemy. Начали применяться Alembic-миграции.

На это у меня ушел примерно месяц, за который у меня получилось сделать первый бэкенд своими руками. Я узнал о разных библиотеках — Pydantic(валидация входящих данных), Pytest(тестирование Python-кода;), HTTPX(http-клиент для тестирования API и взаимодействия между сервисами). Научился исправлять ошибки, погрузился в тестирование. Так узнал, что в FastAPI есть swagger, в котором удобно проверять работу API, подёргал ручки с помощью Postman и узнал что в нём этот процесс можно автоматизировать. Особо интересным мне показалось интергационное тестирование — это тестирование уровней и их взаимосвязи друг с другом. Увидел перспективы автоматического тестирования, сделал первый автотест.

Когда одного CRUD’а мало

После того, как у меня получился базовый CRUD, пришло понимание, что хочется чего-то больше похожего на реальное настоящее приложение, а не учебный проект. Для базового CRUD’а нет смысла, допустим, настраивать мониторинг потому, — что там нечего мониторить. К нему не создать интересное клиент-приложение, такой проект нельзя разместить в портфолио потому, что «как-то не серьёзно». Возникла задача создать что-то боевое и настоящее, чем реально можно пользоваться.

Было бы неплохо создать настоящую инфраструктуру, на примере который можно было бы изучить и применить брокеры сообщений и кеширование, применить репликацию. С технологиями я уже определился, — можно было бы добавить в проект Redis и RabbitMQ (со вторым познакомился на работе). Но вопрос, — какие задачи выполняет сервис, в котором применяются данные технологии, и какие из этих задач актуальны в качестве идеи для проекта, разрабатываемого в домашних условиях?

Из возможных вариантов были следующие:

  • система обработки файлов и документов

  • система уведомлений

  • маркетплейс

  • облачный сервис

  • стриминговая платформа

  • видеоплатформа

Выбор осуществлялся методом исключения вариантов:

  • система обработки файлов и документов — не достаточно масштабно

  • система уведомлений — влечёт за собой вопрос «кого и о чем уведомлять?»

  • маркетплейс — слишком типовой проект, его нужно делать не абстрактным, а под конкретный магазин, которого у меня нет.

  • облачные сервис — в сети есть готовые открытые решения, зачем делать свой, если можно просто поднять тот же NextCloud?

  • стриминговая платформа — стоит понять — кому и зачем, нужно стримить и смотреть стримы у вас дома?

Осталась только видеоплатформа для загрузки и просмотра видео на подобие Ютьюба или Рутьюба.

Начинаем делать реальный проект

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

В этот момент я понял, что для упорядочивания работы мне необходимо документировать свои действия, ставить и описывать цели, описывать результаты и проводить анализ своих действий. Это значит, что необходим какой-то инструмент, который позволяет это делать — система по работе с заявками и документацией. Нужно где-то документировать и описывать свой проект, API должно быть описано, должна быть схема проекта, должно быть описано как его тестировать и запускать, должны быть описаны различные нюансы и особенности которые могут иметь значение. После недолгих раздумий и выбора сервиса решил использовать RedMine потому, что я с ним очень хорошо знаком. Поднял прямо на самом ПК с убунтой на борту, настроил автоматические бэкапы базы данных на внешний носитель, так как блочные устройства имеют свойство периодически выходить из строя, а вся информация из тикетов хранится как раз в БД. Данное решение позволило мне существенно упорядочить работу над проектом, я смог таким образом ставить перед собой конкретные цели того, что мне нужно сделать. Большие задачи я разбивал на большое количество мелких задач и решал их все по-отдельности. Данный способ дал мне определённость в том, что я буду делать сегодня и завтра, в том что мне предстоит в принципе сделать и позволил мне наладить тайм-менеджмент. По решённым задачам я смог отслеживать свой прогресс и составлять дальнейшие планы. В заявках оставлял комментарии с важной информацией, описывал нововведения/изменения, ветку и коммит из Git с датами.

Вернёмся к проекту, — после настройки системы заявок я добавил функционал работы с видео, API начало быть не просто заглушками — а реально работающими ручками. Видео стало загружаться и храниться пока что в локальном storage на ПК, на этапе загрузки стал возвращаться статус загрузки — ready/failed. Я создал тестовую страницу html-страницу для просмотра видео, чтобы наблюдать за работой сервиса, отслеживать ошибки через DevTools. Загруженное видео начало быть готовым для просмотра в качестве 360p/720p/1080p. Был реализован HLS (HTTP Live Streaming), — деление потока видео при просмотре на сегменты 2-10 секунд в формате .ts или .m4s. Ffmpeg стал генерировать завершённый статический HLS-плейлист — который управляет очередностью сегментов. Таким образом браузер при просмотре видео подгружает сегменты видео при просмотре, а не всё видео целиком. Создаётся Thumbnail — превью-картинка к видео. С помощью Range(http-механизм частичной загрузки файла) осуществляется перемотка видео в плеере. Вот так был реализован работающий HLS VOD — просмотр видео по запросу, где видео загружается сегментами. VOD означает «Video On Demand» — видео по запросу.

Перед разделением на микросервисы

Ранее я хотел на собственном опыте познакомиться с использованием RabbitMQ и Redis в проекте, решил сделать это уже сейчас:

  • Redis используетлся для обеспечения идемпотентности обработки видео и координации работы нескольких processing-worker’ов. Если одно и то же видео повторно попадёт в очередь задач, Redis через distributed lock позволяет избежать параллельной обработки одного и того же файла несколькими воркерами одновременно.

  • RabbitMQ используется как брокер сообщений и очередь задач для обработки видео. Это позволяет сделать загрузку асинхронной — пользователь не ждёт завершения transcoding во время upload-запроса, а обработка выполняется processing-worker’ами в фоне. Такой подход также позволяет независимо масштабировать количество воркеров в зависимости от нагрузки. Дополнительно через RabbitMQ реализованы retry-механизмы и DLQ (dead-letter queues) для повторной обработки failed-задач.

На данном этапе бэкенд видеоплатформы был еще похож на MVP, но далее следовало большое количество доработок, ходе которых я начал внедрять практики и решения, характерные для production-проектов. Была обеспечена идемпотентность на уровне БД даже без Redis, реализована асинхронная загрузка видео, введена JWT-авторизация пользователей, реализована возможность подключения S3-хранилища и использования CDN, сделано понятное логирование.

Интересной задачей оказалась добавление на платформу возможности стриминга. Нужно было создать новые эндпоинты для контроля сессии, научить платформу принимать live-поток и осуществлять транскодирование, генерировать hls-сегменты на лету и проводить очистку устаревших сегментов с диска после определённого TTL, чтобы не забивалось пространство.

С появлением стриминга у меня появилось три новых docker-контейнера:

  • ingest nginx — принимает live-поток в RTMP

  • origin nginx — раздаёт поток для просмотра

  • live-cleaner — проводит очистку чанков после завершения стрима

Я думал, что может стать проблемой реализация DVR (Digital Video Recorder) — в контексте видеоплатформы это возможность перемотки и паузы во время прямого эфира, перепросмотра стрима, — но оказалось, что это не проблема. По опыту работы с видеонаблюдением у меня было представление, что для хранения и просмотра записей нам необходим рекордер, — сервер со специальным ПО, который принимает и записывает видеопоток. Но чуть глубже разобравшись с вопросом мне стало понятно, что рекордер как таковой — это программный менеджер, который управляет процессом принятия видеопотока, нарезания его на сегменты, составление манифеста/плейлиста — который позволяет плееру понимать, как можно перематывать видео. В нашем случае функцию такого менеджера выполняет сам бекенд, а записи можно сохранять на S3-хранилище. То есть — я думал что рекордер нам будет нужен в качестве отдельного программного решения, которое нужно будет разработать но — оказалось, что в этом нет необходимости. В нашем случае возможность отмотки видео назад зависит от TTL хранения сегментов этого видео, который можно изменить как нам угодно или вовсе убрать. В итоге стриминг был успешно реализован.

Разделение на микросервисы

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

Разделению предшествовала многоступенчатая подготовка, задачи с наиболее понятными мотивами были бы сформулированы таким образом:

  • фиксация архитектурных границ сервисов, — определение окончательных зон ответственности каждого сервиса

  • подготовка каждого сервиса к изоляции, — убрана жёсткая связанность бизнес-логики с сервисом авторизации, подготовка storage-контракта к переходу на S3 чтобы это не требовало изменения бизнес-логики

  • сквозная корреляция запросов — один request_id проходит через все сервисы, в итоге в логах каждого сервиса можно отследить запрос по единому request_id

  • разделение API и Delivery — API не отдаёт контент а возвращает ссылку, контент отдаёт origin nginx

Само разделение на микросервисы было не сложным, сложной и долгой была подготовка к нему.
После разделения у нас получился следующий список сервисов:

  • processing-worker — асинхронный обработчик видео

  • upload-service — сервис загрузки видео

  • video-api — основной сервис метаданных

  • outbox-publisher — читает записи событий из БД и публикует их в RabbitMQ

  • video-events-consumer — читает события из RabbitMQ, обновляет статусы в БД

  • live-api — управляет live-сессиями

  • live-cleaner — удаляет неактуальный контент из live-storage

  • identity-service — сервис авторизации

  • dlq-replayer — осуществляет retry failed-событий возвращая их в outbox-publisher

  • migrate — одноразовый job для применения Alembic-миграций

  • ingest nginx — принимает RTMP-поток стрима, пишет live HLS-файлы

  • origin nginx — раздаёт HLS-плейлисты, контент

  • RabbitMQ — брокер сообщейний

  • Redis — runtime-хранилище для locks/coordination

  • PostgreSQL(Master+Replica) — база данных Complete_K8S_Stend.png

Схема взаимодействия микросервисов

Схема взаимодействия микросервисов

После разделения платформы на микросервисы появилась проблема согласованности между базой данных и RabbitMQ. Например, сервис мог успешно сохранить изменения в PostgreSQL, но не успеть отправить событие в очередь из-за ошибки или рестарта контейнера.Для решения этой проблемы был реализован outbox pattern. События сначала сохраняются в отдельную outbox-таблицу внутри той же транзакции PostgreSQL, что и изменения основных данных. После этого отдельный сервис «outbox-publisher» считывает события из таблицы и публикует их в RabbitMQ.Этот подход подход позволяет избежать потери событий и обеспечивает более надёжное взаимодействие между микросервисами.

Создание клиентских приложений

До текущего момента тестирование функционала происходило посредством Unit- и E2E — тестов, также с помощью тестовой html-страницы. Возникло желание создать MVP-клиент, который будет работать с API, чтобы посмотреть на сколько оно работоспособно в реальных условиях. Из опыта создания клиентских приложений у меня совершенно не было опыта создания сайтов, но был небольшой опыт создания мобильных приложений под Android. Ранее я использовал Flutter для создания собственного приложения для списка покупок, когда не смог подобрать себе подходящее приложение из тех, что уже были(тогда мне было нужно, чтобы приложение не было перегружено лишним функционалом и имело всё необходимое). В данном случае Flutter позволил бы обеспечить мультиплатформенность, — так как один и тот же код с небольшими правками можно использовать для создания приложения под Android, IOS и веб-сайта, если использовать Flutter Web.

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

Не обошлось без пары доработок API: пришлось дорабатывать ручки стриминга таким образом, чтобы не только создавалась сессия, но и транслировался поток. Пришлось исправить работу live pipline — взаимодействия всех сервисов задействованых в стриминге и привести в порядок эндпоинт запуска сессии, чтобы он возвращал корректную ссылку. Так же пришлось создавать отсутствовавший в принципе эндпоинт для предоставления клиенту Thumbnail, — это картинка/превью в карточке видео. Создание приложения оправдало свои мотивы, — оно помогло выявить недоработки в API, устранить их и в последствии заставить стабильно работать клиентскую часть и бекенд как единый сервис.

Экраны приложения

Экраны приложения

С веб-версией я пришёл к выводу, что для ведоплатформы всё же оптимальнее использовать Next.js, а не Flutter Web — так как последний больше про веб-версию мобильного приложения. А Next.js проще работать с API и HLS-стримингом. Сайт тоже был сделан, почти в той же стилистике и с теми страницами и функционалом что и приложение. Из самых больших отличий — стриминг на сайте происходит через OBS. Пришлось доработать API, чтобы оно корректно отдавало ссылку на стрим и ключ для OBS.

Таким образом появилось возможность мультиплатформенной поддержки сервиса.

Добавление мониторинга

Локально на ПК, где велась разработка, проект запускался через docker-compose, количество контейнеров было около 18. Наверное было бы неплохо, чтобы можно было всё это эффективно наблюдать и быстро понимать, где возникают проблемы. Так я задумался о мониторинге, который в последствии был обеспечен с помощью Prometeus+Grafana. Ну и само-собой — куда же без логов? Так как полнотекстовым поиском в логах моих сервисов искать особо нечего, решил что в Elastic для нас нет необходимости, будем использовать Loki.

Так у нас появилось аж 4 дашборда:

  • Video Platform Overview — показывает состояние всех сервисов, + панель с логами по основных из них (web, upload, video, live, identity)

  • Video Platform Pipeline — показывает работу пайплайна из сервисов по загрузке видео, + их логи (processing-worker, outbox-publisher, video-events-consumer, live-cleaner)

  • Video Platform API — показывает нагрузку на API-сервисы, ошибки, количество запросов в секунду, + логи

  • Video Platform SLO — показывает стабильность пайплайнов, нагрузку на систему, где «застревают»

Перевод проекта в Kubernetes: dev- и cloud-стенды

Наверное у читателя может возникнуть вопрос, — а зачем в данном проекте и в данном случае K8s?

Отвечу честно, — он здесь незачем:

  • у нас нет мультисервера на несколько машин

  • автоматическое масштабирование таких сервисов как processing-worker, live-api, origin nginx без реального запуска проекта в прод в нашем случае будет скорее учебной задачей

  • для нас пока что не критичен отказ сервиса на пару секунд И исходя из этого было бы практичнее оставить проект в docker и может быть использовать Docker Swarm по необходимости, но мне хотелось пощупать руками K8s, поэтому я захотел взяться за эту задачу.

Если не вдаваться в подробности, — переход в K8s благополучно удался. В ходе его реализации я на практике столкнулся с рядом проблем:

  • приведение к рабочему виду переменных окружения, — из .env нужно было разделить ConfigMap и secrets

  • установить правильный порядок старта сервисов, — у меня изначально Alembic-миграции(отдельный job) запускался раньше БД, и миграции не осуществлялись. Теперь job ждёт доступности БД

  • решение проблем с портами и маршрутизацией — сервисы должны быть доступны не только внутри Pod, но и снаружи Kubernetes-кластера. Для внешнего доступа используются NodePort/Ingress-механизмы, а маршрутизация в итоге строится по цепочке: Ingress → Service → targetPort → containerPort.

  • мониторинг так же пришлось перерабатывать под K8s, точнее сделан отдельный мониторинг под K8s-версию стенда

На этом этапе я задумался о том, насколько проект готов к эксплуатации, и рассмотрел возможность развернуть отдельное окружение для друзей. Наверное было бы неплохой идеей арендовать облако и задеплоить туда весь проект, попутно применив на практике Terraform и подключив реальное S3-хранилище, — неплохая практика. После того, как произвёл расчет конфигурации облака, пришло понимание того, что production-like стенд является довольно ресурсоёмким, а аренда на несколько месяцев, не говоря уже о постоянной доступности сервиса, — весьма затратное занятие (около 60-120$ в месяц). Тогда мне вспомнился рассказ одного знакомого DevOPS’a о том, как он собрал дома системный блок под сервер, и появилось понимание мотивов, — почему он это сделал. Для того, чтобы обеспечить постоянную доступность моей видеоплатформы на длительный срок, с финансовой точки зрения было бы выгоднее собрать под неё свой сервер. Оба варианта, — с облачной инфраструктурой и собственным сервером подразумевали под собой финансовые издержки, которые на данный момент не были бы в должной мере целесообразными. Поэтому с «closed beta» я пока решил повременить.

Полностью отказываться от облачного деплоя мне не хотелось, — хотелось понять, как деплоить в облако и использовать Terraform. Тогда возникла необходимость создать для этого облегчённый стенд, — срез из уменьшенного списка сервисов, позволяющий осуществлять только базовые сценарии загрузки и просмотра видео. Облачный срез был организован не как отдельный проект, а именно как еще один стенд в рамках одного проекта.

В него вошли сервисы:

  • identity-service

  • upload-service

  • processing-worker

  • video-api

  • migrate

  • db-master

  • web

  • origin

  • rabbitmq

  • redis

Он тоже был развернут в Kubernetes, для управления конфигурацией на этот раз использовался Helm. Для этого стенда также был создан мониторинг Prometeus+Grafana+Loki. Создана сборка мобильного приложения и сайта для работы с ним. По факту, по сравнению с полной версией, которую можно именовать «локальный dev-стенд», — мы убрали возможность стриминга.

Если в локальном dev-стенде конфигурация описывалась через manifests-файлы, к появлению cloud-стенда уже стало понятно, что поддерживать большое количество manifests не удобно.
Cloud-окружению потребовалось:

  • отдельная конфигурация ingress nginx

  • другие images tages

  • другой набор сервисов

  • отдельные secrets и variables

  • возможность переиспользовать шаблоны

Cloud deployment был переведён в Helm. Он позволил шаблонизировать K8s-конфигурацию и управлять окружением(пока одним) через values-файлы без дублирования manifests. В последствии поддержка cloud-стенда стала существенно проще.

Cloud Deployment

Ранее я уже выполнял ручной деплой на виртуальную машину и VPS с использованием Docker Compose, однако теперь мне возникла необходимость разобраться на практике, как выглядит автоматизированный cloud deployment. После сравнения цен и конфигураций у различных cloud-провайдеров арендовал подходящую VPS-конфигурацию в Timeweb Cloud. Для подготовки облачного окружения использовался Terraform, это позволило описать инфраструктуру в виде кода и с возможностью воспроизведения развернуть необходимые cloud-ресурсы.

В качестве CI/CD-платформы использовался GitLab. Pipeline был разделён на несколько stages:

  • test

  • build

  • security

  • deploy

  • smoke

Успешно пройденные stages из списка выше

Успешно пройденные stages из списка выше

Перейдём к боли и слезам, — пайплайны постоянно сыпались по самым разным причинам. До того момента, как весь pipeline прошел успешно и все stages были завершены без ошибок, произошло около 15-17 падений. Ошибки самыми были разнообразными, ниже описаны некоторые из них(разбиты по категориям).

CI/CD и GitLab:

  • Старый/неработающий GitLab Runner, — создавал на ПК новый и регистрировал

  • CI/CD variables были Protected — REGISTRY_PULL_USER и REGISTRY_PULL_TOKEN не передавались в pipeline потому, что ветка была не protected

  • Smoke-test проверял неправильный endpoint — «curl http://$PROD_DOMAIN/health» давал 404, потому что реальный route ещё не готов, временно сделали smoke non-blocking

  • Rollout checks были слишком жёсткими для первого деплоя — «rollout status deployment/web —timeout=180s» падал раньше, чем сервисы успевали

Работа с GitLab Registry и private images:

  • K8s не мог скачать private images из GitLab Registry — были ошибки 403 Forbidden при pull образов, решили через Project Access Token и imagePullSecret

  • imagePullSecrets не применялись к Pod’ам — добавили imagePullSecrets в templates и дополнительно привязали secret к default ServiceAccount

  • Неверный image tag PostgreSQL — bitnami/postgresql:16 не существовал/не тянулся, использовали конкретный рабочий tag «16.4.0»

Helm и K8s deployment:

  • Helm конфликтовал с уже существующими ресурсами — Namespace и Secrets были созданы вручную/CI отдельно, а Helm не мог “импортировать” их без своих labels/annotations, — дали Helm управлять ресурсами самому

  • Job «migrate» нельзя обновлять как обычный Deployment — помогло удаление старого «migrate job» перед «helm upgrade»

  • Старые failed deploy’ы мешали новым — остатки namespace/resources/jobs приводили к конфликтам, решено иметь процедуру cleanup перед повторным деплоем

K8s networking и ingress:

  • Ingress class не соответствовал кластеру — Chart был настроен на nginx, а в k3s используется traefik, из-за этого запросы давали 404, учли ingress-controller конкретного кластера

Так как в облачном стенде на момент деплоя еще не были реализованы port forwarding и маршрутизация, — API стенда пока что были недоступны, и smoke-тест был по-сути заглушкой. Но позже это было исправлено, и smoke стал делать health-check сервисов.

После того как весь pipeline начал проходить успешно, успешно проходил smoke-тест, к облачному стенду было подключено реально S3-хранилище. Это было сделано, чтобы убедиться, что система способна работать комплексно. CDN’ы я подключать не стал, — это более актуально для полного реального продакшен-стенда.

На этом я решил остановиться и пока приостановить работу над проектом.

Итоги

Всё время работы над проектом мною правило желание изучать что-то новое посредством применения этого на практике.

Если кого-то интересует, использовал ли я нейросети — да, использовал для автоматизации рутины. Приоритетом моей работы не был кодинг как таковой, — более интересными были изучение фреймворка FastAPI, DevOPS-методологии и применение различных технологий. Первый CRUD я написал руками, а по мере роста проекта начал активно использовать ИИ. Основной интерес для меня представляли DevOps-практики, поэтому ИИ выступал скорее инструментом автоматизации рутинной разработки.

На данный момент работа над видеоплатформой завершена, подготовлена документация и мониторинги. Проект готов к развёртыванию, подключению S3-хранилища и CDN. За время работы он разросся настолько, что дальнейшее развитие уже потребует не только доработки бэкенда с инфраструктурой, но и работой над сайтом и приложением, — то есть пользовательской частью в целом.

Создание бизнеса/стартапа мне не интересны, поэтому выкатывать в публичный прод я его не планирую. Но он вполне себе подходит на выполнение роли испытательного полигона для изучения технологий и отработки практических навыков.

За время работы над проектом произошло несколько интересных событий, — однажды перестали быть доступны образы с Docker Hub, пришлось переключаться на Yandex Container Registry. Были ужесточены требования к сайтам и сервисам в интернете. Названия и вывески стали требовать на русском языке, а у меня платформа на английском. На фоне всех этих событий спешить пока не хочется.

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

ссылка на оригинал статьи https://habr.com/ru/articles/1050658/