-
v1.1.1
Суффикс добавляется к идентификатору реплики: нужен, когда в одном поде несколько контейнеров участвуют в выборах каждый со своим Lease. Без суффикса у них одинаковый holderIdentity, что затрудняет диагностику по Lease. Обратная совместимость сохранена: без переменной поведение прежнее. и правки по логирования ошибки одной
-
v1.1.0
Sidecar `leader-election:v0.5` считывал ServiceAccount-токен только один раз при запуске контейнера. После ротации projected-токена sidecar продолжал использовать старый токен, из-за чего Kubernetes API возвращал ошибку 401. В результате контейнер переставал продлевать блокировку, и среди реплик больше не оставалось активного лидера. При этом диспетчер событий не падал и не сообщал об ошибке. Он продолжал работать, но постоянно находился в состоянии «я не лидер». Liveness-проба оставалась зелёной, поэтому Kubernetes не перезапускал pod. В результате события продолжали накапливаться в таблице events, а для восстановления работоспособности требовался ручной перезапуск pod. Для устранения проблемы механизм выбора лидера был перенесён из отдельного sidecar-контейнера непосредственно в само приложение. Теперь выбор лидера выполняется с использованием объекта Lease из группы coordination.k8s.io. Для работы с ним используется client-go, который перечитывает файл с токеном по мере необходимости. Поэтому ротация ServiceAccount-токена теперь обрабатывается автоматически и не приводит к потере лидерства. Для реализации используется пакет gitlab.systems-fd.com/packages/golang/servers/leader-election версии v1.1.0. Публичный API пакета при этом не изменился, поэтому код самого сервиса дополнительно менять не требуется. В рамках изменений был удалён sidecar leader-election и его подключение из deployment.yaml. Также были изменены права ClusterRole: разрешения для работы с endpoints и неиспользуемые разрешения для persistentvolumes, persistentvolumeclaims, storageclasses и events заменены необходимыми правами для работы с leases. Переменная LEADER_ELECTION_HOST была заменена на LEADER_ELECTION_NAME, в которой указывается имя объекта Lease. Переменная LEADER_ELECTION_SERVICE_NAME продолжает использоваться без изменений. Из values.yaml был удалён блок leaderElection, а из Service — отдельный порт election. Кроме того, Leader Election [STUB] был удалён из списка сервисов. При работе вне Kubernetes реплика автоматически считает себя лидером. Перед слиянием изменений необходимо влить MR по пакету и установить тег v1.1.0, после чего обновить версию пакета в go.mod. Выполнять merge и деплой до этого нельзя, поскольку Helm-чарт уже не содержит sidecar и соответствующей конфигурации. Если оставить старую версию пакета, приложение продолжит искать лидера через HTTP на localhost:27890. Поскольку такой лидер больше не будет запущен, отправка событий остановится на всех репликах. При раскатке необходимо учитывать особенности переходного периода. Во время rolling update старые pod будут определять лидерство через Endpoints, а новые — уже через Lease. Поскольку используются разные объекты Kubernetes, в течение короткого промежутка времени теоретически могут существовать два лидера одновременно. Дополнительный риск связан с тем, что LoadEvents выполняет чтение без FOR UPDATE, поэтому в этот момент возможна повторная отправка одних и тех же событий в Kafka. Окно такого состояния небольшое, однако если получатели событий не поддерживают идемпотентную обработку, на время раскатки рекомендуется оставить одну реплику либо выполнять обновление в период минимальной нагрузки. После деплоя необходимо проверить, что объект Lease создаётся и корректно обновляется. Для этого можно выполнить kubectl get lease -n <ns> и kubectl describe lease <chart>-leader-election -n <ns>. В поле holderIdentity должен находиться pod, который в данный момент является лидером. Также для проверки перехода на новый механизм можно удалить старый объект Endpoints командой kubectl delete endpoints <chart>-leader-election -n <ns>. Этот объект является остатком старой реализации через sidecar и после перехода на Lease больше не должен использоваться для выбора лидера.