Kubernetes デプロイメントの 10 のアンチパターン

Kubernetes デプロイメントの 10 のアンチパターン

コンテナの採用と使用が増加し続けるにつれて、Kubernetes (K8s) はコンテナ オーケストレーションの主要プラットフォームになりました。これは、315 社を超える企業から数万人の貢献者が参加するオープンソース プロジェクトであり、スケーラブルで非依存であることを目指しており、すべての主要なクラウド プロバイダーの基盤となっています。

[[341879]]

コンテナを本番環境で実行する場合、災害を回避するために、本番環境をできるだけ安定して回復力のあるものにする必要があります (ブラックフライデーのオンライン ショッピング体験を思い浮かべてください)。コンテナがクラッシュした場合、時間帯に関係なく (または深夜でも)、代わりに別のコンテナを起動する必要があります。 Kubernetes は、スケーリングからフェイルオーバー、負荷分散など、分散システムを回復力を持って実行するためのフレームワークを提供します。また、ニーズに合わせて Kubernetes と統合するツールも多数あります。

ベスト プラクティスは時間の経過とともに進化するため、Kubernetes を使用した開発のより良い方法について継続的に調査および実験することが常に重要です。これはまだ新しい技術であるため、私たちは常にその理解と使用方法の向上に努めています。

この記事では、Kubernetes デプロイメントにおける、より高いレベルでより優れたソリューションを提供する 10 の一般的なプラクティスについて説明します。カスタム実装は異なる可能性があるため、ベスト プラクティスについては詳しく説明しません。

  • 設定ファイルをDockerイメージ内または隣に置く
  • Helmやその他のテンプレートは使用しない
  • 特定の順序でデプロイします。 (依存関係がまだ準備ができていないため、アプリケーションがクラッシュすることはありません。)
  • メモリやCPUの制限を設定せずにポッドをデプロイする
  • 最新のタグを本番環境のコンテナにプルする
  • 再起動時に新しい Docker イメージをプルするようにポッドを強制終了して、新しい更新/修正を展開します。
  • 同じクラスター内で本番環境と非本番環境のワークロードを混在させます。
  • ミッションクリティカルなデプロイメントでは、ブルーグリーン デプロイメントやカナリア デプロイメントを使用しないでください。 (Kubernetes のデフォルトのローリング アップデートは必ずしも十分ではありません。)
  • 展開が成功したかどうかを把握するための指標は用意されていません。 (ヘルスチェックにはアプリケーションのサポートが必要です。)
  • クラウドベンダーロックイン: IaaS プロバイダーの Kubernetes またはサーバーレス コンピューティング サービスにロックインする

Kubernetes のアンチパターン 10 個

1. 設定ファイルをDockerイメージ内または隣に置く

この Kubernetes アンチパターンは、Docker アンチパターンに関連しています (この記事のアンチパターン 5 と 8 を参照)。コンテナは、開発/QA からステージング、本番環境まで、本番環境におけるソフトウェアのライフサイクル全体にわたって単一のイメージを使用する方法を開発者に提供します。

ただし、ライフサイクルの各ステージに独自のイメージを提供し、各ステージをその環境 (QA、ステージング、または本番) に固有のさまざまな成果物で構築するのが一般的です。しかし、今ではテスト済みの製品を展開していません。

