Команда Netflix Cloud Data Engineering с радостью открывает исходный код s3-flash-bootloader, нашего инструмента для выполнения обновления образа ОС на месте на государственных облачных инстансах, подставляя новый AMI вместо старого. В этом посте я расскажу о некоторых моментах, побудивших нас разработать этот инструмент, и обсужу, как он на порядок ускорил обновление Cassandra и Elasticsearch.

Первоначальная мотивация

В конце 2017 года я занимался разработкой AMI для бенчмарка Cassandra, который работает на инстансах c cохранением состояния. Нестационарные инстансы отличаются быстрым временем итерации, поскольку мы можем развернуть новые облачные инстансы для замены старых. В отличие от них, stateful инстансы Cassandra медленно развертывались, поскольку им требовалось скопировать все данные со старого инстанса на новый. Мне стало интересно, смогу ли я достичь безэталонного уровня маневренности с помощью облачных инстансов, работающих на эфемерном хранилище без состояния. Я начал искать способы выпекать AMI, как обычно, но развертывать их в уже запущенных инстансах EC2. Я спросил: есть ли способ перезаписать старый AMI более новым?

В EC2 AMI - это, по сути, просто снимок EBS, упакованный вместе с некоторыми дополнительными метаданными о том, как запустить инстанс (существуют также AMI "instance-store", которые поддерживаются объектами в S3, но они менее распространены). Когда инстанс запускается, EC2 создает новый том EBS из снимка, и этот том EBS становится корневой файловой системой виртуальной машины. В своей первой попытке я пытался найти способ подменить корневое устройство EBS только что запущенного инстанса корневым устройством старого инстанса. Этот подход не сработал: EC2 (разумно) не позволяет отсоединять корневое устройство EBS от работающего инстанса. Я также не мог остановить инстанс, поскольку остановка инстанса привела бы к депровизации его эфемерного хранилища, что потребовало бы длительной перекачки данных от других членов кластера. Целью здесь была скорость, поэтому любое решение, требующее перемещения терабайтов данных, было неприемлемо.

Затeм я искал способы изменить содержимое корневого тома EBS, чтобы оно точно соответствовало только что созданному AMI. Другие подходы могли бы использовать управление конфигурацией (например, Puppet, Chef, Ansible) для выполнения необходимых программных изменений. Проблема с этими инструментами заключается в том, что они вносят дрейф и не могут обеспечить гарантии того, что создаваемое ими состояние машины будет точно соответствовать AMI, который был пропущен через наш конвейер сборки и проверки.

В итоге я выбрал более простой подход: сценарий, который перезагружает инстанс в операционную систему в памяти (подобно Linux LiveCD). При запуске ОС-загрузчик обращается к S3, загружает образ, который байт за байтом идентичен снимку EBS, содержащемуся в запеченном AMI, и "прошивает" его на корневое устройство. После этого процесса файловая система неотличима от корневого устройства только что запущенного AMI. Перезагрузитесь еще раз, и машина загрузится в новый образ ОС вместо старого.

Другая мотивация

Когда я представлял результаты своего бенчмарка команде, я упомянул, как я прошивал AMI, чтобы увеличить скорость итераций, и что это может быть полезной техникой для других членов команды, чтобы использовать ее при интеграционном тестировании своих собственных AMI. Мой коллега Джоуи Линч ответил: "Забудьте об использовании этого в dev, что если бы мы использовали это в prod!".

Отдельно от моей работы Джоуи и наша команда Cassandra оценивали способы обновления ОС на нашем парке из десятков тысяч инстансов. Netflix переходил с Ubuntu Trusty на Ubuntu Xenial (см. также доклад Эда Хантера на LISA18). Кроме того, команда хотела развернуть новую версию самого хранилища данных. Учитывая наши масштабы, мы хотели свести к минимуму участие человека, необходимое для осуществления этого перехода, и (конечно же) мы хотели добиться этого с минимально возможным риском.

Альтернативы

Прежде чем перейти к обновлению на месте, мы рассмотрели два других класса подходов к решению проблемы обновления ОС:

  • использование встроенных в Ubuntu возможностей обновления релиза (do-release-upgrade)

  • перемещение данных в новые инстансы

Ранее мы использовали встроенные возможности обновления Ubuntu в гораздо меньших масштабах, но идея использовать их для флота нашего размера была непривлекательной. Нам пришлось бы отвлекать узлы от производственного трафика, пока каждый из них выполнял обновление, и каждому узлу потребовалось бы больше времени на мутацию, чем на простую прошивку образа ОС объемом 10 ГБ. Кроме того, не было никакой гарантии, что обновленные серверы будут иметь ту же конфигурацию, что и свежезагруженные: каждый обновленный сервер был бы своей собственной уникальной снежинкой.

