Skip to content

Instantly share code, notes, and snippets.

@nwiizo
Last active January 21, 2020 09:22
Show Gist options
  • Save nwiizo/05f01ea110e500b9d97f752476762d0c to your computer and use it in GitHub Desktop.
Save nwiizo/05f01ea110e500b9d97f752476762d0c to your computer and use it in GitHub Desktop.
Book Review: Kubernetes Best Practices

書評:Kubernetesのベストプラクティス 最近、Brendan Burns、Eddie Villalba、Dave Strebel、およびLachlan EvensonによるKubernetes Best Practicesを読み終えました。

私は最近Kubernetesに興味を持っていたので、この本を読んだときにKubernetesについてある程度の知識がありました(しかし、それほどではありませんでした)。

特に、第3章(「Kubernetesでの監視とログ」)、第4章(「構成、シークレット、およびRBAC」)、第10章(「ポッドとコンテナーセキュリティ」)、および第11章(「クラスターのポリシーとガバナンス」「) 大きな価値があります。

メモ/興味のある点が他の誰かに何らかの利益をもたらす場合に備えて、この特定の出版物を読んだことのハイライトを共有することにしました。だから、ここに私のハイライトがあります(章ごと)。すべての章がハイライトを持っているわけではないことに注意してください(内容と私の仕事の主な焦点によって異なります)。

第1章:基本サービスの設定

アプリケーションの状態を宣言するとき、Kubernetesは両方をサポートしますが、人々は通常、JSONよりもYAMLを好みます。これは、YAMLの方がJSONよりもやや冗長で、人間が編集しやすいためです。ただし、YAMLはインデントに敏感であることに注意してください。多くの場合、Kubernetes構成のエラーは、YAMLの誤ったインデントに起因する可能性があります。期待通りに動作しない場合は、インデントを確認することをお勧めします。 アプリケーションのファイルシステムのレイアウトに関しては、一般的に、ファイルシステムに付属のフォルダー編成を使用してコンポーネントを編成する価値があります。通常、単一のディレクトリを使用して、チームに役立つApplication Serviceの定義のアプリケーションサービスを包含します。そのディレクトリ内で、アプリケーションのサブコンポーネントにサブディレクトリが使用されます。 一般に、イメージビルドプロセスは「サプライチェーン攻撃」に対して脆弱です。このような攻撃では、悪意のあるユーザーがコードまたはバイナリを信頼できるソースから依存関係に挿入し、アプリケーションに組み込まれます。このような攻撃のリスクがあるため、画像を作成するときは、有名で信頼できる画像プロバイダーのみに基づいて画像を作成することが重要です。または、すべての画像をゼロから作成することもできます。 イメージレジストリ内のコンテナイメージのバージョンは理論的には変更可能ですが、バージョンタグは不変として扱う必要があります。特に、イメージを作成したコミットのセマンティックバージョンとSHAハッシュの組み合わせは、イメージに名前を付けるための良い習慣です(例、v1.0.1-bfeda01f)。イメージバージョンを指定しない場合、デフォルトで最新が使用されます。これは開発では便利ですが、新しいイメージが作成されるたびに最新版が明らかに変更されるため、実稼働環境での使用には適していません。 Kubernetesでは、ReplicaSetはコンテナ化されたアプリケーションの複製を管理するリソースであるため、直接使用することはベストプラクティスではありません。代わりに、Deploymentリソースを使用します。デプロイメントは、ReplicaSetのレプリケーション機能とバージョン管理および段階的なロールアウトを実行する機能を組み合わせたものです。デプロイメントを使用すると、Kubernetesの組み込みツールを使用して、アプリケーションのあるバージョンから次のバージョンに移動できます。 アプリケーションを実行する場合、リクエストは、それが実行されるホストマシン上で保証される予約です。制限は、コンテナが許可される最大リソース使用量です。 CI / CDを既存の必須のデプロイ済みアプリケーションに組み込むことは非常に困難です。 また、クラスターのコンテンツがソース管理のコンテンツと正確に一致するようにすることもベストプラクティスです。これを保証する最良のパターンは、GitOpsアプローチを採用し、継続的統合(CI)/継続的配信(CD)自動化を使用して、ソース管理の特定のブランチからのみ本番環境にデプロイすることです。 既定では、クラスターリソースはクラスター自体内でのみ使用できます。アプリケーションを世界に公開するには、サービスとロードバランサーを作成して、外部IPアドレスを提供し、コンテナーにトラフィックを取り込む必要があります。 ConfigMapには、構成情報またはファイルを表す複数のキー/値のペアが含まれています。この構成情報は、ファイルまたは環境変数を介してポッド内のコンテナーに提示できます。 設定を変更しても、実際には既存のポッドの更新はトリガーされません。ポッドが再起動されたときにのみ設定が適用されます。このため、ロールアウトはヘルスベースではなく、アドホックまたはランダムになります。 注:Kubernetesの秘密は、デフォルトで暗号化されずに保存されます。暗号化されたシークレットを保存する場合は、キープロバイダーと統合して、Kubernetesがクラスター内のすべてのシークレットを暗号化するために使用するキーを提供できます。これにより、etcdデータベースへの直接攻撃からキーが保護されますが、Kubernetes APIサーバーを介したアクセスが適切に保護されるようにする必要があります。 ボリュームは、事実上、ユーザーが指定した場所で実行中のコンテナーにマウントできるファイルまたはディレクトリです。 シークレットの場合、ボリュームはtmpfs RAM-backedファイルシステムとして作成され、コンテナにマウントされます。これにより、マシンが物理的に危険にさらされた場合(クラウドではほとんど発生しませんが、データセンターでは可能です)でも、攻撃者がシークレットを取得するのははるかに困難になります。 Kubernetesでステートフルワークロードを実行する場合、リモートのPersistentVolumesを使用してアプリケーションに関連付けられた状態を管理することが重要です。 秘密とは異なり、PersistentVolumesは一般に、ネットワークファイルシステム(NFS)やサーバーメッセージブロック(SMB)などのファイルベース、またはブロックベース(iSCSI、クラウドベースのディスクなど)のネットワークプロトコルを介してマウントされるリモートストレージです。 。 一般に、データベースなどのアプリケーションの場合、ブロックベースのディスクは一般にパフォーマンスが向上するため好ましいですが、パフォーマンスがあまり考慮されない場合、ファイルベースのディスクの柔軟性が向上する場合があります。 注:状態の管理は一般に複雑であり、Kubernetesも例外ではありません。ステートフルサービス(たとえば、サービスとしてのMySQL、サービスとしてのRedis)をサポートする環境で実行している場合は、一般にそれらのステートフルサービスを使用することをお勧めします。最初は、ステートフルサービスとしてのソフトウェア(SaaS)のコストプレミアムは高価に見えるかもしれませんが、状態のすべての運用要件(バックアップ、データの局所性、冗長性など)、および状態の存在Kubernetesクラスターでは、クラスター間でアプリケーションを移動するのが困難になるため、ほとんどの場合、ストレージSaaSが価格プレミアムの価値があることが明らかになります。 StatefulSetは、一貫性のある名前(ランダムハッシュなし!)やスケールアップとスケールダウンの定義された順序など、わずかに強力な保証を提供します。シングルトンを展開する場合、これはやや重要ではありませんが、複製された状態を展開する場合、これらの属性は非常に便利です。 多くのPersistentVolumeタイプは単一のポッドのみにマウントできますが、ボリュームクレームを使用して、複製可能で各ポッドに固有のPersistentVolumeを割り当てることができるテンプレートを作成できます。 ヘッドレスサービスを作成します。ヘッドレスサービスにはクラスターIPアドレスがありません。代わりに、StatefulSet内のすべてのポッドのDNSエントリをプログラムします。 次のベストプラクティスを使用します。ほとんどのサービスは、展開リソースとして展開する必要があります。デプロイメントは、冗長性とスケールのために同一のレプリカを作成します。展開は、実質的にロードバランサーであるサービスを使用して公開できます。サービスは、クラスター内(デフォルト)または外部に公開できます。HTTPアプリケーションを公開する場合は、Ingressコントローラーを使用して、リクエストルーティングやSSLなどを追加できます。最終的には、アプリケーションをパラメーター化して、さまざまな環境で構成を再利用しやすくする必要があります。Helmなどのパッケージツールは、この種のパラメーター化に最適です。

第2章:開発者のワークフロー

