Как я могу разделить развертывание приложений Django в одном проекте с общими моделями и базой данных?

У меня есть архитектурный вопрос: У нас есть проект Django, состоящий из нескольких приложений. Есть основное приложение, которое хранит основные модели, используемые для других приложений. Затем, у нас есть несколько приложений для пользовательских API. Наконец, у нас есть несколько внутренних приложений и инструментов, используемых только разработчиками, которые доступны в Admin UI как расширенные возможности.

Наш процесс развертывания очень монолитен. Мы используем Kubernetes и развертываем весь проект как единое целое. Это означает, что если у нас есть изменения только во внутреннем приложении, и нам нужно это в продакшене, мы соберем новый образ Docker и развернем новый релиз с новым тегом версии, увеличенным.

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

Мне стало интересно, есть ли способ разделить эти развертывания (может быть, сделать их микросервисной архитектурой?). Таким образом, мы могли бы развернуть приложения для пользователей отдельно от внутренних инструментов. Я знаю, что могу создавать отдельные изображения, теги и все остальное для частей проекта, но я не уверен, как они могут взаимодействовать между собой, если internal_app_1 зависит от моделей приложения core и потенциально от файлов settings.py и manage.py

Кроме того, поскольку в Kubernetes разделение приложений означает разделение развертывания с двумя запущенными серверами, это означает два отдельных проекта Django, изолированных друг от друга, но использующих одну и ту же базу данных.

Кто-нибудь работал с чем-то подобным или хотел бы предложить альтернативу, если таковая имеется?

Ниже приведен пример дерева того, как наш проект структурирован на данный момент:

├── core
|   ├── models.py
|   ├── views.py
|   └── urls.py
├── userapi_1
|   ├── views.py
|   └── urls.py
├── userapi_2
|   ├── views.py
|   └── urls.py
├── insternal_app_1
|   ├── templates
|   |   └── ...
|   ├── models.py
|   ├── views.py
|   └── urls.py
├── manage.py
├── settings.py
└── Dockerfiles
    ├── Dockerfile.core
    └── Dockerfile.internal_app_1

Django и микросервисы? Да, может быть, где-то в параллельной вселенной...

Единственное, что я могу порекомендовать, это создать два одинаковых сервиса, например django_container_internal и django_container_production. В этом случае вы сможете выпускать internal tools без остановки production одного.

Если вы хотите предотвратить доступ к функциональности production с конечными точками internal, вы можете деактивировать production URL с помощью ENVs. Обычно проект Django имеет общую config/urls.py, которая объединяет все конечные точки URL и выглядит как

urlpatterns = [
    url('core/api/v1/', include(core.urls)),
    url('insternal/api/v1/', include(insternal_app_1.urls)),
    url('user/api/v1/', include(userapi_1.urls))
    ...
]

Например, вы можете добавить переменную окружения IS_INTERNAL_TOOLS и обновить urls.py следующим образом

from os import environ

urlpatterns = [
    url('core/api/v1/', include(core.urls)),
    ...
]

if environ.get('IS_INTERNAL_TOOLS', 'false').lower() in ('true', '1', 'yes'):
    urlpatterns.append(url('insternal/api/v1/', include(insternal_app_1.urls)))
else:
    urlpatterns.append(url('user/api/v1/', include(userapi_1.urls)))
  • Плюсы:

    • Все модели будут доступны на обоих сервисах (только один общий DAO => никакой двойной работы разработчиков по созданию моделей дважды)
    • Функциональность разделена, поэтому доступны только необходимые функции
    • Легко реализовать
  • Против:

    • Весь исходный код хранится внутри обоих контейнеров, даже если половина его не используется
    • .
    • Если вы используете две раздельные базы данных для внутренних инструментов и внешнего API, вы должны создать все таблицы в обеих (но похоже, что это не ваш случай)
    • .
    • Потому что это все еще монолит internal и production части сильно зависят от общего core и невозможно развернуть только обновленное ядро отдельно
    • .
Вернуться на верх