[レポート] AWS のためのコンテナをビルドする #CON325 #reinvent
アノテーション テクニカルサポートの川崎です。
本記事は AWS re:Invent 2022 のセッションレポートとなります。
概要
AWS にコンテナをデプロイする際には、多くの選択肢があります。 AWS Lambda、Amazon ECS、または Amazon EKS を使用した Kubernetes のいずれでビルドする場合でも、プロセスはイメージのビルドから始まります。 このセッションでは、コンテナを使用したビルドに関するガイダンスを 2 つの部分に分けます。 まず、開発ツールの一般的な選択肢をいくつか見て、完全にオープンソースの開発環境を開始する最も簡単な方法を見つけてください。 次に、開発パターンについて学び、AWS でのコンテナ開発に関する実践的なアドバイスを聞きます。
セッション動画
アジェンダ
- コンテナとイメージ
- オープンソースのコンテナ開発ツール
- イメージのビルド、および配布とデプロイの計画
コンテナとイメージ
AWS 上のコンテナ
コンピューティング パラダイムとしてのコンテナ
- 大規模なマルチクラスター資産のオーケストレーションから、1 回限りの Web アプリケーションまで
- 多くのユースケースでの他の AWS サービスとの統合
- ソフトウェアのライフサイクル全体を通して再現可能で一貫性があります
パッケージおよび流通用のコンテナ
- バージョン管理された不変のアーティファクトに基づくすべてのインスタンス
- すべてのコンポーネントと依存関係はビルド時に定義され、証明可能です
- レジストリは基盤であり、両方がビルドされます
- 宛先とデプロイ元
コンテナは単純ですが、スケールは複雑です
- コンテナを使い始めるのは非常に簡単ですが、複雑さが忍び寄る可能性があります
- 長期的な導入は、コンテナ化されたワークロードをデプロイするだけではありません
- イメージ ビルドの標準、ソフトウェアの依存関係、および配布方法はすべて、大規模に重要です
- デプロイするのにどれくらいかかりますか? どのくらいの頻度で? イメージのサイズとビルドにかかる時間は?.
Linux コンテナについて理解する
- ワークロードを実行したり、パッケージ化を簡素化したりするために、コンテナで使用する AWS のサービスに関係なく、イメージから始めます
- 開発作業の一環としてこれらのイメージをビルドする場合は、優れたツールと、それらが解決する問題についてのコンテキストが必要です
- そのコンテキストを設定するために、コンテナがどのように機能するか、およびさまざまな可動部分を処理するソフトウェアの簡単なツアーから始めます
コンテキスト用の Linux コンテナ
- Linux コンテナは、実際には特定のものではありません
- それらは、カーネル機能とユーザー空間ソフトウェアで構成される構造です
- 目標は、一見プライベートなコンピューティングでプロセスまたは一連のプロセスを開始することです
- ソフトウェアの特定のバンドルからの環境
- コンテナがバンドルから開始されるときはいつでも、コンテナは一貫している必要があります
名前空間
- それ以外の場合はグローバル リソースの一見分離されたインスタンスを作成できます
- コンテナでは、多数のリソースの名前空間を構成します
- マウント、PID、ネットワーク、UTS、IPS、およびユーザーが例です
- 名前空間は、を作るものです
- コンテナは孤立したシステムのようです
コントロール グループ (cgroup)
- プロセスまたは一連のプロセスに制限と監視を提供します
- CPU、メモリ、ネットワーク IO、およびディスク IO はすべて、cgroup によって制御できるリソースです
- Linux をビルドするための 2 番目の主要コンポーネントには、次のものが含まれています
レスキューのためのツール
- この時点で考えているかもしれませんが、スライドが数枚入っているだけで、心配する必要はもうありません
- 賛成です! だからこそ、ツールはとても重要です
- コンテナは、多くの問題に対する優れたソリューションです
- 一貫性のある反復可能なランタイム環境
- 依存関係の管理、パッケージ化、および配布
- 一意の識別子によって配布に結び付けられた不変のデプロイ アーティファクト
- コンテナは非常に便利です。私たちのツールはコンテナを使いやすくするものです
どこから始めれば
- コンテナの開発ツールのコンポーネントについて説明し、後でイメージをビルドするためのガイダンスを提供する際に、いくつかのコンテキストが必要になります
- ボトムアップから始めて、ランタイムが必要です
- コンテナ ランタイムは、カーネル機能とその他のコンポーネント ソフトウェアを抽象化し、コンテナ インスタンスの作成と実行をスムーズに処理します
- ランタイムには、プロセスを実行するための環境が必要であり、移植可能なファイル システムまたはイメージが必要になります
簡単な歴史、Open Containers Initiative
- Open Containers Initiative は、コンテナ イメージのフォーマットとランタイムの標準を設定するために作成されました
- OCI ランタイムおよびイメージ仕様 v1.0 は、2017 年 7 月にリリースされました
コンテナの作成
- OCI ランタイム仕様は、コンテナの構成、実行環境、およびライフサイクルを指定します
- 構成は構成ファイルで指定され、環境仕様によりコンテナの一貫性が保証されます
- これらは標準ファイルにまとめられています
- コンテナを作成できるシステム バンドル
リファレンス実装 runc
- Docker のエンジニアによって実装されました
- OCI ランタイム仕様のリファレンス実装として寄贈されました
- 準拠したバンドルが与えられると、コンテナが生まれます
- ルート ファイル システムがすでに配置されている必要があります
コンテナ イメージ
- OCI Image Specification は、コンテナ イメージのビルド、転送、および準備のためのツールを有効にします
- イメージ・マニフェスト、イメージ・インデックス、一連のファイル・システム・レイヤーおよび構成で構成されるOCIイメージを指定します
イメージのビルド
- Linux コンテナ イメージは組み込みレイヤーです
- 各レイヤーは、スタック内の前のレイヤーに依存します
- レイヤーは下から順にビルドされます
- このセッションでは、Build Kit と Dockerfiles に焦点を当てます
イメージのビルド
- BuildKit は成熟した機能豊富なイメージビルドシステムです
- イメージレイヤーと構成をビルドする実際の作業を処理します
- クライアントはビルド コンテキスト (通常はビルド環境内のパス) を渡します
- ビルド コンテキストが読み込まれ、BuildKit が Dockerfile を反復処理します
Dockerfiles からビルドします
- Dockerfile の各行は p
- 処理済み、上から下
- 命令を変更すると、イメージ レイヤーがビルドされます。これは、最終イメージのボトムアップと見なされます
- COPY などの rootfs を変更する命令や、パッケージをインストールする RUN コマンドを実行すると、新しいレイヤーが作成されます
イメージとは?
- OCI イメージはマニフェストによって記述されます。マニフェストは、他のメタデータと共にダイジェストによってイメージ レイヤーを指定します
- Dockerfile からビルドされた (トップダウンで読み取られてビルドされた) レイヤーは、ボトムアップのイメージ レイヤーを表します
- イメージは事実上、下のレイヤーに依存する tarball のスタックです
イメージレイヤー
- 特定のレイヤーの変更のみが保存されます。 その後、コンテナが作成されると、レイヤーが再ビルドされます
- コンテナがローカルで作成されると、これらのレイヤーが再ビルドされます
- レイヤーは不変であり、コンテンツのダイジェストによって識別されます
- イメージは不変ですが、通常はコンテナ内のプロセスがファイル システムに書き込めるようにする必要があります
不変のイメージ
- 新しいコンテナは、スタックの最上部にある読み取り/書き込みレイヤーから始まります
- 下位層は変更されず、ダイジェストによって識別されます
- イメージ マニフェストもダイジェストによって識別されます
- イメージコンテンツは、特定のダイジェストによって常に説明できます
マルチプラットフォーム イメージ
- イメージは個別のアーティファクトです
- 特定の OS およびアーキテクチャのコンテンツ
- コンテナは複数でサポートされています
- システムとアーキテクチャ
- マルチプラットフォーム イメージには次のものが含まれます
- マニフェスト リスト、または OCI インデックス
マルチプラットフォーム イメージ
- これは、プラットフォームの注釈が付けられた他のマニフェストのインデックスです
- クライアントは、オペレーティング システムとアーキテクチャに適したイメージをプルするように実装されます
containerd ですべてを整理します
- これで、コンテナを作成する方法と、コンテナを作成するためのイメージ、およびそれらのイメージを配布する方法が得られました
- 複数のコンテナインスタンスとそのイメージを管理し、合理的なシステムをビルドするための何かが必要です
containerd ですべてを整理します
- containerd は Linux の標準コンテナ スーパーバイザーであり、これも Docker のエンジニアによって開始され、寄付されました (今回は CNCF に寄付されました)
- これは、コンテナを実行するシステム サービスとして実行され、コンテナ インスタンスの作成と管理、イメージのプルなどを担当します
- containerd は多くの開発ツールで使用されており、Kubernetes および AWS Fargate のデフォルトのランタイムです
レスキューのためのツール
- 何が抽象化されているかを理解するのは良いことなので、これは大雑把なツアーでした
- お客様は、ツールではなく、ソフトウェアのビルドに集中したいと考えています
- 優れたツールは複雑さを抽象化し、シンプルなワークフローを可能にします
オープンソースのコンテナ開発ツール
コンテナ開発
- セッションのこのセクションでは、コンテナ開発ツールについて説明します
- 具体的には、macOS などの非 Linux 環境向けの Linux コンテナ ツールについてお話したいと思います
- 私たちは、私たちが持っている要件を満たすオープンソース コンポーネントに焦点を当てます
- また、それらを簡単に使用できる新しいオープンソース プロジェクトについて詳しく説明します
仮想マシン
- ほとんどのコンテナ開発は Linux を対象としています
- ほとんどの開発環境は macOS または Windows です
- これまで見てきたように、Linux コンテナを実行して Linux イメージをビルドするには Linux が必要です
- 救助のための仮想化。 最初はアドホックですが、その後はエンド ツー エンドのソリューションです
エンドツーエンドのソリューション
- Docker Desktop は、このニーズを満たす最初の製品であり、Hyperkit を使用する Docker の主力コンテナ開発製品です
- Red Hat は、libpod ライブラリの一部として提供されるコマンドライン ユーティリティである Podman と、QEMU を活用した Podman Desktop を今年初めに導入しました
- Rancher Desktop は、Lima (QEMU を管理する) を活用して、nerdctl および Docker ベースのコンテナ管理でデスクトップ Kubernetes ソリューションを拡張しました
- Colima は、Lima を使用して Linux VM で nerdctl または Docker を簡単に使用できるようにする、非常に人気のあるオープンソース プロジェクトです
Finch の紹介
- Finch は、コンテナ開発用の新しいオープン ソース クライアントです
- これは、containerd のクライアントである nerdctl と直接統合する macOS ネイティブ クライアントを提供します
- これは、Lima が管理する独自の仮想マシン構成でインストールされます
- Finch は、nerdctl、containerd、および関連ソフトウェアとの統合と拡張に重点を置いています
- すでに多くの関心が寄せられており、最初の数日で GitHub に 1,000 個以上のスターがつきました
オープンソースのビルディング ブロック
- Finch は、多くの既存の革新的なオープン ソース コンポーネントに依存しています
- containerd、nerdctl、Lima、BuildKit が主要なコンポーネントです
- Finch は、精選された統合ソリューションを使用してこれらを簡単に採用できるようにします
なぜFinch ?
- お客様との会話がこのプロジェクトの指針となりました 一部のお客様は、シンプルなオープンソース ソリューションによるサポートを求めていました
- 他の顧客は、彼らのニーズに集中できるように統合とリリース作業を引き受けるために、独自のカスタマイズの開始点を求めていました.
- これにより、軽量のクライアントとインストーラーを組み合わせたオープン ソース コンポーネントの配布という観点から考えるようになりました
それはどこにフィットしますか?
- オープンソースとは、境界を越えて新しいものを構築することです
- また、すでに機能しているものを認識し、その改善と維持を支援することでもあります
- チームが最初に行ったことの 1 つは、既存のソフトウェア セットの要件を調査することでした
- ここに「再発明」の語呂合わせを挿入します
ディストリビューションとしてのFinch
- AWS は containerd に投資しており、スタッフには数人のメンテナーがいます
- この投資に傾倒することで、私たちのコンポーネントが明確になりました
- nerdctl は、1.0 リリースを達成して現在安定している containerd クライアントです
- Lima は、nerdctl を開始した同じエンジニアによって開始された新しいプロジェクトです
Finch ♡リマ
- Lima は、Finch ディストリビューションの主要コンポーネントです
- Lima は新しいプロジェクトですが、非常に人気があり、最近、サンドボックス プロジェクトとして CNCF に参加しました
- 新しいものをビルドするのではなく、チームは Lima に積極的に貢献しています
- Finch は、独自の Lima 構成をインストールの一部としてデプロイします
- これには、nerdctl、containerd、BuildKit、および開始するためのすべての依存関係が含まれます
Finch のインストール
- Finch 0.1 は、GitHub からダウンロード可能な pkg インストーラーを介して利用できるようになりました
- Homebrew のサポートを追加する予定です
- 初回起動時はmacOSに対応
- 最小 macOS バージョン 10.15
- Intel (x86_64) および Apple Silicon (M1)
Finch を始める
- Finch クライアント自体は macOS ネイティブです
- Windows のサポートは、私たちが取り組む予定の機能のリストに含まれています
- Finch はホスト OS 上でネイティブに実行され、Linux 環境の nerdctl と直接統合されます
- VM を初期化して起動する以外に、基盤となる VM と対話する必要はありません
Finch を始める
- Finch は、コマンドを macOS から nerdctl に渡します
- nerdctl は、Docker クライアントによって確立された事実上の標準のコマンドとオプションを採用しました
- 経験豊富な開発者は、使い慣れたコマンドですぐに始めることができます
- 新しい開発者にとっては、数多くの既存のブログやチュートリアルが引き続き役に立ちます
コンテナの実行とテスト
コンテナの実行とテスト
クロス アーキテクチャのサポート
- Finch は、基盤となる VM でユーザー空間エミュレーションを利用します
- --platform オプションは、amd64 または arm64 コンテナの実行をサポートします
- 計画中: 統合されたマルチアーキテクチャ イメージ ビルド
コンテナの実行とテスト
イメージのビルド
- Dockerfile ビルドは、ビルド キットの統合を通じてサポートされます
- --platform を使用して、複数のアーキテクチャ (amd64、arm64) でビルドすることもできます
- 計画中: カスタム BuildKit 構文のサポート
クロス アーキテクチャのサポート
- Finch は、基盤となる VM でユーザー空間エミュレーションを利用します
- --platform オプションは、amd64 または arm64 コンテナの実行をサポートします
- 計画中: 統合されたマルチアーキテクチャ イメージ ビルド
イメージの公開
- レジストリへの認証も、おなじみのワークフローに従います
- ログイン、タグ付け、プッシュするだけです
- 計画中: 認証情報ヘルパーのインストールがより簡単になりました
参加しませんか!
- Finch をぜひお試しください
- チームはイシューの準備ができており、プル リクエストは大歓迎です!.
イメージのビルド、および配布とデプロイの計画
高レベルの目標
- イメージ ビルドの一般的なガイダンス
- 小さいイメージ
- より高速なビルド
- スコープを制限します
高レベルの目標
- イメージ ビルドの一般的なガイダンス
- イメージを小さくすると、プルが速くなり、攻撃対象領域が少なくなり、理想的には更新頻度が低くなります
- ビルドを高速化して、変更を本番環境に迅速に移行します
- 大規模なシステムとして疎結合サービスを実現する手段として、コンテナの価値を受け入れる範囲を限定します
ベースイメージについて話しましょう
- これらは、Dockerfile の FROM 行で指定されているイメージです
- これはファイル システム コンテンツの最下層であり、独自のコンテンツを作成できます
- Docker 公式イメージは、基本イメージの標準となっています
- これらには通常、同等のイメージを縮小した「スリム」バージョンがあります
- Docker パブリッシャーのページから ECR Public で入手できます
ベースイメージ、Lambda エディションについて話しましょう
- AWS は、Lambda で使用する一連のイメージをキュレートします
- 独自の基本イメージをビルドすることは可能ですが、それには十分な理由が必要です
- これらはすぐに使用できるイメージであり、ビルドのベース イメージとして使用するのに最適です
ベースイメージを独自のものにします
- ベース イメージは、独自のイメージ ビルドのルートです
- または、システムでこれらのイメージを直接、変更せずに使用することもできます
- ECR レジストリ インスタンスで独自のものを作成することを検討してください
- 可用性、潜在的な強化、スキャン、およびその他の価値のあるものを制御します
- ECR プルスルー キャッシュが役に立ちます
できるだけ頻繁に(常に)明示的なタグを使用してください
- 「最新」は、1 回限りのテストに便利です
- 本番環境では、具体的に指定することをお勧めします
- 依存関係を知ってください
- これは、ビルドに対するアドバイスでもあります
- 「レポの最新のもの」に対して大規模なコンパイル済みソフトウェアプロジェクトをビルドすることはありません
多段ビルド
- 小さいイメージをビルドするための簡単な方法は、マルチステージ ビルドを使用することです
- 最初に Docker で利用可能になり、現在はすべての BuildKit 統合 (Finch を含む) で利用できます
- Dockerfile を簡単に変更して、レイヤーと全体的なイメージ サイズを縮小します
- 基本的に、複数の FROM を宣言し、アーティファクトを前方にコピーします
多段ビルド
- コンパイラ、リンター、その他のビルド ツール、および依存関係をインストールします
- ビルド手順が完了したら、新しいステージを宣言します
- 成果物と依存関係をビルド段階から最終段階にコピーします
-
これにより、約 140 MB 節約できます
静的バイナリとスクラッチ イメージ
- これは、静的バイナリにコンパイルできる場合に特に便利です
- 最終段階でスクラッチイメージを使用すると、非常に小さなイメージが得られます
-
このイメージは 1.7 MB です
フリーの高速化: 多段階の並列ビルド
- BuildKit は、ビルドを開始する前に Dockerfile を分析します
- ステージに依存関係がないと判断された場合、ビルドが開始されます
- 複数ある場合は、それらが並行してビルドされるため、ビルド全体が高速になります
- ステージ間の不要な依存関係を回避することで、これを利用してください
-
ビルドに8秒強
関連する操作を組み合わせてレイヤーを削減します
- 多くの場合、パッケージ操作など、関連する命令があります
- 可能であれば、これらを 1 つの命令に結合してください
- 同じコマンドで、単一のレイヤーになります
ビルド キャッシュを活用します
- BuildKit は、ローカル ビルド キャッシュを管理して、後続のビルドを高速化します
ビルド キャッシュを活用します
- BuildKit は、ローカル ビルド キャッシュを管理して、後続のビルドを高速化します
- レイヤーでキャッシュがウォームアップされると、変更されていないレイヤーが使用されます
ビルド キャッシュを活用します
- BuildKit は、ローカル ビルド キャッシュを管理して、後続のビルドを高速化します
- レイヤーでキャッシュがウォームアップされると、変更されていないレイヤーが使用されます
- 命令によって変更が生じる場合、キャッシュされたレイヤーは無効になります
ビルド キャッシュを活用します
- BuildKit は、ローカル ビルド キャッシュを管理して、後続のビルドを高速化します
- レイヤーでキャッシュがウォームアップされると、変更されていないレイヤーが使用されます
- 命令によって変更が生じる場合、キャッシュされたレイヤーは無効になります
- レイヤーは相互に依存しているため、後続のレイヤーもすべて無効になります
ビルド キャッシュを活用します
- 変更頻度の低いものからトップダウンで指示を並べます
- たとえば、依存関係のパッケージ インストールの設定は早い段階で行われます
- コードのビルドは後で行います
ENTRYPOINT または CMD
- これはそれほど難しくも速くもありません
- どちらもデフォルトの起動プロセスを提供します
- CMD は CLI からオーバーライドできます
- ENTRYPOINT は CLI から引数を取ります
- 通常、CMD を使用する理由がない場合は、ENTRYPOINT を使用します
- ユーザーに独自の開始プロセスを定義させたい場合は、CMD を使用します
関連するシェル形式と実行形式
- 繰り返しますが、どちらにもユースケースがあります(それほどではありません)
- これは実際には、ガイダンス以上に知っておくべきことです
- シェル形式は、シェルを介してすべてのコマンドを呼び出し、毎回環境を解釈します
- Exec 形式は、指定されたコマンドを実行するだけです
- 通常、Shell 形式を使用する理由がない場合は、Exec を使用します
ビルド引数ではなく、シークレットを使用します
- --build-arg を使用してコンテナ ビルドにシークレットを渡さないでください。これらは埋め込まれています
- 絶対に秘密ファイルを追加してから削除しないでください - 残ります
- 代わりに、BuildKit シークレットを使用してください
- これらは特別なマウントを使用しており、秘密の痕跡を残しません
スコープを制限します
- 「1 つのことを正しく行う」という UNIX の哲学は、コンテナに特に当てはまります
- モノリスを単純にコンテナ化したくなるかもしれませんが、これではコンテナの価値が解き放たれません
- おそらく、インスタンスでモノリスを実行する方が簡単です
- 受け入れ、リファクタリングし、最小化します
まとめ
私たちとつながり、Finch をチェックしてください!
- 私たちの新しいプロジェクトを見に来てください
- 何を改善できるかを聞き、一緒に何をビルドできるかについて話したいと思います
- ディスカッション、Issue、プルリクエストはすべて歓迎します!
- より洗練された公開ロードマップと専用サイトが進行中です