ユーザーごとに開発クラスターを使用することを選択した場合、このアプローチの大きな欠点は、より高価で効率が悪くなり、管理する開発クラスターが多数になることです。追加のコストは、各クラスターの使用率が非常に低い可能性が高いという事実から生じます。また、開発者が異なるクラスターを作成すると、使用されなくなったリソースの追跡とガベージコレクションがより困難になります。 独自のクラスターであり、隔離されているため、異なる開発者がお互いの足指を踏むことははるかに困難です。 ユーザーごとのクラスターアプローチの利点は単純さです。各開発者はセルフサービスで管理できます。 一方、単一の開発クラスターの方がはるかに効率的です。共有クラスターで同じ数の開発者を3分の1(またはそれ以下)の価格で維持できます。さらに、監視やログなどの共有クラスターサービスのインストールがはるかに簡単になり、開発者に優しいクラスターの作成が大幅に簡単になります。 共有開発クラスターの欠点は、ユーザー管理と開発者間の潜在的な干渉のプロセスです。Kubernetesクラスターに新しいユーザーと名前空間を追加するプロセスは現在合理化されていないため、新しい開発者をオンボードするにはプロセスをアクティブ化する必要があります。 推奨事項は、すべての開発者に単一の大規模クラスターを使用することです。開発者間の干渉には課題がありますが、それらを管理でき、最終的にはコスト効率とクラスターに組織全体の機能を簡単に追加する能力が干渉のリスクを上回ります。ただし、開発者の登録、リソース管理、ガベージコレクションのプロセスに投資する必要があります。 名前空間は、あるユーザーのフロントエンドサービスが別のユーザーのフロントエンドサービスに干渉しないように、サービスの展開のスコープとして機能できます。名前空間はRBACのスコープでもあり、ある開発者が別の開発者の作業を誤って削除できないようにします。 一般に、2つの異なるIDソースを維持する必要がないため、外部IDシステムの使用がベストプラクティスですが、場合によってはこれが不可能であり、証明書を使用する必要があります。 合理的な方法は、クラスター全体へのアクセスをリーダーに許可することです。このようにして、開発者は自分の作業に干渉している場合に他の人が何をしているかを確認できます。ただし、このような読み取りアクセスを許可する場合は注意してください。クラスター内の秘密リソースへのアクセスが含まれるためです。 特定のネームスペースが消費するリソースの量を制限する場合は、ResourceQuotaリソースを使用して、特定のネームスペースが消費するリソースの総数に制限を設定できます。 別のアプローチは、一時的にネームスペースを作成して割り当て、有効期限(TTL)を設定することです。これにより、開発者はクラスター内のリソースを一時的なものと見なし、TTLの有効期限が切れたときに名前空間全体を削除する自動化を簡単に構築できます。 Kubernetesとの統合を強化する場合は、カスタムリソース定義(CRD)を使用して、ユーザーがkubectlツールを使用して新しい名前空間を動的に作成および割り当てることができます。時間と傾向がある場合は、名前空間管理を宣言型にし、Kubernetes RBACの使用も可能にするため、これは間違いなく良い習慣です。 このリスクと代替手段があるため、ベストプラクティスはデプロイメントを削除して再作成することです。 これらのベストプラクティスに従うことで、開発者が迅速に稼働できるようになります。オンボーディング、開発、テストの3つのフェーズで開発者のエクスペリエンスを検討します。構築する開発環境がこれらの3つのフェーズすべてをサポートしていることを確認してください。開発クラスターを構築する場合、開発者ごとに1つの大きなクラスターとクラスターを選択できます。それぞれに長所と短所がありますが、一般的には単一の大規模なクラスターがより良いアプローチです。ユーザーをクラスターに追加するときは、独自のIDと独自の名前空間へのアクセス権を持つユーザーを追加します。リソース制限を使用して、使用できるクラスターの量を制限します。名前空間を管理するときは、古い未使用のリソースをどのように刈り取ることができるかを考えてください。開発者は、使用されていないものを削除することについて、衛生状態が悪いでしょう。オートメーションを使用してそれらをクリーンアップします。すべてのユーザーに対して設定できるログや監視などのクラスターレベルのサービスについて考えてください。データベースのようなクラスターレベルの依存関係は、ヘルムチャートのようなテンプレートを使用して、すべてのユーザーに代わって設定するのにも役立つ場合があります。 開発者がKubernetes上でアプリケーションを正常に構築できるようにすることを検討する場合、アプリケーションのオンボーディング、反復、テスト、およびデバッグに関する主要な目標について考えることが重要です。 同様に、ユーザーのオンボーディング、名前空間のプロビジョニング、および基本的なログの集計などのクラスターサービスに固有の基本的なツールに投資することは有益です。

第3章:Kubernetesでの監視とログ

ブラックボックスモニタリングは、インフラストラクチャレベルでのモニタリングに引き続き役立ちますが、アプリケーションの動作に関する洞察とコンテキストが不足しています。 USEメソッドは、「すべてのリソースについて、使用率、飽和、エラー率を確認します」と説明されています。 USEメソッドはインフラストラクチャコンポーネントに焦点を当て、REDメソッドはアプリケーションのエンドユーザーエクスペリエンスの監視に焦点を当てているため、USEメソッドとREDメソッドは互いに補完的です。 cAdvisorは、すべてのコンテナメトリックの真実のソースと見なす必要があります。 カスタムメトリックスAPIを使用すると、監視システムが任意のメトリックスを収集できます。これにより、監視ソリューションは、コアリソースメトリックの外側に拡張できるカスタムアダプタを構築できます。 Resource Metrics APIの標準的な実装は、メトリックサーバーです。メトリックサーバーは、CPUやメモリなどのリソースメトリックを収集します。これらのメトリックをkubeletのAPIから収集し、メモリに保存します。Kubernetesは、スケジューラ、水平ポッドオートスケーラー(HPA)、および垂直ポッドオートスケーラー(VPA)でこれらのリソースメトリックを使用します。 kube-state-metricsは、クラスターにデプロイされたKubernetesオブジェクトの条件を識別することに焦点を当てています。 この記事の執筆時点では、kube-state-metricsが追跡する22のオブジェクトタイプがあります。これらは常に拡張されており、Githubリポジトリでドキュメントを見つけることができます。 メトリックを監視するツールの実装を検討する際の1つの重要な側面は、メトリックがどのように保存されるかを調べることです。キー/値のペアを含む時系列データベースを提供するツールは、メトリックの高度な属性を提供します。 「ユーティリティクラスタ」からクラスタを監視して、監視システムに影響を与える実稼働上の問題を回避することをお勧めします。 ヒント:あまりにも多くのダッシュボード(別名「グラフの壁」)を作成しないようにしてください。これは、トラブルシューティングの状況でエンジニアが推論するのが難しい場合があるためです。ダッシュボードにより多くの情報があると、より良い監視を意味すると思うかもしれませんが、大部分の時間はダッシュボードを見ているユーザーにより多くの混乱を引き起こします。結果と解決までの時間にダッシュボードの設計を集中します。 エンドユーザーの経験から、30〜45日間の履歴ログを保存するのが適切です。これにより、長期間にわたって現れる問題の調査が可能になりますが、ログの保存に必要なリソースの量も削減されます。 Kubernetesの監査ログは、システム内で誰が何をしたかについての洞察を与えるため、セキュリティ監視と考えることができます。 最初の推奨される方法は、すべてのアプリケーションログをSTDOUTに送信することです。これにより、アプリケーションロギングの統一された方法が提供され、監視デーモンセットはDockerデーモンから直接ログを収集できます。 もう1つの方法は、サイドカーパターンを使用して、Kubernetesポッドのアプリケーションコンテナーの隣にログ転送コンテナーを実行することです。アプリケーションがファイルシステムにログを記録する場合、このパターンを使用する必要があります。 このツールには、Kubernetes DaemonSetとして実行する機能と、STDOUTにログを送信しないアプリケーションのサイドカーとして実行するソリューションが必要です。 ログを集中管理するツールを探す場合、ホスト型ソリューションは多くの運用コストをオフロードするため、多くの価値を提供できます。独自のロギングソリューションをホストすることは、N日には素晴らしいように思えますが、環境が成長するにつれて、ソリューションを維持するのに非常に時間がかかる場合があります。 サービスレベル目標(SLO)に影響を与えるイベントにアラートを集中させる必要があります。 オンコールエンジニアへのアラートは、すぐに人間の注意を必要とする問題であり、アプリケーションのUXに影響を与えます。 一般に、誤検知を排除するために、5分以上のしきい値を設定することをお勧めします。 アラートの通知を作成するときは、たとえば、問題の解決に関するトラブルシューティングやその他の役立つ情報を提供する「プレイブック」へのリンクを提供するなど、通知に関連情報を提供する必要があります。 通知には、データセンター、地域、アプリの所有者、影響を受けるシステムに関する情報も含める必要があります。このすべての情報を提供することで、エンジニアは問題に関する理論をすばやく形式化できます。 注:システムでのアラートへのアプローチおよび管理方法の詳細については、Googleのサイト信頼性エンジニア(SRE)としてのRobの観察に基づいたRob Ewaschukの「アラートに関する私の哲学」をお読みください。 以下は、監視、ログ、および警告に関して採用すべきベストプラクティスです。 モニタリング ノードとすべてのKubernetesコンポーネントの使用率、飽和率、エラー率を監視し、アプリケーションの率、エラー、期間を監視します。 ブラックボックスモニタリングを使用して、システムの状態を予測するのではなく、症状を監視します。 ホワイトボックスモニタリングを使用して、計装でシステムとその内部を検査します。 時系列ベースのメトリックを実装して、アプリケーションの動作内の洞察を得ることができる高精度のメトリックを取得します。 プロメテウスのような監視システムを活用して、高次元の重要なラベルを提供します。これにより、影響のある問題の症状をより適切に把握できます。 平均メトリックを使用して、事実データに基づいて小計とメトリックを視覚化します。合計メトリックを使用して、特定のメトリック全体の分布を視覚化します。 ロギング ロギングをメトリックス監視と組み合わせて使用​​して、環境の動作の全体像を把握する必要があります。 ログを30〜45日間以上保存することに注意し、必要に応じて、「安価なリソースを長期アーカイブに使用します。 サイドカーパターンでログフォワーダーの使用を制限します。これは、ログフォワーダーがより多くのリソースを使用するためです。ログフォワーダにDaemonSetを使用し、ログをSTDOUTに送信することを選択します。 アラート 人やプロセスに悪い振る舞いをもたらす可能性があるため、注意深い疲労に注意してください。 アラートの段階的な改善を常に検討し、常に完全ではないことを受け入れます。 SLOと顧客に影響する症状には注意してください。すぐに人間の注意を払う必要がない一時的な問題には注意してください。

第4章:構成、シークレット、およびRBAC

