Гибкая непрерывная интеграция для iOS

18 мая 2023

Как Airbnb использует AWS, Packer и Terraform для обновления macOS на сотнях машин непрерывной интеграции (CI) за несколько часов вместо нескольких дней.

Авторы: Michael Bachand, Xianwen Chen

В Airbnb мы запускаем комплексный набор задач непрерывной интеграции (CI) перед объединением каждого изменения кода iOS. Эти задачи гарантируют, что основная ветка проекта остается стабильной, выполняя критически важные рабочие процессы разработчиков, такие как создание приложения iOS и выполнение тестов. Мы также планируем задания, которые выполняют периодические задачи, такие как отчётность о метриках и загрузка артефактов.

Многие из наших задач непрерывной интеграции (CI) iOS выполняются на компьютерах Mac, что позволяет запускать инструменты разработчика, предоставляемые Apple. Задачи непрерывной интеграции (CI) для всех остальных платформ Airbnb выполняются в контейнерах на экземплярах Amazon EC2 на операционной системе Linux.

Чтобы удовлетворить требованиям macOS для задач CI на iOS, исторически мы поддерживали альтернативную инфраструктуру CI вне AWS, специально для разработки под iOS. Появление компьютеров Mac в AWS дало нам возможность переосмыслить наш подход к CI в iOS.

Мы разработали следующую итерацию нашей системы CI для iOS в конце 2021 года, завершили переход на
новую систему в середине 2022 года и дорабатывали систему до конца 2022 года. CI для iOS и всех других
платформ в Airbnb уже использовали Buildkite для диспетчеризации заданий. Теперь мы развертываем
инфраструктуру непрерывной интеграции iOS на AWS с помощью Terraform, что помогает согласовать CI для
iOS с CI для других платформ в Airbnb.

В этой статье мы с радостью поделимся с вами подробностями гибкой и легко поддерживаемой системы CI
для iOS, которую мы реализовали с помощью экземпляров Amazon EC2 на Mac.

 

Проблемы при работе CI на физических компьютерах Mac.

Исторически мы запускали систему CI для iOS в Airbnb на физических компьютерах Mac. Нас устраивала
скорость выполнения CI без виртуализации, но при этом мы несли значительные затраты на обслуживание,
связанные с запуском задач CI непосредственно на физическом оборудовании. Инженеру инфраструктуры
для iOS приходилось авторизоваться на каждом из более чем 300 компьютеров, чтобы выполнить задачи по
администрированию, такие как регистрация Mac в нашей системе управления мобильными устройствами
(MDM - Mobile Device Management) и обновление macOS. Требования по ручному обслуживанию ограничивали
масштабируемость парка компьютеров и занимали время инженера, которое можно было бы лучше
использовать для более приоритетных проектов.

Инженер удаленно обновляет несколько физических компьютеров Mac до macOS Big Sur. EC2 macOS AMI устранил эту ручную работу.

Наши старые машины CI редко перезапускались и слишком часто переходили в неоптимальное состояние.
Когда это происходило, лучший сценарий заключался в том, чтобы инженер мог авторизоваться на
проблемной машине, определить, какие конфигурационные отклонения вызывают проблемы, и вручную
привести машину в рабочее состояние. Чаще всего мы выключали поврежденную машину, чтобы она больше
не принимала новые задачи CI. Периодически мы просили вендора, управляющего нашими физическими Mac
компьютерами, восстановить поврежденные машины до чистой установки macOS. Когда машины в конечном
счёте снова заходили в сеть, мы вручную повторно регистрировали каждую машину в MDM, чтобы
восстановить полную емкость нашего парка.

Обновление до новой версии Xcode также часто приводило к ошибкам. Мы стремимся регулярно внедрять
новые версии Xcode, так как многие инженеры iOS в Airbnb внимательно следят за релизами Swift и Xcode и
стремятся использовать новые возможности языка для улучшения среды разработки. Однако фиксированная
емкость нашего парка Mac компьютеров затрудняла нам тщательную проверку задач CI для iOS на новых
версиях; любая машина, выделенная для тестирования новой версии Xcode, больше не могла принимать
задачи CI от предыдущей версии Xcode. Риск при каждом обновлении Xcode возрастал еще и потому, что
откат к предыдущей версии Xcode на всем парке компьютеров был бы нецелесообразным.
 

 

Обновление CI с помощью пользовательских образов AMIs (Amazon Machine Images) для macOS

Оценивая AWS мы были в восторге от возможности запуска экземпляров на основе образов Amazon Machine
Images (AMI). AMI представляет собой снимок состояния экземпляра, включая содержимое его файловой
системы и другие метаданные. Amazon предоставляет базовые образы AMI для каждой версии macOS и
позволяет клиентам создавать собственные образы AMI на основе работающих экземпляров.

AMI позволяют нам добавлять новые экземпляры в наш парк компьютеров без вмешательства человека.
Экземпляр EC2 Mac на основе бесплатно настраиваемого AMI готов принимать новые задачи сразу после
инициализации. При обновлении macOS нам больше не требуется авторизоваться на каждой машине в нашем
парке. Вместо этого мы авторизуемся в одном экземпляре, запущенном на базе AMI от Amazon для
обновления до новой версии macOS. После выполнения нескольких ручных настроек, таких как включение
автоматического входа в систему
, мы создаем базовый AMI Airbnb на основе этого экземпляра.