Перемещение данных в новые инстансы было привлекательным, потому что такое решение позволяло осуществить программные и аппаратные изменения за один шаг. К сожалению, такое решение является более рискованным и ресурсоемким по сравнению с оставлением данных на месте и изменением операционной системы. Риск возрастает, поскольку перемещение данных создает вероятность их повреждения, в то время как при прошивке на месте объем данных остается нетронутым. Если оценивать ресурсоемкость, то инстанс EC2 i3.8xlarge может хранить до 7600 ГБ и имеет сетевую карту 10 Гбит/с. Даже если бы мы насытили сетевую карту инстанса, передача набора данных заняла бы 1 час 41 минуту. В итоге мы пришли к выводу, что решения, связанные с перемещением данных, желательны, но мы не хотим блокировать обновление программного обеспечения в рамках отдельного проекта для обеспечения возможности замены оборудования.

Примечание: это не уникальная ситуация.

Модернизация компьютера путем прошивки нового образа диска поверх старого - это несколько необычно для облака, но вполне типично для других областей вычислительной техники. Для многих типов встроенных устройств и сетевого оборудования все обновления выполняются именно таким образом. В двух известных мне популярных операционных системах, ChromeOS и CoreOS, этот способ обновления является основным. (А CoreOS работает в облаке!).

Большинство систем, которые обновляются путем прошивки, имеют два раздела, основной и резервный. Это позволяет им прошивать образ на резервный раздел без перезагрузки в операционную систему в памяти, но требует дополнительных функций от загрузчика для переключения между двумя разделами. Остальная часть Netflix не использует такую функциональность, поэтому ее создание поставило бы нашу команду "в тупик" на пути поддержки. Такие изменения также нарушили бы наше желание сохранить байт за байтом верность между корневым устройством обновленного инстанса и корневым устройством только что запущенного AMI. На самом деле, единственной подсказкой, указывающей на то, что обновление произошло на месте, является метка инстанса EC2, которую мы создаем для использования нашими системами аудита инфраструктуры.

Кэш страниц

Когда машина перезагружается, она, к сожалению, теряет страничный кэш ОС, который она использовала для ускорения чтения с диска. Для достижения базовых задержек наши инстансы полагаются на данные, находящиеся в кэше страниц в горячем состоянии, поэтому запуск с пустым кэшем страниц приведет к возникновению от нескольких минут до нескольких часов задержек, нарушающих SLO. Чтобы избежать этой проблемы, мы использовали написанный мной инструмент под названием happycache для сброса местоположений кэшированных страниц перед перезагрузкой. Как только система восстанавливается, happycache перезагружает страницы, которые были ранее кэшированы. Это существенно снижает наблюдаемую задержку, вызванную перезагрузкой.

Заключение: как все прошло?

После того, как мы усовершенствовали наш инструментарий, мы могли обновлять узлы и обслуживать трафик на производстве с интервалом в 10 минут. Только около 5 минут из этого времени было посвящено самому обновлению, а остальное время использовалось для изящного удаления узла из производственного трафика, загрузки новой ОС и перезагрузки кэшированных страниц с диска с помощью happycache.

Мы завершили наше первое обновление в течение нескольких недель, успешно перейдя с Trusty на Xenial и развернув новый дистрибутив Cassandra. Теперь мы используем эту технику для регулярного обновления как Cassandra, так и Elasticsearch. Наличие такого инструмента позволило нам создать интегрированный конвейер, который тестирует новые версии наших AMI и развертывает их, когда они проходят проверку, обеспечивая настоящий CI/CD для stateful services в Netflix. Но для меня самым большим достижением стало то, что мы смогли сказать команде безопасности: "каким бы ни был патч, мы можем полностью развернуть его за 24 часа".

Благодарность

Джоуи Линчу за его работу по созданию s3-flash-bootloader и за то, что он изначально указал на полезность этой техники в производстве.

Харшаду Фадке за адаптацию s3-flash-bootloader для использования с Elasticsearch.

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


  1. serge_nn
    09.08.2022 20:48
    +2

    Перевод просто ужасен. Для начала, заголовок статьи говорит не "в будущем", а "в будущее" ("into the future"). Увидев "на государственных облачных инстансах", я решил, что лучше прочитаю оригинал.

    (В переводе, чуть ниже слово "stateful" вообще не переведено, а просто оставлено как есть; "stateless" неправильно переведено как "нестационарные". Есть еще много "интересных" моментов, хотелось бы подчеркнуть, что "gracefully" в этом контексте не значит "изящно". IMHO, русский язык для подобных статей неадекватен, лучше читать оригиналы.)