ConfigMap APIは、実際には機密データではない文字列データ向けです。アプリケーションがより機密性の高いデータを必要とする場合は、Secrets APIがより適切です。 シークレットデータはbase64でエンコードされた情報として表され、これは暗号化されていないことを理解することが重要です。シークレットがポッドに挿入されるとすぐに、ポッド自体がシークレットデータをプレーンテキストで見ることができます。 秘密データは、base64でエンコードされたデータのKubernetesでデフォルトでサイズが1 MBに制限された少量のデータであるため、エンコードのオーバーヘッドのために実際のデータが約750 KBであることを確認してください。 また、シークレットは、シークレットを必要とするポッドがあるノード上でのみtmpfsにマウントされ、必要なポッドがなくなると削除されます。 デフォルトでは、シークレットはプレーンテキストでKubernetesのetcdデータストアに保存されることを知っておくことが重要です。システム管理者またはクラウドサービスプロバイダーは、mTLSを含むetcd環境のセキュリティを確保するために努力することが重要です。 etcdノードおよびetcdデータの保管時の暗号化の有効化。 ポッドの新しいバージョンを再デプロイせずにアプリケーションへの動的な変更をサポートするには、ConfigMaps / Secretsをボリュームとしてマウントし、ファイルウォッチャーでアプリケーションを構成して、変更されたファイルデータを検出し、必要に応じて自身を再構成します。 volumeMounts.subPathプロパティを使用してConfigMaps / Secretsをマウントしないでください。これにより、ConfigMap / Secretを新しいデータで更新した場合、ボリューム内のデータが動的に更新されなくなります。 ConfigMap / Secretが作成されたらすぐに、ポッドの仕様にボリュームとして追加します。次に、そのボリュームをコンテナのファイルシステムにマウントします。 ConfigMap / Secretsは、ポッドがデプロイされる前にそれらを使用するポッドのネームスペースに存在する必要があります。オプションのフラグを使用して、ConfigMap / Secretが存在しない場合にポッドが起動しないようにすることができます。 カスタムアドミッションコントローラーを記述することなく、アノテーションに基づいてConfigMapとシークレットをすべてのポッドに適用できるPodPresetsと呼ばれるアルファAPIがあります。 アドミッションコントローラーを使用して、特定の構成データを確認するか、特定の構成値が設定されていない展開を防止します。 Helmを使用してアプリケーションを環境にリリースしている場合、ライフサイクルフックを使用して、展開が適用される前にConfigMap / Secretテンプレートが展開されていることを確認できます。 一部のアプリケーションでは、設定をJSONファイルやYAMLファイルなどの単一ファイルとして適用する必要があります。ConfigMap / Secretsでは、|を使用して生データのブロック全体を許可します。シンボル アプリケーションがシステム環境変数を使用してその構成を決定する場合、ConfigMapデータの注入を使用して、ポッドへの環境変数マッピングを作成できます。 configMapKeyRefメソッドまたはsecretKeyRefメソッドを使用している場合、実際のキーが存在しない場合、ポッドが起動しないことに注意してください。 envFromを使用してすべてのキー/値のペアをConfigMap / Secretからポッドにロードする場合、無効な環境値と見なされるキーはスキップされます。ただし、ポッドの起動は許可されます。ポッドのイベントには、理由がInvalidVariableNamesであるイベントと、キーがスキップされたという適切なメッセージが含まれます。 コマンドライン引数をコンテナに渡す必要がある場合、$(ENV_KEY)補間構文を使用して環境変数データを取得できます。 ポッドを更新し、ポッドを削除してReplicaSetコントローラーに新しいポッドを作成させるか、展開の更新をトリガーしてポッドを再起動する必要があります。これは、展開仕様で宣言されている適切なアプリケーション更新戦略に従います。 ConfigMap / Secretデータを環境変数として使用する場合、ConfigMap / Secretのデータを更新しても、環境変数またはボリュームを使用している場合でも、コードが新しい構成データを取得することを理解することは非常に重要です。 ConfigMap / Secretへのすべての変更には、展開全体の更新が必要であると想定する方が簡単です。これにより、Helmを使用してアプリケーションコードをKubernetesにリリースしている場合、展開テンプレートの注釈を利用してConfigMap / Secretのsha256チェックサムを確認できます。これにより、ConfigMap / Secret内のデータが変更されたときにHelmがトリガーされ、helm upgradeコマンドを使用してDeploymentが更新されます。 imagePullSecretsを、ポッドがpod.specで宣言することなく自動的にシークレットをマウントするために使用するサービスアカウントに割り当てます。 CI / CD機能を使用して、リリースパイプライン中にハードウェアセキュリティモジュール(HSM)を使用して、安全な格納域または暗号化されたストアから秘密を取得します。これにより、職務の分離が可能になります。セキュリティ管理チームはシークレットを作成および暗号化でき、開発者は必要なシークレットの名前を参照するだけです。これは、より動的なアプリケーション配信プロセスを確保するための推奨DevOpsプロセスでもあります。 KubernetesのRBACプロセスには、定義する必要のある3つの主要コンポーネントがあります。サブジェクト、ルール、およびロールバインディングです。 注:Kubernetesのサービスアカウントは、Kubernetesに内部的に保存されている名前空間にバインドされているという点でユーザーアカウントとは異なります。これらはプロセスを表すためのものであり、人ではなく、ネイティブKubernetesコントローラーによって管理されます。 Kubernetesには、roleとclusterRoleの2種類のロールがあります。違いは、ロールがネームスペースに固有であり、clusterRoleがすべてのクラスター全体のロールであることです。 名前空間。 バインディングには、ネームスペースに固有のroleBindingとクラスター全体にわたるclusterRoleBindingの2つのモードもあります。 Kubernetesで実行するために開発されたアプリケーションには、RBACロールとそれに関連付けられたロールバインディングが必要になることはほとんどありません。アプリケーションコードが実際にKubernetes APIと直接対話する場合にのみ、アプリケーションはRBAC構成を必要とします。 ベストプラクティス: サービスに対して、または特定のネームスペース内のすべてのポッドをリストする必要がある場合のベストプラクティスは、ポッド仕様で指定される新しいサービスアカウントを作成することです。次に、目標を達成するために必要な最小限の特権を持つロールを作成します。 アプリケーションがKubernetes APIに直接アクセスして、おそらく追加されるエンドポイントに応じて構成を変更する必要がある場合 ID管理と、必要に応じて2要素認証を可能にするOpenID Connectサービスを使用します。これにより、より高いレベルのID認証が可能になります。ユーザーグループを、ジョブの実行に必要な最小限の特権を持つロールにマップします。 ジャストインタイム(JIT)アクセスシステムを使用して、サイト信頼性エンジニア(SRE)、オペレーター、および非常に特定のタスクを実行するために短時間エスカレーションされた特権が必要なユーザーを許可する必要があります。 Kubernetesクラスターに展開するCI / CDツールには、特定のサービスアカウントを使用する必要があります。これにより、クラスター内の監査機能と、クラスター内のオブジェクトを展開または削除した可能性のあるユーザーを把握できます。 Helmを使用してアプリケーションを展開する場合、デフォルトのサービスアカウントはkiller-systemに展開されるTillerです。その名前空間を対象とするTiller専用のサービスアカウントを使用して、各名前空間にTillerを展開することをお勧めします。Helm install / upgradeコマンドを呼び出すCI / CDツールで、事前ステップとして、サービスアカウントとデプロイメントの特定のネームスペースでHelmクライアントを初期化します。サービスアカウント名は各ネームスペースで同じにすることができますが、ネームスペースは固有のものでなければなりません。 Secrets APIで監視とリストを必要とするアプリケーションを制限します。これにより、基本的に、アプリケーションまたはポッドをデプロイした人がその名前空間の秘密を表示できます。アプリケーションが特定のシークレットのSecrets APIにアクセスする必要がある場合、アプリケーションが直接割り当てられたもの以外の読み取りが必要な特定のシークレットの取得の使用を制限します。

第5章:継続的な統合、テスト、および展開