Изначально мы использовали в нашем парке EC2 Mac вручную созданные AMI. Инженер настраивал один
экземпляр и создавал AMI на основе состояния этого экземпляра. Затем мы могли запускать любое
количество дополнительных экземпляров из этого AMI. Это было значительным улучшением по сравнению с
управлением физическими машинами, поскольку мы могли развернуть целый парк идентичных экземпляров
после успешной настройки только одного экземпляра.

Теперь мы создаем AMI с помощью Packer. Packer программирует запуск и настройку экземпляра EC2 с
использованием шаблона, определенного на языке конфигурации HashiCorp (HCL). Затем Packer создает AMI
из настроенного экземпляра EC2. Сценарий-оболочка на Ruby последовательно вызывает Packer и выполняет
полезные проверки, такие как проверка того, что пользователь принял соответствующую роль AWS. Мы
проверяем код шаблона HCL в системе контроля версий, и все изменения в нашем шаблоне Packer и
сопутствующих сценариях осуществляются через запросы на внесение изменений в GitHub.

$ time ./make_ami.rb \

--instance-type mac2.metal \

--source-ami macos_arm_autologin_enabled \

--xcode-version 'Xcode 14.2.0 (14C18)'

# real 60m21.652s

# user 0m41.418s

# sys 0m32.152s

Статистика времени создания нового Arm AMI с помощью Packer. Эта команда выполнялась на экземпляре EC2 mac2.metal.

Изначально мы запускали Packer с ноутбуков разработчиков, но ноутбук должен был быть включенным и
подключенным к Интернету на протяжении всего процесса сборки с использованием Packer. В итоге мы
создали отдельный пайплайн для сборки AMI в облаке. Разработчик может запустить новую сборку в этом
пайплайне всего лишь несколькими кликами. Успешная сборка приведет к созданию свежих и проверенных
образов AMI для архитектур процессоров x86 и Arm (Apple Silicon) в течение нескольких часов.

 

Определение среды непрерывной интеграции (CI) в Terraform.

Наша новая система CI, использующая эти образы AMI, состоит из нескольких сред, каждой из которых можно
управлять независимо. Центральным компонентом AWS каждой среды CI является группа
автомасштабирования (Auto Scaling group), которая отвечает за запуск экземпляров EC2 Mac. Количество
экземпляров в группе автомасштабирования определяется свойством desired capacity и ограничивается
свойствами min и max size.

Группа автоматического масштабирования (Auto Scaling) создает новые экземпляры с использованием
шаблона запуска. Шаблон запуска определяет конфигурацию каждого экземпляра, включая AMI, и позволяет
запускать "пользовательский сценарий" при запуске экземпляра. Шаблоны запуска могут иметь несколько
версий, и каждая группа Auto Scaling настроена на запуск экземпляров из определенной версии своего
шаблона запуска.

Несмотря на то, что введение сред разработки сделало нашу топологию непрерывной интеграции (CI) более
сложной, мы считаем, что эта сложность управляема, когда наша инфраструктура определена в виде кода.
Вся наша инфраструктура AWS для CI iOS описана в коде Terraform, который мы проверяем в системе контроля версий. Каждый раз, когда мы объединяем запрос на включение изменений, связанных с CI iOS,
Terraform Enterprise автоматически применяет наши изменения к нашей учетной записи AWS. Мы определили
модуль Terraform, который мы можем вызывать каждый раз, когда мы хотим создать новую среду CI.

module "ios-ci-arm-xcode-14-2" {

source = "../modules/ios-platform"

instance_type = "mac2.metal"

launch_template_version = 23

ami_filter = "ios-ci-xcode_14_2_0-*"

max_num_instances = # redacted

max_num_instances_weekends = # redacted

buildkite_tags = {

queue = "ios-ci-arm-xcode-14-2"

}

# additional configuration excluded for brevity

}

Вызов модуля Terraform для создания среды CI Arm Mac Minis с установленным Xcode 14.2.

Внутренняя служба масштабирования управляет необходимой емкостью группы Auto Scaling в каждой среде разработки. Этот сервис, являющийся модифицированным ответвлением buildkite-agent-scaler, увеличивает желаемую емкость группы Auto Scaling среды по мере увеличенияобъема CI-задач для этой среды. Мы указываем максимальное количество экземпляров для каждой среды CI, в частности, потому что On-Demand EC2 Mac Dedicated Hosts в настоящее время имеют минимальное распределние хостов и продолжительность выставления счета в течение 24 часов.

Эскиз новой системы CI Airbnb для iOS.

Каждая среда CI имеет уникальное имя очереди Buildkite. Отдельные задачи CI могут быть направлены на
экземпляры в определенной среде, указав соответствующее имя очереди. Если имя очереди не указано явно,
задачи будут выполняться в среде CI по умолчанию.

 

Преимущества нашей новой системы iOS CI

