Объединение контейнеров OSTree и SW для надежного обновления IoT-устройств

Это пост от гостя Дрю Мозли, архитектора технических решений в Toradex, в котором объясняется, как компания обновляет прошивку Linux IoT-устройств с помощью инструмента для сборки и развертывания операционной системы с открытым исходным кодом OSTree (также известного как libostree), а также программных контейнеров Docker.

Каждый день на рынок выводится все больше и больше подключенных устройств, а общий размер рынка Интернета вещей (IoT) к 2027 году по прогнозам достигнет 1,5 триллиона долларов. Бензиновые насосы, медицинские устройства и системы торговых точек все чаще подключаются друг к другу, что делает практически невозможным избежать взаимодействия с этими устройствами даже для тех, кто абсолютно даек от современных технологий. В домашних условиях такие устройства, как измерители мощности, выключатели света и камеры видеонаблюдения, как правило, подключены к Интернету, что обеспечивает функциональность умного дома.

Уровень сложности программного обеспечения для этих устройств увеличивается с увеличением функциональности, а количество устройств с дефектами программного обеспечения на местах растет. Во многих случаях эти системы проектируются, производятся и поставляются без учета предоставления обновлений программного обеспечения сверх начальной загрузки программы. Это серьезная проблема, и она может выходить далеко за рамки причинения проблем владельцу устройства, добавления гарантии или расходов на отзыв для производителя. Во многих случаях IoT-устройства можно объединить в большие ботнеты IoT, которые из-за большого количества использовались для крупномасштабных атак на критически важные части инфраструктуры, таких как распределенная атака отказа в обслуживании (DDOS) против Dyn Domain Name Service (DNS), что приводит к перебоям в обслуживании крупных организаций, таких как Twitter и Github.

Зачем обновлять устройства?

Самая очевидная причина для предоставления обновлений программного обеспечения устройствам в полевых условиях – устранение уязвимостей программного обеспечения. Не все уязвимости превращаются в эксплойты, приводящие к крупномасштабным атакам, как упоминалось выше, но риск значительный. А поскольку в домах ваших пользователей становится все больше и больше устройств, возможно, появится возможность связать уязвимости с нескольких устройств вместе, чтобы получить более широкий доступ к данным ваших пользователей. На ум приходит один инцидент в неназванном казино была взломана база данных хайроллеров из-за уязвимости в термометре для аквариума с подключением к Интернету. В самолете 787 Dreamliner примерно 14 миллионов строк кода (вероятно, данные ограниченны системой авионики и не включают такие вещи, как бортовые развлекательные системы), по сравнению с примерно 28 миллионами строк кода только в ядре Linux (по состоянию на январь 2020 года). Имейте в виду, что ядро ​​Linux – это только одна часть системы Linux, что указывает на масштаб проблемы. Эти многочисленные строки кода, несомненно, будут содержать множество ошибок, требующих исправления на протяжении всего срока службы вашего продукта.

Предоставление возможности обновления для ваших устройств также позволяет вам предоставлять новые функции вашим пользователям. В зависимости от вашей бизнес-модели это может быть полезно для долгосрочного удержания клиентов или просто для обеспечения возможностей дополнительных продаж и увеличения доходов. Учитывая преимущества возможности обновления, вы можете задаться вопросом, почему какое-либо устройство будет поставляться без этого. Мы с трудом можем определить вариант использования, при котором обновления программного обеспечения были бы совершенно ненужными.

OTA сервер

Любое полностью автоматизированное решение для обновления OTA требует сервера, который управляет парком и позволяет операционному персоналу управлять устройствами. Подробное обсуждение серверной части выходит за рамки этой статьи, но существует множество вариантов. В общем, вы захотите выбрать комплексное решение, означающее, что и сервер обновлений, и клиенты обновлений были разработаны как полное решение, или, по крайней мере, комбинация сервера и клиента была хорошо протестирована и интегрированы друг с другом.

