本番環境での Google Kubernetes Engine の準備

このドキュメントでは、コンテナ化されたワークロードを Google Kubernetes Engine(GKE)に、より安全で信頼性が高く、費用対効果の高い方法でオンボーディングする方法について説明します。クラスタへの管理アクセスおよびネットワーク アクセスを構成するためのガイダンスを提供します。この記事では、Kubernetes リソースとクラスタ管理について実践的に理解し、Google Cloud ネットワーク機能に精通していることを前提としています。

サンプル アーキテクチャ

次の図は、GKE クラスタをデプロイするための柔軟で可用性の高い構造の例を示しています。

プロジェクト、ネットワーク、クラスタ構造

プロジェクト

Google Cloud はプロジェクト エンティティ内にそのすべてのリソースを作成します。

プロジェクトを使用して、さまざまなオペレーティング環境を表すことができます。たとえば、オペレーション チーム向けに production および staging プロジェクトを設定し、デベロッパー向けには development プロジェクトを設定する場合などです。最もミッション クリティカルで機密性の高いデータとワークロードを保持するプロジェクトには、実験のための制限が緩やかで柔軟なポリシーを適用することができます。これにより、development 環境のデベロッパーに対して、実験のための制限が緩やかで柔軟なポリシーを適用することができます。

クラスタ

プロジェクトには複数のクラスタを含めることができます。複数のワークロードをデプロイする場合、それらのワークロードに単一の共有クラスタを使用するか、または別々のクラスタを使用するかを選択できます。

ネットワークとサブネット

各プロジェクト内では、1 つ以上の VPC ネットワークを使用できます。VPC ネットワークは、物理ネットワークの仮想バージョンです。各 VPC ネットワークは、ネットワーク関連の他のリソース(サブネット、外部 IP アドレス、ファイアウォール ルール、ルート、VPN、Cloud Router など)が含まれるグローバル リソースです。VPC ネットワーク内では、リージョン リソースであるサブネットを使用して、GKE クラスタ間の各リージョン内外へのトラフィックを分離して制御できます。

各プロジェクトには、1 つのデフォルト ネットワークが付属しています。追加のネットワークを作成して、既存の IP アドレス管理(IPAM)規則にマップするように構成できます。そのネットワークにファイアウォール ルールを適用することで、GKE ノードに出入りするトラフィックをフィルタできます。デフォルトでは、GKE ノードへのすべての外部トラフィックが拒否されます。

サブネット間の通信を制御するには、サブネット間でのトラフィックの受け渡しを許可するファイアウォール ルールを作成する必要があります。ファイアウォール ルールを有効にするには、クラスタまたはノードプールの作成時に --tags フラグを使用して、GKE ノードに適切なタグを付けます。必要に応じて、タグを使用してサブネット間のルートを作成することもできます。

ゾーンクラスタとリージョン クラスタ

標準クラスタと Autopilot クラスタを作成できます。Autopilot クラスタはリージョン クラスタです。標準クラスタは、リージョン クラスタまたはゾーンクラスタです。ゾーンクラスタは、シングルゾーンにもマルチゾーンにもできます。マルチゾーン クラスタとリージョン クラスタは、リージョン内の複数のゾーンにリソースを分散させることで、クラスタの可用性と復元力を向上させることができます。

ゾーンクラスタには次のプロパティがあります。

  • シングルゾーンで動作するコントロール プレーンの単一のレプリカを作成します。
  • マルチゾーンの場合は、複数のゾーンでノードを実行します。

リージョン クラスタのプロパティは次のとおりです。

  • 3 つのゾーンにコントロール プレーンを複製します。
  • 構成されたノードのロケーションに応じて、複数のゾーンまたは単一ゾーンで実行できます。

クラスタの作成時に、ゾーンクラスタまたはリージョン クラスタを作成することを選択できます。マルチゾーン クラスタを作成するには、既存のクラスタに新しいノードを追加します。ただし、既存のゾーンクラスタをリージョン クラスタに変更することはできません。また、リージョン クラスタをゾーンクラスタに変更することはできません。

GKE マネージド クラスタ内のノードのサービス可用性は、Compute Engine サービスレベル契約(SLA)の適用を受けます。

ゾーンクラスタとリージョン クラスタについて詳しくは、GKE のドキュメントをご覧ください。

ID とアクセスの管理

Identity and Access Management(IAM)のロールとグループ

個々のユーザーに IAM ロールを付与するだけでなく、グループを使用して簡単にロールを適用することもできます。

次の IAM ポリシー レイアウトの図は、デベロッパーが今後リリースされる機能とバグ修正の開発とテストを行うために設定された dev プロジェクトと、本番環境のトラフィック用の prod プロジェクトのための、最小限の権限の原則を示しています。

ID とアクセスの管理。

次の表に示すように、組織内には、2 つのプロジェクト全体で IAM ロールを通じて許可された、さまざまなレベルの権限を持つ 4 つのユーザーのグループがあります。

チーム IAM の役割 プロジェクト 権限
デベロッパー roles/container.developer dev プロジェクト内に、既存のクラスタ用の Kubernetes リソースを作成することはできますが、クラスタを作成または削除することはできません。
運用 roles/container.admin prod プロジェクト内で実行されているクラスタおよび Kubernetes リソースへの完全な管理アクセス。
セキュリティ roles/container.viewer
roles/compute.securityAdmin
prod ファイアウォール ルールと SSL 証明書の作成、変更、削除、ならびに実行中の Pod のログを含む各クラスタ内で作成されたリソースの表示。
ネットワーク roles/compute.networkAdmin prod ネットワーク リソース(ファイアウォール ルールと SSL 証明書を除く)の作成、変更、削除。

prod プロジェクトに対するアクセス権を持つ 3 チームに加えて、追加のサービス アカウントprod に対する container.developer のロールを付与すると、クラスタ内でリソースを作成、一覧表示、削除できるようになります。サービス アカウントを使用すると、自動化スクリプトやデプロイ フレームワークに、自動的に処理する機能を与えることができます。本番環境プロジェクトとクラスタへのデプロイは、自動化されたパイプラインで進められるはずです。

dev プロジェクトには、同じクラスタ内の同じアプリケーションを操作する複数のデベロッパーがいます。これは、クラスタ ユーザーが作成できる名前空間によって容易になります。各開発者は、独自の名前空間内にリソースを作成できるため、名前の競合が避けられます。また、同じ YAML 構成ファイルをデプロイに再利用できるので、開発の繰り返し時に可能な限り同じ構成が維持されます。

名前空間を使用して、クラスタ内の CPU、メモリ、ストレージの使用の割り当てを作成して、1 人の開発者が使用するクラスタ内のリソースが多すぎないようにすることもできます。名前空間の使用について詳しくは、Kubernetes のベスト プラクティス: YAML での名前空間の指定をご覧ください。

次のセクションでは、特定の名前空間内でオペレーションするようにユーザーを制限する方法について説明します。

ロールベースのアクセス制御

Kubernetes 1.6 以降を実行している GKE クラスタでは、個々のクラスタでユーザーに実行を許可する機能に関してさらに制限を加えることができます。IAM によって、ユーザーはクラスタとその中のリソースにアクセスできるようになりますが、Kubernetes ロールベースのアクセス制御(RBAC)により、Kubernetes API を使用して、ユーザーがクラスタ内で行えるアクションをさらに制限することが可能になります。

RBAC により、クラスタ管理者は、クラスタ内の個々の名前空間またはクラスタ全体に詳細なポリシーを適用します。Kubernetes kubectl ツールは、gcloud ツールからのアクティブな認証情報を使用するため、クラスタ管理者はロールを Google Cloud Identity(ユーザー、サービス アカウント、Google グループ)に RoleBinding の subjects としてマッピングできます。

Google Groups for RBAC を使用すると、Kubernetes RBAC で Google グループを使用できます。この機能を使用するには、Google Workspace の Google グループを構成し、この機能を有効にしたクラスタを作成する必要があります。また、RoleBinding を使用してグループとロールを関連付ける必要があります。詳細については、ロールベースのアクセス制御をご覧ください。

次の図の例では、user-auser-b という 2 人のユーザーには、app-a 名前空間上で config-reader ロールと pod-reader ロールが割り当てられています。

RBAC 認証。

別の例として、特定のユーザーにプロジェクト内のすべてのクラスタへのアクセス権を付与する Google Cloud プロジェクト レベルの IAM のロールがあります。さらに、特定のクラスタや名前空間内のリソースに対する粒度の細かいアクセス権を付与する RBAC によって、個々の名前空間およびクラスタレベルのロール バインディングが追加されます。

IAM RoleBindings。

Kubernetes にはデフォルトのロールがいくつか含まれていますが、クラスタ管理者は組織のニーズにより密接に対応する独自のロールを作成できます。次の例のロールの場合、delete 動詞が含まれていないため、ユーザーが行えるのは ConfigMaps の表示、編集、更新に限られ、削除はできません。

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: config-editor
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]

ロールを定義したら、バインディングによって、クラスタまたは名前空間にこれらのロールを適用できます。バインディングは、ロールをユーザー、グループ、またはサービス アカウントに関連付けます。次の例は、以前に作成したロール(config-editor)を、bob@example.org ユーザーと development 名前空間にバインドする方法を示しています。

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: config-editors
  namespace: development
subjects:
- kind: User
  name: bob@example.org
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: config-editor
  apiGroup: rbac.authorization.k8s.io

RBAC の詳細については、GKE のドキュメントをご覧ください。

イメージのアクセスと共有

Container Registry または Artifact Registry のイメージは、Cloud Storage に保存されます。

このセクションでは、イメージを共有する次の方法について説明します。

  • イメージを公開します。
  • プロジェクト間でイメージを共有する。

限定公開クラスタを有効にする場合は、Artifact Registry を使用することが重要です。限定公開クラスタでは、Cloud NAT を設定しない限り、クラスタのコンテナ ランタイムで外部コンテナ レジストリからコンテナ イメージを直接 pull できません。コンテナ ランタイムは、Cloud NAT や限定公開の Google アクセスを使用せずに、限定公開クラスタ内の Artifact Registry からイメージを pull できます。ノードが Artifact Registry と直接通信する必要がある場合は、限定公開の Google アクセスが有効になっているサブネットにノードを配置する必要があります(たとえば、ノードで新しいアーティファクトを作成し、Artifact Registry に保存する必要がある場合)。詳細については、イメージ レジストリからコンテナ イメージを pull するをご覧ください。

Artifact Registry 内のイメージを公開する

オブジェクトとバケットを Artifact Registry に公開することで、イメージを公開できます。詳細な手順については、Artifact Registry のアクセス制御のドキュメントを参照してください。

公開イメージを使用する必要がある場合は、クラスタへのデプロイを許可する公開イメージのセットの検証を検討してください(詳細については、Binary Authorization をご覧ください)。

Artifact Registry 内のプロジェクト間でイメージを共有する

Kubernetes ノードにサービス アカウントを使用させることで、プロジェクト間でコンテナ イメージを共有できます。Artifact Registry を使用するプロジェクトに対して、storage.viewer としてサービス アカウントにアクセス権を付与できます。デフォルトのサービス アカウントにはプロジェクト全体に対する編集権限があるため、権限を制限したカスタム サービス アカウントを使用します。

クラスタで別のサービス アカウントを使用するには、クラスタまたはノードプールの作成時に --service- account フラグを使用してサービス アカウントを指定します。

詳細については、アクセス制御の構成をご覧ください。

適切なイメージ pull ポリシーを決定する

Kubernetes の imagePullPolicy プロパティは、Pod の起動時に kubelet でイメージを pull するかどうかを指定します。適切な imagePullPolicy 設定を構成して、コンテナ イメージに指定します。たとえば、次のイメージ pull ポリシーを指定できます。

imagePullPolicy: IfNotPresent

この場合、Kubelet はノードのキャッシュでイメージを使用できない場合にのみ、イメージのコピーを取得します。

指定できるイメージ pull ポリシーの詳細については、Kubernetes のドキュメントのコンテナ イメージをご覧ください。

ダイナミック アドミッション コントローラを使用してポリシーを適用する

ダイナミック アドミッション コントローラは、Kubernetes コントロール プレーンの一部です。API サーバーに対して行われた受信リクエストをインターセプトできます。アドミッション コントローラは、GKE クラスタに企業固有のカスタム ポリシーを適用できる強力なツールです。

Kubernetes は、変更用アドミッション コントローラと検証用アドミッション コントローラという 2 種類のアドミッション コントローラをサポートしています。

変更用アドミッション コントローラは、アドミッション リクエストをインターセプトし、リクエストを変更できます。リクエストはその後、API サーバーに渡されます。

検証用アドミッション コントローラは、リクエストを調べて、指定したルールに従って有効かどうかを判断します。クラスタに検証用コントローラが構成されている場合、リクエストが API サーバーによって検証された後、Webhook が起動されます。検証用アドミッション コントローラは、Webhook で定義されているポリシーを遵守していることを保証するためにリクエストを拒否できます。

たとえば、変更用アドミッション コントローラを使用して、イメージ pull ポリシーを適用すると、Pod 作成リクエストを送信したデベロッパーによって指定された imagePullPolicy 設定に関係なく、ポリシーが Always に設定されることを保証できます。

Google Cloud Marketplace のパッケージ化されたアプリを使用する

また、Google Cloud Marketplace からパッケージ化された Kubernetes アプリをデプロイすることも検討できます。Google Cloud マーケットプレイスにある Kubernetes アプリには、脆弱性スキャンやメンテナンスおよびサポートに関するパートナー契約など、Google によるテストと調査が実施されています。

Workload Identity を使用して Google Cloud サービス API を操作する

多くの場合、企業のアーキテクチャには、クラウド サービス(クラウド マネージド サービスおよびホスト型サービス)にまたがるアーキテクチャ コンポーネントが含まれています。GKE アプリケーションまたはサービスが、Cloud Storage や BigQuery などの Google Cloud マネージド サービスと通信する必要がある場合の一般的なパターンです。一例として、GKE でバッチジョブによって処理されたお客様の記録を、あとで分析するために BigQuery に保存する必要がある場合です。

Workload Identity を使用すると、GKE クラスタ内の Kubernetes サービス アカウントが IAM サービス アカウントとして機能します。構成された Kubernetes サービス アカウントを使用する Pod は、Google Cloud API にアクセスするときに IAM サービス アカウントとして自動的に認証されます。これは、サービスに必要なアクセスレベルが、Google Cloud サービス アカウントに付与されていることを前提としています。

クラスタ セキュリティを管理する

セキュリティは、GKE クラスタのエンタープライズ デプロイメントで非常に重要な分野で、多面的な対策が求められます。このセクションでは、クラスタのセキュリティを強化するために使用できるいくつかの要素について説明します。

イメージの脆弱性スキャン

Artifact Registry では、イメージに既知のセキュリティの脆弱性がないかスキャンできます。サポートされているイメージには、Ubuntu、Debian、RedHat などが含まれます(完全なリストについては、脆弱性ソースをご覧ください)。GKE クラスタで使用する予定のイメージをスキャンすることをおすすめします。

可能であれば、セキュリティ リスクをさらに軽減するために Container Analysis も有効にします。

イメージの脆弱性を表示するには、イメージの自動スキャンをご覧ください。

Artifact Registry リポジトリが変更されたときに、通知の追跡と受信を自動的に行うことができます。たとえば、新しいイメージが作成されたときや、画像が削除されたときに通知を受信できます。アプリケーション リスナーが登録されている Pub/Sub トピックに Artifact Registry イベントがパブリッシュされるようにパイプラインを構築できます。さらに、これらのイベントを使用してビルドまたは自動デプロイをトリガーできます。詳細については、Artifact Registry のドキュメントをご覧ください。

Binary Authorization

Kubernetes を使用して、クラスタへのイメージのデプロイが有効であると判断することと、判断するタイミングを決定する必要があります。このタスクには、Binary Authorization を使用できます。これは、イメージに必要となるクラスタにデプロイ可能な署名(証明書)に適用するワークフローを定義できるようにする、デプロイ時のコンストラクトです。

ワークフローはポリシーの観点から定義されます。CI / CD パイプラインでコードとコンテナ イメージを移動すると、Binary Authorization は Binary Authorization ポリシーの定義に従って、各ステージで証明書を記録します。これらの証明書は、定義されたマイルストーンをイメージが正常に通過していることを証明します。

Binary Authorization は GKE Deployment API と統合されており、イメージのデプロイが、必要なすべての証明書を持つイメージの対象になります。失敗したデプロイ試行は自動的にログに記録され、クラスタ管理者が確認して監査できます。

Cloud Build を使用して GKE で Binary Authorization を実装する方法のチュートリアルについては、Cloud Build と GKE を使用した Binary Authorization の実装をご覧ください。

GKE Sandbox での gVisor による安全なアクセス

コンテナによりセキュリティとカーネルの間に分離層ができますが、攻撃者がホストのオペレーティング システム(OS)へのアクセス権を取得するような侵害が発生する可能性が残されています。コンテナとホスト OS 間のセキュリティ分離でより高い復元性を実現するには、別の分離レイヤを作成します。その 1 つの方法が GKE Sandbox の使用です。

GKE Sandbox は、Google がリリースしたオープンソースのコンテナ ランタイムである gVisor を使用します。内部的には、gVisor によりコンテナと対話する仮想カーネルが作成されます。このカーネルは、コンテナによるホストカーネルへの接続を抽象化します。また、コンテナが行うことができるファイルとネットワークのオペレーションの制御も行います。

GKE Sandbox は追加の分離レイヤを作成するため、メモリと CPU のオーバーヘッドが増える可能性があります。GKE Sandbox を使用する前に、どのワークロードにこのような高度なセキュリティが必要となるかについて検討してください。通常、外部イメージに基づくサービスが良い候補になります。

GKE を有効にしてノードプールを作成する方法については、GKE Sandbox によるワークロード分離の強化をご覧ください。

監査ロギング

Kubernetes 監査ロギングでは、Kubernetes API サーバーに対するすべての API リクエストが記録されます。このロギングは、アクセスと構成設定の異常値や異常なパターンを検出するのに役立ちます。確認とアラートの対象の例としては、次のようなものがあります。

  • デプロイを削除する場合。
  • 特権アクセスのあるコンテナに接続、または exec を使用してアクセスする場合。
  • ClusterRole オブジェクトを変更するか、クラスタのロールのためにロール バインディングを作成する場合。
  • kube-system 名前空間にサービス アカウントを作成する場合。

GKE によって Kubernetes 監査ロギングが Cloud Audit LogsCloud Logging に組み込まれます。これらのログには、Cloud プロジェクトで実行されるリソースのログと同じ方法でアクセスできます。Kubernetes API サーバーに対して行われた API リクエストはログに記録され、それを使用して API アクティビティ パターンを確認できます。

Kubernetes API サーバーでキャプチャされた各リクエスト(イベント)は、定義した 1 つ以上のポリシーによって処理されます。たとえば、ログに記録するイベントを判断する Kubernetes 監査ポリシーや、管理アクティビティ ログまたはデータログに記録するイベントを判断する Google Kubernetes Engine 監査ポリシーによって処理されます。管理アクティビティ ログはデフォルトで有効になっています。クラスタ内で読み取りまたは書き込みが行われたメタデータの詳細をログに記録する場合は、データアクセス ロギングも有効にします。ただし、データアクセス ロギングを有効にすると、追加料金が発生する場合があります。詳細については、料金のドキュメントをご覧ください。

ポッドのセキュリティ ポリシー

よくある攻撃ベクトルは、Kubernetes クラスタへのアクセス権を取得するために、権限を昇格した Pod をデプロイする方法です。Gatekeeper は、Pod に許可する操作を記述したポリシーを使用するアドミッション コントローラです。これを使用して、名前空間の使用方法、ボリューム タイプの使用方法、基盤となる OS 機能に対するアクセスを制限できます。

コンテナのセキュリティに関する考慮事項

Kubernetes サービスの基本的な構成要素はコンテナです。クラスタのセキュリティとポリシーを計画する際には、コンテナのセキュリティが重要な要素になります。次の点を考慮してください。

  • コンテナを構築する元となるイメージ。
  • コンテナに割り当てる特権。
  • コンテナがホスト OS や他のサービスとやり取りする方法。
  • コンテナで機密情報にアクセスしてログに記録する方法。
  • クラスタ内のコンテナのライフサイクルを管理する方法。

詳細とベスト プラクティスについては、コンテナの構築操作に関するドキュメントをご覧ください。

ネットワークの構成

Kubernetes は、クラスタ内の Pod セット全体だけでなく、クラスタ外で走行している以前のシステムに対する負荷分散とサービス ディスカバリを含むサービスの抽象化を提供します。以下のセクションでは、Kubernetes Pod と他の Kubernetes クラスタを含む他のシステム間の通信のベスト プラクティスについて説明します。

VPC ネイティブ クラスタとルートベース クラスタの比較

GKE クラスタが Pod から別の Pod にトラフィックをルーティングする方法によって、クラスタは 2 つのタイプに分類できます。

  • トラフィックのルーティングにエイリアス IP 範囲を使用するクラスタは、VPC ネイティブ クラスタと呼ばれています。
  • Google Cloud のルートを使用するクラスタは、ルートベース クラスタと呼ばれています。

VPC ネイティブ クラスタでは、Pod ネットワークにエイリアス IP 範囲を使用します。つまり、GKE クラスタ内の各ノードの静的ルートを構成して管理する代わりに、コントロール プレーンで Pod のルーティング構成が自動的に管理されます。エイリアス IP 範囲を使用すると、個別のネットワーク インターフェースを定義せずに、VM にホストされているコンテナまたはアプリケーションを表す複数の内部 IP アドレスを構成できます。Google Cloud では、プライマリ ネットワーク インターフェースのプライマリ範囲とエイリアス IP 範囲の VPC ネットワーク ルートが自動的にインストールされます。これにより、Pod 間のトラフィック ルーティングが大幅に簡素化されます。

また、VPC ネイティブ クラスタはルート割り当の対象ではありません。クラスタ ファブリックのエイリアス IP 範囲を活用することで、Cloud Storage や BigQuery などの Google サービスに直接アクセスできます。この方法以外でアクセスできるのは、NAT ゲートウェイのみです。

これは、GKE クラスタで、アプリケーションとサービスのオンプレミス エコシステムと安全に通信するための一般的なパターンです。エイリアス IP 範囲では、Cloud VPN または Cloud Interconnect を介してエイリアス IP アドレスを検出できるため、これが許可されます。これにより、オンプレミス インフラストラクチャと Google Cloud インフラストラクチャの間の安全な接続を実現できます。

ネットワーク トポロジに最適なクラスタタイプを決定する必要があります。主な要素は、ネットワーク内の IP アドレスの可用性、企業内のクラスタ(ノード)拡張プラン、エコシステム内の他のアプリケーションとの接続です。VPC ネイティブのクラスタでは、ネットワークでより多くの IP アドレスが必要になる傾向があるため、その点を考慮する必要があります。作成後には、VPC ネイティブ クラスタをルートベースのクラスタに、ルートベースのクラスタを VPC ネイティブ クラスタに移行できないため、実装する前に自身の選択に関する影響を理解することが重要です。

コントロール プレーン アクセス用の承認済みネットワーク

承認済みネットワーク オプションを使用すると、指定した CIDR 範囲からコントロール プレーン エンドポイント(API サーバー)へのアクセスを制限し、ネットワーク内のチームのみがクラスタを管理できるようになります。

この機能には次の要件があります。

  • 指定できる CIDR 範囲は 50 個までです。
  • CI/CD パイプラインを使用している場合、CI/CD ツールがクラスタの API サーバーにアクセスできるようにするには、IP アドレスまたは CIDR 範囲を許可リストに追加する必要があります(VPC ファイアウォール ルールの概要をご覧ください)。

限定公開クラスタ

デフォルトでは、GKE クラスタ内のすべてのノードにパブリック IP アドレスが割り振られます。すべてのワーカーノードにプライベート RFC 1918 の IP アドレスのみを付与する限定公開クラスタの作成をおすすめします。限定公開クラスタはネットワーク分離を適用するので、クラスタのリスクを軽減できます。限定公開クラスタを使用すると、デフォルトでは、ネットワーク内のクライアントのみがクラスタ内のサービスにアクセスできます。外部サービスがクラスタ内のサービスに到達できるように、HTTP(S) ロードバランサまたはネットワーク ロードバランサを使用できます。

VPC ネットワークの外部にあるコントロール プレーンへのアクセスを開通する場合は、承認済みネットワークで限定公開クラスタを使用します。承認済みネットワークを有効にすると、クラスタ コントロール プレーンのエンドポイントが内部(プライベート)アドレスとパブリック アドレスの 2 つの IP アドレスを取得します。内部 IP アドレスは、同じリージョン内にある自身のネットワークへのすべての内部通信で使用されます。コントロール プレーンのパブリック IP アドレスは、ネットワークの外部にあり、許可された CIDR 範囲または IP アドレスからのすべてのユーザーまたはプロセスで使用されます。また、この機能を Cloud Interconnect または Cloud VPN と組み合わせて、プライベート データセンター内からコントロール プレーン ノードのみへのアクセスを有効にすることも可能です。

データの引き出しからの保護

また、VPC Service Controls を使用すると、データ漏洩のリスクを軽減できます。VPC Service Controls を使用すると、1 つ以上のプロジェクトでマネージド Google Cloud サービスを保護し、これらのサービスにアクセスするためのサービス境界を定義できます。これらのマネージド サービスに到達するためのアクセス権を GKE クラスタで実行するアプリケーションに付与するには、適切なアクセスレベルを設定します。また、VPC Service Controls を使用して GKE クラスタ作成コントロール プレーンを保護できます。

同一クラスタ内の通信

サービス ディスカバリ

Kubernetes では、一連のラベルに基づいて、クラスタ内で実行されているポッドをグループ化するサービスを定義できます。DNS を使用して、この Pod のグループをクラスタ内で検出できます。Kubernetes でのサービス ディスカバリの詳細については、アプリケーションとサービスの接続のドキュメントをご覧ください。

DNS

クラスタ ローカルの DNS サーバー kube-dns が各 GKE クラスタにデプロイされ、サービス名と正常な Pod の IP とのマッピングを処理します。デフォルトで、Kubernetes DNS サーバーはサービスのクラスタ IP アドレスを返します。この IP アドレスは、サービスの存続期間を通じて静的です。この IP にトラフィックを送信すると、ノード上の iptables は、サービスのセレクタに一致する準備完了状態の Pod 全体でパケットを負荷分散します。これらの iptables は、各ノードで実行する kube-proxy サービスによって自動的にプログラムされます。

kube-dns の詳細については、サービス ディスカバリと DNS をご覧ください。

パケットフロー: ClusterIP

次の図は、標準 Kubernetes サービスの DNS レスポンスとパケットフローを示しています。Pod IP アドレスはクラスタ外からルーティング可能ですが、サービスのクラスタ IP はクラスタ内でのみアクセス可能です。これらの仮想 IP アドレスは、各 Kubernetes ノードで宛先ネットワーク アドレス変換(DNAT)を行うことによって実装されます。各ノードで実行されている kube-proxy サービスが、クラスタ IP アドレスをクラスタ全体の正常な Pod IP アドレスにマップする転送ルールを、各ノードで最新の状態に維持します。ローカルノードで走行しているサービスの Pod がある場合は、その Pod が使用されます。ない場合はクラスタ内の Pod がランダムに選択されます。

クラスタ IP サービス。

ClusterIP の実装方法の詳細については、Kubernetes のドキュメントをご覧ください。

ヘッドレス サービス

サービス ディスカバリと稼働状況のモニタリングが必要な場合に、DNS サービスで仮想 IP アドレスではなく、Pod の IP アドレスが返されるようにするには、ClusterIP フィールドを None に設定して、サービスをプロビジョニングし、サービスをヘッドレスにします。

この場合、DNS サーバーが返すのは、サービスで定義されたラベルセレクタに一致する準備完了状態の Pod のレコードにサービスの DNS 名をマップするレコードのリストです。レスポンス内のレコードがローテーションし、さまざまな Pod 間への負荷の分散を容易にします。一部のクライアント側 DNS リゾルバは DNS レスポンスをキャッシュに保存するため、レコードのローテーションが無効になることがあります。ClusterIP を使用する利点は、Kubernetes のドキュメントに示されています。GKE で ClusterIP を使用する方法の詳細については、サービスを使用したアプリケーションの公開をご覧ください。

ヘッドレス サービスの典型的な使用例の一つは、StatefulSets です。StatefulSets は、レプリカ間の安定したストレージとネットワークを必要とするステートフルなアプリケーションを実行する場合に適しています。このタイプのデプロイでは、安定したネットワーク ID を持つ Pod をプロビジョニングします。つまり、クラスタ内でホスト名を解決できます。Pod の IP アドレスは変更される可能性がありますが、そのホスト名 DNS エントリは最新の状態に維持されて、解決可能になります。

ヘッドレス サービスの DNS レスポンスとトラフィック パターンの例を次に示します。Pod IP アドレスは、デフォルトの Google Cloud サブネット ルートテーブルによってルーティング可能であり、アプリケーションから直接アクセスされます。

ヘッドレス サービスの DNS レスポンスとトラフィック パターンの例。

ネットワーク ポリシー

GKE のネットワーク ポリシーの適用を使用すると、クラスタの Pod とサービス間の通信を制御できます。GKE でネットワーク ポリシーを定義するには、Kubernetes ネットワーク ポリシー API を使用して Pod レベルのファイアウォール ルールを作成します。これらのファイアウォール ルールは、クラスタ内でどの Pod とサービスが互いにアクセスできるかを決定します。

ネットワーク ポリシーを使用すると、クラスタで実行されているワークロードのセキュリティを強化できます。たとえば、アプリケーション内の不正使用されたフロントエンド サービスが数レベル下の課金サービスや会計サービスと直接通信できないようにするネットワーク ポリシーを作成することができます。

ネットワーク ポリシーを使用して、異なるテナントに属するワークロードを分離することもできます。たとえば、名前空間ごとに 1 つのテナントがあるモデルを定義することで、安全なマルチテナンシーを提供できます。このようなモデルでは、ネットワーク ポリシールールにより、特定の名前空間内の Pod やサービスが異なる名前空間内の他の Pod やサービスにアクセスできないようにすることができます。

Google Cloud の内部から GKE クラスタに接続する

クラスタの外部(ただし Google Cloud ネットワークのプライベート IP アドレス空間内)からサービスに接続するには、内部負荷分散を使用します。Kubernetes 内でサービスを作成するときに type: Load Balancercloud.google.com/load-balancer-type: Internal アノテーションを指定すると、Google プロジェクト内に内部ネットワーク ロードバランサが作成され、TCP と UDP のトラフィックを Pod 間で分散するように構成されます。

クラスタ内から外部サービスへの接続

多くの場合、Kubernetes 内で走行しているアプリケーションを、クラスタの外部にあるサービス、データベース、アプリケーションと接続する必要があります。次のセクションで説明するように、3 つのオプションがあります。

設定説明
スタブドメインKubernetes 1.6 以降では、特定のドメインの DNS クエリを外部 DNS サーバーに転送するようにクラスタ内部 DNS サービス(kube-dns)を構成できます。これは、Kubernetes Pod が使用する必要があるドメインについて、クエリを実行する優先 DNS サーバーがある場合に便利です。
外部ネームサービス外部ネームサービスを使用すると、DNS レコードをクラスタ内のサービス名にマップできます。この場合、クラスタ内サービスの DNS ルックアップでは、選択した CNAME レコードが返されます。既存の DNS サービスにマップするレコードが少ない場合は、これを使用します。
セレクタのないサービスセレクタなしでサービスを作成し、エンドポイントをそれに手動で追加して、サービス検出に正しい値を設定できます。これにより、クラスタ内サービスに対して同じサービス検出メカニズムを使用して、DNS によるサービス検出がないシステムにも確実に到達できるようにします。このアプローチは最も柔軟性がありますが、長期的に最も構成とメンテナンスを必要とします。

DNS の詳細については、Kubernetes DNS の Pod と Service のドキュメント ページをご覧ください。

インターネット トラフィックを受信するように Kubernetes でサービスを構成する

Kubernetes サービスは、NodePort、ClusterIP、および LoadBalancer を使用して公開できます。

ただし、外部向けサービスが多数ある場合は、Kubernetes Ingress リソースの使用を検討してください。Ingress はクラスタ向けのエントリ ポイントを提供し、受信リクエストをクラスタ内の 1 つ以上のバックエンド サービスにルーティングするルーティング ルールの定義を可能にします。GKE では、GKE Ingress コントローラによって Ingress リソースが Google Cloud HTTP(S) ロードバランサとして実装され、Ingress リソースとその関連サービスの情報に従って構成されます。詳細については、外部負荷分散向け Ingress の構成をご覧ください。

Kubernetes Ingress リソースは、アプリケーションが HTTP(S) 経由でトラフィックを提供する場合にのみ使用できます。バックエンド サービスが TCP または UDP プロトコルを使用している場合は、代わりにネットワーク ロードバランサを使用する必要があります。これは、データベースをサービスとして公開する必要がある場合などに、必要になることがあります。

バックエンドの構成

BackendConfig は、Kubernetes Ingress コントローラで使用される追加の指示を与える構成を提供できるカスタム リソース定義です。Ingress オブジェクトを GKE クラスタにデプロイすると、Kubernetes Ingress コントローラによって、Ingress マニフェストで指定したバックエンド サービスに、受信リクエストをルーティングする HTTP(S) ロードバランサが構成されます。

ロードバランサの構成は、次のような仕様で補完できます。

  • Cloud CDN でキャッシュを有効にする。
  • Google Cloud Armor を使用して、IP アドレスまたは CIDR 許可リストを追加する。
  • Identity-Aware Proxy(IAP)でアプリケーション レベルのアクセス制御を行う。
  • クラスタ内の Ingress オブジェクトによって管理されるサービスのサービス タイムアウトとコネクション ドレインのタイムアウトを構成する。

GKE で BackendConfig カスタム リソースを構成する方法の詳細については、Ingress の機能をご覧ください。

サービス メッシュの使用

サービス メッシュを使用すると、Kubernetes クラスタで走行しているマイクロサービスの接続、保護、管理を統一された方法で行うことができます。たとえば、GKE アドオンとして追加できる Istio サービス メッシュを使用すると、サービス間認証と通信の管理、アクセス ポリシーの適用、GKE クラスタの監査と管理に使用できるリッチなテレメトリー データポイント収集を行うことができます。

サービス メッシュの主な特徴は、次のとおりです。

  • トラフィック管理。サービス メッシュでは、トラフィックをサービス間または同じサービスの異なるバージョン間でルーティングして分割する方法を決定する詳細なルールを定義できます。これにより、カナリア デプロイと Blue/Green デプロイのロールアウトが容易になります。

  • 組み込みのオブザーバビリティ。メッシュは、サービスをインストルメント化するためにコードを記述する必要がなくても、ネットワーク トラフィック(レイヤ 4 とレイヤ 7)の指標を統一された方法で記録します。

  • セキュリティ。メッシュにより、サービス間の相互 TLS(mTLS)が有効になります。転送中のデータのための安全なチャネルが提供されるだけでなく、メッシュ内のサービスの認証と認可も管理できます。

まとめると、Istio などのサービス メッシュを使用すると、システムレベルのタスクをメッシュ インフラストラクチャに委任できます。これにより、Kubernetes クラスタで走行しているサービスの全体的なアジリティ、堅牢性、疎結合が改善されます。

Anthos でのサービス メッシュの使用については、Anthos Service Mesh についてをご覧ください。

ファイアウォール

GKE ノードは Compute Engine にインスタンスとしてプロビジョニングされます。そのため、他のインスタンスと同じステートフルなファイアウォール メカニズムに従います。これらのファイアウォール ルールはタグを使用して、ネットワーク内でインスタンスに適用されます。各ノードプールは、ルールで使用できる独自のタグセットを受け取ります。デフォルトでは、ノードプールに属する各インスタンスは、このノードプールが属する特定の Kubernetes Engine クラスタを識別するタグを受け取ります。このタグは、Kubernetes Engine が自動的に作成するファイアウォール ルールで使用されます。クラスタまたはノードプールの作成時に、gcloud ツールで --tags フラグを使用して、独自のカスタムタグを追加できます。

たとえば、内部ロードバランサがすべてのノードのポート 8080 にアクセスできるようにするには、次のコマンドを使用します。

gcloud compute firewall-rules create allow-8080-fwr \
    --target-tags allow-8080 \
    --allow tcp:8080 \
    --network gke \
    --source-range 130.211.0.0/22
gcloud container clusters create my-cluster --tags allow-8080

次の例では、あるクラスタにタグを付けてインターネット トラフィックがポート 30000 上のノードにアクセスできるようにする一方、他のクラスタには VPN からポート 40000 へのトラフィックを許可するタグを付けています。これは、VPN などの特権ネットワークを使用してのみ、会社のデータセンターにアクセスできるようにするか、プロジェクト内の別のクラスタからアクセスできるようにする必要のあるサービスを NodePort によって公開する場合に便利です。

2 つのクラスタに異なるタグを付ける。

オンプレミスのデータセンターへの接続

オンプレミスのデータセンターへの接続には、Cloud Interconnect または Cloud VPN を使用できます。これらのオプションは相互に排他的ではないため、ワークロードと要件に基づいて組み合わせることができます。以下のオプションがあります。

  • Dedicated Interconnect を使用すると、ネットワーク間で大量のデータを低レイテンシで転送できます。

  • データセンターが Dedicated Interconnect コロケーション施設内にない場合は、Partner Interconnect を使用します。Google は世界各地のサービス プロバイダに接続する 100 を超える PoP(接続拠点)を提供しています。

  • 専用の帯域幅を必要とし、レイテンシによる影響を受けやすく、Google Workspace とサポート対象の Google API にアクセスする必要があるワークロードには、ダイレクト ピアリングを使用します。ダイレクト ピアリングは BGP ルートの交換によって行われるレイヤ 3 接続であるため、登録済みの ASN が必要です。

  • 登録済みの ASN がない場合や、優先サービス プロバイダとの関係がすでにある場合は、キャリア ピアリングを使用します。キャリア ピアリングは、サービス プロバイダを通じて行われることを除けば、ダイレクト ピアリングと同じです。

  • IPSec 暗号化が必要な場合、またはプライベート ネットワークをプライベート Compute Engine ネットワークに拡張する場合は、Cloud VPN を使用します。Cloud VPN は、レイヤ 3 相互接続とインターネット オプション(1、2、3)で構成します。

クラスタの操作性の管理

このセクションでは、GKE クラスタの管理や運用を行う際に考慮すべき重要な要素について説明します。

リソースの割り当て

Kubernetes リソースの割り当ては、クラスタ内の各 Namespace で許容されるリソース使用量の合計を制限する制約を提供します。ビジネス機能または開発ステージを分離する Kubernetes Namespace を持つクラスタがある場合、割り当てを使用して、CPU 使用率、メモリ、名前空間内に作成できる Pod とサービスの数など、リソースの広い配列を制限できます。GKE クラスタのコントロール プレーンの安定性を確保するため、5 ノード以下の GKE クラスタ内の各 Namespace に、オーバーライドできないデフォルトのリソース割り当てが自動的に適用されます。

リソースの上限

Kubernetes の LimitRange オブジェクトを使用すると、コンテナと Pod を作成できる最小リソースまたは最大リソースの境界にきめ細かい制約を適用できます。次の例は、LimitRange の使用方法を示しています。

apiVersion: v1
kind: LimitRange
metadata:
  name: sample-limits
spec:
  limits:
    - max:
        cpu: "400m"
        memory: "1Gi"
      defaultRequest:
        cpu: "200m"
        memory: "500Mi"
      type: Container

Pod 停止予算

Pod 停止予算(PDB)を使用すると、チームによる Pod やデプロイの自発的な削除や、偶発的な削除を防ぐことができます。PDB は、ノードの停止や再起動が原因の意図しない中断を防ぐことはできません。通常、オペレーターはアプリケーションのために Pod のレプリカの最低数を定義するアプリケーション用の PDB を作成します。

デベロッパーによって複数のアプリケーションが運用されている企業ではミスが起こり、デベロッパーまたは管理者が、Pod やデプロイを削除する、つまり、Kubernetes リソースを削除するスクリプトを誤って実行する可能性があります。しかし、PDB を定義することで、Kubernetes アプリケーションに最小限の必要なリソースセットを常時維持できるようになります。

GKE クラスタに構成する PDB は、GKE のアップグレード中に適用されます。つまり、アップグレード中もアプリケーションの可用性を制御できます。次の例は、PDB の構成方法を示しています。

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: nginx-pdb
  spec:
    minAvailable: 4
    selector:
      matchLabels:
        app: nginx

Kubernetes のアップグレードの管理

GKE 上の Kubernetes クラスタは、要件を満たす Kubernetes の最新バージョンにしておきます。コントロール プレーンやノードを自動的にアップグレードするか、自分でアップグレードを制御するかを選択できます。

アップグレードの通知は、コンソールの Anthos のセキュリティ情報、およびクラスタのアップグレード通知で確認できます。ノードを手動でアップグレードする場合は、リリース コンテンツを確認し、アップグレード対象のバージョンで稼働中のサンドボックス クラスタ内でアプリケーションをテストしてから、バージョンのアップグレードをトリガーすることをおすすめします。

ゾーンクラスタのコントロール プレーンは、アップグレードの進行中は使用できません。つまり、API サーバーとやり取りして、クラスタ内のリソースを追加または削除することはできません。コントロール プレーンのアップグレードによるダウンタイムが許容できない場合は、代わりにリージョン GKE クラスタをデプロイすると、コントロール プレーンの可用性を向上させることができます。この方法により、ゾーン全体に分散する複数のコントロール プレーンを持つことができます。一方のコントロール プレーンがアップグレードされると、API サーバーへのコントロール プレーン リクエストはどれも、もう一方のコントロール プレーンにルーティングされます。

アップグレードが適用されると、GKE はワーカーノードにローリング アップデートを適用します。新しい置換ノードが受信リクエストへの応答に使用可能になると、ローリング アップグレードはノードを系統的にドレインして停止させ、1 回に 1 つのノードをアップグレードします。

ノードの自動修復

GKE ノードの自動修復機能では、GKE ノードのヘルスチェックを管理します。いずれかのノードで異常が見つかった場合、GKE でノードの修復プロセスが開始されます。

GKE クラスタに複数のノードプールがある場合は、自動修復機能を使用すると、ノードの自動修復を有効にするノードプールをきめ細かく制御できます。

GKE クラスタの自動スケーリング

企業は多くの場合、Kubernetes クラスタで走行しているアプリケーション上で、変化する受信読み込みを経験します。これらのビジネス主導の変化に対応するために、GKE クラスタで自動的に対応を行い、指標に基づいてスケールアップとスケールダウンを行うことができます。

次のセクションで説明するように、自動スケーリングには、複数の特徴があります。

クラスタ オートスケーラー

GKE クラスタ オートスケーラーは、ワークロードの需要に応じて、クラスタのノードを自動的に追加または削除します。クラスタ オートスケーラーは、個々のノードプールに対して有効になっています。GKE は、各ノードプールで容量不足のためにスケジューリング待ちになっている Pod があるかどうか確認します。このような Pod がある場合、クラスタ オートスケーラーはノードプールにノードを追加します。

クラスタ オートスケーラーは、リソース リクエストに基づいてスケールダウンまたはスケールアップを行います。ノードが十分に活用されておらず、実行中の Pod が容量のある他のノードでスケジュールされる場合、使用率の低いノードはドレインされ、終了します。

クラスタ オートスケーラーでスケーリングできる最小と最大ノードのノード数を指定することにより、ノードプールの境界を設定できます。

ノードの自動プロビジョニング

ノード自動プロビジョニングを使用すると、GKE クラスタ オートスケーラーは、追加のノードプールが必要であると判断したときに、自動的に追加のノードプールをプロビジョニングできます。クラスタ オートスケーラーは、ノードプールにノードがなくなったときに、自動プロビジョニングされたノードプールを削除できます。

ノードの自動プロビジョニングの決定は、いくつかの要因に基づいて GKE クラスタ オートスケーラーによって行われます。この要因には、Pod によって要求されたリソースの量、指定した Pod アフィニティ、GKE クラスタで定義された node taints と tolerations が含まれます。

ノードの自動プロビジョニングは、GKE クラスタでさまざまなワークロードが実行される場合に役立ちます。たとえば、GKE クラスタに GPU を利用するワークロードがある場合、GPU 対応ノードでプロビジョニングされた専用のノードプールでこのワークロードを実行できます。ノードプールのスケーリング境界を定義するには、ノードプールの最小サイズと最大サイズを指定します。

ノード自動プロビジョニングの詳細と有効にする場合については、ノードの自動プロビジョニングの使用をご覧ください。

水平ポッド自動スケーリング

Kubernetes では、水平ポッド自動スケーリングを作成できます。これにより、Kubernetes の Deployment または ReplicaSet のスケーリング方法と、どの指標に基づきスケーリングを決定するかを構成できます。デフォルトでは、水平ポッド自動スケーリング コントローラは CPU 使用率に関する自動スケーリングの決定を基準としています。ただし、水平ポッド自動スケーリング コントローラは、HTTP リクエストの数など、カスタム指標に基づいて Pod をスケーリングする方法を計算できます。水平ポッド自動スケーリングがカスタム指標に応答するためには、通常、追加のモニタリング インストルメンテーションが必要です。

詳細については、KubernetesGKE のドキュメントをご覧ください。

垂直 Pod 自動スケーリング

GKE クラスタの垂直 Pod 自動スケーリング機能を使用すると、コンテナ用の最適な CPU とメモリ要求を特定するタスクから解放されます。必要に応じて、垂直 Pod 自動スケーリングはクラスタ内のコンテナに対するリソースの割り当てを調整します。垂直 Pod 自動スケーリングは、ノードごとにコンテナレベルで最適化することにより、クラスタに対するリソースの利用を最適化します。また、VPA を使用することで、リソースの維持に必要だった管理の時間から解放されます。

垂直 Pod 自動スケーリングは、次のセクションで説明するノード自動プロビジョニング機能と連携して動作します。

Kubernetes の制限により、Pod のリソース リクエストを変更するには Pod の再起動が必要です。このため、変更する場合は、垂直 Pod 自動スケーリングによって Pod が強制排除されます。詳細については、GKEKubernetes のドキュメントをご覧ください。

Autopilot

Autopilot とは、GKE がユーザーに代わってクラスタの基盤となるインフラストラクチャをプロビジョニングして管理することを意味します。Autopilot では、次のような項目が管理されます。

  • ノードとノードプール

  • リソースのプロビジョニング

  • ノードイメージのタイプ

  • クラスタの種類や CIDR 範囲などのネットワーク機能

  • Workload Identity や Shielded VM などのセキュリティ機能

Autopilot は、運用上の負荷を軽減する必要があり、より複雑なワークロードのために特定のアイテムを構成する機能を必要としない場合に役立ちます。

次のステップ

  • クラスタのセキュリティを強化するためのベスト プラクティスの詳細を確認する。

  • コンテナの構築操作のベスト プラクティスについて学習する。

  • このチュートリアルで、Istio を使用して Cloud Run on GKE でエンドユーザーの認証を行う方法について学習する。

  • Google Cloud に関するリファレンス アーキテクチャ、図、チュートリアル、ベスト プラクティスについて確認する。Cloud Architecture Center を確認します。