CI / CDの目標は、開発者がコードをチェックインしてから新しいコードを本番環境にロールアウトするまで、完全に自動化されたプロセスを持つことです。Kubernetesにデプロイされたアプリは、非常にエラーが発生する可能性があるため、手動でアップデートをロールアウトすることは避けたいです。 Gitはソース管理プラットフォームとして業界標準になり、すべてのGitリポジトリにはmasterブランチが含まれます。マスターブランチには、運用コードが含まれています。 KubernetesマニフェストやHelmチャートなどのアプリケーションコードと構成コードの両方を含めると、通信とコラボレーションの優れたDevOps原則を促進するのに役立ちます。 アプリケーション開発者と運用エンジニアの両方が単一のリポジトリで協力することにより、チームがアプリケーションを本番環境に提供する自信が生まれます。 本番環境へのインフラストラクチャとアプリケーションの配信の自動化を開始するとき、コードベースのすべての部分に対して自動化されたテストを実行することを考える必要があります。 コードベースと本番環境への配信のテストはチームの努力であり、エンドツーエンドで実装する必要があります。 次の戦略は、アプリケーションで可能な限り最小のイメージを構築するのに役立ちます。 多段階ビルド これらにより、アプリケーションの実行に不要な依存関係を削除できます。 Distrolessベースイメージ これらは、不要なバイナリとシェルをすべてイメージから削除します。これにより、画像のサイズが本当に小さくなり、セキュリティが向上します。ディストリビューションのないイメージとのトレードオフは、シェルがないため、デバッガーをイメージにアタッチできないことです。これはすばらしいと思うかもしれませんが、アプリケーションをデバッグするのは苦痛です。Distrolessイメージにはパッケージマネージャー、シェル、またはその他の一般的なOSパッケージが含まれていないため、一般的なOSに慣れているデバッグツールにアクセスできない場合があります。 最適化されたベース画像 これらは、OS層から不要なものを取り除くことに焦点を当てたイメージで、スリム化されたイメージを提供します。 最適化された画像は、開発に期待する機能を提供すると同時に、画像サイズとセキュリティの露出を最適化するため、これはあなたにとって良いオプションかもしれません。 画像を最適化することは非常に重要であり、多くの場合ユーザーに見落とされます。企業での使用が承認されているOSの企業標準に起因する理由があるかもしれませんが、コンテナの価値を最大化できるようにこれらを後押ししてください。 環境に展開したバージョン管理されたイメージを簡単に識別できるように、イメージのタグ付け戦略を立てることが重要です。 説教できない最も重要なことの1つは、イメージタグとして「最新」を使用しないことです。これを画像タグとして使用することはバージョンではなく、どのコード変更がロールアウトされた画像に属しているかを特定する機能を持たないことになります。CIパイプラインでビルドされるすべてのイメージには、ビルドされたイメージの一意のタグが必要です。 次の戦略により、コードの変更とそれらが関連付けられているビルドを簡単に識別できます。 BuildID CIビルドが開始されると、ビルドIDが関連付けられます。タグのこの部分を使用すると、イメージを組み立てたビルドを参照できます。 ビルドシステム-BuildID これはBuildIDと同じですが、複数のビルドシステムを持つユーザーにビルドシステムを追加します。 Git Hash 新しいコードコミットでは、Gitハッシュが生成されます。タグにハッシュを使用すると、どのコミットがイメージを生成したかを簡単に参照できます。 githash-buildID これにより、コードコミットとイメージを生成したbuildIDの両方を参照できます。ここでの唯一の注意点は、タグが長くなる可能性があることです。 心に留めておくべきことの1つは、CDに焦点を合わせる前に、しっかりしたCIパイプラインをセットアップする必要があるということです。パイプラインの早い段階で問題を検出するための堅牢なテストセットがない場合、すべての環境に不正なコードが転がってしまいます。 ローリング更新はKubernetesに組み込まれているため、ダウンタイムなしで現在実行中のアプリケーションの更新をトリガーできます。 また、Deploymentオブジェクトを使用すると、更新するレプリカの最大量と、ロールアウト時に使用できないポッドの最大数を構成できます。 この戦略を使用すると接続が切断される可能性があるため、ローリング更新には注意する必要があります。この問題に対処するには、レディネスプローブとpreStopライフサイクルフックを利用できます。 準備状況プローブは、デプロイされた新しいバージョンがトラフィックを受け入れる準備ができていることを確認しますが、preStopフックは、現在デプロイされたアプリケーションで接続が排出されることを確認できます。 ローリング更新に関するもう1つの懸念は、ロールオーバー中に2つのバージョンのアプリケーションが同時に実行されることです。データベーススキーマは、アプリケーションの両方のバージョンをサポートする必要があります。機能フラグ戦略を使用して、スキーマが新しいアプリバージョンによって作成された新しい列を示すこともできます。ローリング更新が完了したら、古い列を削除できます。 注:Canaryリリースでは、アプリケーションの複数のバージョンが同時に実行されているという問題もあります。データベーススキーマは、アプリケーションの両方のバージョンをサポートする必要があります。これらの戦略を使用する場合、依存サービスを処理し、複数のバージョンを実行する方法に本当に焦点を合わせる必要があります。これには、強力なAPIコントラクトの使用と、データサービスが同時にデプロイした複数のバージョンをサポートすることの確認が含まれます。 実稼働環境でのテストの効果を特定できる、徹底した可観測性戦略を確立する必要があります。 また、システムに注入した障害から自動的に回復できるように、高度な自動化が必要です。 パイプラインを繰り返し改善するために、次のベストプラクティスのいくつかを検討してください。 CIを使用すると、自動化と迅速なビルドの提供に集中できます。ビルド速度を最適化すると、変更によってビルドが壊れた場合に開発者に迅速なフィードバックが提供されます。 パイプラインで信頼できるテストを提供することに焦点を当てます。これにより、開発者はコードの問題に関する迅速なフィードバックを得ることができます。開発者へのフィードバックループが高速になるほど、ワークフローの生産性が向上します。 CI / CDツールを決定するときは、ツールでパイプラインをコードとして定義できることを確認してください。これにより、アプリケーションコードでパイプラインをバージョン管理できます。 イメージを最適化して、イメージのサイズを縮小し、実稼働環境でイメージを実行する際の攻撃対象領域を削減できるようにしてください。マルチステージDockerビルドを使用すると、アプリケーションの実行に不要なパッケージを削除できます。 イメージタグとして「最新」を使用するのを避け、buildIDまたはGitコミットに参照されるタグを利用します。 CDを初めて使用する場合は、Kubernetesのローリングアップグレードを利用して開始してください。それらは使いやすく、展開に慣れるでしょう。CDに慣れて自信がついたら、ブルー/グリーンおよびカナリアの展開戦略を活用することを検討してください。 CDを使用して、クライアント接続とデータベーススキーマのアップグレードがアプリケーションでどのように処理されるかをテストしてください。 実稼働環境でのテストは、アプリケーションに信頼性を組み込み、適切な監視を確実に行うのに役立ちます。実稼働環境でのテストでは、小規模から始めて、実験の爆風半径を制限します。

第6章:バージョン管理、リリース、およびロールアウト

パッチは、APIの変更がないバグ修正またはごくわずかな変更を含む増分リリースを意味します。マイナーバージョンは、新しいAPIが変更される可能性があるが、以前のバージョンとの下位互換性がある更新を示します。 メジャーバージョンは、コードに対する重大な変更の増分です。ほとんどの場合、APIは同じコードのメジャーバージョン間で互換性がなくなりました。 ラベルセレクターは作成後に不変であるということを理解することが重要です。つまり、新しいセレクターを追加し、ポッドのラベルに対応する一致がある場合、既存のReplicaSetへのアップグレードではなく、新しいReplicaSetが作成されます。これは、ロールアウトを扱うときに理解することが非常に重要になります 展開コントローラーは、仕様への変更を決定でき、仕様で定義されている戦略に基づいて展開を更新するアクションを実行します。Kubernetesの展開は、rollingUpdateとrecreateの2つの戦略をサポートします。前者はデフォルトです。 以下に示すベストプラクティスは、DevOpsチームがソフトウェアをスムーズに展開するのに役立つ一貫したパラメーターを定義するのに役立ちます。 アプリケーション全体を構成するコンテナのバージョンおよびポッド展開のバージョンとは異なる、アプリケーション全体のセマンティックバージョニングを使用します。これにより、アプリケーションとアプリケーション全体を構成するコンテナの独立したライフサイクルが可能になります。これは最初は非常に混乱する可能性がありますが、一方が他方を変更するときに原則的な階層的アプローチを採用すれば、簡単に追跡できます。 展開メタデータでリリースおよびリリースバージョン/番号ラベルを使用して、CI / CDパイプラインからリリースを追跡します。リリース名とリリース番号は、CI / CDツールレコードの実際のリリースと調整する必要があります。これにより、CI / CDプロセスからクラスターへのトレーサビリティが可能になり、ロールバックの識別が容易になります。 Helmを使用してKubernetesに展開するサービスをパッケージ化する場合は、ロールバックまたはアップグレードが必要なサービスをまとめて同じHelmチャートにまとめるように特に注意してください。 組織の運用テンポに合ったリリース命名法に同意します。ほとんどの場合、単純な安定、カナリア、およびアルファ状態で十分です。

第7章:世界規模のアプリケーション配布とステージング