Методы обновления

Существует несколько распространенных методов обновления программного обеспечения.

  • Обновления на основе пакетов на месте : это механизм, используемый большинством операционных систем для настольных ПК. Обычно приложение-установщик или система упаковки запускаются в текущем активном образе ОС. Это может установить все, что необходимо системе, но должно быть сложно гарантировать, что все устройства в вашем парке работают с теми же двоичными файлами, которые вы тестировали в своих конструкторских лабораториях.
    Асимметричные обновления образов: этот метод обычно использует отдельный раздел установщика, который может загружать соответствующие образы и перезаписывать основной раздел ОС. Это устраняет проблему частично установленных наборов пакетов, которая возникает при обновлении на месте, но может привести к длительным простоям ваших пользователей. Это метод, который до недавнего времени использовался для большинства обновлений мобильных телефонов, и мы уверены, что всех нас раздражало количество времени, которое занимает эти обновления.
  • Симметричные обновления образов (обычно называемые двойными обновлениями A / B): этот метод использует полностью избыточные разделы, содержащие активный и пассивный разделы. Во время работы в активном разделе клиент обновления может загрузить и установить полный образ в пассивный раздел. Поскольку все это может происходить в фоновом режиме, пока код вашего приложения активен, это устраняет проблемы простоя, связанные с асимметричными образами. Однако, поскольку он использует полностью избыточные разделы, он обычно занимает больше места на блочном устройстве, чем другие методы.
  • Обновления на основе OSTree : это тема следующего раздела и обеспечивает хорошее сочетание функций, позволяющих минимизировать время простоя устройства и не требуя дополнительного хранилища для размещения избыточных разделов.

OSTree

В документации к проекту OSTree определяется следующим образом:

libostree – это и общая библиотека, и набор инструментов командной строки, которые объединяют в себе «git-подобную» модель для фиксации и загрузки деревьев загрузочных файловых систем, а также уровень для их развертывания и управления конфигурацией загрузчика.

Определение немного туманно, поэтому давайте рассмотрим пример. Сначала мы создадим пустой репозиторий в подкаталоге на нашей рабочей станции разработки. OSTree обычно используется для целых файловых систем, но для простоты мы будем использовать каталог для этого примера.

Мы инициализировали пустой репозиторий. Вы можете видеть, что он создал несколько пустых каталогов и один файл конфигурации. Метаданные репозитория имеют много общего с git. Вы видите знакомые каталоги, такие как refs/head, которые используются аналогичным образом. Теперь добавим файл в репозиторий:

Мы видим, что создано много новых объектов. Файлы .dirmeta, .dirtree и .commit представляют собой метаданные, которые отслеживают метаданные файлов и каталогов (разрешения, владение и т. д.), древовидную структуру каталогов и метаданные фиксации соответственно. Файл refs/Heads/main file содержит хэш фиксации для новой фиксации:

Также обратите внимание, что объект, созданный с расширением .file, идентичен файлу, который мы создали. Это обычно называется хранилищем с адресацией по содержимому, что просто означает, что файлы в хранилище объектов именуются на основе их содержимого. Имя объекта (в данном случае 92/d6c7afcaedabd4504d2e16de3ffc200cd156ac733306cf7b8991f56859bcd5.file) генерируется из sha256sum самого файла, а также атрибутов файла.

Важно отметить, что эти файлы на самом деле являются жесткими ссылками на одни и те же блоки файловой системы. Это важный принцип OStree, который показывает, что он будет очень экономным; любые файлы, которые не меняются между версиями, не будут дублироваться, что приведет к значительной экономии места как для блочного хранилища на устройстве, так и для пропускной способности загрузки при получении новых ревизий.

Как и в случае с git, мы можем удалить файл, а затем снова проверить его из репозитория.

Теперь давайте добавим в репозиторий полную корневую файловую систему. Мы создали простую файловую систему для устройства QEMU Arm с помощью Buildroot.

