KRM を使用したプラットフォームの構築: パート 4 - マルチクラスタ環境の管理
Google Cloud Japan Team
※この投稿は米国時間 2021 年 7 月 1 日に、Google Cloud blog に投稿されたものの抄訳です。
この投稿は、Kubernetes Resource Model に関するシリーズのパート 4 です。詳細については、パート 1、2、3 をご参照ください。
Kubernetes クラスタはスケーリングが可能です。オープンソースの Kubernetes は最大 5,000 ノードをサポートし、GKE は最大 15,000 ノードをサポートします。しかし単一クラスタのスケールアップでは可用性に問題があります。たとえばクラスタのコントロール プレーンが停止すると、プラットフォーム全体が停止します。クラスタが稼働している Cloud リージョンでサービスの中断が発生すると、アプリでもサービスの中断が発生します。
このため多くの企業は複数の Kubernetes クラスタの運用を選択します。可用性を高めるという目的以外に、マルチクラスタを選択する多くの理由があります。たとえば、開発チームごとにクラスタを割り振る、クラウドとオンプレミスでワークロードを分割する、トラフィックの急増に備えてバースト機能を提供する、などです。
しかし、マルチクラスタ プラットフォームを運用することには特有の課題があります。多数のクラスタを一度に一貫して管理するにはどうすればよいか。クラスタの安全性はどのように確保するか。複数のクラスタにまたがって実行されるアプリケーションをどうやってデプロイ、モニタリングするか。あるリージョンから別のリージョンへのフェイル オーバーをシームレスに行うにはどうすればよいか。
この投稿では、プラットフォーム チームがマルチクラスタ Kubernetes 環境をより簡単に管理できるツールについてご説明します。
Config Sync を使用するプラットフォーム ベースレイヤ
前回の投稿では、プラットフォームを抽象化することで、CI / CD などの自動化でステージング クラスタと本番環境クラスタとのすべてのインタラクションを処理するマルチクラスタ環境など、アプリのデベロッパーの作業負担を軽減する方法について説明しました。これと同様に重要なのが、プラットフォーム ベースレイヤ(サービス間で共有する Kubernetes リソースと構成)です。プラットフォーム ベースレイヤは Namespace、ロールベースのアクセス制御、Prometheus などの共有ワークロードで構成されます。
プラットフォームの抽象化はこうしたベースレイヤ リソースの存在によって変化します。プラットフォーム全体のセキュリティと安定性も同様に変化します。このリソースはデプロイだけでなく保持することが重要です。CI / CD はリソースの優れたデプロイ方法ですが、デプロイを確実にするにはどうすればよいでしょうか。Kubernetes Namespace が削除された場合やPrometheus StatefulSet が変更された場合の対処方法はありますか。
Kubernetes のジョブは、クラスタの実際の状態を希望の状態と一致させるためのものです。しかし、ときには「希望の」状態が望ましいものではないことがあります。デベロッパーがリソースを誤って変更した場合や、不正な行為者がシステムへのアクセス権を得た場合などです。このため、プラットフォーム ベースレイヤは 1 回限定ではない CI / CD パイプラインを必要とします。これには Config Sync と呼ばれるツールで対応できます。
Config Sync は、Git リポジトリからの Kubernetes リソースを 1 つ以上の GKE クラスタまたは Anthos クラスタと同期する、Google Cloud プロダクトです。Cloud Build などの CI / CD ツールとは異なり、Config Sync はクラスタを常時監視し、クラスタ内の対象リソースの状態を Git 内の状態と常に一致させます。Config Sync は主に名前空間や RBAC のようなベースレイヤ リソース向けに設計されています。このように、Config Sync は CI / CD の代替となるものではなく、補完するものです。
Config Sync は Kubernetes クラスタ内の Pod で実行され、Git config リポジトリが変更されていないか監視します。またクラスタ自体についても、Git 内の希望する状態から変更されていないか監視します。Git に保管されている内容に構成のずれが見つかった場合、Config Sync は API サーバーを更新します。
同じ Git リポジトリで複数の Config Sync デプロイを参照できます。これで、信頼できる同じ情報源を使用して、複数のクラスタのベースレイヤ プラットフォーム リソースを管理できるようになります。Git を Config のランディング ゾーンとして追加すると、構成の変更の監査とロールバックを行う機能など、パート 2 で説明した GitOps の原則のいくつかからメリットが得られます。
Config Sync を使用してベースレイヤ リソースを管理する方法の例を見ていきましょう。
Cymbal Bank のプラットフォームは、管理、開発、ステージング、本番という 4 つの GKE クラスタで構成されています。gcloud ツールまたは Google Cloud Console を使用して、この 4 つのクラスタすべてに Config Sync をインストールできます。これで、cymbalbank-policy と呼ばれる 1 つの Git リポジトリで 4 つすべてを参照できるようになります。このリポジトリはアプリケーション ソースと構成リポジトリから分離され、プラットフォーム チームによって管理されます。Console で、4 つのクラスタすべてが cymbalbank-policy リポジトリの同じ commit と同期していることがわかります。
では、Cymbal Bank のプラットフォーム チームが、各アプリケーション チームがサービスに対してリクエストできる CPU とメモリのリソース量に制限を設けるとしましょう。Kubernetes の ResourceQuotas でこの制限をサポートし、予期せぬ Pod のエビクションを防ぐことができます。
プラットフォーム チームはアプリケーションの名前空間ごとに一連の ResourceQuotas を定義できます。リソースをクラスタのサブセット(本番環境クラスタなど)のみに適用するように、スコープの設定も可能です(クラスタ名セレクタが指定されていないと、Config Sync はデフォルトでリソースをすべてのクラスタにデプロイします)。
ここで、プラットフォーム チームはリソースを cymbalbank-policy リポジトリに commit できます。ポリシー リポジトリを常時監視する Config Sync は、リソースを本番環境クラスタにデプロイします。
デベロッパーが ResourceQuotas の 1 つを削除しようとすると、Config Sync はそのリクエストをブロックし、そのベースレイヤ リソースを保持しようとします。
このように、Config Sync はプラットフォーム チームが一度に複数のクラスタでリソースの整合性を確保できるようにするだけでなく、プラットフォーム ベースレイヤの安定性確保にも役立ちます。これで、組織が新しいクラスタを自身の環境に加える際の複雑さが軽減されます。
Kubernetes リソースでポリシーを適用する
Config Sync はそれ自体が強力なツールであり、クラスタが認識するすべての Kubernetes リソースで動作します。カスタム リソース定義(CRD)と、一緒にインストールされる Anthos Service Mesh などのアドオンが含まれます。
デフォルトでは、Config Sync には Kubernetes リソースの「良好と不良」に関する基準がありません。組織にセキュリティ上のリスクが発生する可能性があるリソースでも、Git にあるどのリソースもデプロイします。セキュリティはすべてのデベロッパー プラットフォームにとって重要な機能であり、特に Kubernetes に関しては、ソフトウェアの最初の設計段階からセキュリティを考慮し、セキュリティに関するベスト プラクティスを念頭に置いてクラスタをセットアップすることが重要です。
デプロイ時のセキュリティを考慮するのと同じくらい重要なことが、ほかにもあります。誰と何がクラスタにアクセスできるか。許可される Kubernetes リソースの種類と、リソース内のフィールドはどれか。こうした判断は、アプリケーションが扱うデータの種類や業界固有の規制など、さまざまな要因で変わってきます。
KRM の一般的なセキュリティ ユースケースの一つとして、kubectl、CI / CD、Config Sync を介して受信する Kubernetes リソースをモニタリングする必要性があります。複数のクラスタがあれば、Kubernetes 環境には複数の API サーバーが備わっているので、エントリ ポイントが複数になります。
Google ツールの Policy Controller の利用で、複数のクラスタ間でリソースのモニタリングを自動化できます。Policy Controller は、定義済みのカスタム ポリシーに基づいて受信リソースを承認または拒否できる Kubernetes アドミッション コントローラです。Policy Controller は OpenPolicyAgent Gatekeeper プロジェクトをベースにしていて、ポリシー(「制約」)を KRM として定義できます。つまり、Git を介して Config Sync を使用してポリシーをデプロイできます。デプロイされると、Policy Controller は制約を一連のルールとして使用し、すべての受信 KRM を評価して、コンプライアンスから外れたリソースを拒否します。
いくつか例をご紹介します。Cymbal Bank のセキュリティ チームは、開発中のコードが一般公開できないようにしたいと考えています。LoadBalancer 型の Kubernetes Services はデフォルトでパブリック IP アドレスを公開するので、プラットフォーム チームは開発 GKE クラスタでこの型の Service をブロックする PolicyController 制約を定義できます。
これを行うため、プラットフォーム チームが Policy Controller の制約を KRM として定義できます。この制約は、プリインストールされている制約テンプレート ライブラリを介して提供される、制約テンプレートを使用します。制約テンプレートはポリシー自体のロジックを定義し、制約でポリシーのロジックを実行するために必要な変数を入力して、このテンプレートを具体化します。ここでは Config Sync クラスタ名アノテーションを追加し、このリソースを開発クラスタにのみ適用するようにスコープを設定します。
次に、プラットフォーム チームが cymbalbank-policy リポジトリにリソースを commit し、Config Sync が開発クラスタにリソースをデプロイします。
ここでは、アプリ デベロッパーが外部からアクセス可能な Kubernetes Service を作成しようとすると、Policy Controller はリソースが作成されないようブロックします。
プラットフォーム チームは必要なだけの制約を定義し、制約ごとに別のポリシーを定めます。
カスタム ポリシーの作成
Policy Controller の制約テンプレート ライブラリには、特権コンテナをブロックする、特定のリソースラベルの指定を要求する、アプリチームによる特定の名前空間へのデプロイを禁止するなど、多くの機能が備わっています。カスタム ロジックを組織の KRM に適用するには、カスタムの制約テンプレートを作成する必要があります。
制約テンプレートは Rego と呼ばれるクエリ言語で作成されています。Rego はポリシールールの評価のために設計され、Kubernetes リソース フィールドをイントロスペクトし、リソースが使用できるかどうか、結論を下すことができます。
たとえば、プラットフォーム チームが 1 つのアプリケーション Pod 内で使用できるコンテナの数を制限する場合を考えてみましょう。Pod ごとのコンテナの数が多すぎると、停止リスクの原因となります。1 つのコンテナがクラッシュすると、Pod 全体がクラッシュします。
このポリシーを適用するため、プラットフォーム チームは Rego 言語を使用して制約テンプレートを定義します。次のように、リソースの内部に、Pod ごとのコンテナの数が制限値以内に収まっているのが確認できます。
最後に、プラットフォーム チームはこれらのリソースを cymbalbank-policy リポジトリに push し、Config Sync はポリシーを 4 つのクラスタすべてにデプロイします。デベロッパーが Pod ごとに許可されているよりも多くのコンテナを含む Kubernetes Deployment を定義しようとすると、リソースがデプロイ時にブロックされます。
カスタム制約テンプレートによって、プラットフォーム チームは Kubernetes 環境で定義、適用するポリシーの型を柔軟に指定できるようになります。
CI / CD にポリシー チェックを組み込む
前述のとおり、Config Sync と CI / CD は互いに補完するツールです。Config Sync はベースレイヤ プラットフォーム リソースとポリシーに最適です。一方 CI / CD はアプリケーション テストとデプロイに適しています。
しかし 2 つの KRM デプロイ メカニズムがあることで、アプリのデベロッパーが、リソースを本番環境にデプロイしようとするまでポリシー違反に気付かないおそれがあります。特に、ResourceQuota の例にあるように、一部のポリシーが本番環境のみをスコープとしている場合にポリシー違反が発生する可能性が高くなります。新しいリソースまたは変更されたリソースがポリシー遵守を維持しているかどうか、デベロッパーとコード レビューアに事前に知らせる方法がプラットフォーム チームにあることが理想的です。Google はポリシー チェックを既存の Cymbal Bank CI / CD に組み込むことで、このユースケースを実現できます。
Policy Controller はデフォルトで、クラスタ内部で実行される Kubernetes アドミッション コントローラとして動作します。Policy Controller には同時にコンテナ内部で実行される「スタンドアロン」モードもあります。Cloud Build パイプライン内部からなど、クラスタの外部で使用できます。
以下の例では、Cloud Build が cymbalbank-app-config マニフェストを取得し、cymbalbank-policy リソースのクローンを作成して、「policy-controller-validate」コンテナ イメージでポリシーに対するアプリのマニフェストの評価を行い、Policy Controller チェックを行います。
ここで、アプリのデベロッパーまたはオペレーターは、pull リクエストの Cloud Build の出力を確認することで、リソースが組織全体のポリシーに違反していないか知ることができます。
ポリシー チェックを CI / CD に組み込むことで、アプリ開発チームは、リソースがポリシーを遵守しているかどうかがわかり、プラットフォーム チームは追加のポリシー チェック レイヤをプラットフォームに加えます。
全体としては、Config Sync と Policy Controller は、マルチクラスタ環境でベースレイヤ構成を標準化するための強力なツールチェーンを提供します。パート 4 のデモで、それぞれの例を紹介しています。
また、パート 5 にもご期待ください。クラウドでホストされるリソースの管理に KRM を使用する方法について説明する予定です。
-デベロッパー プログラム エンジニア Megan O'Keefe