本番環境でテストで検出されなかった障害が発生した場合、テストを拡張および拡張する必要があることを示す強力な指標となります。 この発煙までの時間は、一般に、ロールアウトが完了してから問題の兆候が表示されるまでにかかる時間の目安です。 発煙までの時間は、リリースが正常に動作しているという強い確率を得るために待機する時間を示す確率分布です。一般的に言えば、まともな経験則は、問題が顕在化するのにかかる平均時間を2倍にすることです。 この時点で、ロールアウトを加速したくなるかもしれませんが、リリースへの入力またはロードの大幅な変更を表す単一の領域のみにロールアウトすることが非常に重要です。 危機の暑さとパニックでは、脳に大きなストレスがかかり、最も単純なプロセスでさえ覚えることははるかに困難です。 ロールアウトで問題が発生した場合、迅速に、落ち着いて、正しく対応できることが重要です。 瞬間の暑さの中で、最も明白で簡単なステップでさえ、忘れられて誤ってスキップされたステップになる可能性があります。 必要なすべてが正しく行われ、正しい順序で行われるようにするには、実行される順序で整理されたタスクの明確なチェックリストと、各ステップの予想される出力が必要です。どんなに明白であっても、すべてのステップを書き留めてください これを可能にするには、アーキテクチャの変更が必要になる場合があります。人間がコマンドをカットアンドペーストしないように、自動化を追加する必要がある場合があります。 チームの全員が適切な応答に精通し、システムが変更されても応答が最新の状態に保たれるようにするために、定期的な練習のリズムを設定する必要があります。 世界展開のベストプラクティス 各画像を世界中に配布します。ロールアウトが成功するかどうかは、使用する場所の近くにあるリリースビット(バイナリ、イメージなど)に依存します。これにより、ネットワークの速度低下や不規則性が存在する場合でも、展開の信頼性が確保されます。地理的分布は、一貫性を保証する自動リリースパイプラインの一部である必要があります。 可能な限りアプリケーションの広範な統合およびリプレイテストを行うことにより、テストを可能な限り左にシフトします。正しいと強く信じているリリースでのみロールアウトを開始します。 カナリア地域でリリースを開始します。これは、大規模なロールアウトを開始する前に、他のチームまたは大規模な顧客がサービスの使用を検証できる運用前環境です。 ロールアウトする地域のさまざまな特性を特定します。それぞれの違いは、障害と完全または部分的な停止の原因となる可能性があります。最初にリスクの低い地域に展開してください。 発生する可能性のある問題またはプロセス(ロールバックなど)に対する応答を文書化して練習します。その瞬間に何をすべきかを思い出そうとすることは、何かを忘れて悪い問題を悪化させるためのレシピです。」 第8章:リソース管理 違いは、GPU対応ノードを要求する場合にnodeSelectorを使用するのに対して、汚染はGPUワークロードのみにノードを予約することです。 汚染はノードで使用され、ポッドがそれらに対してスケジュールされないようにします。 汚染は許容範囲と連動して機能し、汚染されたノードを上書きできます。2つの組み合わせにより、非アフィニティルールをきめ細かく制御できます。 一般に、次の使用例では汚染と許容を使用します。 専用ノードハードウェア 専用ノードリソース 劣化したノードの回避 ポッドリソースの管理では、CPUとメモリを管理して、Kubernetesクラスターの全体的な使用率を最適化します。 CPU制限により、コンテナは、指定された制限を超える使用を抑制されます。メモリ制限がある場合、ポッドが制限に達すると再起動されます。ポッドは、クラスター内の同じホストまたは別のホストで再起動される場合があります。 PodDisruptionBudgetを使用すると、自発的な立ち退きイベント中に利用可能な最小ポッドと最大利用不可ポッドにポリシーを設定できます Kubernetesクラスターを設計する際には、クラスターリソースのサイズを検討して、障害が発生した多数のノードを処理できるようにすることが不可欠です。 注:ポッドの中断予算をパーセンテージで指定する場合、特定のポッド数と相関しない場合があります。 この場合、Kubernetesは最も近い整数に切り上げます 単一のクラスターを使用する複数のチームがある場合、通常は各チームに名前空間を割り当てるのが最善です。クラスターが1つのチーム専用である場合、クラスターに展開された各サービスに名前空間を割り当てることが理にかなっている場合があります。これに対する単一の解決策はありません。チームの組織と責任が設計を推進します。 ヒント:複数の名前空間とクラスターを扱う場合、異なる名前空間とクラスターコンテキストを設定するのは面倒です。kubensとkubectxを使用すると、これらの異なる名前空間とコンテキストを簡単に切り替えることができることがわかりました。 複数のチームまたはアプリケーションが単一のクラスターを共有する場合、名前空間にResourceQuotasを設定することが重要です。ResourceQuotasを使用すると、単一の名前空間がクラスター内のリソースのシェアを超えて消費できないように、クラスターを論理単位で分割できます。 クラスターの自動スケーリングを考慮する必要があることがあります。ほとんどのユーザーは、リソースが必要なときにノードを事前に手動でスケーリングすることから始める方がよいことがわかりました。 クラスターオートスケーラーの欠点は、ポッドが保留になる前にのみ新しいノードが追加されるため、スケジュールされたときにワークロードが新しいノードがオンラインになるのを待つことになります。 PodDisruptionBudgetを使用して、アプリケーションがドレイン操作を実行してクラスターからノードを削除するときにアプリケーションに悪影響を与えないようにする必要があります。 アプリケーションのバグや問題のためにHPAがレプリカを無限に拡大したくないため、最小値と最大値を設定することが重要です。 注:自動スケーリングアルゴリズムの内部の詳細については、設計提案をご覧ください。Kubernetes v1.15の時点では、VPAは実稼働展開には推奨されていません。 リソース管理のベストプラクティス ポッドの非アフィニティを使用して、ワークロードを複数の可用性ゾーンに分散し、アプリケーションの高可用性を確保します。 GPU対応ノードなどの特殊なハードウェアを使用している場合、汚染を利用して、GPUを必要とするワークロードのみがそれらのノードにスケジュールされるようにします。 NodeConditionの汚染を使用して、ノードの障害または劣化を事前に回避します。 nodeSelectorsをポッド仕様に適用して、クラスターにデプロイした専用ハードウェアにポッドをスケジュールします。 実稼働に進む前に、さまざまなノードサイズを試して、ノードタイプのコストとパフォーマンスの適切な組み合わせを見つけます。 さまざまなパフォーマンス特性を持つワークロードを組み合わせて展開する場合は、ノードプールを使用して、単一のクラスターにノードタイプを混在させます。 クラスターにデプロイされたすべてのポッドにメモリとCPUの制限を設定してください。 ResourceQuotasを使用して、複数のチームまたはアプリケーションがクラスター内のリソースの公平な配分を確実に割り当てられるようにします。 LimitRangeを実装して、制限またはリクエストを設定しないポッド仕様のデフォルトの制限とリクエストを設定します。 Kubernetesのワークロードプロファイルを理解するまで、手動のクラスタースケーリングから始めます。自動スケーリングを使用できますが、ノードのスピンアップ時間とクラスターのスケールダウンに関する追加の考慮事項があります。 HPAは、変動し、使用量に予期しないスパイクがあるワークロードに使用します。 第9章:ネットワーク、ネットワークセキュリティ、およびサービスメッシュ Kubenetは、Kubernetesですぐに使用できる最も基本的なネットワークプラグインです。最も単純なプラグインであり、接続されたポッド用の仮想イーサネットペアであるLinuxブリッジcbr0を提供します。 Kubenetベストプラクティス Kubenetは単純なネットワークスタックを可能にし、すでに混雑しているネットワークで貴重なIPアドレスを消費しません。これは、オンプレミスのデータセンターに拡張されたクラウドネットワークに特に当てはまります。 ポッドのCIDR範囲が、クラスターおよび各クラスター内のポッドの潜在的なサイズを処理するのに十分な大きさであることを確認してください。kubeletで設定されたノードごとのデフォルトのポッドは110ですが、これを調整できます。 トラフィックが適切なノードでポッドを見つけることができるように、ルートルールを適切に理解し、計画してください。クラウドプロバイダーでは、これは通常自動化されていますが、オンプレミスまたはエッジケースには自動化と強固なネットワーク管理が必要です。 CNIベストプラクティス インフラストラクチャの全体的なネットワーク目標を達成するために必要な機能セットを評価します。一部のCNIプラグインは、ネイティブの高可用性、マルチクラウド接続、Kubernetesネットワークポリシーサポート、およびその他のさまざまな機能を提供します。 パブリッククラウドプロバイダーを介してクラスターを実行している場合、クラウドプロバイダーのソフトウェア定義ネットワーク(SDN)にネイティブではないCNIプラグインが実際にサポートされていることを確認します。 ネットワークセキュリティツール、ネットワーク監視可能性、および管理ツールが選択したCNIプラグインと互換性があることを確認し、互換性がない場合は、既存のツールを置き換えることができるツールを調査します。 どのツールを使用する場合でも、少なくとも、ネットワークスタックと4つのゴールデンシグナルに関する洞察を提供する必要があります。これは、驚くべきGoogle SREチームとRob Ewashuckに人気があります:レイテンシ、トラフィック、エラー、飽和。 SDNネットワークスペースとは別のオーバーレイネットワークを提供しないCNIを使用している場合は、ノードのIP、ポッドIP、内部ロードバランサー、およびクラスターのアップグレードとスケールアウトプロセスのオーバーヘッドを処理する適切なネットワークアドレススペースがあることを確認してください。 サービスおよびイングレスコントローラーのベストプラクティス クラスターの外部からアクセスする必要があるサービスの数を制限します。理想的には、ほとんどのサービスはClusterIPであり、外部向けサービスのみがクラスターの外部に公開されます。 公開する必要があるサービスが主にHTTP / HTTPSベースのサービスである場合は、イングレスAPIとイングレスコントローラーを使用して、TLS終端を備えたバッキングサービスにトラフィックをルーティングすることをお勧めします。使用するイングレスコントローラーのタイプに応じて、レート制限、ヘッダーの書き換え、OAuth認証、可観測性、およびその他のサービスなどの機能を、アプリケーション自体に組み込むことなく使用可能にすることができます。 Webベースのワークロードの安全な入力に必要な機能を備えた入力コントローラーを選択します。特定の構成アノテーションの多くは実装ごとに異なり、エンタープライズKubernetes実装間での展開コードの移植性を妨げているため、1つを標準化して企業全体で使用します。 クラウドサービスプロバイダー固有のイングレスコントローラーオプションを評価して、インフラストラクチャ管理とイングレスの負荷をクラスターから移動しますが、それでもKubernetes APIの構成は可能です。 ほとんどのAPIを外部で提供する場合は、KongやAmbassadorなど、APIベースのワークロードをさらに微調整できるAPI固有のIngressコントローラーを評価します。NGINX、Traefik、およびその他がAPIチューニングを提供する場合がありますが、特定のAPIプロキシシステムほど細かくはなりません。 IngressコントローラーをポッドベースのワークロードとしてKubernetesに展開する場合、展開が高可用性と総パフォーマンススループットのために設計されていることを確認してください。メトリックの可観測性を使用して、イングレスを適切にスケーリングしますが、ワークロードのスケーリング中にクライアントの中断を防ぐのに十分なクッションを含めます。 ネットワークポリシーには複雑に見える単純なYAML構造がありますが、単純な東西トラフィックファイアウォールと考えると、少し理解しやすくなります。 同じポッドをターゲットにできる複数のNetworkPolicy定義を作成でき、その効果は本質的に付加的です。 セレクターの一致のためにポッドがポリシーのスコープに該当する場合、すべてのトラフィックは、入力ルールまたは出力ルールで明示的に定義されていない限りブロックされます。このわずかなニュアンスの詳細は、ポッドがセレクターの一致のためにポリシーに該当しない場合、すべての入出力がポッドに許可されることを意味します。 入力フィールドを空のままにすると、すべてを拒否する受信のようになります。同様に、出力を空のままにすると、すべての送信が拒否されます。 イングレスが想定されており、明示的に定義する必要はありません。 ネットワークポリシーのベストプラクティス ゆっくりと始めて、ポッドへのトラフィックの進入に集中します。入力と出力のルールで問題を複雑にすると、ネットワークトレースが悪夢になります。トラフィックが予想どおりに流れるとすぐに、出力ルールを調べて、機密性の高いワークロードへのフローをさらに制御できます。イングレスルールリストに何も入力されていない場合でも多くのオプションがデフォルト設定されるため、この仕様ではイングレスも優先されます。 使用するネットワークプラグインがNetworkPolicy APIへの独自のインターフェイスを持っているか、他のよく知られているプラ​​グインをサポートしていることを確認してください。 ネットワークチームが「既定の拒否」ポリシーの導入に慣れている場合は、保護するワークロードを含むクラスター内の各名前空間に対して、次のようなネットワークポリシーを作成します。これにより、別のネットワークポリシーが削除されても、ポッドが誤って「公開」されることはありません。 インターネットからアクセスする必要があるポッドがある場合、ラベルを使用して、イングレスを許可するネットワークポリシーを明示的に適用します。パケットの送信元である実際のIPがインターネットではなく、ロードバランサー、ファイアウォール、またはその他のネットワークデバイスの内部IPである場合、フロー全体に注意してください。 ルール自体はネームスペース固有であるため、ルールの作成を容易にするために、アプリケーションワークロードを単一のネームスペースに合わせてみてください。ネームスペース間の通信が必要な場合は、可能な限り明示的に指定し、おそらく特定のラベルを使用してフローパターンを識別してください。 必要に応じて適切なトラフィックパターンを調査する時間を確保するために、制限ポリシーがあったとしても少ないテストベッドの名前空間を用意します。 現在利用可能なサービスメッシュの大半は、データプレーンの一部であるプロキシを、メッシュのメンバーである各ポッドに注入します。これにより、コントロールプレーンコンポーネントによってメッシュ全体でポリシーとセキュリティを同期できます。 サービスメッシュのベストプラクティス これらのベストプラクティスは、この記事の執筆時点では、サービスメッシュが現在解決しようとしている一般的な必需品に基づいています。 サービスメッシュが提供する主要な機能の重要性を評価し、現在のどのサービスが最小のオーバーヘッドで最も重要な機能を提供するかを決定します。ここでのオーバーヘッドは、人間の技術的負債とインフラ資源の負債の両方です。 マルチクラウドまたはハイブリッドシナリオなどのシステム間メッシュの必要性は重要な要件ですか?すべてのサービスメッシュがこの機能を提供するわけではありません。提供する場合、環境に脆弱性をもたらす複雑なプロセスです。 サービスメッシュ製品の多くはコミュニティベースのオープンソースプロジェクトであり、環境を管理するチームがサービスメッシュを初めて使用する場合は、商業的にサポートされる製品の方が適している可能性があります。Istioに基づいて商業的にサポートおよび管理されたサービスメッシュを提供し始めている企業があります。これは、Istioが管理が複雑なシステムであることがほぼ一般に合意されているため役立ちます。