Теперь мы создадим вторую версию файловой системы. Мы использовали предыдущую конфигурацию Buildroot и добавили служебную программу bc, которая указана в разделе Целевые пакеты\Разное при запуске конфигуратора make menuconfig.

Теперь предположим, что мы решили, что нам больше не нужен двоичный файл bc. Без перестройки мы можем просто вернуться к предыдущему выпуску. Сначала мы проверяем, существует ли bc в нашей текущей файловой системе; потом откатываемся; наконец, мы проверяем, что bc снова является символической ссылкой на busybox:

Последняя функция, которая важна для системы обновления по воздуху, – это удаленные репозитории. Подобно тому, как git использует репозитории – удаленно доступные хранилища данных, содержащие метаданные OSTree. Этот пример выполняется в системе Toradex Verdin i.MX8M Mini под управлением Torizon, который представляет собой промышленную встраиваемую систему Linux, основанную на OSTree. Мы подключаем его к репозиторию Toradex TorizonCore OSTree и проверяем последний ночной выпуск. Есть дополнительные подробности, не описанные здесь, связанные с переключением на новую версию файловой системы при загрузке, так что это атомарная операция.

С набором функций, показанным OSTree, у нас есть основные функции, необходимые для системы обновления OTA:

  • Возможность хранения нескольких версий всей файловой системы.
  • Сохранение старых версий используется для обеспечения надежной возможности отката.
  • Жесткие ссылки используются для оптимизации места для хранения.
  • Удаленные репозитории позволяют подключенным устройствам загружать обновления «по воздуху».

Контейнеры

Контейнеры – это форма виртуализации на уровне ОС, позволяющая запускать приложения в изолированных средах. Они отличаются от виртуальных машин тем, что не виртуализируют всю аппаратную платформу и не запускают полную операционную систему. Их основной вариант использования – инкапсулировать приложение со всеми зависимостями, библиотеками и т. д., которые необходимы ему для работы. Настройка приложения в контейнере позволяет гарантировать соблюдение всех зависимостей без необходимости установки дополнительных пакетов в базовую ОС. Например, если вы запускаете приложение NodeJS, вы упаковываете его в контейнер со средой выполнения JavaScript и всеми другими необходимыми компонентами. Вы можете указать версии каждой зависимости, протестировать все вместе, а затем развернуть точную комбинацию; это избавляет от опасений, что базовый образ ОС может иметь другую версию определенного пакета. Кроме того, он позволяет различным контейнерам при необходимости содержать разные версии компонентов; например, вы можете запустить один пакет с приложением Python с Python v2, а другой контейнер с пакетом, которому требуется Python v3.

В дополнение к управлению зависимостями контейнеры могут изолироваться от других компонентов системы, потенциально повышая безопасность. Используя стандартные функции ядра базовой ОС, контейнеры могут быть ограничены только определенными частями файловой системы, определенными устройствами и даже конкретным процессором в многоядерной системе. В зависимости от используемой среды выполнения контейнера вы можете ограничить общее использование ЦП или памяти отдельными контейнерами, позволяя вашей системе настраиваться в зависимости от шаблонов использования.

Третья главная особенность контейнерных систем – это встроенный механизм доставки. Используя docker, один из самых популярных контейнерных движков, вы можете создавать новые контейнеры, которые наследуют функциональность многих базовых образов, предоставляемых различными поставщиками программного обеспечения. Если у вас есть приложение, написанное на Python v3, и вы хотите запустить его в среде стиля Debian, вы можете создать Dockerfile, который будет выглядеть следующим образом:

Затем вы создаете файл myapp.py в том же каталоге, где находится ваше приложение. В качестве тестового приложения мы будем использовать следующее:

Теперь вы можете собрать и запустить этот контейнер прямо в вашей системе сборки, выполнив следующие действия:

Первая команда создает образы и теги с именем myapp и последней версией. Вторая команда запускает контейнер с командой start, как указано в Dockerfile с оператором CMD. Обратите внимание, что на данном этапе мы не работаем на нашем встроенном устройстве. Вы можете использовать контейнеры для разработки и устранения неполадок на рабочем столе. Для многих задач разработки приложений это более эффективно, чем разработка непосредственно на встроенном устройстве. Когда вы будете готовы запустить контейнер на своем встроенном устройстве, вы можете скопировать весь рабочий каталог на свое устройство и повторно запустить указанные выше команды. Это сработает, когда вы тестируете или имеете дело с небольшим количеством устройств, однако по мере увеличения размера вашего парка вам понадобится лучший механизм доставки. Docker предоставляет удобный механизм для обмена образами. Мы уже использовали это, когда указывали оператор FROM в нашем Dockerfile. Это указывает докеру, что в основе нашего образа лежит образ python: buster, доступном в концентраторе docker. Вы также можете отправить свои образы в концентратор docker или любой другой репозиторий docker, что полезно, если вы хотите, чтобы ваши контейнеры оставались конфиденциальными. После того, как вы создали учетную запись Docker Hub, вы можете создать собственный образ для целевой архитектуры и опубликовать его, используя следующее:

Поскольку мы создали версии для Arm32, Arm64 и AMD64, вы можете запустить свой образ из любой системы, основанной на этих архитектурах, следующим образом:

Обновление OTA

Комбинация OStree и контейнеров обеспечивает богатый набор функций, на основе которых мы можем разработать полные возможности обновления OTA. Взятые вместе, эти два проекта представляют собой мощную систему, способную удовлетворить потребности разрабатываемых сегодня подключенных устройств.

Как обсуждалось выше, OSTree обеспечивает:

  • Стабильный, устойчивый к энергопотреблению механизм для управления двоичными файлами вашей операционной системы.
  • Эффективное использование хранилища и пропускной способности загрузки с возможностью повторного использования любых неизмененных файлов.
  • Функция отката, чтобы гарантировать, что ломанное обновление не нанесет вред вашему парку устройств.

Использование контейнеров для размещения вашего стека приложений обеспечивает:

  • Гибкую и знакомую среду разработки программного обеспечения. Ваши разработчики могут продолжать использовать инструменты, с которыми они уже знакомы, в своих настольных системах Linux.
  • Вам не придется изобретать велосипед, и вы сможем воспользоваться проверенными в отрасли решениями.
  • Активное сообщество разработчиков. Количество документации, сообщений в блогах и готовых контейнеров, доступных для повторного использования, огромно, и их можно использовать в качестве отправной точки для ваших усилий по разработке.

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

Чтобы возможность обновления была наиболее полезной, она должна быть автоматической, автономной и доступной через какое-либо сетевое соединение; обычно называется беспроводным (OTA), но это не обязательно подразумевает беспроводное соединение. Пользователи этих устройств не думают о них как о компьютерах, требующих обслуживания, а скорее как о устройствах, которые должны «просто работать». Если обновление требует вмешательства пользователя, то, вероятно, в вашем парке будет много устаревших устройств. Среди сфер применения, такие как медицинские устройства, где возможность подключения устройств может быть намеренно ограничена, но даже в этих случаях обновление должно быть автоматизировано настолько, насколько это возможно, например, когда устройство подключено к своей док-станции для зарядки.

Безопасность

Хотя безопасность не является целью этой статьи, было бы упущением, если бы мы не обсуждали ее хотя бы немного. Одна из самых больших угроз для любой программной системы – это возможность запускать произвольный код. Поскольку весь смысл системы обновлений OTA состоит в том, чтобы установить и запустить новый код в системе, необходимо проявлять особую осторожность, чтобы убедиться, что устанавливаемый код не был изменен и является ожидаемым образом для вашей системы.

