ソフトウェア/ファームウェアの自動更新戦略


9

「クライアントデモ用のカフェインを使用した粗雑なプロトタイプ」フェーズの終わりに近づいており、「将来を考える」フェーズに移行する中規模プロジェクトができました。プロジェクトは、ソフトウェアとファームウェアを備えたLinuxベースのデバイス、および中央管理Webサーバーで構成されています。現在10個のプロトタイプが存在し、生産は1000年代のオーダーになると予想されます。

自動更新の技術に精通しておらず、時間が足りないので、私は自分のソフトウェアの展開/自動更新戦略をすぐに展開しました。現在、次の要素で構成されています。

  • ホストされたgitリポジトリ(GitLab)と本番リリースブランチ(Webサーバーのソースもこの同じリポジトリにあることに注意してください)。
  • 次のようなWebインターフェースの「更新の展開」ボタン
    1. 最新バージョンを本番リリースブランチからローカルリポジトリエリアにプルし、それを一時パッケージ準備ステージングエリアにもコピーします。
    2. ステージング領域でサニタイズスクリプト(リポジトリに格納されている)を実行して、無関係なソースファイル(サーバーソース、ファームウェアソースなど)と.gitファイルを削除します。
    3. 現在のgitハッシュを更新パッケージのファイルに書き込みます(目的は以下で明らかになります)。
    4. すべてうまくいった場合は、gzipで圧縮し、以前のgzipで圧縮されたパッケージを同じ名前のファイルで上書きしてサービスの準備を整え、ステージング領域を削除します。
    5. サーバー上に現在のデバイスソフトウェアの2つのコピーが存在することに注意してください。これらは同期がとられていることが期待されています。同じバージョン。
  • デバイス上のソフトウェアは、という名前のディレクトリに自己完結し/opt/example/currentています。これは、ソフトウェアの現在のバージョンへのシンボリックリンクです。
  • 起動時に次のことを行うデバイスの自動更新機能:
    1. do_not_updateファイルの存在を確認し、ファイルが存在する場合はそれ以上のアクションを実行しません(開発デバイスについては、以下を参照してください)。
    2. 上記のテキストファイルから現在のコミットハッシュを読み取ります。
    3. そのハッシュをクエリパラメータとして使用して、サーバーにHTTPリクエストを送信します。サーバーは304(ハッシュは現在のバージョン)で応答するか、gzip圧縮された更新パッケージを提供します。
    4. 更新パッケージを受け取った場合は、次の方法でインストールします/opt/example
      1. という名前のフォルダーに更新されたソフトウェア情報を抽出していますstage
      2. 更新に必要なローカル変更などを行う更新パッケージからのインストール後スクリプトの実行
      3. 現在のソフトウェアルートフォルダーをにコピーしますprevious(存在するprevious場合は、最初に既存のものを削除します)。
      4. stageフォルダをコピーしますlatest(存在するlatest場合は、最初に既存のものを削除します)。
      5. 確保currentへのポイントへのシンボリックリンクをlatest
      6. デバイスを再起動します(ファームウェアの更新がある場合は、再起動時に適用されます)。

新しく構築されたデバイスでの初期展開の問題もあります。デバイスは現在 SDカードベースである(ここでは範囲外の独自の問題があります)ため、このプロセスは次のように構成されます。

  1. 以前のバージョンのソフトウェアが含まれているSDイメージが存在します。
  2. この画像からSDカードが作成されます。
  3. 初回起動時に、さまざまな初回のデバイス固有(シリアル番号ベース)の初期化が行われ、その後、オートアップデーターがソフトウェアの最新の製品バージョンを取得して通常どおりインストールします。

さらに、開発デバイスのサポートも必要でした。開発デバイスの場合:

  • 完全なローカルgitリポジトリがデバイスで維持されます。
  • currentシンボリックリンクは、開発ディレクトリを指します。
  • do_not_update自動アップデーターがプロダクションアップデートで開発コードを吹き飛ばすのを防ぐローカルファイルが存在します。

現在、展開プロセスは理論的には次のように意図されていました。

  1. コードをデプロイする準備ができたら、リリースブランチにプッシュします。
  2. サーバーの[更新の展開]ボタンを押します。
  3. これでアップデートが公開され、デバイスは次回チェック時に自動更新されます。

