деплоймент что это такое кфс
Непрерывный деплоймент на практике
Автор: Mike Bria
Вот что говорит Maurya насчет того, почему не сработал предыдущий процесс с однонедельным циклом релизов:
Процесс выпуска релиза занимал полдня, а иногда и день. Выделение до 20 процентов времени в неделю на выпуск релиза очень расточительно для маленькой команды. Это не считая усилий по координации, необходимых для приоритезации постоянно меняющегося состава релиза.
Его переход к непрерывному деплойменту начался со статьи Eric Reis 5 step continuous deployment primer. Далее его рассказ посвящен тому, что Maurya считает наиболее сложным аспектом: просто “освоиться с постоянными релизами.”
Мы пошли простым путем – делали небольшие изменения и маниакально проверяли процесс релиза. Я начал полагаться на функциональные тесты (а не на unit тесты), что позволяло мне тестировать изменения так, как это сделал бы сам пользователь. Я определил набор событий, которые могли бы сигнализировать когда что-то идет совсем не так (например, в системе нет пользователей) и создал систему оповещения о них в реальном времени (используя nagios/ganglia). Наша уверенность росла, и мы начали вносить (commit) все бОльшие изменения, состоящие из нескольких частей. Каждый раз мы дополняли набор наших тестов и скриптов для мониторинга системы. После нескольких итераций наш уровень страха стал ниже, чем был на поэтапных (staged) релизах. Поскольку мы вносили меньше кода за релиз, мы могли точнее связывать появление проблем с произошедшей выкладкой.
Maurya описывает следующие принципы/практики непрерывного деплоймента:
Case Study: Непрерывный деплоймент
Автор: Ash Maurya
В данной статье приводится пример (case study) перехода от традиционного цикла разработки к непрерывному деплойменту. Многие люди все еще считают эту идею сложной, даже те компании, которые работают исключительно в web. В этом примере все даже сложнее: разбирается ситуация непрерывного деплоймента для настольного приложения. Возможно ли обеспечить деплоймент на постоянной основе в этом случае? Читайте далее.
Ash Maurya основатель WiredReach. Это startup, которым он управлял в течение семи лет. Недавно он увлекся темой Lean Startup и начал писать о своем опыте применения принципов lean startup и customer development. Его пост Achieving Flow in a Lean Startup я назвал одним из моих любимых постов за 2009 год.
Ниже описан его личный опыт, возникшие проблемы и решения, которые он для них находил. Если вы хотите опубликовать статью о своем опыте, можно начать с добавления ее в секцию Lean Startup Wiki case study section. –Eric
Eric Ries, автор блога Startup Lessons Learned
Из всех методов Lean Startup-а наиболее спорным является непрерывный деплоймент. Непрерывный деплоймент это процесс, по которому программное обеспечение выпускается несколько раз в день: минуты в противовес дням, неделям или месяцам. Непрерывный поток производства – это Lean метод. Производительность повышается за счет перестройки производственных процессов таким образом, что продукт создается от начала и до конца, один за раз (цельный поток производства), в отличие от более распространенного подхода с партиями и очередями.
Непрерывный деплоймент – это непрерывный поток в применении к производству программного обеспечения. В обоих случаях задача – ликвидировать потери. Самые крупные потери в производстве создаются из-за необходимости перевозить продукцию из одного места в другое. Самые крупные потери в разработке ПО создаются из-за ожиданий, пока ПО переходит из одного состояния в другое: ожидание кода, результатов тестирования, деплоймента. Уменьшение или исключение этих ожиданий ведет к ускорению итераций, что является ключом к успеху.
Мой переход к непрерывному деплойменту
До перехода на непрерывный деплоймент у меня был недельный график релизов. Я считал это достаточно подвижным, дисциплинированным и агрессивным процессом. В понедельник я идентифицировал код, который нужно будет обязательно поставить. Четверг был официальным днем отсечки кода для релиза. Пятница была днем релиза. Процесс релиза занимал по крайней мере полдня, а иногда и весь день. 20 процентов времени в неделю уходило на процесс релиза, что очень расточительно для маленькой команды. Это не считая усилий по координации, необходимых для приоритезации постоянно меняющегося состава релиза. Несмотря на эти проблемы, я боролся с искушением перейти на более длинный двухнедельный или ежемесячный цикл релизов, потому что я хотел быстро реагировать на запросы клиентов (что они очень ценят). Управление еженедельными релизами стало намного сложнее, когда я начал customer development. Я проводил больше времени вне своего офиса, что означало – меньше времени для кодирования, тестирования и деплоймента. Некоторые вещи начали ускользать от меня. Тогда я разработал набор мер (описанных здесь), что в итоге привело меня к непрерывному деплойменту.
Основная сложность непрерывного деплоймента – освоиться с постоянными релизами.
С непрерывным деплойментом релизы перестают быть событиями, а добавление кода в базу становится триггером для создания нового релиза. С одной стороны это позволяет моментально реагировать на запросы заказчиков. С другой стороны это очень пугает. В поэтапных релизах время обеспечивает (в чем-то иллюзорную) безопасность. Более комфортно разделять ответственность за тестирование с кем-то еще (с командой тестировщиков). Никто не хочет отвечать в одиночку за то, что рабочая система “упала”. Мне не нужно было рассматривать эти аргументы. У меня не было времени и команды тестировщиков.
Я пошел простым путем – делал небольшие изменения и маниакально проверял процесс релиза. Я начал полагаться на функциональные тесты (а не на unit тесты), что позволяло мне тестировать изменения так, как это сделал бы сам пользователь. Я определил набор событий, которые могли бы сигнализировать когда что-то идет совсем не так (например, в системе нет пользователей) и создал систему оповещения о них в реальном времени (используя nagios/ganglia). Наша уверенность росла, и мы начали вносить (commit) все бОльшие изменения, состоящие из нескольких частей. Каждый раз мы дополняли набор наших тестов и скриптов для мониторинга системы. После нескольких итераций наш уровень страха стал ниже, чем был на поэтапных (staged) релизах. Поскольку мы вносили меньше кода за релиз, мы могли точнее связывать появление проблем с произошедшей выкладкой.
Мы не удивляемся непредвиденным ошибкам, которые могли произойти из-за слияния больших кусков кода (поскольку нет ветвления – branching). Мы полагаемся на автоматизацию тестирования и мониторинга, это более надежно и последовательно, чем то, что мы делали до этого.
У нас бывают ошибки, и иногда мы вносим плохой код. Но все это не приводит к падению системы. Вместо того, чтобы считать это недостатком процесса, мы рассматриваем это как возможность построить нашу Кластерную Иммунную Систему. Мы стараемся следовать подходу Пяти почему (Five Whys) и не повторять ошибки.Вот что это значит для нас: больше тестов, больше мониторинга, больше оповещений, больше кода и больше процесса.
Мне было необходимо сбалансировать активности “внутри здания” и “вне здания”. Применение непрерывного деплоймента позволило мне построить свой день так, чтобы успевать и то и другое. Ранние релизы это не единственное преимущество непрерывного деплоймента. Небольшие релизы ведут к более быстрым циклам построения/измерения/обучения. Я использовал эти циклы для оптимизации потока активации пользователя (User Activation flow). Также это позволило мне радовать заказчиков почти мгновенным исправлением ошибок, и даже исключать фичи, которыми никто не пользуется.
Конечно легче настроить непрерывный деплоймент для web-приложения. Однако, используя некоторую дисциплину, можно построить процесс непрерывного деплоймента и для настольного приложения. Далее описано, как я реализовал непрерывный деплоймент для своего настольного приложения (CloudFire).
Мой процесс непрерывного деплоймента
Вытягивание против выталкивания фичи (features)
Обнаруженная проблема стоит того, чтобы ее решили. Необходимо построить минимальный жизнеспособный продукт (minimum viable product – MVP). Не нужно добавлять новые фичи, пока вы не определили MVP. Ненужные фичи это потери. Они не только создают больше работы, они еще и бесполезно усложняют продукт.
В идеале, каждая новая фича должна потребоваться более чем одному заказчику, прежде чем попасть в релиз.
Стройте систему в ответ на сигналы от заказчика, а если их нет, то занимайтесь улучшениями.
Как технолог, я очень люблю измерять прогресс базируясь на том, насколько разрослась система. Но я направляю свою энергию не на появление новых фич, а в основном (80%) на измерения и оптимизацию существующих фич. Я не выступаю против того, чтобы совсем не добавлять новые фичи. Обычно пользователи просят больше, и ваш MVP по определению минимальный, и требует больше внимания. Просто не выталкивайте фичи.
Небольшие куски кода (small batches)
Я уже описывал свои двухчасовые блоки работы для максимизации своего рабочего процесса.Перед тем, как начать блок работы, я четко определяю, что нужно сделать (цель) и как (дизайн).
Важно отметить, что целью не обязательно является фича, видимая пользователю, и не обязательно фича целиком. Добавление небольших кусков кода в систему позволяет постепенно решать проблемы интеграции. В течение блока работы я кодирую, делаю unit тестирование, создаю или меняю функциональные тесты. В конце я вношу код (check-in), что автоматически запускает создание билда на сервере. Затем этот билд проходит через unit-тесты и функциональные тесты. В конце создаются следующие артефакты: инсталляции для mac и windows (для новых пользователей) и Eclipse P2 репозиторий (OSGI) для автоматических обновлений (для текущих пользователей). Процесс релиза занимает 15 минут и идет в фоновом режиме.
Предпочитайте функциональные тесты unit тестам, когда это возможно
Я не верю в слепое написание unit тестов для достижения 100% покрытия кода, что обещают некоторые инструменты. Чтобы сделать это, мне нужно было бы смоделировать слишком много критически важных компонентов. Я считаю чрезмерное unit-тестирование напрасной тратой. Когда это возможно, я полагаюсь на функциональные тесты, чтобы проконтролировать действия пользователя. Я использую Selenium, он позволяет контролировать работу приложения на нескольких браузерах и под несколькими операционными системами.Нужно с осторожностью относится к следующему: функциональные тесты работают дольше unit тестов, и это постепенно увеличивает время релиза. Это решается распараллеливанием тестирования на нескольких машинах. Я еще не дошел до этой точки, но, думаю, подойдет Selenium Grid. То же самое делает Go Test It.
Всегда тестируйте путь активации пользователя (User Activation flow)
После прогона интеграционных тестов и после того, как собран программный пакет, я всегда проверяю путь активации пользователя. Путь активации пользователя – это наиболее критический путь для достижения удовлетворенности пользователей или для удовлетворения требований рынка. У меня путь активации пользователя автоматически тестируется на машинах под mac и windows.
Используйте авто-МАГИЧЕСКИЕ обновления
Главная проблема с настольными приложениями (в отличие от web-приложений) это распространение программных обновлений. Исследования показывают, что пользователям мешают диалоги программных обновлений.Чтобы преодолеть это, я использую другую стратегию: обновление происходит незаметно для пользователя, ему не надо прерывать свою работу. Подобная стратегия обновлений используется для Google Chrome. Правда, некоторые пользователи могут рассматривать такой подход как “навязывание”. Но пока что никто из пользователей не жаловался и многим пользователям нравятся авто-обновления. Помогает то, что приложение CloudFire имеет UI, работающий через браузер (это p2web app приложение).
Вот как работает процесс обновлений сейчас:
1. В конце каждого билда мы выкатываем репозиторий Eclipse P2 (OSGI), это набор версионированных plug-in-ов, которые составляют приложение. Поскольку приложение состоит из большого числа маленьких plug-in-ов, и мы добавляем небольшие куски кода, то размер каждого обновления небольшой и обновление быстро загружается.
2. Каждый раз, когда пользователь загружает приложение, оно проверяет, есть ли новое обновление, и если есть, загружает и устанавливает его. В зависимости от типа обновления, оно может начать действовать немедленно или требовать перезагрузки приложения. Если требуется перезагрузка приложения, мы ждем, пока пользователь в следующий раз запустит приложение, или же запускаем его, пока система бездействует.
3. Когда приложение работает, оно периодически проверяет наличие новых обновлений. Если есть обновление, оно загружается и устанавливается в фоновом режиме (как описано выше), не прерывая работу пользователя.
Оповещения и мониторинг
Я использую nagios и ganglia для реализации мониторинга и оповещений о любом ненормальном поведении системы.Примеры того, что попадает под мониторинг: число пользовательских активаций, число активных пользователей, число посещений страниц. Любое выходящее за норму падение этих показателей немедленно оповещает нас (через twitter/SMS) о потенциальной проблеме.
Диагностика уровня приложения
Несмотря на хорошее тестирование, все же бывают дефекты. Увеличение объема тестирования не всегда решает проблему, поскольку некоторые дефекты проявляются непостоянно и зависят от пользовательского окружения. Невозможно протестировать все комбинации аппаратного обеспечения, ОС, браузеров и других приложений (например, Norton anti-virus, Zone Alarm, и т.д.).
Пользователи не всегда сообщают о возникших ошибках. Поэтому нам пришлось встроить диагностику в приложение.Она сообщает пользователю и нам о неожиданных ошибках, и позволяет нам удаленно получить информацию о конфигурации и логи. В случае необходимости мы можем сделать откат обновления.
Допускайте неожиданные ошибки только раз
Неожиданные ошибки дают возможность изучить систему и проверить на прочность. Игнорирование их и создание быстрых и “грязных” патчей ведет к повторению ошибок, т.е. является еще одной формой потерь. Я пытаюсь следовать формализованному процессу Пяти почему (используя внутренний wiki) для каждой ошибки. Это заставляет нас остановиться, подумать и исправить правильную проблему (или проблемы).
Мой процесс непрерывного деплоймента можно представить так:
Так почему же непрерывный деплоймент является спорным?
В своем блоге Eric уже рассмотрел многие из возражений.Одно из них, это то, что для реализации непрерывного деплоймента нужно иметь большую команду. Я бы сказал, что чем более ранняя стадия цикла разработки, и чем меньше команда, тем легче реализовать процесс непрерывного деплоймента. Если вы являетесь start-up командой с MVP, то лучшего момента для внедрения непрерывного деплоймента не найти. У вас пока нет сотен заказчиков, и дюжин фич. Намного проще заложить фундамент сейчас, когда время на вашей стороне.
Что такое деплой?
Деплой — процесс «разворачивания» веб-сервиса, например, сайта, в рабочем окружении. Рабочее окружение — место, где сайт запускается и доступен для запросов. Это может быть как готовый хостинг, так и своя собственная серверная инфраструктура.
Деплоятся не только веб-сервисы, но любые сервисы, доступные по сети. Даже если эта сеть внутренняя и не доступна для запросов через интернет.
Как это происходит. Разработчики добавляют код в репозиторий. В какой-то момент они решают, что пора доставить его до продакшена. Это может происходить как по регулярному расписанию, например раз в две недели, так и просто по необходимости, вплоть до выкатки после каждого изменения. Во многом количество деплоев зависит от уровня его автоматизации — того, насколько процесс легкий в проведении и откате в случае проблем. На Хекслете деплои выполняются практически после каждого изменения, около 3 деплоев в день.
Каждый раз, когда разработчики решили что все, пора, они создают релиз. Под релизом обычно понимают тег в Git, который фиксирует, что уйдет в деплой. То есть изменения, добавленные в мастер после создания тега, не повлияют на сам тег, а значит мы точно уверены в том, что деплоим.
Для статических сайтов или отдельного фронтенда (только HTML, CSS и статические файлы) деплой сводится к обновлению кода на сервере. В ситуации деплоя бэкенда, как минимум, подключается база данных. В общем случае деплой может быть сложной процедурой, занимающей приличное время. В распределенных системах, состоящих из множества независимых веб-сервисов, вообще не бывает общего деплоя — каждая часть приложения деплоится (выкатывается) независимо.
Стоит сказать, что PaaS-платформы, такие как Heroku, берут деплой полностью на себя. Там достаточно выполнить коммит, и дальше все произойдет само. Цена за это — стоимость самой платформы
Шаги деплоя
Доставка кода на сервер
Возможны разные варианты доставки кода на сервер в зависимости от способа его упаковки. Иногда код просто копируют на сервер как набор файлов, но такое встречается редко, чаще он обновляется через Git. Раньше был популярен способ деплоя через стандартные пакетные менеджеры Linux-дистрибутивов. Сейчас он тоже встречается, и для определенных ситуаций подходит лучше всего.
Обновление базы данных
Новая версия приложения, как правило, требует изменений в базе данных. Для этого во время (или до) деплоя запускают миграции — специальные скрипты, содержащие правила обновления базы данных. Например sql-скрипты:
Запуск и остановка
Где-то в этом процессе происходит остановка старой версии и запуск новой. Если сначала остановить старую версию, а потом выполнить миграции и запустить новую, то мы получим простой (downtime) в работе сервиса. Так действительно работают многие, но это может быть болезненно для бизнеса и частых деплоев. Поэтому самые продвинутые проекты не останавливаются во время деплоя. О том, как это делать — ниже.
Автоматизация
Деплой нужно максимально автоматизировать, от этого зависит Time To Market, ключевая характеристика бизнес-ориентированных приложений. Чем быстрее и чаще мы доставляем изменения пользователю, тем лучше. Быстрее проверяем гипотезы, быстрее вносим исправления, быстрее оправдываем деньги, вложенные в разработку. Без автоматизации разработчики боятся выполнять деплой, он становится обузой, что приводит к снижению числа деплоев и регулярному стрессу для всей команды, с засиживанием на работе до позднего вечера.
Основных способа автоматизации три:
Но даже если автоматизация выполнена, все равно остается задача «запустить деплой». Запуск тоже автоматизируется. Существует целый подход, который называется Непрерывная доставка(continuous delivery). Его сложно внедрить и он не везде подходит, но если получилось, то про деплой забывают. Он выполняется полностью сам без участия людей. Главное в таком варианте — хороший мониторинг и система оповещения (алертинг) для реакции на ошибки.
Zero Downtime Deployment
Если не предпринимать специальных шагов, то каждый деплой будет приводить к остановке (возможно частичной) сервиса. В это время пользователи либо увидят ошибку, либо сообщение о происходящем обновлении. Но такого не происходит на большинстве крупных сервисов в интернете. Почему? Из-за реализации подхода «деплой без даунтайма» (downtime — простои в работе сервиса).
Zero Downtime Deployment выглядит так, как будто сервис никогда не останавливается, но при этом обновляется. Достигается это за счет одновременного запуска старой версии и новой кода. То есть когда деплоится приложение, то сначала поднимается новая версия рядом со старой. И только когда автоматика убеждается, что новая версия запустилась и работает, происходит остановка старой версии. Для выполнения этой процедуры понадобится следующее:
10 антипаттернов деплоя в Kubernetes: распространенные практики, для которых есть другие решения
Когда есть контейнеры, работающие в продакшен, нужно, чтобы продакшен-окружение оставалось стабильным и отказоустойчивым. Если один из контейнеров падает, нужно, чтобы в любое время ему на замену был запущен другой.
Kubernetes предоставляет платформу для отказоустойчивой работы распределенных систем — от масштабирования до аварийного переключения и балансировки нагрузки. И есть много инструментов, которые интегрируются с Kubernetes, чтобы помочь вам в этом.
Перевели статью о десяти распространенных практиках развертывания Kubernetes, для которых есть другие решения. Автор не вдается в детали практик, поскольку реализация может различаться у разных пользователей.
1. Размещение файлов конфигурации внутри/рядом с образом Docker
Этот антипаттерн Kubernetes связан с антипаттерном Docker (см. антипаттерны 5 и 8 в этой статье). Контейнеры дают разработчикам возможность использовать единый образ на протяжении всего жизненного цикла программного обеспечения, от разработки/контроля качества до подготовки к продакшен и деплоя в продакшен.
Однако общепринятой практикой является предоставление каждой фазе жизненного цикла собственных образов, каждый из которых построен с различными артефактами, характерными для его среды: контроль качества, stage или продакшен. Но тогда вы больше не деплоите то, что тестировали.
Не включайте конфигурационные файлы в докер-образы. Источник
Лучшей практикой является хранение конфигурации общего назначения в ConfigMaps, в то время как конфиденциальная информация (например, ключи и секреты API) может храниться в ресурсе Secrets. Он имеет кодировку Base64, но в остальном работает так же, как ConfigMaps.
ConfigMaps можно монтировать как тома или передавать как переменные среды, но секреты следует монтировать как тома. Я упоминаю ConfigMaps и Secrets, потому что они являются собственными ресурсами Kubernetes и не требуют интеграции, но у них есть свои ограничения.
Если вы отделили конфигурацию от приложения, больше не нужно пересобирать приложение, когда нужно обновить конфигурацию. Ее можно обновлять во время работы приложения. Ваши приложения получают конфигурацию во время выполнения, а не во время сборки. Что еще более важно, вы используете один и тот же исходный код на всех этапах жизненного цикла программного обеспечения.
Загрузка конфигурации во время выполнения. Источник
2. Работа без Helm или других шаблонизаторов
Вы можете управлять деплоем в Kubernetes, напрямую обновляя YAML. При развертывании новой версии кода вам, вероятно, придется обновить один или несколько ресурсов:
Этот процесс может оказаться утомительным, если вы управляете несколькими кластерами и применяете одни и те же обновления в своих средах разработки, тестовой и производственной среде. Вы в основном изменяете одни и те же файлы с небольшими изменениями во всех ваших развертываниях. Здесь много операций копирования и вставки или поиска и замены, при этом нужно не забыть о среде, для которой предназначено ваше развертывание YAML.
В этом процессе есть много возможностей для ошибок:
Возможно, вам нужно изменить ряд вещей в YAML, и если вы будете невнимательны, YAML одного деплоймента можно легко принять за YAML другого деплоймента.
Шаблоны помогают упростить установку приложений Kubernetes и управление ими. Поскольку Kubernetes не предоставляет собственный механизм шаблонов, мы должны искать сторонние шаблонизаторы.
Helm был первым доступным менеджером пакетов, появился в 2015 году. Он был назван «Homebrew для Kubernetes» и расширен за счет включения возможностей создания шаблонов.
Helm упаковывает свои ресурсы с помощью чартов, где чарт представляет собой набор файлов, описывающих связанный набор ресурсов Kubernetes. В репозитории чартов имеется более 1400 общедоступных чартов (вы также можете использовать helm search hub [ключевое слово] [флаги]), в основном многоразовые рецепты для установки, обновления и удаления в Kubernetes.
С помощью чартов Helm вы можете изменить файл values.yaml, чтобы задать изменения, необходимые для деплойментов в Kubernetes, и вы можете иметь разные чарты Helm для каждой среды. Поэтому, если у вас есть среда контроля качества, промежуточная и производственная среды, нужно управлять только тремя чартами Helm вместо того, чтобы изменять каждый YAML в каждом деплойменте в каждой среде.
Еще одно преимущество Helm заключается в том, что с помощью откатов Helm можно легко вернуться к предыдущей версии, если что-то пойдет не так:
Если вы хотите вернуться к предыдущей версии, вы можете использовать:
Вы увидите что-то вроде:
И история чарта Helm прекрасно это отслеживает:
3. Деплой приложения в определенном порядке
Приложения не должны аварийно завершаться, потому что зависимость не готова. В традиционной разработке существует определенный порядок запуска и остановки задач при запуске приложений.
Важно не переносить это мышление в оркестровку контейнеров, то есть в Kubernetes, Docker и так далее. Эти компоненты запускаются одновременно, что делает невозможным определение порядка запуска. Даже когда приложение запущено и работает, его зависимости могут выйти из строя или быть перенесены, что приведет к дальнейшим проблемам.
В реальности Kubernetes также существует множество точек потенциальных сбоев связи, где невозможно установить зависимости, во время которых может произойти сбой модуля или служба может стать недоступной. Задержки в сети, такие как слабый сигнал или прерывание сетевого соединения, является частой причиной сбоев связи.
Для простоты давайте рассмотрим гипотетическое приложение для покупок, в котором есть две службы: база данных инвентаризации и пользовательский интерфейс витрины. Прежде чем приложение сможет запуститься, внутренняя служба должна запуститься, пройти все проверки и начать работу. Затем интерфейсная служба может запуститься, выполнить ее проверки и начать работу.
Допустим, мы принудительно установили порядок деплоя с помощью команды kubectl wait, например:
Но если это условие никогда не выполнится, следующий деплой не может быть продолжен, процесс прерывается.
Вот упрощенная схема того, как может выглядеть порядок развертывания:
Процесс не может двигаться дальше, пока предыдущий этап не завершен
Поскольку Kubernetes является самовосстанавливающимся, стандартный подход состоит в том, чтобы позволить всем службам в приложении запускаться одновременно, а контейнерам дать возможность сбоя и перезапуска, пока все они не будут запущены и не заработают.
У меня есть службы A и B, запускаемые независимо, как и должно быть построено облачное приложение без сохранения состояния. Но для удобства пользователя, возможно, я мог бы указать пользовательскому интерфейсу (службе B) отображать красивое сообщение о загрузке, пока служба A не готова. При этом фактический запуск службы B не должен зависеть от службы A.
Теперь, если в поде происходит сбой, Kubernetes перезапускает службу, пока все не заработает. Если вы застряли в CrashLoopBackOff, стоит проверить свой код, конфигурацию или конкуренцию за ресурсы
Конечно, нужно делать больше, чем просто полагаться на самовосстановление. Стоит внедрять решения, справляющиеся с отказами, которые неизбежны и будут. Мы должны предвидеть, что они произойдут, и заложить основы для реагирования таким образом, чтобы избежать простоев и/или потери данных.
В моем гипотетическом приложении для покупок пользовательский интерфейс витрины (услуга B) нуждается во второй части (услуга A), чтобы предоставить пользователю то, что нужно. Поэтому при сбоях, например, если служба A недоступна в течение какого-то времени, система все равно должна иметь возможность восстановиться после этой проблемы.
Подобные временные сбои возможны, а чтобы минимизировать их последствия, мы можем реализовать шаблон Retry.
Шаблоны повторных попыток помогают повысить стабильность приложения с помощью таких стратегий, как:
Реализация схемы отключения также является важной стратегией при создании отказоустойчивых приложений на основе микросервисов. Как автоматический выключатель в доме сам отключается, чтобы защитить вас от серьезных повреждений из-за чрезмерного тока или короткого замыкания, так схема отключения цепи предоставляет метод написания приложений с ограничением влияния неожиданных сбоев, которые могут занять много времени. Это такие сбои, как, например, частичная потеря связи или полный отказ службы.
В таких ситуациях, если повторная попытка не сработает, приложение должно уметь установить, что произошел сбой, и отреагировать соответствующим образом.
4. Развертывание модулей без установленных ограничений на память и/или CPU.
Распределение ресурсов зависит от сервиса, который вы деплоите. Может быть сложно предсказать, какие ресурсы потребуются контейнеру для оптимальной производительности без тестирования в реальных условиях. Для одного сервиса может потребоваться фиксированный профиль потребления CPU и памяти, в то время как профиль потребления другого сервиса может быть динамическим.
Когда вы деплоите модули без тщательного анализа ограничений памяти и CPU, это может привести к сценариям конкуренции за ресурсы и нестабильным рабочим средам.
Если контейнер не имеет ограничения памяти или CPU, планировщик видит его использование памяти и CPU как нулевое, поэтому на любом узле можно запланировать неограниченное количество модулей. Это может привести к чрезмерному использованию ресурсов и возможным сбоям узлов и кубелетов.
Когда ограничение памяти не указано для контейнера, есть несколько возможных сценариев (они также применимы к CPU):
Объявление ограничений памяти и CPU для контейнеров в кластере позволяет эффективно использовать ресурсы, доступные на узлах кластера. Это помогает планировщику Kubernetes определить, на каком узле должен располагаться под для наиболее эффективного использования оборудования.
При установке лимитов памяти и CPU для контейнера следует позаботиться о том, чтобы не запрашивать больше ресурсов, чем установлено лимитами. Для модулей, содержащих более одного контейнера, совокупные запросы ресурсов не должны превышать установленные лимиты — в противном случае под никогда не будет запланирован.
Запросы ресурсов не должны превышать лимиты
Установка запросов памяти и CPU ниже их лимитов позволяет добиться двух целей:
Хорошей практикой считается использовать запросы CPU на уровне одного ядра или ниже, и использовать ReplicaSets для масштабирования.
Что происходит, когда разные команды соревнуются за ресурсы при деплое контейнеров в одном кластере? Если процесс превысит предел по памяти, он будет остановлен, а если он превысит предел по CPU, для процесса будет включен троттлинг, что приведет к снижению производительности.
Вы можете управлять ограничениями ресурсов с помощью квот ресурсов и LimitRange в настройках пространства имен. Эти параметры помогают учитывать развертывание контейнеров без ограничений или с большими запросами ресурсов.
Установка жестких ограничений ресурсов может быть не лучшим выбором для ваших нужд. Другой вариант — использовать режим рекомендаций ресурсов в Vertical Pod Autoscaler.
5. Использование тега latest в продакшене
Использование тега latest считается плохой практикой, особенно в производственной среде. Модули неожиданно аварийно завершают работу по разным причинам, поэтому они могут в любой момент удалить докер-образы.
К сожалению, последний тег не очень информативен, когда дело доходит до определения того, когда сборка сломалась. Какая версия образа была запущена? Когда в последний раз он работал? Это особенно плохо в продакшене, поскольку вам нужна возможность восстановить работу с минимальным временем простоя.
Не используйте тег latest в продакшен
По умолчанию для imagePullPolicy установлено значение Always, при перезапуске образ всегда скачивается. Если вы не укажете тег, Kubernetes по умолчанию будет использовать последнюю версию.
Однако развертывание будет обновлено только в случае сбоя, когда под удаляет образ при перезапуске, или при изменении шаблона модуля развертывания (.spec.template). Смотрите это обсуждение на форуме, чтобы увидеть, как тег latest не работает должным образом в процессе разработки.
Даже если вы изменили imagePullPolicy на другое значение, кроме Always, ваш под все равно будет скачивать образ, если ему необходимо перезапуститься, будь то из-за сбоя или преднамеренной перезагрузки.
Если вы используете управление версиями и устанавливаете imagePullPolicy со значимым тегом, например v1.4.0, то можете вернуться к самой последней стабильной версии и легче устранять неполадки, если что-то в коде пошло не так. Вы можете узнать больше о передовых методах управления версиями в Semantic Versioning Specification и GCP Best Practices.
Помимо использования конкретных и значимых тегов Docker, вы также должны помнить, что контейнеры не имеют состояния и неизменны. Они также должны быть эфемерными, вы должны хранить любые данные вне контейнеров в постоянном хранилище. После того, как вы развернули контейнер, нельзя его изменять: никаких патчей, никаких обновлений, никаких изменений конфигурации. Когда вам нужно обновить конфигурацию, вы должны развернуть новый контейнер с обновленной конфигурацией.
Неизменность Docker, взято из Best Practices for Operating Containers
Эта неизменность обеспечивает более безопасное и повторяемое развертывание. Вы также можете легко выполнить откат, если нужно повторно развернуть старый образ. Сохраняя неизменными образы Docker и сам контейнер, вы можете развернуть один и тот же образ контейнера в каждой отдельной среде. Смотрите антипаттерн №1, где мы говорили об экстернализации данных конфигурации, чтобы ваши образы оставались неизменными.
Мы можем вернуться к предыдущей стабильной версии, пока будем устранять неполадки
6. Деплой новых обновлений/исправлений путем уничтожения модулей, чтобы они извлекали новые образы Docker во время процесса перезапуска
Подобно тому как полагаться на тег latest для получения обновлений, полагаться на удаление модулей для развертывания новых обновлений — плохая практика, поскольку вы не управляете версиями своего кода.
Если вы убиваете модули для получения обновленных образов Docker в продакшен, то так лучше не делать. После того, как версия была выпущена в продакшен, ее нельзя перезаписывать. Если что-то сломается, вы не будете знать, где и когда что-то пошло не так и как далеко нужно вернуться, если нужно откатить код во время устранения неполадок.
Kubernetes запустит обновление с нулевым временем простоя:
7. Смешивание производственной и непроизводственной нагрузок в одном кластере
Kubernetes поддерживает пространства имен, которые позволяют пользователям управлять разными окружениями (виртуальными кластерами) в одном физическом кластере. Их можно рассматривать как экономичный способ управления различными окружениями в одном физическом кластере. Например, вы можете запустить stage и продакшен окружения в одном кластере и сэкономить ресурсы и деньги. Однако существует большая разница между запуском Kubernetes в разработке и запуском Kubernetes в рабочем окружении.
При смешивании производственных и непроизводственных нагрузок в одном кластере необходимо учитывать множество факторов. Так, нужно будет рассмотреть ограничения ресурсов, чтобы убедиться, что производительность продакшен окружения не скомпрометирована. Обычная практика — это не ставить квоты на продакшен пространства имен и устанавливать квоты на любые непродакшен пространства имен.
Вам также следует помнить об изоляции. Разработчикам требуется гораздо больше доступов и разрешений, чем нужно в продакшен окружении, и которые вы хотели бы максимально заблокировать. Хотя пространства имен скрыты друг от друга, по умолчанию они не изолированы полностью. Это означает, что ваши приложения в пространстве имен для разработки могут вызывать приложения в тестовом, промежуточном или продакшен окружении (или наоборот), что не считается хорошей практикой. Конечно, вы можете использовать NetworkPolicies, чтобы установить правила для изоляции пространств имен.