Среды непрерывной интеграции (CI) обладают высокой гибкостью.

С помощью этой новой настройки Terraform мы можем поддерживать произвольное количество сред CI с
минимальными накладными расходами. Мы создаем новую среду CI для каждой архитектуры процессора и
версии Xcode. Мы даже можем дублировать эти среды на нескольких версиях macOS при выполнении
обновления операционной системы в нашем парке устройств. Мы используем выделенные промежуточные
среды для тестирования задач CI на экземплярах, запущенных из нового AMI, прежде чем широко внедрять
это AMI.

Когда мы больше не используем CI-среду регулярно, мы можем указать минимальную емкость нуля при
вызове модуля Terraform, что приведет к установке такого же значения в базовой группе Auto Scaling. Затем
группа Auto Scaling будет запускать экземпляры только тогда, когда ее желаемая емкость увеличивается
службой масштабирования. На практике мы обычно удаляем более старые среды из нашего кода Terraform.
Однако даже после завершения работы со средой, восстановить эту среду так же просто, как отменить
несколько коммитов в Git и повторно развернуть службу масштабирования.

 

Ротация экземпляров повышает согласованность CI

Чтобы свести к минимуму возможность отклонения экземпляров EC2, мы ежедневно завершаем все
экземпляры и заменяем их. Таким образом, мы можем быть уверены, что наш парк CI находится в заведомо
рабочем состоянии в начале каждого дня.

Когда экземпляр завершается, базовый Dedicated Host проходит процесс очистки перед запуском нового
экземпляра на этом хосте. Мы завершаем экземпляры в период низкого количества запросов на CI, чтобы
процесс очистки EC2 Mac мог завершиться до того, как нам потребуется запускать новые экземпляры на тех
же хостах. Когда экземпляр завершает работу накануне, он уменьшает желаемую емкость группы
автоматического масштабирования, к которой он относится. Когда инженеры начинают вносить коммиты на
следующий день, служба масштабирования увеличивает желаемую емкость в соответствующих группах Auto
Scaling, что приводит к запуску новых экземпляров.

Задачи CI переносятся с Xcode 14.1 на 14.2. 24-го числа мы временно увеличили емкость для версии 14.2, чтобы справиться с ростом количества задач.

Благодаря этим возможностям iOS разработчики Airbnb получают быстрый доступ к новым функциям языка
Swift и улучшениям среды разработки Xcode. Фактически, благодаря нашей новой системе непрерывной
интеграции (CI), мы заметили увеличение скорости обновления Xcode более чем на 20%. На момент
написания статьи, мы уже внедрили все доступные основные и второстепенные версии Xcode 14 (14.0–14.3),
сразу после их выпуска.

 

Миграция завершена

За последние три месяца 2022 года наша новая система непрерывной интеграции (CI) обработала более 10
миллионов минут CI-задач. После перехода на EC2 мы заметно сократили количество часов, затрачиваемых
на обслуживание, несмотря на растущий объем кодовой базы и постоянно высокую загрузку задач. Наша
новая возможность масштабирования CI для удовлетворения изменяющихся потребностей сообщества iOS
разработчиков Airbnb оправдывает возросшую сложность перестроенной системы.

После миграции на AWS, iOS CI получает ещё больше преимуществ от общей инфраструктуры, которая уже
успешно используется внутри Airbnb. Например, новая архитектура iOS CI позволила нам избежать
реализации iOS-специфического решения для автоматического масштабирования емкости. Вместо этого мы
используем вышеупомянутую модифицированную версию buildkite-agent-scaler, которую инженеры Airbnb уже
преобразовали во внутреннюю службу Airbnb с отдельной линией развертывания. Кроме того, мы
использовали существующие модули Terraform, поддерживаемые другими командами, для интеграции с IAM и
SSM.

Мы обнаружили, что экземпляры EC2 Mac, запущенные из пользовательских AMI, обеспечивают множество
преимуществ виртуализации без ущерба для производительности, характерного для выполнения виртуальной
машиной. Мы считаем, что AWS, Packer и Terraform являются неотъемлемыми технологиями для создания
гибкой системы непрерывной интеграции (CI) для масштабной разработки iOS в 2023 году.

...
Ксианвэнь Чен, технический лидер этого проекта, разработал топологию системы iOS CI, реализовал ее с
помощью Terraform и позже обеспечил возможность создания AMI в облаке. Майкл Баканд создал
первоначальную версию нашего инструментария Packer и использовал его для создания первых программно
создаваемых AMI, способных выполнять задачи iOS CI. Стивен Хептинг производственно внедрил наш
инструментарий Packer, добавив поддержку Arm AMI и развивая шаблон Packer таким образом, чтобы все
задачи iOS CI в Airbnb могли успешно выполняться на обеих архитектурах процессора.

Мы получили бесценную поддержку от множества экспертов по предметной области в Airbnb, которые щедро
уделили свое время. Большое спасибо Брэндону Куртцу за консультации по контенту и стилю во время
множественных правок данной статьи.

Автор статьи: Майкл Баканд
Статья написана для The Airbnb Tech Blog


Оригинал статьи

Содержание