— Усталым хипстерам глаголим истину.

Все мы (то есть я) любим тянуть всё новое и блестящее в продакшн, чтобы, наконец-то, заменить одни проблемы другими. Нам (то есть мне) и посвящается эта история.

Чтобы понять и простить дальнейший текст вам понадобятся поверхностные знания как работать с Kubernetes на уровне пользователя и какие-нибудь слухи про Helm.

Давайте сначала абстрагируемся, а потом пусть кто-нибудь с этим разбирается. Представьте себе на минуточку, что мы — эдакий Колумб в мире смузи, электросамокатов и Kubernetes. Наш народ толпится в перенаселённой старушке Европе в одном из её мелких бесконечных государств, разворачивает деплойменты с кронджобами on daily basis под хруст квадрокоптеров. Но астрономы уже обнаружили объяснение подозрительному искривлению горизонта. И вот прям появляется ощущение, что мы — тот самый Чузен Ван современности. (А ведь не просил никто.) И где-то там, за полукруглым океаном — кратчайший путь в Индию! Бескрайние просторы, свобода от бремени рутины и много бесплатных ароматных специй. Нужно просто привести туда наших людей и, наконец, освободить их! Раздвигать океаны перед собой — это чересчур даже для такого великолепия как мы. Поэтому нужно строить корабли, паковать в них наши деплойменты, кронджобы и прочих демонов, поднимать сервисы вместо парусов и рулить прямо в светлое туда. Чтобы рулить нужен штурвал, то есть Helm. Он же — шлем. Шлем точно бы пригодился, знай мы наперёд что нас ждёт впереди. Но есть только штурвал. Строить корабли — дело непростое, поэтому нам как бы нужна помощь, но наш народ вечно занят чем-то очень бесполезным. Поэтому приходится как бы самому и как всегда. Потихоньку начинаем, строим маленькую лодочку, гребём в Индию, видим своими глазами бескрайние просторы, берём одну специю, плывём обратно, показываем людям. Людям нравится, они благословляют наши потуги. Затем готовим великий исход, приводим в порядок конфигурации, строим уже много кораблей. Люди подходят, интересуются. Показываем, рассказываем, просвещаем, обещаем, обещаем, обещаем… Чем больше кораблей — тем больше интерес. Кто-то присоединяется, помогает. Чтобы зря всё это не простаивало, плаваем в staging неподалёку, специй там ещё нет, жить там невозможно, но туристам нравится. И вот, спустя недели/месяцы/лучшие-годы/рукава он, ТОТ САМЫЙ ДЕНЬ, настал! Пора выпустить флотилию и покорить заветную terra incognita. С трепетом в душе плывём наш народ в Индию, а там, нутыпонел, Америка. И всё вроде очень похоже, но вот это предчувствие… Наши люди конечно сразу входят во вкус (ха-ха, им вообще всё-равно, на самом деле), начинают осваивать территорию, домики там, капуста, сервисы всякие разворачивают. Но то тут, то там что-то периодически пропадает, как сквозь землю. То этаж исчезнет, то кокос не родит. И мы такие бормочем с нарастающим гулом “погодите, постойте, я ещё не готов, дайте только день…”. А ещё так прищуриваемся внимательно, а там, впереди, за каждым кустом ВНЕЗАПНО проявляются индейцы с томагавками и смотрят так… недобро что ли… И холодок вот прям холодный пробегает по межушному ганглию. А народ такой: — «А чё это там? А этаж мой где?» А мы такие: — “Мой народ! Не то, чтобы я 40 лет вводил вас в заблуждение, да и назад никто, конечно, не погребёт, но вот прям срочно, *****, НАДО СТРОИТЬ ЧАСТОКОЛ!!!!!!” А они такие: — «А, ну понятно, как всегда опять».

Вот примерно так я себя почувствовал, когда перевёл энное количество сервисов в production с чистого Kubernetes на Helm, а потом напоролся на это.

Ну и в конце обещанная спасительная соломинка. Сначала лайт-версия, зато с объяснением вышесказанного бреда. Вот демонстрационный сценарий:

  1. Допустим, я разворачиваю chart для project:1.5. Впервые с Helm, а до этого был просто Kubernetes.
  2. Затем обнаруживаю, что в релизе есть бага, а в версии 1.4 её не было. И надо бы откатиться, но для неё и Helm чарта тоже не было. Поэтому решаю сделать по старинке: kubectl set image deployment/project project=registry.project.com/project:1.4 --record. Для этого и для пачки других сервисов, которые разворачивались вместе.
  3. Затем обнаруживается, что бага как бы не в этом сервисе, а в соседнем, а с этим всё хорошо и надо вернуть 1.5. Вот если вызвать helm upgrade --install, то ждёт большой сюрприз (больше деталей): image будет всё ещё от 1.4, а labels — от 1.5. И Helm показывает, что всё хорошо, там вообще-то 1.5 развёрнут и даже pods перезапущены были (CI-билд зелёный).