Обратите внимание на следующие моменты:

  • Физическая безопасность : у вас, вероятно, есть контроль над серверной инфраструктурой, поэтому убедитесь, что вы максимально заблокировали физический доступ. Однако учтите, что это вряд ли возможно для клиентских устройств.
  • Шифрование транспорта : необходимо убедиться, что транспорт между клиентом и сервером правильно зашифрован. В идеале вы должны использовать правильную проверку сертификата TLS на обеих конечных точках, чтобы убедиться, что вы разговариваете с ожидаемым устройством.
  • Проверка образа : вашим клиентским устройствам необходим механизм для проверки устанавливаемых образов. Для защиты от произвольной установки программного обеспечения следует использовать криптографическую проверку.
  • Управление ключами безопасности : любая архитектура безопасности будет полагаться на какие-то ключи. Архитектура должна обеспечивать механизмы истечения срока действия старых ключей и смены новых ключей, а также соответствующую защиту ключей.

Существуют платформы с открытым исходным кодом, которые обеспечивают чрезвычайно безопасный дизайн, который вы можете использовать при реализации своей системы обновлений OTA. Framework Update и Uptane два заметных проекта, которые вы должны рассмотреть, если вам необходимо разработать систему пользовательских обновлений.

Существует множество проектов с открытым исходным кодом, которые реализуют системы обновления OTA, которые вы можете интегрировать в свой дизайн, чтобы избежать накладных расходов и рисков, связанных с проектированием вашей системы. Платформа Torizon – это проект, в котором мы сейчас участвуем, и он реализует полную систему OTA, как описано в этом посте. OStree предоставляет ограниченные функции безопасности, такие как криптографическая фиксация подписи и дельта-объектов. Torizon основан на архитектуре Uptane, обеспечивающей готовое высокозащищенное решение для сквозного обновления OTA.

Заключение

Мы обсудили, как объединить несколько проектов с открытым исходным кодом в качестве инфраструктуры для создания полностью автоматизированного комплексного решения для обновления OTA.

Использование OSTree в качестве основного хранилища операционной системы позволяет получить очень компактное решение и не требует использования полностью избыточных разделов. Он обеспечивает атомарные транзакционные обновления, что сокращает время простоя для пользователей устройства. OSTree был тщательно разработан, чтобы быть устойчивым к непредсказуемым циклам включения питания и допускать откат при обнаружении проблем с обновлением.

Использование контейнеров для стека приложений обеспечивает удобный механизм упаковки и доставки, которым можно управлять независимо от базовой операционной системы. Контейнеры относительно просты в использовании, и многие разработчики уже имеют навыки работы с ними. Вы можете выбрать базовый образ, соответствующий вашему настольному дистрибутиву Linux, что позволит вам работать в знакомой среде с богатым набором инструментов в вашем распоряжении. Или вы можете выбрать базовый образ, оптимизированный для контейнеров (например, Alpine Linux ), который должен быть небольшим и изначально более безопасным; в конце концов, самое безопасное программное обеспечение – это то, что не установлено.

Комбинирование контейнеров и OSTree дает разработчикам лучшее из всех возможных при рассмотрении воспроизводимости сборки, удобства сопровождения и гибкости. Использование системы, такой как Torizon, предоставляет готовое решение, использующее описанную здесь архитектуру. Это позволяет вам быстро приступить к разработке приложения, не беспокоясь о деталях обновлений OSTree, контейнеров и OTA, и при этом быть уверенным в том, что у вас есть надежное решение для управления сроком службы вашего парка устройств.

Обеспечение надлежащих обновлений для ваших устройств должно считаться обязательным для любого современного дизайна подключенных устройств. Риск для ваших пользователей и вашего бренда слишком велик, чтобы его игнорировать.

Выражаем свою благодарность источнику из которого взята и переведена статья, сайту cnx-software.com.

Оригинал статьи вы можете прочитать здесь.

0 0 votes
Article Rating
Подписаться
Уведомление о
guest

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

0 Комментарий
Inline Feedbacks
View all comments