Kubernetes前書きスケーラビリティ、移植性、堅牢性を念頭に置いてアプリケーションを設計および実行することは、特にシステムの複雑さが増すにつれて困難になる可能性があります。アプリケーションまたはシステムのアーキテクチャは、実行方法、環境からの期待、関連するコンポーネントとの密接な関係に大きく影響します。設計段階で特定のパターンに従い、特定の運用プラクティスを順守すると、高度に分散された環境で実行するときにアプリケーションが直面する最も一般的な問題のいくつかに対処するのに役立ちます。ソフトウェア設計パターンと開発方法論は、適切なスケーリング特性を持つアプリケーションを作成できますが、インフラストラクチャと環境は展開されたシステムの動作に影響を与えます。Dockerやhttps://kubernetes.io/[Kubernetes]のようなテクノロジーは、チームがソフトウェアをパッケージ化し、分散コンピューターのプラットフォーム上で配布、展開、スケーリングを行うのに役立ちます。向上したアプリケーションを管理できます。このガイドでは、Kubernetesでのワークロードのスケーリングと管理を支援するために採用できる原則とパターンのいくつかについて説明します。Kubernetesは多くの種類のワークロードを実行できますが、選択内容は操作の容易さと展開で利用可能な可能性に影響を与える可能性があります。アプリケーションの設計と構築、コンテナ内でのサービスのパッケージ化、Kubernetes内でのライフサイクル管理と動作の構成は、それぞれエクスペリエンスに影響します。アプリケーションのスケーラビリティのための設計ソフトウェアを作成する場合、多くの要件が、採用するパターンとアーキテクチャに影響を与えます。Kubernetesで最も重要な要因の1つは、*水平方向にスケーリング*する機能です。アプリケーションの同一コピーの数を調整して、負荷を分散し、可用性を高めます。これは、*垂直スケーリング*に代わるものです。これは、より多くのまたはより少ないリソースを持つマシンにデプロイすることにより、同じ要素を操作しようとします。*は、クラスター上のスケーラブルな展開に適したソフトウェア設計パターンです。APIを介してネットワークを介して通信する小さな構成可能なアプリケーションを作成します。モノリシックアプリケーションを個別の単一目的コンポーネントに分解すると、各機能を個別にスケーリングすることができます。通常アプリケーションレベルに存在する複雑さと構成の多くは、Kubernetesなどのプラットフォームで管理できる運用領域に転送されます。特定のソフトウェアパターンを超えて、*クラウドネイティブ*アプリケーションは、いくつかの追加の考慮事項を念頭に置いて設計されています。管理機能を備えたマイクロサービスアーキテクチャパターンに従って、クラウド内のクラスター化プラットフォームによって提供される環境に適応するプログラムです。クラウドネイティブアプリケーションは、インスタンスが異常になった場合にプラットフォームがライフサイクルイベントを管理できるように、ヘルスレポートメトリックで構築されます。堅牢なテレメトリデータを生成(およびエクスポート可能)して、オペレーターに問題を警告し、情報に基づいた意思決定を可能にします。アプリケーションは、データを破損したり応答しなくなったりすることなく、定期的な再起動と障害、バックエンドの可用性の変化、高負荷を処理するように設計されています。開発者と運用チームがクラウドで実行するように設計されたWebサービスが共有するコア品質を理解できるように書かれたこの原則は、Kubernetesのようなクラスター環境に存在するソフトウェアに非常によく当てはまります。モノリシックアプリケーションはこれらの推奨事項に従うことでメリットが得られますが、これらの原則に基づいて設計されたマイクロサービスアーキテクチャは特にうまく機能します。12の要因の簡単な要約は次のとおりです。*コードベース:*バージョン管理システム(GitやMercurialなど)のすべてのコードを管理します。コードベースは、展開するものを包括的に指示します。*依存関係:*依存関係は、コードベースで完全に明示的に管理する必要があり、ベンダー(コードと共に保存)またはパッケージマネージャーがインストールできる形式に固定されたバージョンのいずれかです。Config:*構成パラメーターをアプリケーションから分離し、アプリケーション自体にベイクするのではなく、デプロイメント環境で定義します。*バッキングサービス:*ローカルサービスとリモートサービスは両方とも、ネットワークアクセス可能なリソースとして抽象化され、接続の詳細が設定されています。*ビルド、リリース、実行:*アプリケーションのビルド段階は、アプリケーションのリリースおよび運用プロセスから完全に分離する必要があります。ビルドステージはソースコードからデプロイメントアーティファクトを作成し、リリースステージはアーティファクトと構成を組み合わせ、実行ステージはリリースを実行します。*プロセス:*アプリケーションは、状態をローカルに保存することに依存してはならないプロセスとして実装されます。4番目の要因で説明されているように、状態はバッキングサービスにオフロードされる必要があります。*ポートバインディング:*アプリケーションはネイティブにポートにバインドし、接続をリッスンする必要があります。ルーティングとリクエストの転送は外部で処理する必要があります。*同時実行性:*アプリケーションは、プロセスモデル全体のスケーリングに依存する必要があります。複数のサーバー間でアプリケーションの複数のコピーを同時に実行すると、アプリケーションコードを調整せずにスケーリングできます。*ディスポーザビリティ:*プロセスは、深刻な副作用なしに迅速に開始し、正常に停止できる必要があります。*開発/製品パリティ:*テスト、ステージング、および運用環境は密接に一致し、同期を保つ必要があります。環境間の違いは、非互換性と未テストの構成が現れる機会です。*ログ:*外部サービスがログを最適に処理する方法を決定できるように、アプリケーションはログを標準出力にストリームする必要があります。1回限りの管理プロセスは、特定のリリースに対して実行し、メインプロセスコードと共に出荷する必要があります。Factorsが提供するガイドラインに従うことで、Kubernetes実行環境に適合するモデルを使用してアプリケーションを作成および実行できます。Factorsは、開発者がアプリケーションの主な責任に集中し、コンポーネント間の動作条件とインターフェースを考慮し、入力、出力、および標準プロセス管理機能を使用してKubernetesで予測どおりに実行することを奨励します。アプリケーションコンポーネントのコンテナ化Kubernetesは、コンテナを使用して、クラスタノード全体でパッケージ化された分離されたアプリケーションを実行します。Kubernetesで実行するには、アプリケーションを1つ以上のコンテナーイメージにカプセル化し、Dockerなどのコンテナーランタイムを使用して実行する必要があります。コンポーネントをコンテナ化することはKubernetesの要件ですが、上記の12因子アプリ手法の原則の多くを強化するのにも役立ち、スケーリングと管理が容易になります。コンテナは、アプリケーション環境と外部ホストシステム間の分離を提供し、アプリケーション間通信に対するネットワーク化されたサービス指向のアプローチをサポートし、通常は環境変数を通じて設定を行い、標準エラーおよび標準出力に書き込まれたログを公開します。コンテナ自体は、プロセスベースの同時実行性を促進し、独立してスケーラブルであり、プロセスのランタイム環境をバンドルすることにより、開発/製品パリティを維持します。これらの特性により、アプリケーションをパッケージ化して、Kubernetes上でスムーズに実行できるようになります。コンテナの最適化に関するガイドラインコンテナテクノロジーの柔軟性により、アプリケーションをカプセル化するさまざまな方法が可能になります。一部の方法はKubernetes環境で他の方法よりもうまく機能します。アプリケーションのコンテナ化に関するベストプラクティスのほとんどは、イメージの構築に関するものです。イメージの構築では、コンテナ内からソフトウェアをセットアップして実行する方法を定義します。一般に、画像サイズを小さく構成可能に保つことには、多くの利点があります。サイズが最適化されたイメージは、フットプリントを管理しやすくし、イメージの更新間で既存のレイヤーを再利用することで、クラスターで新しいコンテナーを起動するために必要な時間とリソースを削減できます。コンテナイメージを作成する際の最初の良いステップは、本番環境で実行される最終イメージからビルドステップを分離するために最善を尽くすことです。通常、ソフトウェアの構築には追加のツールが必要であり、時間がかかり、環境によってはコンテナ間で一貫性のない、または最終的なランタイム環境に不要なアーティファクトが生成されます。builds]を使用することです。マルチステージビルド構成により、ビルドプロセス中に使用する1つのベースイメージを指定し、実行時に使用する別のベースイメージを定義できます。これにより、すべてのビルドツールがインストールされたイメージを使用してソフトウェアをビルドし、結果のアーティファクトをスリムでスリムなイメージにコピーして、後で毎回使用できます。親イメージの上に実稼働イメージを構築することをお勧めします。`でイメージを構築できます-Dockerの最小ベース画像-親として。」ベースレイヤーは多くのコアツールへのアクセスを提供せず、多くの場合、一部のソフトウェアが保持している環境に関する仮定を破ります。+`イメージは、小さくても完全に機能するLinuxディストリビューションを提供する堅実で最小限のベース環境として人気を博しています。PythonやRubyなどのインタープリター言語では、コンパイル段階がなく、実稼働環境でコードを実行するためにインタープリターが使用可能でなければならないため、パラダイムはわずかに変わります。Hub]で利用可能です。インタープリター言語に小さなイメージを使用する利点は、コンパイルされた言語に似ています。Kubernetesは、必要なすべてのコンテナーイメージを新しいノードにすばやくプルして、意味のある作業を開始できるようになります。*はKubernetesが直接管理できる抽象化の最小単位です。ポッドは、1つ以上の密接に結合されたコンテナーで構成されるKubernetesオブジェクトです。ポッド内のコンテナはライフサイクルを共有し、単一のユニットとして一緒に管理されます。コンテナは常に同じノードでスケジュールされ、同時に開始または停止され、ファイルシステムやIPスペースなどのリソースを共有します。最初は、アプリケーションをコンテナとポッドに分割する最適な方法を見つけるのは難しい場合があります。これにより、Kubernetesがこれらのコンポーネントを処理する方法と、抽象化の各レイヤーがシステムに提供するものを理解することが重要になります。これらの各抽象化を使用して、アプリケーションのカプセル化の自然なポイントを識別するのに役立ついくつかの考慮事項があります。コンテナの有効な範囲を決定する1つの方法は、自然な開発境界を探すことです。システムがマイクロサービスアーキテクチャを使用して動作している場合、適切に設計されたコンテナは、多くの場合、さまざまなコンテキストで使用できる機能の個別のユニットを表すように構築されます。このレベルの抽象化により、チームはコンテナイメージへの変更をリリースし、これらのイメージが使用されるすべての環境にこの新しい機能を展開できます。アプリケーションは、それぞれが特定の機能を果たす個別のコンテナを構成することで構築できますが、プロセス全体を単独で実行することはできません。上記とは対照的に、ポッドは通常、システムのどの部分が独立した_管理_から最も利益を得るかを考えることによって構築されます。Kubernetesはポッドをユーザー向けの最小の抽象化として使用するため、これらはKubernetesツールとAPIが直接やり取りして制御できる最も原始的なユニットです。ポッドを開始、停止、および再起動するか、ポッド上に構築された高レベルのオブジェクトを使用して、レプリケーションおよびライフサイクル管理機能を導入できます。Kubernetesでは、ポッド内のコンテナを個別に管理することは許可されていないため、個別の管理から恩恵を受ける可能性のあるコンテナをグループ化しないでください。Kubernetesの多くの機能と抽象化はポッドを直接処理するため、単一のポッドで一緒にスケーリングするアイテムをバンドルし、独立してスケーリングするアイテムを分離することは理にかなっています。Webサーバーを異なるポッドのアプリケーションサーバーから分離すると、必要に応じて各レイヤーを個別にスケーリングできます。Webサーバーとデータベースアダプターを同じポッドにバンドルすると、アダプターがWebサーバーが適切に機能するために必要な重要な機能を提供する場合に意味があります。通常、プライマリコンテナはポッドのコア機能を実行しますが、プライマリコンテナを変更または拡張したり、独自の展開環境への接続を支援したりする追加のコンテナを定義できます。Webサーバーポッドでは、Nginxコンテナーが要求をリッスンしてコンテンツを提供する一方で、リポジトリが変更されると、関連するコンテナーが静的ファイルを更新します。これらのコンポーネントの両方を単一のコンテナにパッケージ化するのは魅力的かもしれませんが、それらを個別のコンテナとして実装することには大きな利点があります。Webサーバーコンテナとリポジトリプーラーの両方は、異なるコンテキストで独立して使用できます。それらは異なるチームによって維持され、それぞれが異なるコンパニオンコンテナで動作するように動作を一般化するように開発できます。[コンテナのデザインパターンベースの分散システム]。これらは、ポッドでコンテナを一緒にパッケージ化するための最も一般的なユースケースのいくつかを表しています:*サイドカー:*このパターンでは、セカンダリコンテナーはプライマリコンテナーのコア機能を拡張および強化します。このパターンには、別のコンテナでの非標準またはユーティリティ関数の実行が含まれます。更新された構成値のログまたはウォッチを転送するコンテナは、主要なフォーカスを大幅に変更することなくポッドの機能を強化できます。ambassadorパターンは、補助コンテナを使用して、メインコンテナのリモートリソースを抽象化します。プライマリコンテナーは、アンバサダーコンテナーに直接接続し、アンバサダーコンテナーは、分散Redisクラスターなど、潜在的に複雑な外部リソースのプールに接続して抽象化します。プライマリコンテナは、外部サービスに接続するために実際の展開環境を知っている必要はありません。*アダプタ:*アダプタパターンは、プライマリコンテナのデータ、プロトコル、またはインターフェースを変換して、外部の関係者が期待する標準に合わせるために使用されます。アダプタコンテナを使用すると、サービスを提供するアプリケーションが互換性のないインターフェイスのみをネイティブにサポートしている場合でも、集中化されたサービスに均一にアクセスできます。ConfigMapsおよびSecretsへの構成の抽出アプリケーションの構成は、コンテナイメージに焼き付けることができますが、複数のコンテキストでの展開をサポートし、より柔軟な管理を可能にするために、実行時にコンポーネントを構成できるようにすることをお勧めします。*と呼ばれる2つのオブジェクトを提供します。ConfigMapは、実行時にポッドや他のオブジェクトに公開できるデータを保存するために使用されるメカニズムです。ConfigMaps内に保存されたデータは、環境変数として提示するか、ポッド内のファイルとしてマウントできます。これらの場所から読み取るようにアプリケーションを設計することにより、ConfigMapを使用して実行時に構成を注入し、コンテナイメージを再構築することなくコンポーネントの動作を変更できます。シークレットは同様のKubernetesオブジェクトタイプであり、機密データを安全に保存し、必要に応じてポッドやその他のコンポーネントへのアクセスを選択的に許可します。シークレットは、通常の構成で簡単にアクセスできる場所にプレーンテキストとして保存せずに、機密資料をアプリケーションに渡す便利な方法です。機能的には、ConfigMapとほぼ同じように機能するため、アプリケーションは同じメカニズムを使用してConfigMapとSecretsからデータを消費できます。ConfigMapsおよびSecretsは、Kubernetesオブジェクト定義に構成を直接配置することを回避するのに役立ちます。値の代わりに構成キーをマップして、ConfigMapまたはSecretを変更することにより、構成をその場で更新できます。これにより、リソースのKubernetes定義を変更せずに、ポッドおよびその他のKubernetesオブジェクトのアクティブなランタイム動作を変更できます。準備状況と活性プローブの実装Kubernetesには、コンポーネントのライフサイクルを管理し、アプリケーションが常に正常で利用可能であることを保証するための、すぐに使用できる多くの機能が含まれています。これらの機能を利用するには、Kubernetesはアプリケーションの状態を監視および解釈する方法を理解する必要があります。*プローブを定義できます。Livenessプローブを使用すると、Kubernetesは、コンテナ内のアプリケーションがアクティブでアクティブに実行されているかどうかを判断できます。Kubernetesは、コンテナ内で定期的にコマンドを実行して、アプリケーションの基本的な動作を確認したり、指定された場所にHTTPまたはTCPネットワーク要求を送信して、プロセスが使用可能で期待どおりに応答できるかどうかを判断したりできます。活性プローブが失敗すると、Kubernetesはコンテナを再起動して、ポッド内の機能の再確立を試みます。準備状況プローブは、ポッドがトラフィックを処理する準備ができているかどうかを判断するために使用される同様のツールです。コンテナ内のアプリケーションは、クライアント要求を受け入れる準備が整う前に初期化手順を実行する必要がある場合があります。新しい構成の通知を受けてリロードする必要がある場合があります。準備プローブが失敗すると、コンテナを再起動する代わりに、Kubernetesは一時的にポッドへのリクエストの送信を停止します。これにより、ポッドはグループ全体の健全性に影響を与えることなく、初期化またはメンテナンスルーチンを完了できます。活性プローブと準備プローブを組み合わせると、Kubernetesにポッドを自動的に再起動するか、バックエンドグループから削除するよう指示できます。これらの機能を利用するようにインフラストラクチャを構成すると、Kubernetesは追加の操作作業なしでアプリケーションの可用性と正常性を管理できます。デプロイメントを使用してスケールと可用性を管理する前に、ポッドの設計の基本について説明するときに、他のKubernetesオブジェクトがこれらのプリミティブに基づいて構築され、より高度な機能を提供することにも言及しました。このような複合オブジェクトの1つである*展開*は、おそらく最も一般的に定義および操作されるKubernetesオブジェクトです。デプロイメントは、他のKubernetesプリミティブ上に構築されて機能を追加する複合オブジェクトです。*と呼ばれる中間オブジェクトに追加します。これらのレプリカセットを使用すると、ポッドテンプレートを定義して、単一のポッドデザインの複数のコピーを起動および管理できます。これにより、インフラストラクチャのスケールアウト、可用性要件の管理、障害発生時のポッドの自動再起動が容易になります。これらの追加機能は、管理フレームワークと、比較的単純なポッドの抽象化に対する自己修復機能を提供します。ポッドは、定義したワークロードを最終的に実行するユニットですが、通常はプロビジョニングおよび管理する必要があるユニットではありません。代わりに、ポッドを、デプロイメントなどの高レベルのオブジェクトを介してプロビジョニングされたときにアプリケーションを堅牢に実行できるビルディングブロックと考えてください。展開により、交換可能なポッドのセットをプロビジョニングおよび管理して、アプリケーションをスケールアウトし、ユーザーの要求を満たすことができます。プロビジョニングされたポッドへのトラフィックのルーティングは別の懸念事項です。ローリングアップデートの一部としてポッドが交換されるか、ホストの障害により再起動または移動されると、以前は実行中のグループに関連付けられていたネットワークアドレスが変更されます。*サービス*を使用すると、ポッドの動的プールのルーティング情報を維持し、インフラストラクチャのさまざまなレイヤーへのアクセスを制御することにより、この複雑さを管理できます。Kubernetesでは、サービスは、トラフィックがポッドのセットにルーティングされる方法を制御する特定のメカニズムです。外部クライアントからのトラフィックの転送でも、複数の内部コンポーネント間の接続の管理でも、サービスを使用すると、トラフィックの流れを制御できます。Kubernetesは、環境が変化し、ネットワーク環境が変化しても、接続を関連するポッドに転送するために必要なすべての情報を更新および維持します。内部でのサービスへのアクセスサービスを効果的に使用するには、まずポッドの各グループの対象となる消費者を決定する必要があります。*サービスタイプを使用すると、クラスター内からのみルーティング可能な安定したIPアドレスを使用してポッドのセットに接続できます。クラスターにデプロイされたオブジェクトは、サービスのIPアドレスにトラフィックを直接送信することにより、複製されたポッドのグループと通信できます。これは最も単純なサービスタイプであり、内部アプリケーションレイヤーに適しています。オプションのDNSアドオンにより、KubernetesはサービスのDNS名を提供できます。これにより、ポッドおよびその他のオブジェクトは、IPアドレスではなく名前でサービスと通信できます。このメカニズムはサービスの使用を大幅に変更することはありませんが、名前ベースの識別子を使用すると、事前にサービスのIPアドレスを知らなくても、コンポーネントの接続や相互作用の定義が簡単になります。公共消費のためのサービスの公開インターフェイスが一般公開されている必要がある場合、通常、最適なオプションは*ロードバランサー*サービスタイプです。これは、特定のクラウドプロバイダーのAPIを使用してロードバランサーをプロビジョニングし、パブリックに公開されたIPアドレスを介してサービスポッドへのトラフィックを提供します。これにより、外部リクエストをサービス内のポッドにルーティングし、内部クラスターネットワークに制御されたネットワークチャネルを提供できます。ロードバランサーサービスタイプはすべてのサービスに対してロードバランサーを作成するため、この方法を使用してKubernetesサービスを公開することは潜在的に費用がかかる可能性があります。*オブジェクトを使用して、事前に定義されたルールセットに基づいて、さまざまなタイプのリクエストをさまざまなサービスにルーティングする方法を説明できます。「example.com」のリクエストはサービスAに送られ、「sammytheshark.com」のリクエストはサービスBにルーティングされます。Ingressオブジェクトは、事前定義されたパターンに基づいて、リクエストの混合ストリームをターゲットサービスに論理的にルーティングする方法を記述する方法を提供します。イングレスルールは、イングレスコントローラー(通常はNginxのような何らかの負荷分散)によって解釈される必要があります。これは、イングレスルールを実装し、トラフィックをKubernetesサービスに転送するポッドとしてクラスター内にデプロイされます。現在、イングレスオブジェクトタイプはベータ版ですが、クラスター所有者が実行する必要がある外部ロードバランサーの数を最小限に抑えるために使用できるいくつかの実装があります。宣言構文を使用してKubernetes状態を管理するKubernetesは、クラスターにデプロイされたリソースの定義と制御において、非常に多くの柔軟性を提供します。+`のようなツールを使用すると、アドホックオブジェクトを強制的に定義して、すぐにクラスターにデプロイできます。これはKubernetesを学習するときにリソースを迅速に展開するのに役立ちますが、このアプローチには長期的な運用管理には望ましくない欠点があります。命令型管理の主な問題の1つは、クラスターに展開した変更の記録を残さないことです。これにより、障害が発生した場合の復旧や、システムに適用された運用上の変更の追跡が困難または不可能になります。+`を使用して構成または変更を適用できる代替の宣言構文を提供します。これらの構成ファイルをバージョン管理リポジトリに保存すると、変更を監視し、組織の他の部分で使用されるレビュープロセスと統合する簡単な方法になります。ファイルベースの管理により、既存の定義をコピーおよび編集することにより、既存のパターンを新しいリソースに簡単に適合させることができます。バージョン管理されたディレクトリにKubernetesオブジェクト定義を保存すると、各時点で目的のクラスター状態のスナップショットを維持できます。システムに導入された意図しない変更の根本原因を追跡する際に非常に役立ちます。結論アプリケーションを実行するインフラストラクチャを管理し、最新のオーケストレーション環境で提供される機能を最大限に活用する方法を学ぶのは困難な場合があります。Kubernetesなどのシステムやコンテナーなどのテクノロジーが提供する多くの利点は、開発と運用のプラクティスがツールの構築コンセプトに沿っている場合に明らかになります。Kubernetesが得意とするパターンを使用してシステムを設計し、特定の機能が非常に複雑な展開に関連するいくつかの課題を軽減する方法を理解すると、プラットフォーム上で実行するエクスペリエンスが向上します。