しかし、そこにあるトン実際に問題のは:

  • Webサーバーのコードはデバイスのコードと同じリポジトリにあり、サーバーにはローカルのgitリポジトリがあり、それを実行しています。最新のWebサーバーコードが最新のデバイスコードと同じブランチにありません。ディレクトリ構造に問題があります。[更新のデプロイ]ボタンをクリックすると、最新バージョンが本番ブランチからプルされ、サーバーコードのサブディレクトリにプルされます。つまり、サーバーに最初からデプロイする場合、デバイスのプロダクションブランチをそこに取り込むことにより、このサブディレクトリを手動で「シード」する必要があります。これは、おそらくgit user errorから、デプロイを試みないと、親ディレクトリのWebサーバーブランチからデバイスコードをプルします。これは、ステージング領域をサーバーのローカルgitリポジトリのサブディレクトリにしないことで解決できると思います。
  • Webサーバーは現在、デバイスソフトウェアのgitハッシュを永続的に維持していません。サーバーの起動時に、git rev-parse HEADローカルデバイスソフトウェアリポジトリで現在のハッシュを取得します。理由がわからないため、ここでは説明しませんが、大量の論理エラーが発生しています。サーバーを再起動すると、特にサーバーが新品で生産がない場合は、問題が発生する可能性があります。ブランチリポジトリはまだ引っ張られています。リクエストがあれば喜んでそのロジックのソースを共有しますが、この投稿は長くなりつつあります。
  • 何らかの理由でサニタイズスクリプト(サーバー側)が失敗した場合、サーバーには最新のレポが残されますが、同期git rev-parse HEADが取れておらず、更新パッケージがないため、実際のハッシュと一致しないハッシュが返されますここで問題はサーバーのコマンドラインで手動で修正する必要があります。つまり、サーバーは更新パッケージが正しくないことを認識しておらず、純粋な信念で常にそうであることを前提としています。これを前のポイントと組み合わせると、サーバーは実際には非常に壊れやすくなります。
  • 最大の問題の一つはデバイス上で動作しているデーモン全く別のアップデータは現在ありません。wifiインターネットアクセスが来るのを待っている複雑さといくつかの土壇場のハッカーのため、デバイスをチェックして更新するのはメインのデバイス制御ソフトウェア自体です。これは、テストが不十分なバージョンが何らかの形で本番環境に移行し、制御ソフトウェアが起動できない場合、存在するすべてのデバイスは、それ自体を更新できなくなるため、本質的に機能しなくなることを意味します。これは、本番環境では絶対的な悪夢です。不運なときに電源が切れた場合の単一のデバイスの同じ取引。
  • その他の主な問題は次のとおりです。増分更新はサポートされていません。たとえば、しばらくの間デバイスの電源が入っていない場合、次にデバイスが更新されたときに、一連のリリースバージョンがスキップされ、直接バージョンスキップの更新を実行できる必要があります。この結果、更新された展開は、特定の更新を特定の過去のバージョンの上に適用できることを確認するという悪夢になります。さらに、gitハッシュはバージョン番号ではなくバージョンを識別するために使用されるため、増分更新を容易にするためのバージョンの辞書式比較は現在不可能です。
  • 現在サポートしていない新しい要件は、管理サーバー側で構成する必要があるデバイスごとの構成オプション(キー/値のペア)がいくつか存在することです。ソフトウェアの更新と同じHTTP要求でデバイスにこれらのデバイスごとのオプションを提供することはどうしても構いません(多分、それをHTTPヘッダー/ Cookieにカプセル化できます)。常に別のHTTPリクエストにします。
  • ハードウェアの2つのバージョン(および将来的にはさらに多く)のハードウェアが存在するため、多少複雑になります。ハードウェアの現在のバージョンは、実際には初期SDイメージの環境変数として格納され(それらは自己識別できません)、すべてのソフトウェアはデバイスのすべてのバージョンと互換性があるように設計されています。ファームウェアの更新はこの環境変数に基づいて選択され、更新パッケージにはハードウェアのすべてのバージョンのファームウェアが含まれています。ちょっと不格好ですがこれで我慢できます。
  • 現在、手動で更新をデバイスにアップロードする方法はありません(要するに、これらのデバイスには2つのwifiアダプターがあり、1つはインターネットへの接続用で、もう1つはユーザーがデバイスの構成に使用するAPモードです。将来的にはデバイスのローカルウェブインターフェースに「アップデートソフトウェア」機能を追加するつもりです)。これは大きな問題ではありませんが、更新のインストール方法にある程度の影響を与えます。
  • 他の欲求不満と一般的な危険性の束。