Как этого избежать? Если делается какое-либо изменение любого ресурса K8s, подконтрольного Helm, чистыми командами kubectl поверх развёрнутого Helm Chart, то отменять эти изменения нужно тоже командами kubectl. Helm может развернуть новый чарт. Но он сравнивает новый чарт с предыдущим, но не с актуальным состоянием ресурсов. И если вы отредактировали image, то будущая версия Chart, вероятно, будет содержать другой image и всё будет хорошо. Но вот если вы отредактировали переменную окружения, или аргументы запуска, или ещё что-то, то новая версия Chart скорее всего не отличается от предыдущей. И ваши ручные изменения останутся на месте после обновления.

А на закуску, тяжелая версия спасительной соломинки для тех, кто не может согласиться с подобной непредсказуемостью состояния.

Новые технологии — источник новых печалей.

Комментарии (5)


  1. shurup
    13.10.2018 07:30

    Вот тут ещё было много критики, одобренной в нашем корпоративном чатике… Мы и сами думали написать что-то подобное:



    (И в комментариях к той статье обозначенная проблема звучала, кстати.)

    Так или иначе — вы уже поспособствовали, и у нас теперь есть ещё один повод. Спасибо, а вы там держитесь… хотя бы за соломинку! :-)


    1. KIVagant Автор
      13.10.2018 10:54

      > UPGRADE FAILED: «foo» has no deployed releases

      Хорошая статья. Хорошо, что не прочитал раньше, а то бы отказался от этой идеи :D

      Я уже наступил на половину граблей из той статьи. Там конечно сказано, что в Helm совсем никакой пользы, но на самом деле она есть. Он убрал ряд бессмысленных вещей, которые приходилось постоянно делать. Самое главное в нём то, что он создаёт пакет из мелких частей и таки позволяет ограниченно темплейтить (хотя Go Templates — то ещё извращение) Я также поддерживаю идею, что Tiller сам по себе бесполезен (хотя неплохо видеть список релизов, а не отдельных ресурсов K8s). От идеи создавать мега-Chart с dependencies всех зависимых проектов я отказался сразу, на этапе Proof of Concept. Слишком уж много подозрительного. Но если не делать гигантские пакеты — то вроде ничего так. А вот то, что в статье указано, что иногда не обновляются лимиты для ресурсов — это печалит, так как это был следующий запланированный этап развития наших Chart. Предупрежу коллег.


  1. prozac_ua
    13.10.2018 10:26

    Очень понравился слог. Прям как у Тургенева. Но Куб далеко не Ася…
    +


  1. past
    15.10.2018 15:11

    А по моему очевидно, что если вы деплоитесь хелмом, то не стоит лезть туда руками, ну и наоборот.
    Это как поставить в дебиан пакет из убунту через dpkg, а потом негодовать, что apt-get сломался.


    1. KIVagant Автор
      15.10.2018 18:58

      И да, и нет. Не совсем очевидно, если вы привыкли пользовать kubectl apply. Всё-таки Kubernetes — система немного отличающаяся от просто операционки. Механизм гарантирует применение отличий и за всё время использования я ни разу не сталкивался с какими-то неожиданными эффектами. И именно поэтому поведение Helm вызывает удивление.
      Имея встроенный механизм в Kubernetes, разработчики не стали его использовать.

      С точки зрения разработки Helm, мне лично не кажется хорошей идеей _запретить_ людям пользоваться kubectl. Очевидно, что существует вагон и тележка случаев, для которых Helm не проектировался. Но установка конкретной версии конфигурации должна гарантировать, что она вся будет применена, а не только какие-то куски, которые отличаются от предыдущей.

      Да и с пакетом дебиан в убунту параллель не совсем удачная. Тут скорее иное: если вы ставите Nginx 1.15, затем редактируете какой-то его файл (не конфигурацию, а именно файл пакета), а затем снова ставите Nginx 1.16 (да или даже 1.15 заново), то врядли вы ожидаете, что apt-get оставит ваш файл нетронутым, верно? Особенно если он именно отчитывается, что поставил и перезапустил пакет, а не просто «эта версия уже установлена».