本番環境での Kubernetes Engine の準備

このソリューションは、安全性、信頼性、および費用対効果の高い方法でワークロードを Kubernetes Engine に展開するためのブループリントと方法を提供します。クラスタへの管理アクセスおよびネットワーク アクセスを構成するためのガイダンスを提供します。この記事では、Kubernetes リソースとクラスタ管理について実践的に理解し、Google Cloud Platform(GCP)ネットワーク機能に精通していることを前提としています。

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

次の図は、プロジェクト、ネットワーク、リージョン、サブネットワーク、ゾーン、クラスタの最適な構造を示しています。

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

プロジェクト

GCP はプロジェクト エンティティ内にそのすべてのリソースを作成します。プロジェクトは課金単位であり、管理者は IAM の役割をユーザーに関連付けることができます。役割は、プロジェクト レベルで適用されると、プロジェクト内にカプセル化されたすべてのリソースに適用されます。プロジェクトを使用して、さまざまなオペレーティング環境をカプセル化する必要があります。たとえば、オペレーション チーム向けに本番ステージングのプロジェクトを、さらに開発者向けにテスト開発プロジェクトを設定できます。最もミッション クリティカルで機密性の高いデータとワークロード(つまり本番環境)を保持するプロジェクトには、より詳細で厳格なポリシーを適用しながら、テスト開発環境の開発者には、実験のための制限が緩やかで柔軟なポリシーを適用することができます。

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

各プロジェクトには、ネットワークとサブネットワークが含まれます。ネットワーク リソースは、サブネットワーク、外部 IP アドレス、ファイアウォール ルール、ルート、VPN、Cloud Router などのその他のリソースをまとめて保持します。GCP では、パフォーマンスと構成の簡素化のため、ネットワークが複数のリージョンにまたがる場合があります。サブネットワークは、Kubernetes Engine クラスタ間の各リージョンに出入りするトラフィックを分離して制御する柔軟性を提供します。デフォルトで、プロジェクトにはネットワークが作成されますが、既存の IP アドレス管理(IPAM)規則にマップする独自のネットワークを作成して構成することをおすすめします。 さらに、このネットワークでファイアウォール ルールを適用して、Kubernetes Engine ノードに出入りするトラフィックをフィルタできます。デフォルトでは、Kubernetes Engine ノードへのすべてのインターネット トラフィックが拒否されます。

サブネットワークは複数のゾーンにまたがることができますが、リージョンをまたがることはできません。サブネットワーク間の通信を制御するには、トラフィックがそれらを通過できるようにするファイアウォール ルールを作成する必要があります。ファイアウォール ルールを有効にするには、クラスタまたはノードプールの作成時に --tags フラグを使用して、Kubernetes Engine ノードに適切なタグを付けます。ファイアウォールに加えて、タグを使用して、カスタム サブネットワーク間のルートを作成することもできます。自動モード サブネットワークでは、サブネット間のルーティングがデフォルトで有効になっており、カスタム サブネットワークでは手動でルートを作成する必要があります。

ID とアクセスの管理

プロジェクト レベルのアクセス

前のセクションで、プロジェクト レベルで IAM の役割をユーザーにバインドできることを説明しました。個々のユーザーに役割を付与するだけでなく、グループを使用して、役割の適用を簡単にすることもできます。

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

ID とアクセスの管理

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

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

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

dev プロジェクトには、同じクラスタ内の同じアプリケーションを操作する複数の開発者がいます。これは、クラスタ ユーザーが作成できる名前空間によって容易になります。各開発者は、独自の名前空間内にリソースを作成できるため、名前の競合が避けられます。また、同じ YAML 構成ファイルをデプロイに再利用できるので、開発の繰り返し時に可能な限り同じ構成が維持されます。名前空間を使用して、クラスタ内の CPU、メモリ、ストレージの使用の割り当てを作成して、1 人の開発者が使用するクラスタ内のリソースが多すぎないようにすることもできます。次のセクションでは、特定の名前空間内でオペレーションするようにユーザーを制限する方法について説明します。

RBAC 認証

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

RBAC により、クラスタ管理者は、クラスタ内の個々の名前空間またはクラスタ全体に詳細なポリシーを適用します。Kubernetes コマンドライン インターフェース kubectl は、gcloud ツールからのアクティブな資格情報を使用して、クラスタ管理者が RoleBindings のサブジェクトとして GCP ID(ユーザーやサービス アカウント)に役割をマップできるようにします。

たとえば、下の図では、user-auser-b の 2 人のユーザーがいて、これらのユーザーには、app-a 名前空間への config-readerpod-reader の役割が付与されています。

RBAC 認証

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

IAM 役割バインディング

Kubernetes にはデフォルトの役割がいくつか含まれていますが、クラスタ管理者は組織のニーズにより密接に対応する独自の役割を作成できます。以下は、delete 動詞が含まれていないため、ユーザーが ConfigMaps を表示、編集、更新のみ可能で、削除することはできない役割の例です。

kind:Role
apiVersion: rbac.authorization.k8s.io/v1beta1
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/v1beta1
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 の詳細については、Kubernetes Engine のドキュメントをご覧ください。

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

Container Registry のイメージは、Cloud Storage に格納されています。このセクションでは、イメージを共有する 2 つの方法について説明します。1 つはイメージを公開すること、もう 1 つはプロジェクト間でイメージを共有することです。

イメージの公開

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

プロジェクト間でのイメージへのアクセス

Kubernetes ノードにサービス アカウントを使用させることで、プロジェクト間でコンテナ イメージを共有できます。プロジェクトに関連付けられるデフォルトのサービス アカウントの形式は [PROJECT_ID]-compute@developer.gserviceaccount.com です。この識別子を用意したら、Container Registry を使用するプロジェクトに関する storage.viewer としてアクセス権を付与できます。ただし、デフォルトでプロジェクト全体へのエディタ アクセス権を持っているので、権限が制限されたカスタム サービス アカウントを使用します。

クラスタに別のサービス アカウントを使用するには、クラスタまたはノードプールの作成時に --service-account フラグを使用してサービス アカウントを指定します。たとえば、プロジェクト my-project で gke-sa サービス アカウントを使用するには、次のように指定します。

gcloud container clusters create west --service-account \
  gke-sa@my-project.google.com.iam.gserviceaccount.com

ネットワークの構成

Kubernetes は、クラスタ内の一連のポッド間に加えて、クラスタ外で実行されているレガシー システムに対しても、負荷分散とサービス検出を提供するサービス抽象化を行います。以下のセクションでは、Kubernetes ポッドと他の Kubernetes クラスタを含む他のシステム間の通信のベスト プラクティスについて説明します。

同じクラスタ内の通信

サービス ディスカバリ

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

DNS

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

サービス検出と稼働状況モニタリングが必要な場合でも、DNS サービスで仮想 IP の代わりにポッドの IP が返されるようにするには、ClusterIP フィールドを「None」に設定して、サービスをプロビジョニングできます。これにより、サービスがヘッドレスになります。この場合、サービスで定義されたラベルセレクタに一致する準備完了状態のポッドの A レコードにサービスの DNS 名をマップする A レコードのリストを DNS サーバーが返します。レスポンス内のレコードがローテーションし、さまざまなポッド間への負荷の分散を容易にします。一部のクライアント側 DNS リゾルバは DNS レスポンスをキャッシュするため、A レコードのローテーションが無効になることがあります。ClusterIP を使用する利点は、Kubernetes のドキュメントのここに示されています。

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

パケットフロー: ClusterIP

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

クラスタ IP サービス

サービス IP の実装方法の詳細については、Kubernetes のドキュメントを参照してください。Kubernetes Engine のネットワーキングの詳細については、YouTube の Next 2017 の講演をご覧ください。

ヘッドレス サービス

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

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

GCP 内部から Kubernetes Engine クラスタへの接続

クラスタの外部から(ただし GCP ネットワークのプライベート IP 空間内から)サービスに接続するには、内部負荷分散を使用する必要があります。クラスタの外部からサービスに到達できるようにするには、NodePort を使用してサービスを公開する必要があります。

内部ロードバランサの使用

このサービスタイプでは、Kubernetes がすべてのクラスタノードにクラスタの外部からサービスにアクセスするために使用できるポートを割り当てます。すべての Kubernetes Engine ノードはインスタンス グループのメンバーであるため、それを内部ロードバランサのバックエンド サービスとして使用できます。このインスタンス グループにはすべてのクラスタノードが含まれ、クラスタのスケーリングやアップグレードに合わせて最新の状態に保たれます。内部ロードバランサのクライアントは、クラスタと同じリージョンになければなりません。ローカル ネットワークからのトラフィックがサービスにアクセスできないようにするには、入力ファイアウォール ルールをノードに適用します。

内部ロードバランサへの接続はまず、構成されたセッション アフィニティに基づいて、クラスタ内のいずれかのノードに到達します。kube-proxy プロセスは、サービスの準備完了ポッドにトラフィックを転送できる最新の iptables ルールセットを保持します。サービスラベル セレクタに一致する準備完了ポッドがない場合、隣接ノード上のポッドにトラフィックを送信します。

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

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

スタブドメイン

Kubernetes 1.6 以降では、特定のドメインの DNS クエリを外部 DNS サーバーに転送するようにクラスタ内部 DNS サービス(kube-dns)を構成できます。これは、Kubernetes ポッドが使用する必要があるドメインについて、クエリを実行する優先 DNS サーバーがある場合に便利です。

外部ネームサービス

外部ネームサービスを使用すると、DNS レコードをクラスタ内のサービス名にマップできます。この場合、クラスタ内サービスの DNS ルックアップでは、選択した CNAME レコードが返されます。既存の DNS サービスにマップするレコードが少ない場合は、これを使用するとよいでしょう。

セレクタのないサービス

セレクタなしでサービスを作成し、エンドポイントをそれに手動で追加して、サービス検出に正しい値を設定できます。これにより、クラスタ内サービスに対して同じサービス検出メカニズムを使用して、DNS によるサービス検出がないシステムにも確実に到達できるようにします。このアプローチは最も柔軟性がありますが、長期的に最も構成とメンテナンスを必要とします。

DNS の詳細については、Kubernetes DNS ポッドおよびサービスのドキュメント ページを参照してください。

インターネットからクラスタへのトラフィックの受信

インターネットからトラフィックを Kubernetes で実行されているサービスに送信するには、2 つの方法、つまりネットワーク負荷分散または HTTP 負荷分散を使用します。

Kubernetes サービスは、外部 TCP / UDP 負荷分散のための LoadBalancer タイプとして作成する必要があります。Kubernetes は GCP プロジェクト内にネットワーク ロードバランサを作成し、それを Kubernetes Engine クラスタのノードにマップします。これは、最小構成で TCP および UDP ワークロードの負荷分散を行う簡単な方法です。ネットワーク ロードバランサはリージョンで範囲指定されているため、同じリージョン内で実行しているポッドに対してのみトラフィックを分散できます。

us-west1 リージョンでのネットワーク ロードバランサ

HTTP(S) 負荷分散の場合は、単一のエニーキャスト IP アドレスを使用して複数のリージョンにトラフィックを負荷分散できる Google のグローバル HTTP(S) ロードバランサを利用する必要があります。Kubernetes では、ホスト名とパスをクラスタ内のサービスにマップできる受信リソースを作成できます。受信が正しく動作するためには、type: NodePort でサービスが作成されている必要があります。

複数リージョンにわたる負荷分散

ファイアウォール

Kubernetes Engine ノードは Compute 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 オプションはいくつかあります。これらのオプションは相互に排他的ではないため、ワークロードと要件に基づいて組み合わせることができます。

  1. 大量のデータを使用することがなく、レイテンシの影響も大きくないワークロード用にインターネット。Google は世界各地のサービス プロバイダに 100 を超える PoP(接続拠点)を提供しています。
  2. 専用の帯域幅を必要とし、レイテンシの影響が大きく、GCP の全プロダクトを含むすべての Google サービスにアクセスするワークロード用のダイレクト ピアリング。ダイレクト ピアリングは BGP ルートの交換によって行われるレイヤ 3 接続であるため、登録された ASN が必要です。
  3. Carrier Interconnect はダイレクト ピアリングと同じですが、サービス プロバイダを通じて行われます。これは、登録された ASN がない場合や、優先するサービス プロバイダとの既存の関係がある場合に適したオプションです。
  4. Cloud VPN は、IPsec 暗号化が必要な場合、またはプライベート ネットワークをプライベート Compute Engine ネットワークに拡張する場合に、レイヤ 3 相互接続とインターネット オプション(1、2、3)で構成します。

次のステップ

  • Google Cloud Platform のその他の機能を試すには、チュートリアルをご覧ください。
このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...