だから...それは長かった。しかし、私の質問はこれに要約されます:

これを適切かつ安全に行うにはどうすればよいですか?既存のプロセスに小さな調整を加えることはできますか?独自の安っぽい更新システムを導入する必要がないように、が活用できる実績のある戦略/既存のシステムはありますか?または、自分でロールする必要がある場合、展開/更新プロセスを安全かつ成功させるために、真実でなければならないことは何ですか?私はまた、ミックスに開発デバイスを含めることができなければなりません。

質問が明確であることを願っています。少しあいまいであることに気づきましたが、これが以前に対処されて正常に解決された問題であることは100%確信しています。


2
デバイスはLinuxベースなので、そこにあるLinuxパッケージマネージャー(apt、yum、rpmなど)を使用することをお勧めします。最初のステップとして、Linuxベースのインストールにまだ付属していないかどうかを確認します。
Bart van Ingen Schenau 2017年

システムのサイズについて教えてください。MBとGBのどちらについて話しているのですか?
lbenini 2017年

MB; 更新パッケージは、gzipした場合、通常1〜2 MBです。
Jason C

回答:


1

使用中のLinuxディストリビューション、ブートローダー、アーキテクチャ(x86、ARM、MIPS?)について詳しく教えてください。

私はどちらかを推測して、うまくいけばあなたを正しい方向に導きます。

それがU-Bootを備えたYoctoベースのディストリビューションである場合は、mender.ioまたはswupdateを確認することをお勧めします。これらのプロジェクトは基準によく適合しているようです。彼らの主な目標は、アトミックな更新を確実にすることです。

最大の問題の1つは、現在、デバイス上で実行されている個別のアップデータデーモンがないことです。wifiインターネットアクセスが来るのを待っている複雑さといくつかの土壇場のハッカーのため、デバイスをチェックして更新するその主要なデバイス制御ソフトウェア自体。これは、テストが不十分なバージョンが何らかの形で本番環境に移行し、制御ソフトウェアが起動できない場合、存在するすべてのデバイスは、それ自体を更新できなくなるため、本質的に機能しなくなることを意味します。これは、本番環境では絶対的な悪夢です。不運なときに電源が切れた場合の単一のデバイスの同じ取引。

Menderは、Goで書かれたデーモン(およびsystemdスクリプトの束)を含む一連のツールを提供します。このプロジェクトはYoctoで非常に簡単に使用できます(特定のケースやパーティションレイアウトに簡単に適応できるはずの多くのデバイスにメタレイヤーを提供します。一般的なSOCにもすぐに使えるソリューションがたくさんあります) 。Yoctoを使用しない場合は、Yocto ベース以外のディストリビューションで使用するために必要な手順を正確に説明しているこの投稿をご覧ください。

swupdateもかなり素晴らしいですが、DENX(U-Bootの背後にある組織)からの1人の努力のようです。それもかなり成熟したようです。

Ubuntu Snappyもあります。私はこれを経験したことがなく、これについてコメントすることはできません(たぶん誰かが提案するでしょう)。アイデアは、自己完結型の「スナップ」でアプリを出荷することです。私が理解したところによると、これはシステム全体ではないものの、問題の解決策はほとんどありません。

質問が明確であることを願っています。少しあいまいであることに気づきましたが、これは以前に取り組み、解決に成功した問題であると100%確信しています。現在受け入れられている戦略が何なのかわかりません。

実際のところ、今日の傾向は、APT / YUMを介してDocker(組み込みシステムでも)と友達を使用することです。後者は一貫性を保証することを非常に難しくするかもしれません。


これは素晴らしいです。この答えに気づかなかったのかはわかりません。要求された情報をすぐに提供します。そのプロジェクトは一時的に延期され、昨日再開されたので、私は馬に戻ってきました。この特定の問題は現在、#1の優先事項です。
Jason C
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.