第10章:ポッドとコンテナーのセキュリティ

PodSecurityPolicyを効果的に実装するのは驚くほど困難であり、他の方法でオフにされたり回避されたりすることはほとんどありません。ただし、PodSecurityPolicyを完全に理解するために時間をかけることを強くお勧めします。これは、クラスターで実行できるものと特権のレベルを制限することにより、攻撃対象領域を減らす最も効果的な手段の1つです。 PodSecurityPolicyを有効にすることは、パブリッククラウドプロバイダーとクラスター運用ツールの間で広く利用できないことに言及する価値があります。 警告:PodSecurityPolicyを有効にするときは、十分な準備が最初に行われないとワークロードがブロックされる可能性があるため、注意して続行してください。 警告:実行中のワークロードがある既存のクラスターでPodSecurityPolicyを有効にする場合、アドミッションコントローラーを有効にする前に、必要なすべてのポリシー、サービスアカウント、ロール、およびロールバインディングを作成する必要があります。 警告:PodSecurityPoliciesが定義されていない場合、暗黙的に拒否されることに注意してください。これは、ワークロードのポリシーが一致しないと、ポッドが作成されないことを意味します。 PodSecurityPolicyは複雑で、エラーが発生しやすい可能性があります。クラスターにPodSecurityPolicyを実装する前に、次のベストプラクティスを参照してください。 それはすべてRBACに帰着します。好むと好まざるとにかかわらず、PodSecurityPolicyはRBACによって決定されます。実際に現在のRBACポリシー設計のすべての欠点を明らかにしているのは、この関係です。RBACおよびPodSecurityPolicyの作成とメンテナンスを自動化することがどれだけ重要かを強調することはできません。特に、サービスアカウントへのアクセスをロックダウンすることは、ポリシーを使用するための鍵です。 ポリシーの範囲を理解します。クラスターでポリシーをどのようにレイアウトするかを決定することは非常に重要です。ポリシーは、クラスター全体、名前空間、またはワークロード固有のスコープにすることができます。より寛容なセキュリティ権限が必要になるKubernetesクラスター操作の一部であるクラスターには常にワークロードがあります。そのため、寛容なポリシーを使用して、不要なワークロードを停止する適切なRBACがあることを確認してください。 既存のクラスターでPodSecurityPolicyを有効にしますか?この便利なオープンソースツールを使用して、現在のリソースに基づいてポリシーを生成します。これは素晴らしいスタートです。そこから、ポリシーを磨くことができます。 慎重な計画と実用的なアプローチにより、PodSecurityPolicyはどのクラスターにも正常に実装できます。 コンテナランタイムは、依然として大部分が安全でないワークロード分離境界と見なされています。 これが内部でどのように実装されるかは、RuntimeClassが、実装するためにContainer Runtime Interface(CRI)に渡されるRuntimeHandlerを指定することです。 次のベストプラクティスは、一般的なワークロードの分離とRuntimeClassの落とし穴を回避するのに役立ちます。 RuntimeClassを介してさまざまなワークロード分離環境を実装すると、運用環境が複雑になります。これは、ワークロードが提供する分離の性質を考えると、異なるコンテナランタイム間でワークロードを移植できない場合があることを意味します。異なるランタイム間でサポートされる機能のマトリックスを理解することは理解するのが複雑であり、ユーザーエクスペリエンスの低下につながります。可能な場合、混乱を避けるために、それぞれが単一のランタイムを持つ個別のクラスターを持つことをお勧めします。 ワークロードの分離は、安全なマルチテナンシーを意味しません。安全なコンテナランタイムを実装している場合でも、KubernetesクラスターとAPIが同じ方法で保護されているという意味ではありません。Kubernetesの総表面積を端から端まで考慮する必要があります。ワークロードが孤立しているからといって、Kubernetes APIを介して悪意のあるアクターが変更することはできません。 異なるランタイム間でのツーリングには一貫性がありません。デバッグとイントロスペクションのためにコンテナランタイムツールに依存するユーザーがいる場合があります。異なるランタイムがあるということは、Docker psを実行して実行中のコンテナーを一覧表示できなくなる可能性があることを意味します。これは、トラブルシューティングの際に混乱と複雑さをもたらします。

第11章:クラスターのポリシーとガバナンス

実行時にポリシーを実装するのではなく、ガバナンスのコンテキストでポリシーについて説明する場合、Kubernetesリソース仕様自体のフィールドと値を制御するポリシーを定義します。 CRDを使用すると、統合されたKubernetesエクスペリエンスを実現し、ポリシー作成を実装から切り離します。 ポリシーテンプレートは制約テンプレートと呼ばれ、クラスター間で共有および再利用できます。 制約について考える最良の方法は、Kubernetesリソース仕様の特定のフィールドと値に適用する制約としてです。これは本当に政策を言う長い方法です。 これは、制約が定義されている場合、これを許可しないことを事実上述べていることを意味します。このアプローチの意味は、拒否を発行する制約なしでリソースが暗黙的に許可されることを意味します。これは重要です。なぜなら、Kubernetesリソース仕様のフィールドと値を許可する代わりに、不要なものだけを拒否するからです。 制約テンプレートは、型指定されたパラメーターと、再利用のためにパラメーター化されたターゲットレゴで構成されます。 制約テンプレートは、ポリシーをテンプレート化して共有または再利用できるようにする手段を提供するカスタムリソース定義(CRD)です。さらに、ポリシーのパラメーターを検証できます。 複数のポリシーが同じフィールドを検証する場合、1つが違反すると、リクエスト全体が拒否されます ゲートキーパーは、設定リソースを使用して、評価を実行するためにOPAにキャッシュされるデータを管理します 監査結果は制約のステータスフィールドに保存されるため、kubectlを使用するだけで簡単に検索できます。 Gatekeeperリポジトリには、銀行のコンプライアンスに対応するためのポリシー作成の詳細な例を紹介する素晴らしいデモコンテンツが付属しています。ゲートキーパーの動作方法の実践的なアプローチについては、デモをご覧になることを強くお勧めします。このGitリポジトリでデモを見つけることができます。 クラスターにポリシーとガバナンスを実装するときは、次のベストプラクティスを考慮する必要があります。 ポッドの特定のフィールドを適用する場合、どのKubernetesリソース仕様を検査および適用するかを決定する必要があります。 制約は、種類、名前空間、ラベルセレクターの基準でKubernetesリソースに適用できます。できるだけ厳密に適用するリソースに制約をスコープすることを強くお勧めします。これにより、クラスター上のリソースが増加しても一貫したポリシー動作が保証され、評価する必要のないリソースがOPAに渡されないため、他の非効率性が生じる可能性があります。 Kubernetesシークレットなどの潜在的に機密性の高いデータを同期および強制することはお勧めしません。OPAがキャッシュ内にこれを保持し(そのデータを複製するように構成されている場合)、リソースがゲートキーパーに渡されると、潜在的な攻撃ベクトルの表面が残ります。 多くの制約が定義されている場合、制約の拒否は、リクエスト全体が拒否されることを意味します。この関数を論理ORにする方法はありません。

第12章:複数のクラスターの管理

以下は、マルチクラスターアーキテクチャとシングルクラスターアーキテクチャのどちらを使用するかを検討する際の考慮事項です。 爆発半径 コンプライアンス セキュリティ ハードマルチテナンシー 地域ベースのワークロード 特殊なワークロード Dan Woodsは、本番Kubernetes環境での実際の連鎖的な失敗に関する素晴らしい記事を書きました。大規模な環境でマルチクラスタアーキテクチャを検討する理由の良い例です。 準拠するワークロードには、セキュリティ強化、非共有コンポーネント、または専用のワークロード要件に関する特定の要件があります。 大規模なKubernetesクラスターが要件に適合すると判断した場合は、セキュリティを変更するための非常に優れた運用プロセスがあることを確認し、RBAC、ネットワークポリシー、およびポッドセキュリティポリシーに変更を加える際の範囲を理解してください。 ユーザーが遭遇する一般的な課題には次のものがあります。 データ複製 サービス発見 ネットワークルーティング 運営管理 継続的な展開 各Kubernetesクラスターは独自のサービス検出レジストリを展開し、レジストリは複数のクラスター間で同期されません。 クラスターへのイングレスは、イングレスリソースを使用するマルチクラスタートポロジをサポートしないため、クラスターへのイングレスの1:1マッピングとして実装されます。また、クラスター間の出力トラフィックとそのトラフィックのルーティング方法を考慮する必要があります。 マルチクラスターを管理するための最も重要な側面の1つは、運用の負担を軽減するのに役立つため、適切な自動化プラクティスを確実に実施することです。 再現性のためにクラスター展開のソース管理を可能にするツールを使用します。 複数のクラスターを扱うときにすぐにインストールする2つのツールは、kubectxとkubensです。これらのツールを使用すると、複数のコンテキストと名前空間を簡単に変更できます。 複数のKubernetesクラスターを管理するときは、次のベストプラクティスを考慮してください。 クラスターの爆発範囲を制限して、連鎖障害がアプリケーションに大きな影響を与えないようにします。 PCI、HIPA、またはHiTrustなどの規制上の懸念がある場合は、マルチクラスターを利用して、これらのワークロードを一般的なワークロードと混合する複雑さを緩和することを検討してください。 ハードマルチテナンシーがビジネス要件である場合、ワークロードは専用クラスターに展開する必要があります。 アプリケーションに複数のリージョンが必要な場合は、グローバルロードバランサーを使用してクラスター間のトラフィックを管理します。 HPCなどの特殊なワークロードを独自の個別のクラスターに分割して、ワークロードの特殊なニーズを確実に満たすことができます。 複数の地域のデータセンターに分散するワークロードを展開する場合、まず、ワークロードにデータ複製戦略があることを確認してください。リージョン間で複数のクラスターを簡単に作成できますが、リージョン間でデータを複製することは複雑になる可能性があるため、非同期および同期ワークロードを処理するための適切な戦略があることを確認してください。 プロメテウス演算子やElasticsearch演算子などのKubernetes演算子を使用して、自動化された操作タスクを処理します。 マルチクラスター戦略を設計するときは、クラスター間のサービス検出とネットワーキングの方法も考慮してください。 CD戦略がリージョン間または複数のクラスター間の複数のロールアウトを処理できることを確認してください。 GitOpsアプローチを使用して複数のクラスター運用コンポーネントを管理し、フリート内のすべてのクラスター間で一貫性を確保することを調査します。GitOpsのアプローチは、すべての環境で常に機能するとは限りませんが、少なくとも、マルチクラスター環境の運用上の負担を軽減するために調査する必要があります。

