Я использую три раскладки: английскую, русскую и чешскую. Первые две переключаю по капслоку, постоянно.
А вот с чешской раскладкой всё немного сложнее. По умолчанию она как стандартная QWERTZ, но с дополнительным рядом букв вместо цифр.
Добавлять ещё одну раскладку в систему и переключать мне очень не хотелось. Поэтому решил замапить чешские символы на английскую раскладку. Таким образом Caps Lock стал для меня своего рода вторым шифтом для ввода чешских символов:
Есть, дажепарочка, правда они уже несколько устарели.
На самом деле я бы советовал обратиться к официальной документации LINSTOR. Там всё более-менее понятно расписано.
Я бы согласился работать по 10 часов в день вместо 8 ради четырёхдневной рабочей недели, но не согласился бы сокращать своё рабочее время, так как его и так всегда не хватает.
Ну а вообще лучше сразу установить 28-часовой день:
Так всё же опционально, опция allow-two-primaries по умолчанию не включена и не позволяет делать больше одного мастера в DRBD-кластере.
Тут ещё интереснее вопрос возникает. Если у нас бездисковый арбитр, то если у нас была авария (питание отключали), то при старте кто победит? Грубо говоря, чья реплика правильная?
Наличие кворума определяет разрешено ресурсу переходить в Primary или нет. Так же при потере кворума, блокируется весь I/O. Таким образом у нас просто не получится завести устройство, до того момента пока не будет восстановлен кворум.
Правильность устройств определяется с помощью DRBD-битмапа. Каждое устройство "помнит" о состоянии каждого. То есть при старте победит тот, кто находится в кворуме и тот кто был в UpToDate на момент инцидента с отключением питания.
Так же полагаю, но не могу быть точно уверен, что так как в нашем случае diskless-реплика потеряет своё состояние, она не сможет проголосовать в кворуме за того или иного кандидата. То есть кластер будет ждать обе diskful-реплики.
Это вы рассказываете, как отрезать гангренозные конечности.
Но ведь вопрос был как решить, а не как предотвратить split brain в условиях двух нод. В целом наличие кворума решает поставленную задачу.
давайте "два мастера" делать.
Мультимастер в DRBD существует всего-лишь для одной простой цели — лайфмиграция, использование опции allow-two-primaries для чего-то ещё на постоянной основе, крайне нерекомендуется даже самим LINBIT.
То есть включать allow-two-primaries и поднимать какой-нибудь OCFS поверх DRBD на двух нодах, как в большинстве статей на хабре — это ужасный антипатерн и так делать никогда не надо :)
Появление третьей ноды радикально решает проблему, но… На трёх нодах уже становится интересным поднять (условный) ceph и не мучать бабушку.
Вы немного застряли в прошлом, когда было принято делать одно большое DRBD-устройство и его нарезать на части, а так же холить и лелеять его.
С девятой версии DRBD поменял курс на "по отдельному DRBD-устройству на виртуалку", стал поддердживать diskless-реплики, появился оркестратор и в целом мазать его по большому кластеру стало намного проще и удобнее.
Считаю что выбирать технологию нужно исходя от задачи. Да, Ceph простой, но медленный, а также за него приходится много платить вычислительными ресурсами.
У DRBD есть несколько киллер-фич:
Во первых это сравнительно дешёвая производительность. В отличие от аналогов он реально быстрый и почти не потребляет ресурсов.
Дата-локалити. То есть мы можем запускать рабочую нагрузку там же где и хранятся данные, получая ещё большую производительность.
А отказ отдельных устройств или всей плоскости управления не приводит к отказу всей системы.
Дополнительные фичи вроде шифрования, снапшотов и дедупликации добавляются с использованием уже существующих технологий: LUKS, ZFS/LVM, VDO
К сожалению за всё это приходится платить удобством использования (обновлять модуль ядра на большом количестве нод - это то ещё удовольствие) и невозможностью создать блочное устройство размером большим чем пул хранения на одной ноде.
Для начала определим что такое split-brain. Каждая реплика может быть как connected так и disconnected по отношению к другой. Если реплика самопроизвольно переходит в StandAlone. Значит что она отказывается принимать состояние и синхронизироваться с другой. Это классический split-brain.
Решение split-brain для двух реплик производится точно так же, как и в случае с несколькими репликами.
Для начала определим с какой реплики мы хотим синхронизироваться. Для этого смотрим в
drbdadm status <res>
Если нужная нам реплика находится в состоянии StandAlone или Outdated/Inconsistent её нужно сначала перевести в UpToDate, для этого заходим на ноду с этой репликой и выполняем:
А для того чтобы заставить остальные реплики забыть о своём состоянии и синхронизировать данные с UpToDate-реплик, логинимся на ноду с ними и выполняем:
Стоит признать что в последних версиях LINSTOR включена по умолчанию функция auto-tiebreaker, которая при создании ресурса в двух репликах автоматически добавляет третью diskless-реплику, которая является своего рода арбитром для поддержания кворума. Таким образом решать split-brain в наши дни приходится всё реже.
Metal3 использует под капотом ironic. Что прикольно: IP адреса и ноды выделяются кластерам полностью в динамическом режиме. С другой стороны там по прежнему имеется процесс установки ОС на хост и, на мой взгляд, несколько переусложнённая логика. Чтобы разобраться и настроить всё это вам потребуется протратить не один день.
Отличная статья, но на мой взгляд местами too opinionated :)
Ничего не имею против Werf, я люблю стандартизацию подходов и тулза у вас вышла отличная, но тем не менее выскажу немного критики по содержанию:
CI/CD у нас обычно несколько окружений (production, staging, development и т. д.). И конфигурация приложения может отличаться для разных окружений.
Технически Helm позволяет конфигурировать описанный chart параметрами, через которые передаются образы приложения и выбранное окружение. Однако конкретный путь — как это делать — не стандартизован. Пользователю Helm приходится решать это самому.
На счёт "не стандартизован" соглашусь, вариантов достичь желаемого достаточно много: можно передавать параметры через опции CLI или переменные окружения; можно пилить umbrela-чарты с оверрайдами для каждого энвайромента, но считаю что подход с использованием нескольких values файлов наиболее стандартным и популярным:
-f base.yaml -f stage.yaml
-f base.yaml -f prod.yaml
Кстати, аналогичным образом можно передавать и секреты.
Если я правильно понял, werf позволяет реализовать тот же паттерн, но в виду упомянутого вами гитерминизма, по прежнему, не является правильным. К слову, тот же Helmfile позволяет указать набор параметров для хельма в зависимости от конкретного энвайромента.
Таким образом у меня по прежнему возникает вопрос: каким образом в werf правильно хранить и передавать параметры для разных энвайроментов? :)
werf должна поддерживать GitOps-подход
GitOps в общем виде — это подход, при котором для развертывания приложений в Kubernetes используется единственный источник правды — Git-репозиторий. Через декларативные действия в Git вы управляете реальным состоянием инфраструктуры, запущенной в Kubernetes. Этот паттерн «из коробки» работает в werf.
У нас есть собственный взгляд на то, как должен быть реализован GitOps для CI/CD (уже упомянутый Giterminism). GitOps в werf поддерживает не только хранение Kubernetes-манифестов в Git, но и версионирование собираемых образов, связанное с Git. Откат до предыдущей версии приложения выполняется без сборки выкатывавшихся ранее образов (при условии, что версия учитывается политиками очистки). Другие существующие реализации GitOps не дают этой гарантии.
Можно долго ходить вокруг да около GitOps (огромное "спасибо" Weaveworks за то что придумали такой неоднозначный термин). Хранение правды в Git да, но всё-таки оно немного не про то.
Использование GitOps подразумевает наличие контроллера или GitOps-оператора (называйте как хотите), который делает непрерывный синк состояния Git-репозитория с Kubernetes-кластером.
По сути — это такой же reconciling loop, по аналогии с тем как контроллеры Kubernetes создают нижестоящие ресурсы. Например Deployment генерирует ReplicaSet, ReplicaSet генерирует Pods. Таким же образом должен работать и GitOps-оператор, отрендерив код описанного приложения в Git-репозитории, он должен непрерывно перекладывать его в Kubernetes.
Оба решения Helm и Werf не обладают данной характеристикой. Однако иметь контроллер Werf для Flux2, думаю, было бы весьма здорово.
Для организации GitOps, в том понимании в котором он изначально задумывался, таких решения сейчас два: ArgoCD и FluxCD. Второй более нативен к хельму, так как непосредственно использует его для деплоя в кластер.
Забавен тот факт, что применение GitOps может быть вообще не завязано на использование Git. Вышеупомянутые тулзы могут следить и работать также с Helm-registry и даже S3-бакетами.
У нас есть собственный взгляд на то, как должен быть реализован GitOps для CI/CD (уже упомянутый Giterminism). GitOps в werf поддерживает не только хранение Kubernetes-манифестов в Git, но и версионирование собираемых образов, связанное с Git. Откат до предыдущей версии приложения выполняется без сборки выкатывавшихся ранее образов (при условии, что версия учитывается политиками очистки). Другие существующие реализации GitOps не дают этой гарантии.
Здесь стоит упомянуть про kbld и kapp и другие утилиты от Caravel, которые делают примерно тоже самое что и Werf, но без жёсткой привязки к конкретному стеку.
И Gitkube, решения, которое может выступать в качестве гейтвея для деплоя с помощью простого git push, оно также умеет собирать образы и подставлять дайджест в темплейты.
Так как оно представляет своего рода гейтвей Git-to-Kubernetes, оно в принципе не позволяет запушить неисправный коммит в кластер. Таким образом, скрепя зубами, его всё таки можно назвать push-based GitOps-решением, однако оно не развивается уже как 3 года и я не советовал бы его использовать.
Моё мнение, что текущий вектор развития Werf, если вы держите курс на GitOps, должен основываться на изложенных выше идеях. При этом вам не потребуется существенно изменять функционал и логику работы Werf. Наоборот, вам просто нужно дополнить её соответствующим контроллером.
В этом плане мне подход Google Cloud нравится больше. Где у вас по прежнему есть только один аккаунт на сотрудника, но основная единица разделения — это проекты.
То есть вам ничто не мешает иметь несколько проектов за одним аккаунтом, и управлять ими по отдельности, как и подключить несколько аккаунтов к одному проекту.
Кстати, а что произойдет с кластером, если мы восстановим бекап etcd?
Ничего не произойдёт. Kube-apiserver спроектирован так, чтобы по возможности не хранить никакого состояния, поэтому он просто подхватит изменения в etcd. Это работает даже без перезапуска apiserver.
Он резко постарается привести себя в то состояние, в котором был и начнет шедулить 100500 недостающих подов?
Это зависит не от apiserver, а скорее от controller-manager и scheduler. После того как вы востановите бэкап, все ваши ноды будут находиться в том же состоянии на момент которого был сделан бэкап. То есть если они были в Ready, то такими они и останутся до поры до времени. И только спустя 30 секунд (таймаут по умолчанию), если кубелеты не сообщили о своём состоянии аписерверу, controller-manager начнёт переводить их в NotReady и триггерить создание новых подов.
Старые поды при этом останутся работать без изменений, то есть кубелеты самостоятельно не предпринимают никаких действий по удалению подов в случае невозможности связаться с apiserver.
про failed proposals, частые re-elect
Про это мне сказать пока что нечего, если кому есть чем дополнить статью, милости прошу в комментарии :)
Я использую три раскладки: английскую, русскую и чешскую.
Первые две переключаю по капслоку, постоянно.
А вот с чешской раскладкой всё немного сложнее. По умолчанию она как стандартная QWERTZ, но с дополнительным рядом букв вместо цифр.
Добавлять ещё одну раскладку в систему и переключать мне очень не хотелось. Поэтому решил замапить чешские символы на английскую раскладку. Таким образом Caps Lock стал для меня своего рода вторым шифтом для ввода чешских символов:
https://github.com/kvaps/dotfiles/blob/24b6407e90aedd1a762c98485d95a2fd981b94b2/skhd/.config/skhd/skhdrc#L8-L38
Есть, даже парочка, правда они уже несколько устарели.
На самом деле я бы советовал обратиться к официальной документации LINSTOR. Там всё более-менее понятно расписано.
Надёжность я воспринял by default, мы же сетевой сторадж выбираем :)
Я бы согласился работать по 10 часов в день вместо 8 ради четырёхдневной рабочей недели, но не согласился бы сокращать своё рабочее время, так как его и так всегда не хватает.
Ну а вообще лучше сразу установить 28-часовой день:
Так всё же опционально, опция
allow-two-primaries
по умолчанию не включена и не позволяет делать больше одного мастера в DRBD-кластере.Наличие кворума определяет разрешено ресурсу переходить в
Primary
или нет. Так же при потере кворума, блокируется весь I/O. Таким образом у нас просто не получится завести устройство, до того момента пока не будет восстановлен кворум.Правильность устройств определяется с помощью DRBD-битмапа. Каждое устройство "помнит" о состоянии каждого. То есть при старте победит тот, кто находится в кворуме и тот кто был в
UpToDate
на момент инцидента с отключением питания.Так же полагаю, но не могу быть точно уверен, что так как в нашем случае diskless-реплика потеряет своё состояние, она не сможет проголосовать в кворуме за того или иного кандидата. То есть кластер будет ждать обе diskful-реплики.
del
Но ведь вопрос был как решить, а не как предотвратить split brain в условиях двух нод. В целом наличие кворума решает поставленную задачу.
Мультимастер в DRBD существует всего-лишь для одной простой цели — лайфмиграция, использование опции
allow-two-primaries
для чего-то ещё на постоянной основе, крайне нерекомендуется даже самим LINBIT.То есть включать
allow-two-primaries
и поднимать какой-нибудь OCFS поверх DRBD на двух нодах, как в большинстве статей на хабре — это ужасный антипатерн и так делать никогда не надо :)Вы немного застряли в прошлом, когда было принято делать одно большое DRBD-устройство и его нарезать на части, а так же холить и лелеять его.
С девятой версии DRBD поменял курс на "по отдельному DRBD-устройству на виртуалку", стал поддердживать diskless-реплики, появился оркестратор и в целом мазать его по большому кластеру стало намного проще и удобнее.
Считаю что выбирать технологию нужно исходя от задачи. Да, Ceph простой, но медленный, а также за него приходится много платить вычислительными ресурсами.
У DRBD есть несколько киллер-фич:
Во первых это сравнительно дешёвая производительность. В отличие от аналогов он реально быстрый и почти не потребляет ресурсов.
Дата-локалити. То есть мы можем запускать рабочую нагрузку там же где и хранятся данные, получая ещё большую производительность.
А отказ отдельных устройств или всей плоскости управления не приводит к отказу всей системы.
Дополнительные фичи вроде шифрования, снапшотов и дедупликации добавляются с использованием уже существующих технологий: LUKS, ZFS/LVM, VDO
К сожалению за всё это приходится платить удобством использования (обновлять модуль ядра на большом количестве нод - это то ещё удовольствие) и невозможностью создать блочное устройство размером большим чем пул хранения на одной ноде.
Для начала определим что такое split-brain. Каждая реплика может быть как connected так и disconnected по отношению к другой. Если реплика самопроизвольно переходит в StandAlone. Значит что она отказывается принимать состояние и синхронизироваться с другой. Это классический split-brain.
Решение split-brain для двух реплик производится точно так же, как и в случае с несколькими репликами.
Для начала определим с какой реплики мы хотим синхронизироваться. Для этого смотрим в
Если нужная нам реплика находится в состоянии StandAlone или Outdated/Inconsistent её нужно сначала перевести в UpToDate, для этого заходим на ноду с этой репликой и выполняем:
А для того чтобы заставить остальные реплики забыть о своём состоянии и синхронизировать данные с UpToDate-реплик, логинимся на ноду с ними и выполняем:
Стоит признать что в последних версиях LINSTOR включена по умолчанию функция auto-tiebreaker, которая при создании ресурса в двух репликах автоматически добавляет третью diskless-реплику, которая является своего рода арбитром для поддержания кворума. Таким образом решать split-brain в наши дни приходится всё реже.
Хабр уже не торт
Спасибо за отзыв!
Metal3 использует под капотом ironic. Что прикольно: IP адреса и ноды выделяются кластерам полностью в динамическом режиме. С другой стороны там по прежнему имеется процесс установки ОС на хост и, на мой взгляд, несколько переусложнённая логика. Чтобы разобраться и настроить всё это вам потребуется протратить не один день.
Краткое содержание статьи ;)
Отличная статья, но на мой взгляд местами too opinionated :)
Ничего не имею против Werf, я люблю стандартизацию подходов и тулза у вас вышла отличная, но тем не менее выскажу немного критики по содержанию:
На счёт "не стандартизован" соглашусь, вариантов достичь желаемого достаточно много: можно передавать параметры через опции CLI или переменные окружения; можно пилить umbrela-чарты с оверрайдами для каждого энвайромента, но считаю что подход с использованием нескольких values файлов наиболее стандартным и популярным:
Кстати, аналогичным образом можно передавать и секреты.
Если я правильно понял, werf позволяет реализовать тот же паттерн, но в виду упомянутого вами гитерминизма, по прежнему, не является правильным. К слову, тот же Helmfile позволяет указать набор параметров для хельма в зависимости от конкретного энвайромента.
Таким образом у меня по прежнему возникает вопрос: каким образом в werf правильно хранить и передавать параметры для разных энвайроментов? :)
Можно долго ходить вокруг да около GitOps (огромное "спасибо" Weaveworks за то что придумали такой неоднозначный термин). Хранение правды в Git да, но всё-таки оно немного не про то.
Использование GitOps подразумевает наличие контроллера или GitOps-оператора (называйте как хотите), который делает непрерывный синк состояния Git-репозитория с Kubernetes-кластером.
По сути — это такой же reconciling loop, по аналогии с тем как контроллеры Kubernetes создают нижестоящие ресурсы. Например Deployment генерирует ReplicaSet, ReplicaSet генерирует Pods. Таким же образом должен работать и GitOps-оператор, отрендерив код описанного приложения в Git-репозитории, он должен непрерывно перекладывать его в Kubernetes.
Оба решения Helm и Werf не обладают данной характеристикой. Однако иметь контроллер Werf для Flux2, думаю, было бы весьма здорово.
Для организации GitOps, в том понимании в котором он изначально задумывался, таких решения сейчас два: ArgoCD и FluxCD. Второй более нативен к хельму, так как непосредственно использует его для деплоя в кластер.
Забавен тот факт, что применение GitOps может быть вообще не завязано на использование Git. Вышеупомянутые тулзы могут следить и работать также с Helm-registry и даже S3-бакетами.
Здесь стоит упомянуть про kbld и kapp и другие утилиты от Caravel, которые делают примерно тоже самое что и Werf, но без жёсткой привязки к конкретному стеку.
И Gitkube, решения, которое может выступать в качестве гейтвея для деплоя с помощью простого
git push
, оно также умеет собирать образы и подставлять дайджест в темплейты.Так как оно представляет своего рода гейтвей Git-to-Kubernetes, оно в принципе не позволяет запушить неисправный коммит в кластер. Таким образом, скрепя зубами, его всё таки можно назвать push-based GitOps-решением, однако оно не развивается уже как 3 года и я не советовал бы его использовать.
Моё мнение, что текущий вектор развития Werf, если вы держите курс на GitOps, должен основываться на изложенных выше идеях. При этом вам не потребуется существенно изменять функционал и логику работы Werf. Наоборот, вам просто нужно дополнить её соответствующим контроллером.
В этом плане мне подход Google Cloud нравится больше. Где у вас по прежнему есть только один аккаунт на сотрудника, но основная единица разделения — это проекты.
То есть вам ничто не мешает иметь несколько проектов за одним аккаунтом, и управлять ими по отдельности, как и подключить несколько аккаунтов к одному проекту.
Дельное замечание, про потерю кворума дополнил.
Ничего не произойдёт. Kube-apiserver спроектирован так, чтобы по возможности не хранить никакого состояния, поэтому он просто подхватит изменения в etcd. Это работает даже без перезапуска apiserver.
Это зависит не от apiserver, а скорее от controller-manager и scheduler. После того как вы востановите бэкап, все ваши ноды будут находиться в том же состоянии на момент которого был сделан бэкап. То есть если они были в
Ready
, то такими они и останутся до поры до времени. И только спустя 30 секунд (таймаут по умолчанию), если кубелеты не сообщили о своём состоянии аписерверу, controller-manager начнёт переводить их вNotReady
и триггерить создание новых подов.Старые поды при этом останутся работать без изменений, то есть кубелеты самостоятельно не предпринимают никаких действий по удалению подов в случае невозможности связаться с apiserver.
Про это мне сказать пока что нечего, если кому есть чем дополнить статью, милости прошу в комментарии :)
Имелось ввиду скорее второе утверждение чем первое, что etcd лежит в основе Kubernetes.
Исправил пунктуацию, спасибо :)
Ох и правда, побежал обновляться!
Вот бы они ещё решили 21-летний баг с Ctrl+Q и цены бы им не было.
https://bugzilla.mozilla.org/show_bug.cgi?id=52821
I don't care about cookies!
UPD: Выше отписал что нашёл более изящное решение.
Имя секретов теперь не меняется, так что это утверждение вновь становится верным.