> ビルド時に設定をハードコードしないでください(https://codefresh.io/containers/docker-anti-より)

ここでのベストプラクティスは、共通の構成を ConfigMaps で外部化することです。一方、API キーやシークレットなどの機密情報は Secrets リソース (Base64 エンコードされていますが、それ以外は ConfigMaps と同じです) に保存できます。 ConfigMap はボリュームとしてマウントして環境変数として渡すことができますが、Secret はボリュームとしてマウントする必要があります。 ConfigMap と Secrets について言及するのは、これらは Kubernetes のネイティブ リソースであり、統合は必要ないが、制限される可能性があるからです。他にも、構成マップ用の HashiCorp の ZooKeeper や Consul、シークレット用の HashiCorp の Vault、Keywhiz、Confidant などのソリューションがあり、こちらの方がニーズに適している可能性があります。

構成をアプリケーションから分離すると、構成を更新する必要があるときにアプリケーションを再コンパイルする必要がなくなり、アプリケーションの実行中に更新できるようになります。アプリケーションは、ビルド プロセス中ではなく実行時に構成を取得します。さらに重要なのは、ソフトウェア ライフサイクルのすべての段階で同じソース コードを使用することです。

> 実行時に構成をロードする (https://codefresh.io/containers/docker-anti-patterns/ より)

2. Helmや他のタイプのテンプレートを使用しない

YAML を直接更新することで、Kubernetes のデプロイメントを管理できます。新しいバージョンのコードをロールアウトする場合、次の 1 つ以上の更新が必要になることがあります。

  • Dockerイメージ名
  • Docker イメージタグ
  • レプリカ番号
  • ラベルサービスラベル
  • ポッド
  • Configmapなど

複数のクラスターを管理し、開発環境、ステージング環境、本番環境で同じ更新を適用する場合、これは面倒な作業になる可能性があります。基本的には、すべてのデプロイメントで、小さな変更を加えて同じファイルを変更します。デプロイメント YAML のターゲット環境も認識しながら、コピー アンド ペーストや検索 アンド 置換を大量に実行します。このプロセス中に間違いが発生する可能性は数多くあります。

  • スペルミス(バージョン番号が間違っている、イメージ名が間違っているなど)
  • 間違った更新で YAML を変更する (例: 間違ったデータベースに接続する)
  • 更新するリソースが不足しているなど

YAML に多くの変更を加える必要がある場合があり、細心の注意を払わないと、ある YAML を別のデプロイメントの YAML と間違えてしまう可能性が高くなります。

テンプレートは、Kubernetes アプリケーションのインストールと管理を簡素化するのに役立ちます。 Kubernetes はネイティブのテンプレート メカニズムを提供しないため、この管理については他の場所を探す必要があります。

Helm は最初に登場したパッケージ マネージャーです (2015 年)。これは「Homebrew for Kubernetes」と呼ばれ、テンプレート機能が追加されて進化しました。 Helm はチャートを通じてリソースをパッケージ化します。チャートは、関連する Kubernetes リソースのセットを記述するファイルのコレクションです。チャート リポジトリには 1,400 を超える公開チャートがあり (helm search hub [キーワード] [フラグ] も使用できます)、Kubernetes でのインストール、アップグレード、アンインストールに再利用可能なレシピです。 Helm Chart を使用すると、values.yaml ファイルを変更して Kubernetes デプロイメントに必要な変更を設定でき、環境ごとに異なる Helm Chart を使用できます。したがって、QA、ステージング、本番環境がある場合、すべての環境のすべてのデプロイメントのすべての YAML を変更する必要はなく、3 つの Helm チャートだけを管理すれば済みます。

Helm を使用するもう 1 つの利点は、何か問題が発生した場合に、Helm ロールバックを使用して簡単に以前のバージョンにロールバックできることです。

  1. helm rollback <リリース> [リビジョン] [フラグ]

以前のバージョンにロールバックする場合は、以下を使用できます。

  1. helm ロールバック<リリース> 0

次のようなものが表示されます:

  1. $ helm アップグレード — インストール — 待機 — タイムアウト 20 デモ demo/
  2. $ helm アップグレード — インストール — 待機 — タイムアウト 20 — 設定
  3. readinessPath =/fail demo demo/$ helm rollback — wait — timeout 20 demo 1ロールバックは成功しました。

Helm Chart の履歴はそれをかなり正確に追跡します:

  1. $ helm 履歴デモ
  2. 改訂ステータスの説明
  3. 1 廃止 インストール完了
  4. 2 廃止 アップグレード「デモ」が失敗しました: 条件を待機中にタイムアウトしました
  5. 3 デプロイ済み 1 にロールバック

Helm に加えて、人気のある代替手段である Google の Kustomize を使用することもできます。

3. 特定の順序で展開する

依存関係がまだ準備ができていないため、アプリケーションがクラッシュすることはありません。従来の開発では、アプリケーションを起動するときに、タスクの開始と停止に特定の順序があります。この考え方をコンテナ オーケストレーションに持ち込まないことが重要です。 Kubernetes、Docker などでは、これらのコンポーネントは同時に起動できるため、起動順序を定義することはできません。アプリケーションが起動して実行されている場合でも、依存関係が失敗したり移行したりして、さらなる問題が発生する可能性があります。 Kubernetes の現実には、依存関係に到達できない潜在的な通信障害が無数に存在し、その間にポッドがクラッシュしたり、サービスが利用できなくなったりする可能性があります。信号が弱かったり、ネットワーク接続が失われたりといったネットワーク遅延は、通信障害の一般的な原因です。

簡単にするために、在庫データベースとストアフロント ユーザー インターフェイスという 2 つのサービスを持つ架空のショッピング アプリケーションを調べてみましょう。アプリケーションを起動する前に、バックエンド サービスを開始し、すべてのチェックを満たして実行を開始する必要があります。その後、フロントエンド サービスを開始し、チェックに合格して実行を開始できます。

たとえば、 kubectl wait コマンドを使用してデプロイメント コマンドを強制実行したとします。

  1. kubectl wait — for =条件=Ready pod/serviceA

ただし、条件が満たされない場合、次のデプロイメントは実行できず、プロセスは中断されます。

デプロイメント シーケンスの簡単なフローは次のとおりです。

> このプロセスは前のステップが完了するまで先に進めません

Kubernetes には自己修復機能があるからです。標準的なアプローチは、アプリケーション内のすべてのサービスを同時に開始し、すべてのサービスが起動して実行されるまでコンテナをクラッシュさせて再起動することです。サービス A と B を独立して起動させます (分離されたステートレス クラウド ネイティブ アプリケーションのように)。ただし、ユーザー エクスペリエンスを考慮して、サービス A の準備ができるまで UI (サービス B) に適切な読み込みメッセージを表示するように指示することはできますが、サービス B の実際の起動はサービス A の影響を受けないようにする必要があります。

> ポッドがクラッシュすると、Kubernetes はすべてが稼働するまでサービスを再起動します。もしy

もちろん、自己治癒だけに頼るだけでは不十分です。避けられず、必ず起こる失敗に対処するソリューションを実装する必要があります。私たちは、こうした事態が発生することを想定して、ダウンタイムやデータ損失を回避するために、こうした事態に対応するためのフレームワークを用意しておく必要があります。

私の仮想ショッピング アプリケーションでは、ユーザーに完全なエクスペリエンスを提供するために、ストアフロント UI (サービス B) に在庫 (サービス A) が必要です。したがって、サービス A が短期間利用できなくなったり、クラッシュしたりするなど、部分的な障害が発生した場合でも、システムは問題から回復できるはずです。

このような一時的な障害は常に発生する可能性があるので、その影響を最小限に抑えるために再試行パターンを実装することができます。再試行モードは、次の戦略を通じてアプリケーションの安定性を向上させるのに役立ちます。

  • キャンセル 失敗が一時的でない場合、またはプロセスを繰り返し試行しても成功する可能性が低い場合は、アプリケーションは操作をキャンセルし、認証の失敗などの例外を報告する必要があります。無効な資格情報では機能しません。
  • 再試行 失敗が異常またはまれな場合は、異常な状況 (ネットワーク パケットの破損など) が原因である可能性があります。同じ障害が再度発生する可能性は低いため、アプリケーションはすぐに要求を再試行する必要があります。
  • 遅延後に再試行します。失敗が一般的な条件 (接続障害やビジー障害など) によるものである場合は、再試行する前に作業のバックログやトラフィックをクリアすることをお勧めします。アプリケーションは待機してからリクエストを再試行する必要があります。
  • 指数バックオフを使用した再試行パターンを実装することもできます (待機時間を指数的に増加し、再試行の最大回数を設定します)。

回復力のあるマイクロサービス アプリケーションを作成する場合、回路遮断パターンを実装することも重要な戦略です。家庭内のブレーカーが自動的に切り替わり、過電流や短絡による甚大な被害から保護するのと同じように、サーキット ブレーカー パターンは、解決に長い時間を要する可能性のある予期しない障害の影響を制限しながらアプリケーションを作成する方法を提供します。接続の部分的な喪失やサービスの完全な障害などの修復。再試行が不可能な場合、アプリケーションは障害が発生したことを受け入れ、それに応じて応答できる必要があります。

4. メモリやCPUの制限を設定せずにポッドをデプロイする

リソースの割り当てはサービスによって異なり、実装をテストせずにコンテナーが最適なパフォーマンスを得るために必要なリソースを予測することは困難です。あるサービスでは固定の CPU およびメモリ使用プロファイルが必要な場合がありますが、別のサービスでは使用プロファイルが動的である場合があります。

メモリと CPU の制限を慎重に考慮せずにポッドをデプロイすると、リソースの競合が発生し、環境が不安定になる可能性があります。コンテナにメモリまたは CPU の制限がない場合、スケジューラはメモリ使用率 (および CPU 使用率) をゼロとして扱うため、任意のノードに無制限の数のポッドをスケジュールできます。これにより、リソースのオーバーコミットが発生し、ノードや kubelet がクラッシュする可能性があります。

コンテナにメモリ制限が指定されていない場合、次の 2 つの状況が考えられます (これらの状況は CPU にも適用されます)。

  • コンテナが使用できるメモリの量に上限はありません。その結果、コンテナはノード上の使用可能なメモリをすべて使用し、OOM (メモリ不足) キラーを引き起こす可能性があります。リソース制限のないコンテナでは、OOM 破壊が発生する可能性が高くなります。
  • コンテナが実行される名前空間のデフォルトのメモリ制限がコンテナに割り当てられます。クラスター管理者は LimitRange を使用して、メモリ制限のデフォルト値を指定できます。

クラスター内のコンテナのメモリと CPU の制限を宣言すると、クラスター ノード上の使用可能なリソースを効率的に使用できるようになります。これにより、kube-scheduler は、ハードウェアを最も効率的に使用するために、どのノードに Pod を配置するかを決定できます。

コンテナのメモリと CPU の制限を設定するときは、制限を超えるリソースを要求しないように注意してください。複数のポッドを持つコンテナの場合、集約リソース要求は設定された制限を超えてはなりません。そうしないと、コンテナはスケジュールされません。

> リソース要求は制限を超えてはいけません

メモリと CPU の要求を制限以下に設定することで、次の 2 つのことが実現されます。

  • ポッドは、利用可能な場合にメモリ/CPU を使用する可能性があり、アクティビティの大規模なバーストが発生します。
  • バースト中、ポッドは適切な量のメモリ/CPU に制限されます。

ベスト プラクティスとしては、CPU リクエストを 1 つのコア以下に抑え、ReplicaSets を使用してスケール アウトすることで、システムの柔軟性と信頼性が向上します。

同じクラスターにコンテナをデプロイする場合、異なるチームがリソースを競い合うとどうなるでしょうか?プロセスがメモリ制限を超えると強制終了され、CPU 制限を超えるとプロセスが調整されます (パフォーマンスが低下します)。

名前空間設定のリソース クォータと LimitRange を介してリソース制限を制御できます。これらの設定は、無制限のコンテナ展開やリソースを大量に消費するコンテナ展開に関する問題を解決するのに役立ちます。

ハードリソース制限を設定することは、ニーズに最適なオプションではない可能性があります。もう 1 つのオプションは、Vertical Pod Autoscaler リソースの推奨モードを使用することです。

5. 「最新」タグを本番環境のコンテナにプルする

Latest タグの使用は、特に本番環境では悪い習慣とみなされます。ポッドはさまざまな理由で予期せずクラッシュする可能性があるため、いつでもイメージをプルダウンできます。残念ながら、ビルドがいつ中断するかを判断する場合、最新のタグはあまり説明的ではありません。実行されているイメージのバージョンはどれですか?最後に動作したのはいつですか?これは特に本番環境では問題です。なぜなら、最小限のダウンタイムでシステムを復旧して稼働させる必要があるからです。

> 本番環境では最新のタグを使用しないでください。

デフォルトでは、imagePullPolicy は「Always」に設定されており、再起動時にイメージは常にプルダウンされます。ラベルを指定しない場合、Kubernetes はデフォルトで最新になります。ただし、デプロイメントは、クラッシュが発生した場合 (ポッドが再起動時にイメージをプルダウンした場合)、またはデプロイメント ポッドのテンプレート (.spec.template) が変更された場合にのみ更新されます。開発時に正しく動作しない最新の例については、このフォーラムのディスカッションを参照してください。

imagePullPolicy を Always 以外の値に変更した場合でも、再起動が必要な場合 (クラッシュまたは意図的な再起動のため)、ポッドはイメージをプルします。バージョン管理を使用し、imagePullPolicy に意味のあるタグ (例: v1.4.0) を設定すると、最新の安定バージョンにロールバックして、コードに問題が発生した場合に、より簡単にトラブルシューティングを行うことができます。バージョニングのベスト プラクティスの詳細については、セマンティック バージョニング仕様と GCP ベスト プラクティスをご覧ください。

特定の意味のある Docker タグを使用するだけでなく、コンテナーはステートレスかつ不変であることも覚えておく必要があります。また、一時的なものである必要があります (すべてのデータはコンテナー外の永続ストレージに保存する必要があります)。コンテナが起動したら、パッチ適用、更新、構成変更など、変更しないでください。構成の更新が必要な場合は、更新された構成で新しいコンテナをデプロイする必要があります。

> Docker の不変性 (コンテナ運用のベスト プラクティスより抜粋)。

この不変性により、より安全で繰り返し可能なデプロイメントが可能になります。また、古いイメージを再展開する必要がある場合、ロールバックも容易になります。 Docker イメージとコンテナを永続的に保持することで、同じコンテナ イメージをそれぞれの環境にデプロイできます。イメージを不変に保つために構成データを外部化する方法の詳細については、アンチパターン 1 を参照してください。

> トラブルシューティング中に、以前の安定バージョンにロールバックできます。

6. 再起動プロセス中に新しいDockerイメージをプルするようにポッドを強制終了して、新しい更新/修正を展開します。

更新を取得するために最新のタグに依存するのと同様に、新しい更新をプッシュするためにポッドを強制終了することに依存するのも、コードのバージョン管理が行われないため、悪い習慣です。本番環境で更新された Docker イメージをプルするためにポッドを強制終了する場合は、実行しないでください。バージョンが本番環境にリリースされると、上書きすることはできません。何か問題が発生した場合、何が問題だったのか、いつ問題が起こったのか、トラブルシューティング中にいつコードをロールバックする必要があるのか​​がわかりません。

もう 1 つの問題は、コンテナを再起動して新しい Docker イメージを取得することが常に可能であるとは限らないことです。 「デプロイメントのロールアウトは、デプロイメントの Pod テンプレート (つまり .spec.template) が変更された場合にのみトリガーされます (例: テンプレートのラベルまたはコンテナ イメージが更新された場合)。デプロイメントのスケーリングなどのその他の更新では、デプロイメントはトリガーされません。」

デプロイメントをトリガーするには、.spec.template を変更する必要があります。

新しい Docker イメージをプルするために Pod を更新する正しい方法は、コードのバージョンを変更し (またはリビジョン/パッチを増分し)、意味のあるタグ (最新ではない、詳細についてはアンチパターン 5 を参照) を反映するようにデプロイメント仕様を変更することです。ただし、v1.4.0 (新規リリースの場合) または v1.4.1 (パッチの場合) に似ています。その後、Kubernetes はダウンタイムなしでアップグレードをトリガーします。

  • Kubernetes は新しいイメージを使用して新しいコンテナを起動します。
  • ヘルスチェックが合格するのを待っています。
  • 古いポッドを削除します。

7. 同じクラスター内で本番環境と非本番環境のワークロードを混在させる

Kubernetes は名前空間機能をサポートしており、ユーザーは同じ物理クラスター内で異なる環境 (仮想クラスター) を管理できます。名前空間は、単一の物理クラスター上でさまざまな環境を管理するためのコスト効率の高い方法と考えることができます。たとえば、ステージング環境と本番環境を同じクラスターで実行して、リソースとコストを節約できます。ただし、開発環境で Kubernetes を実行することと、本番環境で Kubernetes を実行することの間には大きなギャップがあります。

同じクラスター上で本番環境と非本番環境のワークロードを混在させる場合、考慮すべき要素は多数あります。たとえば、運用環境のパフォーマンスに影響が及ばないように、リソース制限を考慮する必要があります (一般的な方法としては、運用環境の名前空間にはクォータを設定せず、運用環境以外の名前空間にはクォータを設定します)。

分離についても考慮する必要があります。開発者には実稼働環境よりも多くのアクセス権と許可が必要なので、できる限りロックダウンすることをお勧めします。名前空間は互いに隠されていますが、デフォルトでは完全に分離されているわけではありません。つまり、開発者名前空間のアプリケーションは、テスト、ステージング、または本番環境のアプリケーションを呼び出すことができます (逆も同様)。これは良い方法ではありません。もちろん、NetworkPolicies を使用して名前空間を分離するルールを設定することもできます。

ただし、リソース制限、パフォーマンス、セキュリティ、信頼性を徹底的にテストするには時間がかかるため、非本番環境のワークロードと同じクラスターで本番環境のワークロードを実行することはお勧めしません。同じクラスター内で本番環境と非本番環境のワークロードを混在させるのではなく、開発/テスト/本番環境に別々のクラスターを使用します。これにより、分離とセキュリティが向上します。人為的エラーの可能性を減らすために、CI/CD とアップグレードも可能な限り自動化する必要があります。生産環境は可能な限り堅牢である必要があります。

8. ミッションクリティカルなタスクにはブルーグリーンやカナリアデプロイメントを使用しない

最近の多くのアプリケーションでは、1 か月に数回の変更から 1 日に複数回のデプロイメントまで、頻繁にデプロイメントが行われます。マイクロサービス アーキテクチャでは、さまざまなコンポーネントが連携してシームレスに動作する限り、さまざまなサイクルで開発、管理、リリースできるため、これが可能になります。もちろん、アップデートを展開している間は、アプリを 24 時間 365 日利用できるようにしておくことが重要です。

Kubernetes のデフォルトのローリングアップデートは必ずしも十分ではありません。更新を実行するための一般的な戦略は、デフォルトの Kubernetes ローリング アップデート機能を使用することです。

  1. .spec.strategy.type ==ローリングアップデート

maxUnavailable (利用可能な Pod の割合または数) および maxSurge フィールド (オプション) を設定して、ローリング更新プロセスを制御できます。適切に実装されていれば、ローリング アップデートにより、ポッドが段階的に更新されるため、ダウンタイムなしで段階的に更新できます。これは、あるチームがローリング アップデートによってダウンタイムなしでアプリケーションを更新した例です。

ただし、デプロイメントを次のバージョンに更新すると、元に戻すのが難しくなります。生産停止の場合に備えて、ロールバックする計画を立てておく必要があります。 Pod が次のバージョンに更新されると、Deployment によって新しい ReplicaSet が作成されます。 Kubernetes は以前の ReplicaSets を保存します (デフォルトでは 10 個ですが、 spec.revisionHistoryLimit で変更できます)。レプリカ セットは app6ff34b8374 のような名前でランダムに保存され、デプロイメント アプリケーション YAML にはレプリカ セットへの参照が見つかりません。以下の方法で見つけることができます:

  1. レプリカセット.メタデータ.注釈

そして、次の方法でリビジョンを確認します。

  1. kubectl レプリカセット app-6ff88c4474 -o yaml を取得します

リビジョン番号を見つけます。これは、YAML リソースにコメントを残さない限りリリース履歴がログを保持しないため複雑です (--record フラグを使用してこれを行うことができます)。

  1. $kubectl ロールアウト履歴 デプロイメント/appREVISION CHANGE-CAUSE1 kubectl create —ファイル名=デプロイメント.yaml —レコード= true  
  2. 2 kubectl apply —ファイル名=デプロイメント.yaml —レコード= true  

数十、数百、あるいは数千ものデプロイメントが同時に更新される場合、それらすべてを一度に追跡することは困難です。保存したリビジョンすべてに同じリグレッションが含まれている場合、本番環境は良好な状態になりません。ローリング アップデートの使用の詳細については、この記事をご覧ください。

その他の質問は次のとおりです:

  • すべてのアプリケーションが複数のバージョンを同時に実行できるわけではありません。
  • 更新の途中でクラスターのリソースが不足し、プロセス全体が中断される可能性があります。

これらはすべて、実稼働環境で遭遇すると非常にイライラさせ、ストレスの多い問題です。

デプロイメントをより確実に更新するための代替方法は次のとおりです。

ブルーグリーン (レッドブラック) デプロイメントでは、ブルー/グリーンを使用し、古いインスタンスと新しいインスタンスの両方がそのまま残ります。青はアクティブなバージョンであり、新しいバージョンは緑のレプリカにデプロイされます。グリーン環境がテストと検証に合格すると、ロード バランサーはトラフィックをグリーンに切り替え、ブルー環境になり、古いバージョンはグリーンになります。完全なバージョンを 2 つ維持しているため、ロールバックの実行は簡単です。ロード バランサーに切り替えるだけで済みます。

> ロード バランサーは青と緑を切り替えてアクティブなバージョンを設定します。継続的デプロイメントから

その他の利点は次のとおりです:

  • 本番環境に直接デプロイすることはないので、グリーンからブルーに変更するときにストレスはほとんどありません。
  • トラフィックのリダイレクトは即座に行われるため、ダウンタイムは発生しません。
  • 切り替え前に、実際の生産を反映するために広範囲にわたるテストを行うことができます。 (前述したように、開発環境は本番環境とは大きく異なります。)

Kubernetes には、ネイティブ ツールの 1 つとしてブルー/グリーン デプロイメントが含まれていません。 CI/CD 自動化にブルー/グリーンを実装する方法の詳細については、このチュートリアルをご覧ください。

カナリア リリース カナリア リリースを使用すると、運用システム/ユーザー ベース全体に影響を及ぼす前に、潜在的な問題をテストし、主要なメトリックを満たすことができます。私たちは、本番環境に直接デプロイすることで(ただし、少数のユーザーのみに)「本番環境でテスト」します。パーセンテージに基づいてルーティングするか、地域/ユーザーの場所、クライアントの種類、課金属性に基づいてルーティングするかを選択できます。より小さなサブセットに展開する場合でも、アプリケーションのパフォーマンスを注意深く監視し、品質しきい値を定義するメトリックに対してエラーを測定することが重要です。アプリケーションが期待どおりに動作する場合、より多くのトラフィックをサポートするために、新しいバージョンのインスタンスをさらに出荷し始めます。

> ロードバランサーは、新しいバージョンを段階的に本番環境にリリースします。継続的デプロイメントSから

その他の利点は次のとおりです:

  • 可観測性
  • 本番環境のトラフィックでテストする機能(実際の本番環境のような開発環境を実現するのは難しい)
  • 大規模なリリースの前に、少数のユーザーグループにリリースして実際のフィードバックを得る機能
  • 早く失敗しましょう。これを本番環境に直接デプロイするため、障害が発生した場合は、迅速に対処(つまり、すぐに元に戻す)でき、コミュニティ全体ではなくサブセットのみに影響します。

9. 導入が成功したかどうかを判断するための適切な指標がない

ヘルスチェックにはアプリケーションのサポートが必要です。

Kubernetes を使用すると、コンテナ オーケストレーションで多くのタスクを実行できます。

  • アプリケーションまたはチームによるリソース消費(名前空間、CPU/メモリ、制限)を制御して、アプリケーションがリソースを過剰に消費するのを防ぎます。
  • 異なるアプリケーションインスタンス間で負荷分散を行い、リソースが不足したりホストがダウンした場合にアプリケーションインスタンスをあるホストから別のホストに移動する
  • 自己修復 - コンテナがクラッシュした場合に再起動する
  • クラスタに新しいホストが追加されると、追加のリソースが自動的に利用されます。
  • その他

そのため、指標や監視を忘れてしまうことが時々あります。ただし、導入が成功したからといって、運用作業が終わるわけではありません。積極的に行動し、予期せぬ事態に備えておく方が良いでしょう。監視するレイヤーがさらに多く、K8s の動的な性質によりトラブルシューティングが困難になります。たとえば、利用可能なリソースを注意深く監視しないと、ポッドの自動再スケジュールによって容量の問題が発生し、アプリがクラッシュしたり、デプロイされなかったりする可能性があります。これは特に本番環境では残念なことです。誰かがバグレポートを提出するか、たまたま確認しない限り、知ることができないからです。

監視には独自の課題があります。監視するレイヤーが多数あり、「エンジニアのメンテナンス負担をかなり低く抑える」必要があります。 Kubernetes 上で実行されているアプリケーションに問題が発生すると、特に複数のマイクロサービスが関係している場合は、調査すべきログ、データ、コンポーネントが大量に発生し、すべてを少数のログに出力する従来のモノリシック アーキテクチャと比較すると問題となります。

アプリケーションのパフォーマンスなど、アプリケーションの動作に関する洞察は、継続的な改善に役立ちます。また、コンテナ、ポッド、サービス、クラスター全体についての総合的な理解も必要です。アプリケーションがリソースをどのように使用しているかを判断できれば、Kubernetes を使用してボトルネックをより適切に検出し、排除することができます。アプリケーションを完全に可視化するには、Prometheus、Grafana、New Relic、Cisco AppDynamics などのアプリケーション パフォーマンス監視ソリューションを使用する必要があります。

監視ソリューションを使用するかどうかに関わらず、Kubernetes ドキュメントでは、次の主要なメトリックを注意深く追跡することを推奨しています。

  • ポッドの実行とそのデプロイメント
  • リソース メトリック: CPU、メモリ使用量、ディスク I/O
  • コンテナネイティブメトリクス
  • アプリケーションインジケーター

10. クラウドベンダーロックイン: IaaSプロバイダーのKubernetesまたはサーバーレスコンピューティングサービスにロックインする

ロックインにはさまざまな種類がありますが (詳細については、Martin Fowler の優れた記事をご覧ください)、ベンダー ロックインは、クラウドへのデプロイの主な価値であるコンテナの柔軟性を無効にします。実際、適切なクラウド プロバイダーを選択するのは簡単な作業ではありません。各プロバイダーには独自のインターフェース、オープン API、独自の仕様と標準があります。さらに、ビジネス要件が予期せず変更されたという理由だけで、あるプロバイダーが他のプロバイダーよりもニーズに適している場合もあります。

幸いなことに、コンテナはプラットフォームに依存せず移植可能であり、すべての主要プロバイダーはクラウドに依存しない Kubernetes 基盤を備えています。クラウド間でワークロードを移動する必要がある場合、アプリケーション コードを再設計したり書き直したりする必要がないため、「リフト アンド シフト」ができないためにクラウド プロバイダーに縛られることがありません。

ベンダー ロックインを防止または最小限に抑える柔軟性を確保するために検討すべき手順を次に示します。

(1)まず、部屋の清掃:細則を必ずお読みください

参入戦略と撤退戦略を交渉します。多くのベンダーは簡単に始められるようにしており、ハマるのも簡単です。これには無料トライアルやボーナスクレジットなどのインセンティブが含まれる場合がありますが、規模が大きくなるにつれてこれらのコストは急速に増加する可能性があります。

自動更新、早期解約料金などがあるかどうか、別のベンダーに移行する際の移行や終了関連の SLA についてプロバイダーが支援してくれるかどうかを確認します。

(2)あらゆるクラウドで実行できるようにアプリケーションを設計する

すでにクラウド向けに開発を行っており、クラウド ネイティブの原則を使用している場合は、アプリケーション コードのリフト アンド シフトが簡単になる可能性が高くなります。コードに関する事項により、クラウド ベンダーにロックインされる可能性があります。たとえば、次のことが可能です。

  • アプリケーションで使用されるサービスと機能 (データベース、API など) が移植可能かどうかを確認します。
  • デプロイメントおよび構成スクリプトがクラウド固有であるかどうかを確認します。一部のクラウドには、独自のネイティブまたは推奨の自動化ツールがあり、他のプロバイダーに簡単に移行できない場合があります。クラウド インフラストラクチャの自動化を支援するツールは数多くあり、Puppet、Ansible、Chef などの主要なクラウド プロバイダーの多くと互換性があります。このブログには、一般的なツールの機能を比較した便利な表があります。
  • DevOps 環境 (通常は Git と CI/CD が含まれます) がどのクラウドでも実行できるかどうかを確認します。たとえば、多くのクラウドには、IBM Cloud Continuous Delivery、Azure CI/CD、AWS Pipelines などの独自の CI/CD ツールがあり、別のクラウド ベンダーに移植するには追加の作業が必要になる場合があります。代わりに、Docker と Kubernetes を強力にサポートし、他の多くの一般的なツールと統合する Codefresh などの完全な CI/CD ソリューションを使用できます。 GitLab、Bamboo、Jenkins、Travis など、CI または CD、あるいはその両方を実行するソリューションは他にも多数あります。
  • プロバイダー間でテストプロセスを変更する必要があるかどうかを確認します。

(3)マルチクラウド戦略を採用することもできます

マルチクラウド戦略を使用すると、提供するアプリケーションの種類に最適なさまざまなクラウドプロバイダーからサービスを選択できます。マルチクラウドの展開を計画する場合、相互運用性を慎重に検討する必要があります。

まとめ

Kubernetesは確かに人気がありますが、開始することは困難であり、伝統的な開発における多くの慣行をクラウドネイティブ開発に変換することはできません。

この記事では、次のように検討しました。

  • Docker画像の隣に構成ファイルを配置します。構成データを外部化します。 ConfigMapとSecretなどを使用できます。
  • ヘルムやその他のタイプのテンプレートを使用していない:ヘルムまたはKustomizeを使用すると、コンテナのオーケストレーションを簡素化し、ヒューマンエラーを減らすことができます。
  • 特定の順序で物事を展開する:依存関係がまだ準備ができていないため、アプリケーションがクラッシュしないでください。 Kubernetesの自己修復メカニズムを活用し、RetriesとCircuit Breakersを実装します。
  • メモリおよび/またはCPU制限を設定せずにポッドを展開する:特に他の人とクラスターを共有している場合は、リソース競合のリスクを減らすためにメモリとCPUの制限を設定することを検討する必要があります。
  • 最新のタグを生産中のコンテナに引き込みます。最新のタグを使用しないでください。意味のあるもの(v1.4.0 / semanticバージョンの仕様に従って)を常に使用し、不変のDocker画像を使用してください。
  • ポッドを殺して新しい更新/パッチを展開して、再起動中に新しいDocker画像をプルするようにします:バージョンのコードがリリースをより適切に管理できるようにします。
  • 同じクラスターで生産と非生産のワークロードを混合します。可能であれば、個別のクラスターで生産と非生産のワークロードを実行します。これにより、リソースの競合と、予期せぬ環境が生産環境に移行するリスクが減少します。
  • ミッションクリティカルな展開にブルーグリーンまたはカナリアの展開を使用しないでください(Kubernetesのデフォルトのローリングアップデートでは常に十分ではありません):青緑色の展開またはカナリアリリースを使用して、生産の圧力を軽減し、より意味のある生産結果を得ることを検討する必要があります。
  • 展開が成功したかどうかを理解するためのメトリックはありません(アプリケーションによって健康チェックをサポートする必要があります):予期しないことが起こらないように展開を監視するようにする必要があります。 Prometheus、Grafana、New Relic、Cisco AppDynamicsなどのツールを使用して、展開の可視性を向上させることができます。
  • クラウドベンダーのロックイン:IAASプロバイダーのKubernetesまたはサーバーレスコンピューティングサービスにロックする:ビジネスのニーズはいつでも変わる可能性があります。クラウドネイティブアプリケーションを簡単に持ち上げてシフトできるため、不注意にクラウドプロバイダーに自分自身をロックすることはできません。

読んでくれてありがとう!

<<:  マルチクラウド環境で成功するために必要なこと

>>:  IBMのハイブリッドマルチクラウドプラットフォームは、企業のアプリケーションの最新化とコンテナ化の実現を支援します。

推薦する

アマゾン ウェブ サービスがマレーシアに新リージョンを発表

最近、Amazon Web Services は、マレーシアに Amazon Web Service...

「万家ショッピング」は中国最大のオンラインねずみ講事件

杭州、8月7日(王毅記者)今朝、金華市婺城区裁判所は、国内最大のオンラインねずみ講事件「万家ショッピ...

ウェブサイトタイムマシン: CodeGuard は無料のウェブサイトバックアップ サービスを提供しています

CodeGuard は、すべてのウェブマスターが自分のウェブサイトをバックアップおよび復元できる無料...

なぜ多くの人がウェブサイト構築に MiTo テンプレートを選択するのでしょうか?

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています2018 ...

クラウドサービスの費用管理を最適化するための4つのヒント

クラウド請求書管理により、経費をより適切に管理または削減する機会を把握し、クラウド投資が最大の利益を...

清華紫光クラウドは、「クラウド、データ、インテリジェンス」の3次元機能を構築し続け、クラウドとインテリジェンスをユビキタス化する。

今日のデジタル経済時代では、クラウドへの移行はほとんどの企業の間でコンセンサスとなっています。クラウ...

2012 年の Google SEO の 3 つのトレンドについて簡単に説明します

2011 年、Google の Panda アルゴリズムは数回のアップデートを経て、コンテンツの品質...

私の経験に基づいたSEOERへの提案

私は数年間 SEO 業界で働いてきました。初めて SEO という言葉を聞いたときは、とても馴染みのな...

ユーザーエクスペリエンス: 印象派のホームページ再設計の視覚的側面に関する簡単な説明

。 。。少し前、私は Impression Pie のサイト全体の再設計に取り組んでいました。これに...

JavaScript が SEO に影響を与えないようにする方法

ご存知のとおり、検索エンジンのスパイダーは現在、JavaScript スクリプトのコンテンツを処理す...

NEC中国グループの人事システムがSaaSクラウドサービスの導入をリード

NEC(中国)は、中国国内の従業員の人事情報をより適切に管理し、従業員の総合的な資質を向上させるとと...

Vultr - VPS クラウド サーバー、無料 $25 (1 年間有効)、データ センター 15 か所、月額 $2.5

Vultr は今回ついに寛大になり、1 年間有効な 25 ドルをプレゼントします。これまで、Vult...

chicagovps - すべての VPS が 50% オフ、年間支払いはわずか 6 ドル、データ センターは 6 か所

Chicagogovps は長い間プロモーションを行っていませんでしたね。こんな感じで覚えてます!誰...

電子商取引時代のオンラインプロモーションにおいて中小企業が勝利するにはどうすればいいのでしょうか?

1998年の「電子商取引の年」以来、電子商取引は世界中で急速に発展してきました。世界各国は、この新し...

#黑5# moonvm: 台湾のダイナミック VPS、ワンクリック IP スイッチ、20% 割引、henet および apol データ センター

moonvmは台湾のコンピュータルームでダイナミックVPSを提供する専門企業です。現在の主力製品はH...