第13章:外部サービスとKubernetesの統合

セレクタなしでKubernetesサービスを作成すると、サービスに一致するポッドはありません。したがって、ロードバランシングは実行されません。代わりに、このセレクターなしのサービスをプログラムして、Kubernetesクラスターに追加する外部リソースの特定のIPアドレスを持つことができます。そのようにして、Kubernetesポッドがデータベースのルックアップを実行すると、ビルトインKubernetes DNSサーバーはそれを外部サービスのサービスIPアドレスに変換します。 内部ロードバランサー経由でサービスをエクスポートすると、クラスターの外部の仮想ネットワークで表示される安定したルーティング可能なIPアドレスを受け取ります。次に、そのIPアドレスを直接使用するか、内部DNS解決をセットアップして、エクスポートされたサービスの検出を提供します。 ネットワーキングのためにクラスターに外部マシンを統合する場合、ポッドネットワークルーティングとDNSベースのサービス検出の両方が正しく機能することを確認する必要があります。 クラスターと外部サービスの接続のベストプラクティス クラスターとオンプレミスの間のネットワーク接続を確立します。ネットワーキングは、サイト、クラウド、クラスター構成ごとに異なる可能性がありますが、最初にポッドがオンプレミスマシンと通信できることを確認してください。 クラスターの外部のサービスにアクセスするには、セレクターなしのサービスを使用して、通信するマシン(データベースなど)のIPアドレスを直接プログラムできます。固定IPアドレスがない場合は、代わりにCNAMEサービスを使用してDNS名にリダイレクトできます。DNS名も固定サービスもない場合は、外部サービスのIPアドレスをKubernetesサービスエンドポイントと定期的に同期する動的オペレーターを作成する必要があります。 Kubernetesからサービスをエクスポートするには、内部ロードバランサーまたはNodePortサービスを使用します。通常、内部ロードバランサーは、Kubernetesサービス自体にバインドできるパブリッククラウド環境で使用する方が簡単です。このようなロードバランサーが利用できない場合、NodePortサービスはクラスター内のすべてのマシンでサービスを公開できます。 これらの2つのアプローチを組み合わせてKubernetesクラスター間の接続を実現し、サービスを外部に公開してから、他のKubernetesクラスターでセレクターなしのサービスとして消費します。

第14章:Kubernetesで機械学習を実行する

多くのクラウドプロバイダーはマルチGPU仮想マシン(VM)タイプを提供しているため、分散トレーニングを検討する前に、VMを4〜8つのGPUに垂直にスケーリングすることをお勧めします。 分散トレーニングはまだ初期段階にあり、最適化が困難です。8つのGPUを必要とするトレーニングジョブを実行すると、それぞれが4つのGPUを備えた2台のマシンと比較して、ほとんどの場合、単一の8GPUマシンでトレーニングする方が速くなります。 分散トレーニングを使用する必要があるのは、使用可能な最大のマシンにモデルが適合しない場合のみです。 また、特定のGPUが複数のスレッドの同時実行をサポートしている場合でも、その容量を利用できないことを意味します。 機械学習ワークロードの最適なパフォーマンスを実現するには、次のベストプラクティスを考慮してください。 スマートなスケジューリングと自動スケーリング。機械学習ワークフローのほとんどの段階は本質的にバッチであるため、クラスターオートスケーラーを使用することをお勧めします。 汚染と許容のいずれかを使用するか、時間固有のクラスターオートスケーラーを使用して、特定の時間にジョブをバッチ処理することをお勧めします。これにより、クラスターは、すぐにではなく、必要なときに機械学習ワークロードのニーズに合わせて拡張できます。 真実は、モデルのトレーニングは微妙なバランスです。1つのエリアで物事をより速く移動できるようにすると、他のエリアでボトルネックが生じることがよくあります。これは、絶え間ない観察と調整の努力です。一般的な経験則として、GPUは最も高価なリソースであるため、GPUをボトルネックにしようとすることをお勧めします。GPUを飽和状態に保ちます。ボトルネックを常に監視し、GPU、CPU、ネットワーク、ストレージの使用率を追跡するように監視を設定する準備をしてください。 機械学習ワークロードの高いパフォーマンス要件を考えると、機械学習ワークロードのみを受け入れるように汚染された別のノードプールを使用することをお勧めします。これは、機械学習ノードプールで実行されている機械学習ワークロードの影響からクラスターの残りを保護するのに役立ちます。さらに、ワークロードの種類に合わせてパフォーマンス特性が異なる複数のGPU対応ノードプールを検討する必要があります。また、機械学習ノードプールでノードの自動スケーリングを有効にすることをお勧めします。混合モードクラスターは、機械学習ワークロードがクラスターに与えるパフォーマンスへの影響を十分に理解してから使用してください。 私たちの経験では、ボトルネックの原因は、ほとんどの場合モデル自体であり、モデルをサポートするインフラストラクチャではありません。

第15章:Kubernetesの上に高レベルのアプリケーションパターンを構築する

Kubernetes用のリンターを実装して、開発者がKubernetesを使用するためのベストプラクティスに従うポッドやその他のリソースを送信できるようにすることができます。 CRDは、既存のKubernetesクラスターに新しいリソースを動的に追加する方法です。 このようなプラットフォームを構築する場合、次のベストプラクティスを念頭に置くことでメリットが得られます。 アドミッションコントローラーを使用して、クラスターへのAPI呼び出しを制限および変更します。アドミッションコントローラは、Kubernetesリソースを検証(および無効)できます。変化するアドミッションコントローラは、APIリソースを自動的に変更して、新しいサイドカーや、ユーザーが知る必要のないその他の変更を追加できます。 kubectlプラグインを使用して、使い慣れた既存のコマンドラインツールに新しいツールを追加することにより、Kubernetesユーザーエクスペリエンスを拡張します。まれに、専用のツールがより適切な場合があります。 Kubernetesの上にプラットフォームを構築するときは、プラットフォームのユーザーとそのニーズがどのように進化するかを慎重に検討してください。物事をシンプルで使いやすいものにすることは明らかに良い目標ですが、これがあなたのプラットフォームの外ですべてを書き直さなければ閉じ込められて成功できないユーザーにつながる場合、それは最終的にイライラする(そして失敗する)体験になります。

第16章:ステートおよびステートフルアプリケーションの管理

