Comments 9
Рассказывать про контейнеры и облака, делая фоточки экрана вместо скриншотов... Киберпанк, который мы заслужили. (:
PS. Еще и с битыми пикселями.
Может, кому пригодится: Запуская Django в кубе с несколькими репликами помните, что миграции придется делать с поддержкой старого кода. Т.е. нельзя будет просто добавить NOT NULL поле, даже если вы укажете default=<value>, т.к. django делает миграции вида
ALTER TABLE mytable
ADD COLUMN mycolumn character varying(50) NOT NULL DEFAULT <value>;
ALTER TABLE ONLY mytable ALTER COLUMN mycolumn DROP DEFAULT;
И по итогу когда вы раскатите вначале на одну реплику код с такой миграцией, то другие реплики начнут падать.
Поэтому лучшим способом здесь будет вначале добавлять nullable поле, задеплоить, затем сделать еще одну миграцию, где убрать это nullable.
Для людей, которые только-только разбираются в кубере:
Никогда не развертывайте СУБД в кубере. Серьезно, не надо. Если используете облако, возьмите managed решение.
Если всё-таки развернуть надо, необходимо использовать statefulset вместо deployment. В статье, к сожалению, ни слова про это.
Job удобная вещь, да. Но для накатывания миграций не годится, лучше использовать init container с deployment приложения.
Спасибо за комментарий! Отвечу по пунктам
На мой взгляд нет ничего страшного в деплое баз данных в Kubernetes. Если понимать, что ты делаешь и делать все аккуратно - проблем, сильно отличающих деплой БД в кубе или нет, не будет. Да, с кубом связан несколько иной процесс выкаток, что нужно перезапускать процессы, это может негативно сказываться на например in-memory кэши БД или если вся база данных in memory - понадобится время, чтобы поднять все обратно в память. В остальном, при наличии хорошего инструментария деплой в кубе наоборот позволяет унифицировать процесс выкаток приложений, особенно если их очень много.
Да, в разделе про недостатки деплоя это имелось в виду, дописал явно про StatefulSet, спасибо.
Хотелось бы услышать ваше мнение более развернуто, почему не годится и почему init контейнер лучше? Если деплоится несколько реплик приложения, то в каждом из них запустится процесс миграций, и оно может начать конфликтовать, плюс чисто логически - зачем запускать одно и тоже действие в параллель несколько раз? Выше правильно написали, что миграции должны быть не ломающими, поэтому если будет фоновая задача которая приведет постепенно схему базы в нужное состояние, наоборот будет лучше, чем выкатка пода заблокируется полностью из-за накатки миграций. Но опять же, может что-то упускаю.
Ну, как вы сами и заметили, необходимо каждый раз удалять джобу перед добавлением новой. Или давать новое имя. Неудобно? Да, потому что джоба нужна для других целей (исключительно моё личное мнение).
Во-вторых, джоба с миграцией никак не связана с подом приложения. То есть, под с новой версией приложения поднялся, а схема БД не может мигрировать из-за каких-либо проблем (это же отдельная джоба, соответственно контейнер с миграцией просто перезапускается). Использование init контейнера не позволило бы в принципе запуститься поду с новой версией приложения.
Прописываете в манифесте джобы .spec.successfulJobsHistoryLimit: 0 и под будет сам удаляться после выполнения.
Какие проблемы могут возникнуть при одновременном запуске нескольких миграций? Одна из них заблокирует базу, остальные будут просто проигнорированы.
Как минимум вы можете использовать helm и часть ваших болей решится с появлением helm.sh/hook и helm.sh/hook-delete-policy
Деплоим приложение на Django в Kubernetes с нуля