現実には、ボリュームマウントは、ステートフルアプリケーションの壮大なスキームの簡単なコンポーネントです。 ボリュームのベストプラクティス ボリュームの使用を、データを共有する必要のある複数のコンテナーを必要とするポッド(アダプターまたはアンバサダータイプのパターンなど)に制限するようにしてください。これらのタイプの共有パターンにはemptyDirを使用します。 ノードベースのエージェントまたはサービスでデータへのアクセスが必要な場合は、hostDirを使用します。 重要なアプリケーションログとイベントをローカルディスクに書き込むサービスを特定し、可能であればそれらをstdoutまたはstderrに変更して、ボリュームマップを活用する代わりに、真のKubernetes対応ログ集約システムにログをストリーミングさせます。 Kubernetesは、PersistentVolumeとPersistentVolumeClaimという2つの異なるAPIを使用してポッドのストレージを管理します。 PersistentVolumeは、ポッドにマウントされているボリュームをバックアップするディスクと考えるのが最適です。PersistentVolumeには、ボリュームを使用するポッドのライフサイクルとは無関係にボリュームのライフスコープを定義するクレームポリシーがあります。 PersistentVolumeClaimがPersistentVolumeと一致する場合にのみ、実際にポッドに割り当てられます。 PersistentVolumeClaimsは、ポッドが使用するストレージのリソース要件定義をKubernetesに提供する方法です。ポッドは要求を参照し、要求要求に一致するpersistentVolumeが存在する場合、その特定のポッドにそのボリュームを割り当てます。 Container Storage Interface(CSI)とFlexVolumeにより、ストレージベンダーは、今日のほとんどのボリュームプラグインのようにKubernetesコードベースに直接コードを追加することなく、カスタムストレージプラグインを作成できます。 一般にKubernetesのストレージに関するこれらのベストプラクティスは、アプリケーション設計に必要なストレージ実装を提供するための効果的なアプローチを設計するのに役立ちます。 可能であれば、DefaultStorageClass許可プラグインを有効にして、デフォルトのストレージクラスを定義します。多くの場合、PersistentVolumesを必要とするアプリケーションのHelmチャートは、チャートのデフォルトのストレージクラスにデフォルト設定されます。これにより、あまり変更を加えることなくアプリケーションをインストールできます。 オンプレミスまたはクラウドプロバイダーでクラスターのアーキテクチャを設計するときは、ノードとPersistentVolumesの両方に適切なラベルを使用し、アフィニティを使用してデータとワークロードを保持するコンピューティングレイヤーとデータレイヤー間のゾーンと接続を考慮しますできるだけ近い。最後に欲しいのは、ゾーンBのノードに接続されているボリュームをマウントしようとするゾーンAのノード上のポッドです。 ディスク上で状態を維持する必要があるワークロードは慎重に検討してください。データベースシステムなどの外部サービスによって、またはクラウドプロバイダーで実行されている場合、現在使用されているAPIと一貫性のあるAPI、たとえばサービスとしてのmongoDBまたはmySQLによってホストされたサービスによって処理できますか? アプリケーションコードをよりステートレスになるように変更するのにどの程度の労力が必要かを判断します。 Kubernetesは、ワークロードのスケジュールに従ってボリュームを追跡およびマウントしますが、それらのボリュームに保存されているデータの冗長性とバックアップをまだ処理していません。CSI仕様には、ストレージバックエンドがサポートできる場合にネイティブスナップショットテクノロジーをプラグインするためのベンダー向けのAPIが追加されています。 ボリュームが保持するデータの適切なライフサイクルを確認します。デフォルトでは、ポッドが削除されるとバッキングストレージプロバイダーからボリュームを削除する、動的にプロビジョニングされたpersistentVolumesに対して再生ポリシーが設定されます。機密データまたはフォレンジック分析に使用できるデータは、回収するように設定する必要があります。 Kubernetesは、展開しているアプリケーションの種類を把握していません。データベースシステムがリーダー選出プロセスを必要とすること、セットのメンバー間のデータ複製を処理できるかできないこと、またはそれがデータベースシステムであることをまったく知りません。 ヘッドレスサービスは通常のサービスと同じですが、通常の負荷分散は行いません ステートフルおよびオペレーターのベストプラクティス アプリケーションが順序付けの命名と信頼できるスケーリングを必要とする場合、常にPersistentVolumesの割り当てを必要とするわけではありません。 クラスター内のノードが応答しなくなっても、StatefulSetの一部であるポッドは自動的に削除されません。代わりに、猶予期間後にTerminatingまたはUnkown状態になります。このポッドをクリアする唯一の方法は、ノードオブジェクトをクラスターから削除すること、kubeletが再び動作を開始してポッドを直接削除すること、またはオペレーターがポッドを削除することです。強制削除は最後のオプションであり、クラスター内に同じ名前の2つのポッドが存在するため、削除されたポッドがあったノードがオンラインに戻らないように細心の注意を払う必要があります。 ポッドを強制的に削除した後でも、不明な状態のままになる可能性があるため、APIサーバーへのパッチによりエントリが削除され、StatefulSetコントローラーが削除されたポッドの新しいインスタンスを作成します 何らかのタイプのリーダー選出またはデータ複製確認プロセスで複雑なデータシステムを実行している場合は、preStopフックを使用して接続を適切に閉じ、リーダー選出を強制するか、正常なシャットダウンプロセスを使用してポッドが削除される前にデータ同期を確認します。 ステートフルデータを必要とするアプリケーションが複雑なデータ管理システムである場合、アプリケーションのより複雑なライフサイクルコンポーネントの管理を支援するために、Operatorが存在するかどうかを確認する価値があります。アプリケーションが社内で構築されている場合、アプリケーションに管理性を追加するためにアプリケーションをオペレーターとしてパッケージ化することが有用かどうかを調査する価値があるかもしれません。例については、CoreOS Operator SDKをご覧ください。 第17章:アドミッションコントロールと承認 アドミッションコントローラの検証と変更の違いは、変更が許可するリクエストオブジェクトを変更できるのに対し、検証はできないことです。 標準のアドミッションコントローラーはAPIサーバーにコンパイルされ、Kubernetesの各リリースのプラグインとして出荷されます。APIサーバーの起動時に設定する必要があります。 一方、動的コントローラーは、実行時に構成可能で、コアKubernetesコードベースの外部で開発されます。ダイナミックアドミッションコントロールの唯一のタイプは、HTTPコールバックを介してアドミッションリクエストを受信するアドミッションウェブフックです。 Kubernetesに同梱されている機能の多くは、特定の標準アドミッションコントローラーの有効化に依存しているため、推奨されるデフォルトのセットがあります。 –enable-admission-plugins = NamespaceLifecycle、LimitRanger、ServiceAccount、DefaultStorageClass、DefaultTolerationSeconds、MutatingAdmissionWebhook、ValidatingAdmissionWebhook、Priority、ResourceQuota、PodSecurityPolicy アドミッションコントロールのベストプラクティス 入場プラグインの順序は関係ありません。Kubernetesの以前のバージョンでは、アドミッションプラグインの順序は処理順序に固有でした。したがって、それは重要でした。現在サポートされているKubernetesバージョンでは、-enable-admission-pluginsを介してAPIサーバーフラグとして指定されたアドミッションプラグインの順序は重要ではなくなりました。ただし、Webhookの入場に関しては順序が小さな役割を果たすため、この場合の要求フローを理解することが重要です。リクエストのアドミタンスまたは拒否は論理ANDとして機能します。つまり、いずれかのアドミッションWebフックがリクエストを拒否すると、リクエスト全体が拒否され、エラーがユーザーに返されます。変化するアドミッションコントローラは、検証するアドミッションコントローラを実行する前に常に実行されることに注意することも重要です。 同じフィールドを変更しないでください。複数の変化する許可Webhookを構成することも課題です。複数の変化するアドミッションWebフックを介して要求フローを順序付ける方法はないため、変化するアドミッションコントローラーが同じフィールドを変更しないようにすることが重要です。予期しない結果が生じる可能性があるためです。複数の変更許可Webhookがある場合、一般に、変更Webhookの後に実行されることが保証されているため、最終的なリソースマニフェストが変更後の予想されるものであることを確認するために、検証許可Webhookを構成することをお勧めします。 フェールオープン/フェールクローズ。失敗と検証の両方のwebhook設定リソースの一部としてfailurePolicyフィールドを見たことを思い出すかもしれません。このフィールドは、許可Webhookにアクセスの問題がある場合や認識されないエラーが発生した場合にAPIサーバーがどのように進むべきかを定義します。このフィールドは、無視または失敗に設定できます。無視は基本的に開くことができません。つまり、要求の処理は続行されますが、失敗は要求全体を拒否します。これは明らかなように思えるかもしれませんが、両方の場合の影響を考慮する必要があります。重要な入場ウェブフックを無視すると、ユーザーが知らないうちにビジネスがリソースに適用されないことに依存するというポリシーが生じる可能性があります。 これから保護するための1つの潜在的なソリューションは、APIサーバーが特定の許可Webhookに到達できないことをログに記録するときにアラートを生成することです。入場ウェブフックで問題が発生している場合、すべてのリクエストを拒否することで、失敗はさらに壊滅的なものになります。これから保護するために、特定のリソースリクエストのみがアドミッションWebhookに設定されるようにルールをスコープできます。教義として、クラスター内のすべてのリソースに適用されるルールは決してありません。 独自の入場Webhookを作成した場合、入場Webhookが決定して応答するまでにかかる時間によって、ユーザー/システムリクエストが直接影響を受ける可能性があることを覚えておくことが重要です。すべてのアドミッションWebhookコールは30秒のタイムアウトで構成され、その後、failurePolicyが有効になります。許可Webhookが許可/拒否の決定を行うのに数秒かかったとしても、クラスターで作業するときのユーザーエクスペリエンスに深刻な影響を与える可能性があります。承認/拒否ロジックを処理するために、複雑なロジックを使用したり、データベースなどの外部システムに依存したりしないでください。 スコーピングアドミッションウェブフック。NamespaceSelectorフィールドを介して、アドミッションWebhookが動作するネームスペースをスコープできるオプションのフィールドがあります。このフィールドのデフォルトは空で、すべてに一致しますが、matchLabelsフィールドを使用して名前空間ラベルを一致させるために使用できます。名前空間ごとに明示的にオプトインできるため、このフィールドを常に使用することをお勧めします。 kube-system名前空間は、すべてのKubernetesクラスターに共通の予約済み名前空間です。すべてのシステムレベルのサービスが動作する場所です。特にこのネームスペースのリソースに対してアドミッションWebhookを実行しないことをお勧めします。NamespaceSelectorフィールドを使用し、kube-systemネームスペースを単に一致させないことでこれを実現できます。また、クラスター操作に必要なシステムレベルの名前空間でも考慮する必要があります。 RBACで入場Webhook構成をロックダウンします。 機密データを送信しないでください。入場ウェブフックは、基本的にAdmissionRequestsを受け入れ、AdmissionResponsesを出力するブラックボックスです。ユーザーがリクエストを保存および操作する方法は、ユーザーには不透明です。入場ウェブフックに送信するリクエストペイロードを考えることが重要です。 Kubernetesでは、各リクエストの認証は認証後、許可前に実行されます。 アドミッションコントローラーとは異なり、単一の承認モジュールがリクエストを承認した場合、リクエストは続行できます。すべてのモジュールがリクエストを拒否した場合のみ、エラーがユーザーに返されます。 クラスターで構成されている承認モジュールを変更する前に、次のベストプラクティスを検討してください。 ABACポリシーを各マスターノードのファイルシステムに配置して同期を維持する必要があることを考えると、マルチマスタークラスターでABACを使用しないことをお勧めします。設定はファイルと存在する対応するフラグに基づいているため、webhookモジュールについても同じことが言えます。さらに、ファイル内のこれらのポリシーを変更するには、APIサーバーを再起動して有効にする必要があります。これは、単一マスタークラスターでのコントロールプレーンの停止またはマルチマスタークラスターでの一貫性のない構成です。これらの詳細を考慮すると、ルールはKubernetes自体で構成および保存されるため、ユーザー認証にはRBACモジュールのみを使用することをお勧めします。 Webhookモジュールは強力ですが、潜在的に非常に危険です。すべてのリクエストが承認プロセスの対象になるため、webhookサービスの障害はクラスターに壊滅的な打撃を与えます。そのため、webhookサービスが到達不能または使用不能になった場合にクラスター障害モードに完全に精通し、慣れている場合を除き、通常は外部認証モジュールを使用しないことをお勧めします。

第18章:結論

KubernetesのAPIとコンポーネントがどのように機能するかを理解することは、Kubernetesのパワーを正常にアンロックして、アプリケーションの開発、管理、展開をより簡単で信頼性の高いものにするために重要です。 同様に、Kubernetesをオンプレミスデータベースや継続的デリバリーシステムなどのさまざまな外部システムやプラクティスとリンクする方法を理解することは、現実世界でKubernetesを効率的に使用するために重要です。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment