このチュートリアルでは、Anthos Service Mesh と Cloud Load Balancing を組み合わせて、サービス メッシュ内のアプリケーションをインターネット クライアントに公開する方法について説明します。
Anthos Service Mesh は Istio をベースにしたマネージド サービス メッシュで、セキュリティが強化された、観測可能で標準化された通信レイヤをアプリケーションに提供します。Anthos Service Mesh、Traffic Director、Istio のいずれを使用する場合でも、サービス メッシュは、メッシュ内で通信しているクライアントに包括的な通信プラットフォームを提供します。ただし、メッシュ外にあるクライアントをメッシュ内でホストされているアプリケーションに接続する方法は課題にあります。
アプリケーションは、クライアントの場所に応じてさまざまな方法でクライアントに公開できます。このチュートリアルでは、ロードバランサをサービス メッシュと統合するために Cloud Load Balancing と Anthos Service Mesh を組み合わせることにより、アプリケーションをクライアントに公開する方法について説明します。このチュートリアルは、Anthos Service Mesh を実行する上級者を対象としていますが、取り扱う内容は Istio on Google Kubernetes Engine に対しても有効です。
Mesh Ingress ゲートウェイ
Istio 0.8 では Mesh Ingress ゲートウェイが導入されました。これは、サービス メッシュ外からのトラフィックに公開されるポートの専用プロキシを提供します。これらのメッシュの上りプロキシでは、アプリケーションのルーティング動作とは別に L4 の露出動作を制御できます。このプロキシでは、アプリケーション サイドカーに到達する前に、メッシュ外部トラフィックにルーティングとポリシーを適用することもできます。Mesh Ingress は、メッシュ内のノードに到達した際のトラフィック処理を定義しますが、外部コンポーネントはトラフィックが最初にメッシュに到着する方法を定義する必要があります。
この外部トラフィックを管理するには、メッシュ外のロードバランサが必要です。このチュートリアルでは、GKE Ingress リソースを通じてプロビジョニングされた Google Cloud Load Balancing を使用して、デプロイを自動化します。この設定の標準的な例は、(Google Cloud の場合は)公開 TCP/UDP ロードバランサをデプロイする外部負荷分散サービスです。このロードバランサは、GKE クラスタの NodePort を参照します。これらの NodePort は、下流のメッシュ サイドカー プロキシにトラフィックをルーティングする Istio Ingress ゲートウェイ ポッドを公開します。次の図は、このトポロジを示しています。内部プライベート トラフィックの負荷分散は、内部 TCP/UDP ロードバランサをデプロイする点を除いて、このアーキテクチャと類似しています。
Mesh Ingress ゲートウェイで L4 の負荷分散を使用すると、次のような利点があります。
- この設定により、ロードバランサのデプロイが簡略化されます。
- ロードバランサは、クラスタの変更、ノードの停止、プロセス停止が発生したときに、安定した仮想 IP(VIP)、ヘルスチェック、信頼性の高いトラフィック分散を提供します。
- すべてのルーティング ルール、TLS 終端、トラフィック ポリシーは、Mesh Ingress ゲートウェイの 1 つの場所で処理されます。
GKE Ingress とサービス
クラスタ外部のクライアントには、さまざまな方法でアプリケーションへのアクセスを提供できます。次の表に、Google Cloud のロードバランサのデプロイに使用できる Kubernetes のプリミティブを示します。アプリケーションをクライアントに公開するために使用すべきロードバランサの種類は、主に次のような点によって決まります: クライアントが外部か内部か、どのようなプロトコルのサポートが必要か、サービス メッシュが複数の GKE クラスタにまたがるか、または単一のクラスタに含まれているか。
次の表に示すロードバランサのタイプはすべて、ユースケースに応じてメッシュでホストされているアプリケーションを公開できます。
GKE リソース | クラウドベースのロードバランサ | 特性 |
---|---|---|
外部 HTTP(S) ロードバランサの Ingress | 外部 HTTP(S) ロードバランサ |
Google エッジ接続拠点(PoP)の L7 プロキシ パブリック VIP グローバル スコープ 単一クラスタ |
内部 HTTP(S) ロードバランサの Ingress | 内部 HTTP(S) ロードバランサ |
Virtual Private Cloud(VPC)ネットワーク内の L7 プロキシ プライベート VIP リージョン スコープ 単一クラスタ |
外部 LoadBalancer サービス |
ネットワーク ロードバランサ |
Google エッジ接続拠点での L4 パススルー パブリック VIP リージョン スコープ 単一クラスタ |
内部 LoadBalancer サービス |
内部 TCP / UDP ロードバランサ |
VPC ルーティング ネットワークの L4 パススルー プライベート VIP リージョン スコープ 単一クラスタ |
複数クラスタ Ingress(複数クラスタ、外部 Ingress) | 外部 HTTP(S) ロードバランサ |
Google エッジ接続拠点の L7 プロキシ パブリック VIP グローバル スコープ 複数クラスタ |
Anthos Service Mesh のデフォルトのロードバランサは外部 TCP/UDP ロードバランサですが、このチュートリアルでは、外部 HTTP(S) ロードバランサを中心に説明します。外部 HTTP(S) ロードバランサは、Identity-Aware Proxy(IAP)、Google Cloud Armor、Cloud CDN などのエッジサービスと、グローバルに分散されたエッジプロキシのネットワークと統合します。次のセクションでは、2 つのレイヤからなる HTTP 負荷分散を使用する際のアーキテクチャとメリットについて説明します。
Cloud Ingress と Mesh Ingress
Mesh Ingress レイヤとともに外部 L7 負荷分散をメッシュ外にデプロイすると、特にインターネット トラフィックに大きなメリットがあります。Anthos Service Mesh と Istio Ingress ゲートウェイはメッシュ内の高度なルーティングとトラフィック管理を提供しますが、一部の機能はネットワークのエッジで提供されます。Google Cloud の外部 HTTP(S) バランサを介したインターネット エッジ ネットワークを活用すると、メッシュベースの Ingress よりも、パフォーマンス、信頼性、セキュリティ関連の大きな利点が得られます。これには、次のような利点があります。
- グローバルなエニーキャスト VIP 広告と、グローバルに分散された TLS と HTTP 終端
- Google Cloud Armor を使用してエッジで DDoS 防御とトラフィック フィルタリング
- IAP による API ゲートウェイ機能
- Google マネージド証明書を使用したによる公開証明書の自動作成とローテーション
- 複数クラスタ Ingress を使用したエッジでのマルチクラスタおよびマルチリージョンの負荷分散
この L7 負荷分散の外部レイヤは、Mesh Ingress で使用されるセルフホストのプロキシではなく、クラウド管理ロードバランサ上に構築されるため、「Cloud Ingress」と呼ばれます。Cloud Ingress と Mesh Ingress を組み合わせる場合、Google Cloud インフラストラクチャとメッシュの補完機能を活用します。次の図は、Cloud Ingress と Mesh Ingress を組み合わせて、インターネット トラフィックの 2 つの負荷分散レイヤとして機能する方法を示しています。
このトポロジでは、Cloud Ingress レイヤがサービス メッシュの外部からのトラフィックを参照し、そのトラフィックを Mesh Ingress レイヤに転送します。その後、この Mesh Ingress レイヤはメッシュでホストされるアプリケーション バックエンドにトラフィックを転送します。
Cloud Ingress と Mesh Ingress のトポロジ
このセクションでは、各 Ingress レイヤを一緒に使用するときに補完する役割について説明します。これらの役割は詳細なルールではなく、各レイヤのメリットを使用するガイドラインです。このパターンのバリエーションは、ユースケースによって異なります。
- Cloud Ingress。Mesh Ingress レイヤと組み合わせて使用する場合、Cloud Ingress レイヤはエッジ セキュリティとグローバル負荷分散に最適です。Cloud Ingress レイヤには DDoS 対策、クラウド ファイアウォール、認証、暗号化サービスがエッジにおいて統合されているため、このレイヤはメッシュ外で上記サービスを実行することに優れています。ルーティング ロジックは通常、このレイヤで比較的単純ですが、マルチクラスタ環境やマルチリージョン環境では、ロジックがより複雑になる可能性があります。インターネットに接続するロードバランサの重要な機能のため、Cloud Ingress レイヤはインフラストラクチャ チームが管理します。このチームはインターネット上でのアプリケーションの公開方法や保護方法について独占的に制御します。この制御により、このレイヤはデベロッパー主導のインフラストラクチャよりも柔軟性や動的性能が低くなります。このことは、このレイヤへの管理者アクセスを提供する対象と提供方法に影響する可能性があります。
- Mesh Ingress。Cloud Ingress と組み合わせて使用する場合、Mesh Ingress レイヤはアプリケーションに近い柔軟なルーティングを可能とします。このような柔軟性があるため、複雑なルーティング ロジックやアプリケーション レベルの可視性のために、Mesh Ingress は Cloud Ingress より優れています。Ingress レイヤを分離することで、アプリケーション オーナーは他のチームに影響を与えずにこのレイヤを直接制御できます。L7 ロードバランサの代わりに L4 ロードバランサを介してサービス メッシュ アプリケーションを公開する場合、アプリケーションを保護するために、メッシュ内の Mesh Ingress レイヤでクライアント TLS を終了する必要があります。
ヘルスチェック
L7 負荷分散の 2 つのレイヤを使用する複雑さの 1 つは、ヘルスチェックです。各ロードバランサを構成して、次のレイヤの健全性を確認して、トラフィックを受信できるようにする必要があります。次の図のトポロジは、Cloud Ingress によって Mesh Ingress プロキシのヘルスチェックを行う方法と、返されたメッシュでアプリケーション バックエンドの健全性を確認する方法を示しています。
このトポロジの考慮事項は次のとおりです。
- Cloud Ingress。このチュートリアルでは、Ingress で Google Cloud ロードバランサを構成し、公開されたヘルスチェック ポートで Mesh Ingress プロキシの健全性を確認します。メッシュ プロキシがダウンしている場合、またはクラスタ、メッシュ、リージョンが利用できない場合、Google Cloud ロードバランサはこの状態を検出し、メッシュ プロキシにトラフィックを送信しません。
- Mesh Ingress。メッシュ アプリケーションでは、バックエンドでヘルスチェックを直接実行し、負荷分散とトラフィック管理をローカルで実行できます。
セキュリティ
前述のトポロジにはいくつかのセキュリティ要素が含まれます。最も重要な要素の 1 つは、暗号化の構成と証明書のデプロイです。外部 HTTP(S) ロードバランサの Ingress は、Google マネージド証明書と緊密に統合されています。この統合により、公開証明書が自動的にプロビジョニングされ、ロードバランサに紐づけられ、宣言型 GKE Ingress インターフェースを通じて証明書の更新とローテーションが行われます。インターネット クライアントは、公開証明書に対する認証を行い、Virtual Private Cloud(VPC)の最初のホップとして外部ロードバランサに接続します。
Google Front End(GFE)と Mesh Ingress プロキシの間にあるネクストホップは、デフォルトで暗号化されます。GFE とバックエンド間のネットワーク レベルの暗号化は自動的に適用されます。ただし、セキュリティ要件によって、プラットフォーム オーナーが暗号鍵の所有権を保持していると判断された場合、クラスタ Ingress(GFE)と Mesh Ingress(Envoy プロキシ インスタンス)の間で TLS 暗号化による HTTP/2 を有効にできます。このパスで TLS 暗号化による HTTP/2 を有効にすると、GFE は認証されないため、自己署名証明書または公開証明書を使用してトラフィックを暗号化できます。暗号化の追加レイヤについては、このガイドで説明します。証明書の誤処理を防ぐため、パブリック ロードバランサには他の場所の公開証明書を使用しないでください。代わりに、サービス メッシュで別個の証明書を使用することをおすすめします。
サービス メッシュで TLS が強制されている場合、すべてのトラフィックはサイドカー プロキシとMesh Ingress との間で暗号化されます。次の図は、クライアントから Google Cloud ロードバランサへの、ロードバランサから Mesh Ingress プロキシ、および Ingress プロキシからサイドカー プロキシへの HTTPS 暗号化を示しています。
目標
- Google Cloud に Google Kubernetes Engine(GKE)クラスタをデプロイします。
- Istio ベースの Anthos Service Mesh を GKE クラスタにデプロイします。
- パブリック HTTPS トラフィックを終了し、そのトラフィックをサービス メッシュでホストされるアプリケーションに転送するように GKE Ingress を構成します。
- インターネット上のクライアントに公開する GKE クラスタに Online Boutique アプリケーションをデプロイします。
費用
このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。
- Google Kubernetes Engine
- Compute Engine
- Cloud Load Balancing
- Anthos Service Mesh
- Google Cloud Armor
- Cloud Endpoints
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。
始める前に
-
Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。
-
Google Cloud コンソールで、「Cloud Shell をアクティブにする」をクリックします。
このチュートリアルでは、Cloud Shell からすべてのターミナル コマンドを実行します。
Google Cloud CLI の最新バージョンにアップグレードします。
gcloud components update
デフォルトの Google Cloud プロジェクトを設定します。
export PROJECT=PROJECT export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT} --format="value(projectNumber)") gcloud config set project ${PROJECT}
PROJECT
は、このチュートリアルで使用するプロジェクト ID に置き換えます。作業ディレクトリを作成します。
mkdir -p ${HOME}/edge-to-mesh cd ${HOME}/edge-to-mesh export WORKDIR=`pwd`
チュートリアルを完了したら、作業ディレクトリを削除できます。
GKE クラスタの作成
このチュートリアルで説明されてる機能には、GKE クラスタ バージョン 1.16 以降が必要です。
Cloud Shell で、新しい
kubeconfig
ファイルを作成します。この手順により、既存の(デフォルト)kubeconfig
ファイルと競合しなくなります。touch edge2mesh_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_kubeconfig
GKE クラスタの環境変数を定義します。
export CLUSTER_NAME=edge-to-mesh export CLUSTER_LOCATION=us-west1-a
Google Kubernetes Engine API を有効にします。
gcloud
gcloud services enable container.googleapis.com
Config Connector
このチュートリアルでは、Config Connector リソースを扱います。これらのリソースを使用して、[
gcloud
] タブと同じタスクを完了できます。これらのリソースを利用するには、Config Connector をインストールし、環境に最適な方法でリソースを適用します。次の
Services
マニフェストを使用します。apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 kind: Service metadata: annotations: cnrm.cloud.google.com/deletion-policy: "abandon" cnrm.cloud.google.com/disable-dependent-services: "false" name: container.googleapis.com spec: resourceID: container.googleapis.com projectRef: external: PROJECT
GKE クラスタを作成する。
gcloud
gcloud container clusters create ${CLUSTER_NAME} \ --machine-type=e2-standard-4 \ --num-nodes=4 \ --zone ${CLUSTER_LOCATION} \ --enable-ip-alias \ --workload-pool=${PROJECT}.svc.id.goog \ --release-channel rapid \ --addons HttpLoadBalancing \ --labels mesh_id=proj-${PROJECT_NUMBER}
Config Connector
次の
ContainerCluster
マニフェストとContainerNodePool
マニフェストを使用します。apiVersion: container.cnrm.cloud.google.com/v1beta1 kind: ContainerNodePool metadata: annotations: cnrm.cloud.google.com/project-id: PROJECT name: edge-to-mesh spec: clusterRef: name: edge-to-mesh location: us-west1-a nodeConfig: machineType: e2-standard-4 nodeCount: 4 --- apiVersion: container.cnrm.cloud.google.com/v1beta1 kind: ContainerCluster metadata: annotations: cnrm.cloud.google.com/project-id: PROJECT cnrm.cloud.google.com/remove-default-node-pool: "true" labels: mesh_id: proj-PROJECT_NUMBER name: edge-to-mesh spec: addonsConfig: httpLoadBalancing: disabled: false location: us-west1-a initialNodeCount: 1 releaseChannel: channel: RAPID workloadIdentityConfig: workloadPool: PROJECT.svc.id.goog
PROJECT_NUMBER
の部分は、以前に取得したPROJECT_NUMBER
環境変数の値に置き換えます。Cloud Ingress を使用するには、HTTP ロード バランシング アドオンが有効になっている必要があります。GKE クラスタの HTTP ロード バランシングはデフォルトで有効になっています。無効にしないでください。
マネージド Anthos Service Mesh を使用するには、クラスタに対して
mesh_id
ラベルを適用する必要があります。クラスタが実行されていることを確認します。
gcloud container clusters list
出力は次のようになります。
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS edge-to-mesh us-west1-a v1.22.6-gke.300 35.233.195.59 e2-standard-4 v1.22.6-gke.300 4 RUNNING
クラスタに接続します。
gcloud container clusters get-credentials ${CLUSTER_NAME} \ --zone ${CLUSTER_LOCATION} \ --project ${PROJECT}
サービス メッシュのインストール
このセクションでは、Fleet API を使用してマネージド Anthos Service Mesh を構成します。
必要な API を有効にします。
gcloud
gcloud services enable mesh.googleapis.com
Config Connector
次の
Services
マニフェストを使用します。apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1 kind: Service metadata: annotations: cnrm.cloud.google.com/deletion-policy: "abandon" cnrm.cloud.google.com/disable-dependent-services: "false" name: mesh.googleapis.com spec: resourceID: mesh.googleapis.com projectRef: external: PROJECT
フリートで Anthos Service Mesh を有効にします。
gcloud
gcloud container fleet mesh enable
Config Connector
次の
GKEHubFeature
マニフェストを使用します。apiVersion: gkehub.cnrm.cloud.google.com/v1beta1 kind: GKEHubFeature metadata: name: servicemesh spec: projectRef: external: PROJECT location: global resourceID: servicemesh
クラスタをフリートに登録します。
gcloud
gcloud container fleet memberships register ${CLUSTER_NAME} \ --gke-cluster ${CLUSTER_LOCATION}/${CLUSTER_NAME} \ --enable-workload-identity
Config Connector
次の
GKEHubMembership
マニフェストを使用します。apiVersion: gkehub.cnrm.cloud.google.com/v1beta1 kind: GKEHubMembership metadata: annotations: cnrm.cloud.google.com/project-id: PROJECT name: edge-to-mesh spec: location: global authority: issuer: https://container.googleapis.com/v1/projects/PROJECT/locations/us-west1-a/clusters/edge-to-mesh endpoint: gkeCluster: resourceRef: name: edge-to-mesh
自動コントロール プレーン管理とマネージド データプレーンを有効にします。
gcloud
gcloud container fleet mesh update \ --management automatic \ --memberships ${CLUSTER_NAME}
Config Connector
次の
GKEHubFeatureMembership
マニフェストを使用します。apiVersion: gkehub.cnrm.cloud.google.com/v1beta1 kind: GKEHubFeatureMembership metadata: name: servicemesh-membership spec: projectRef: external: PROJECT_ID location: global membershipRef: name: edge-to-mesh featureRef: name: servicemesh mesh: management: MANAGEMENT_AUTOMATIC
数分後、コントロール プレーンのステータスが
ACTIVE
になっていることを確認します。gcloud container fleet mesh describe
出力は次のようになります。
... membershipSpecs: projects/841956571429/locations/global/memberships/edge-to-mesh: mesh: management: MANAGEMENT_AUTOMATIC membershipStates: projects/841956571429/locations/global/memberships/edge-to-mesh: servicemesh: controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: 'Revision(s) ready for use: asm-managed-rapid.' updateTime: '2022-09-29T05:30:28.320896186Z' name: projects/your-project/locations/global/features/servicemesh resourceState: state: ACTIVE ...
GKE Ingress をデプロイする
次の手順では、GKE の Ingress コントローラを介して外部 HTTP(S) ロードバランサをデプロイします。Ingress リソースは、ロードバランサ、TLS 証明書、バックエンド ヘルスチェックのプロビジョニングを自動化します。また、Cloud Endpoints を使用して、アプリケーションのパブリック DNS 名が自動的にプロビジョニングされます。
Ingress ゲートウェイをインストールする
セキュリティのベスト プラクティスとして、Ingress ゲートウェイは、コントロール プレーンとは異なる Namespace にデプロイすることをおすすめします。
Cloud Shell で、専用の
asm-ingress
Namespace を作成します。kubectl create namespace asm-ingress
asm-ingress
Namespace に名前空間ラベルを追加します。kubectl label namespace asm-ingress istio-injection=enabled
出力は次のようになります。
namespace/asm-ingress labeled
asm-ingress
名前空間にistio-injection=enabled
というラベルを付けると、アプリケーションのデプロイ時に Envoy サイドカー プロキシを自動挿入するよう Anthos Service Mesh が指示されます。次のコマンドを実行して、
Deployment
マニフェストをingress-deployment.yaml
として作成します。cat <<EOF > ingress-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: asm-ingressgateway namespace: asm-ingress spec: selector: matchLabels: asm: ingressgateway template: metadata: annotations: # This is required to tell Anthos Service Mesh to inject the gateway with the # required configuration. inject.istio.io/templates: gateway labels: asm: ingressgateway spec: securityContext: fsGroup: 1337 runAsGroup: 1337 runAsNonRoot: true runAsUser: 1337 containers: - name: istio-proxy securityContext: allowPrivilegeEscalation: false capabilities: drop: - all privileged: false readOnlyRootFilesystem: true image: auto # The image will automatically update each time the pod starts. resources: limits: cpu: 2000m memory: 1024Mi requests: cpu: 100m memory: 128Mi serviceAccountName: asm-ingressgateway --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: asm-ingressgateway spec: maxReplicas: 5 minReplicas: 3 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: asm-ingressgateway --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: asm-ingressgateway namespace: asm-ingress rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: asm-ingressgateway namespace: asm-ingress roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: asm-ingressgateway subjects: - kind: ServiceAccount name: asm-ingressgateway --- apiVersion: v1 kind: ServiceAccount metadata: name: asm-ingressgateway namespace: asm-ingress EOF
この
Deployment
には、Role
とRoleBinding
が関連付けられた独自のServiceAccount
があり、これによりゲートウェイが証明書にアクセスできます。クラスタに
ingress-deployment.yaml
をデプロイしてDeployment
リソースを作成します。kubectl apply -f ingress-deployment.yaml
出力は次のようになります。
deployment.apps/asm-ingressgateway configured role.rbac.authorization.k8s.io/asm-ingressgateway configured rolebinding.rbac.authorization.k8s.io/asm-ingressgateway configured serviceaccount/asm-ingressgateway created
すべてのデプロイが稼働していることを確認します。
kubectl wait --for=condition=available --timeout=600s deployment --all -n asm-ingress
出力は次のようになります。
deployment.apps/asm-ingressgateway condition met
次のコマンドを実行して、
Service
マニフェストをingress-service.yaml
として作成します。cat <<EOF > ingress-service.yaml apiVersion: v1 kind: Service metadata: name: asm-ingressgateway namespace: asm-ingress annotations: cloud.google.com/neg: '{"ingress": true}' cloud.google.com/backend-config: '{"default": "ingress-backendconfig"}' cloud.google.com/app-protocols: '{"https":"HTTP2"}' # HTTP/2 with TLS encryption labels: asm: ingressgateway spec: ports: # status-port exposes a /healthz/ready endpoint that can be used with GKE Ingress health checks - name: status-port port: 15021 protocol: TCP targetPort: 15021 # Any ports exposed in Gateway resources should be exposed here. - name: http2 port: 80 targetPort: 8080 - name: https port: 443 targetPort: 8443 selector: asm: ingressgateway type: ClusterIP EOF
この
Service
には、デプロイ時に Ingress ロードバランサのパラメータを設定する、次のアノテーションがあります。cloud.google.com/backend-config
は、BackendConfig
というカスタム リソースの名前を指します。Ingress コントローラは、BackendConfig
を使用して Google CloudBackendService
リソースにパラメータを設定します。このリソースは、次のステップで Google Cloud ヘルスチェックのカスタム パラメータを定義するために使用します。cloud.google.com/neg: '{"ingress": true}'
は、コンテナ ネイティブの負荷分散の Ingress バックエンド(この場合は Mesh Ingress プロキシ)を有効にします。これらのバックエンドでは、より効率的で安定した負荷分散を実現するために、インスタンス グループではなくネットワーク エンドポイント グループ(NEG)を使用します。cloud.google.com/app-protocols: '{"https":"HTTP2"}'
は、暗号化の追加レイヤために外部 HTTP(S) 負荷分散の Ingress と外部 HTTP(S) 負荷分散の概要で説明されているように、TLS で HTTP2 を使用してサービス メッシュの Ingress ゲートウェイに接続するように GFE に指示します。
クラスタに
ingress-service.yaml
をデプロイしてService
リソースを作成します。kubectl apply -f ingress-service.yaml
出力は次のようになります。
service/asm-ingressgateway created
バックエンド サービスの設定を適用
Cloud Shell で次のコマンドを実行して、
BackendConfig
マニフェストをingress-backendconfig.yaml
として作成します。cat <<EOF > ingress-backendconfig.yaml apiVersion: cloud.google.com/v1 kind: BackendConfig metadata: name: ingress-backendconfig namespace: asm-ingress spec: healthCheck: requestPath: /healthz/ready port: 15021 type: HTTP securityPolicy: name: edge-fw-policy EOF
BackendConfig
は、Ingress 負荷分散のバックエンド パラメータを定義するカスタム リソース定義(CRD)です。GKE Ingress で構成できるバックエンドとフロントエンドのパラメータの一覧については、Ingress 機能をご覧ください。このチュートリアルでは、
BackendConfig
マニフェストで Mesh Ingress プロキシのカスタム ヘルスチェックを指定します。Anthos Service Mesh と Istio は、サイドカー プロキシのヘルスチェックを/healthz/ready
パスのポート15021
で公開します。Mesh Ingress プロキシのサービスポート(443
)とヘルスチェック ポート(15021
)は異なるため、カスタム ヘルスチェック パラメータが必要です。GKE Ingress は、BackendConfig
の次のヘルスチェック パラメータを使用して、Google Cloud ロードバランサのヘルスチェックを構成します。また、さまざまな種類のネットワーク攻撃から負荷分散トラフィックを保護するセキュリティ ポリシーも参照できます。healthCheck.port
は、各ポッドの IP アドレスの Google Cloud ロードバランサでヘルスチェックを受け取るポートを定義します。healthCheck.requestPath
は、指定されたポートでヘルスチェックを受け取る HTTP パスを定義します。type
は、ヘルスチェックのプロトコル(この場合は HTTP)を定義します。securityPolicy.name
は、Cloud Armor セキュリティ ポリシーの名前です。
クラスタに
ingress-backendconfig.yaml
をデプロイしてBackendConfig
リソースを作成します。kubectl apply -f ingress-backendconfig.yaml
出力は次のようになります。
backendconfig.cloud.google.com/ingress-backendconfig created
Ingress リソースがデプロイされるまで、
BackendConfig
パラメータとasm-ingressgateway
Service アノテーションは Google Cloud ロードバランサには適用されません。Ingress デプロイは、これらのすべてのリソースを結び付けます。
セキュリティ ポリシーの定義
Google Cloud Armor の DDoS 防御とカスタマイズ可能なセキュリティ ポリシーは、Ingress リソースを介してロードバランサに接続できます。次の手順では、事前構成されたルールを使用してクロスサイト スクリプティング(XSS)攻撃をブロックするセキュリティ ポリシーを作成します。このルールは、既知の攻撃の署名と一致するトラフィックをブロックしますが、他のすべてのトラフィックを許可します。ワークロードに応じて、環境に異なるルールが適用される場合があります。
gcloud
Cloud Shell で、
edge-fw-policy
という名前のセキュリティ ポリシーを作成します。gcloud compute security-policies create edge-fw-policy \ --description "Block XSS attacks"
事前構成された XSS フィルタを使用するセキュリティ ポリシー ルールを作成します。
gcloud compute security-policies rules create 1000 \ --security-policy edge-fw-policy \ --expression "evaluatePreconfiguredExpr('xss-stable')" \ --action "deny-403" \ --description "XSS attack filtering"
Config Connector
次の ComputeSecurityPolicy
マニフェストを使用します。
apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeSecurityPolicy
metadata:
annotations:
cnrm.cloud.google.com/project-id: PROJECT_ID
name: edge-fw-policy
spec:
rule:
- action: allow
description: "Default rule"
match:
versionedExpr: SRC_IPS_V1
config:
srcIpRanges:
- "*"
priority: 2147483647
- action: deny-403
description: "XSS attack filtering"
match:
expr:
expression: "evaluatePreconfiguredExpr('xss-stable')"
priority: 1000
edge-fw-policy
は前のセクションの ingress-backendconfig
によって参照されました。Ingress リソースがデプロイされると、このセキュリティ ポリシーをロードバランサにバインドして、asm-ingressgateway
Service のバックエンドを保護します。
IP アドレス指定と DNS の設定
Cloud Shell で、Google Cloud ロードバランサのグローバル静的 IP を作成します。
gcloud
gcloud compute addresses create ingress-ip --global
Config Connector
次の
ComputeAddress
マニフェストを使用します。apiVersion: compute.cnrm.cloud.google.com/v1beta1 kind: ComputeAddress metadata: annotations: cnrm.cloud.google.com/project-id: PROJECT_ID name: ingress-ip spec: location: global
この静的 IP は Ingress リソースによって使用され、外部ロードバランサが変更されても、IP を同じままにできます。
静的 IP アドレスを取得します。
export GCLB_IP=$(gcloud compute addresses describe ingress-ip --global --format "value(address)") echo ${GCLB_IP}
Ingress IP との安定した理解しやすいマッピングを作成するには、パブリック DNS レコードが必要です。任意の DNS プロバイダと自動化を使用できます。このチュートリアルでは、マネージド DNS ゾーンを作成する代わりに Endpoints を使用します。Endpoints は、パブリック IP 用に無料の Google 管理 DNS レコードを提供します。
次のコマンドを実行して、
dns-spec.yaml
という名前の YAML 仕様ファイルを作成します。cat <<EOF > dns-spec.yaml swagger: "2.0" info: description: "Cloud Endpoints DNS" title: "Cloud Endpoints DNS" version: "1.0.0" paths: {} host: "frontend.endpoints.${PROJECT}.cloud.goog" x-google-endpoints: - name: "frontend.endpoints.${PROJECT}.cloud.goog" target: "${GCLB_IP}" EOF
YAML 仕様では、
frontend.endpoints.${PROJECT}.cloud.goog
の形式でパブリック DNS レコードが定義されます。${PROJECT}
は一意のプロジェクト番号です。Cloud プロジェクトに
dns-spec.yaml
ファイルをデプロイします。gcloud endpoints services deploy dns-spec.yaml
出力は次のようになります。
Operation finished successfully. The following command can describe the Operation details: gcloud endpoints operations describe operations/rollouts.frontend.endpoints.edge2mesh.cloud.goog:442b2b38-4aee-4c60-b9fc-28731657ee08 Service Configuration [2021-11-14r0] uploaded for service [frontend.endpoints.edge2mesh.cloud.goog]
IP と DNS が構成されたので、Ingress フロントエンドを保護するための公開証明書を生成できます。GKE Ingress は Kubernetes リソースとして Google マネージド証明書をサポートしており、宣言型の方法でプロビジョニングできます。
TLS 証明書をプロビジョニングする
Cloud Shell で次のコマンドを実行して、
ManagedCertificate
マニフェストをmanaged-cert.yaml
として作成します。cat <<EOF > managed-cert.yaml apiVersion: networking.gke.io/v1 kind: ManagedCertificate metadata: name: gke-ingress-cert namespace: asm-ingress spec: domains: - "frontend.endpoints.${PROJECT}.cloud.goog" EOF
この YAML ファイルでは、Endpoints を通じて作成された DNS 名が公開証明書をプロビジョニングするように指定します。Google がこれらの公開証明書のライフサイクルを完全に管理するため、ユーザーの直接介入なしに、定期的に自動生成およびローテーションされます。
GKE クラスタに
managed-cert.yaml
ファイルをデプロイします。kubectl apply -f managed-cert.yaml
出力は次のようになります。
managedcertificate.networking.gke.io/gke-ingress-cert created
ManagedCertificate
リソースを調べて、証明書の生成の進行状況を確認します。kubectl describe managedcertificate gke-ingress-cert -n asm-ingress
出力は次のようになります。
Name: gke-ingress-cert Namespace: asm-ingress Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.gke.io/v1","kind":"ManagedCertificate","metadata":{"annotations":{},"name":"gke-ingress-cert","namespace":"... API Version: networking.gke.io/v1 Kind: ManagedCertificate Metadata: Creation Timestamp: 2020-08-05T20:44:49Z Generation: 2 Resource Version: 1389781 Self Link: /apis/networking.gke.io/v1/namespaces/asm-ingress/managedcertificates/gke-ingress-cert UID: d74ec346-ced9-47a8-988a-6e6e9ddc4019 Spec: Domains: frontend.endpoints.edge2mesh.cloud.goog Status: Certificate Name: mcrt-306c779e-8439-408a-9634-163664ca6ced Certificate Status: Provisioning Domain Status: Domain: frontend.endpoints.edge2mesh.cloud.goog Status: Provisioning Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Create 44s managed-certificate-controller Create SslCertificate mcrt-306c779e-8439-408a-9634-163664ca6ced
証明書の準備ができると、
Certificate Status
はActive
になります。
Ingress リソースをデプロイする
Cloud Shell で次のコマンドを実行して、
Ingress
マニフェストをingress.yaml
として作成します。cat <<EOF > ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: gke-ingress namespace: asm-ingress annotations: kubernetes.io/ingress.allow-http: "false" kubernetes.io/ingress.global-static-ip-name: "ingress-ip" networking.gke.io/managed-certificates: "gke-ingress-cert" kubernetes.io/ingress.class: "gce" spec: defaultBackend: service: name: asm-ingressgateway port: number: 443 rules: - http: paths: - path: /* pathType: ImplementationSpecific backend: service: name: asm-ingressgateway port: number: 443 EOF
このマニフェストでは、上記のすべてのリソースを関連付ける Ingress リソースが定義されています。このマニフェストでは、次のフィールドを指定します。
kubernetes.io/ingress.allow-http: "false"
は、Google Cloud ロードバランサのポート80
で HTTP トラフィックを無効にします。ポート443
は HTTPS をリッスンし、ポート80
が無効になっているため、クライアントが暗号化されていないトラフィックに接続すると実質的に防止されます。kubernetes.io/ingress.global-static-ip-name: "ingress-ip"
は、以前に作成した IP アドレスをロードバランサにリンクします。このリンクを使用すると、IP アドレスをロードバランサとは別に作成でき、ロードバランサのライフサイクルとは別に再利用できます。networking.gke.io/managed-certificates: "gke-ingress-cert"
はこのロードバランサを、以前に Google が管理する SSL 証明書リソースにリンクします。
クラスタに
ingress.yaml
をデプロイします。kubectl apply -f ingress.yaml
Ingress リソースを調べて、ロードバランサのデプロイの進行状況を確認します。
kubectl describe ingress gke-ingress -n asm-ingress
出力は次のようになります。
... Annotations: ingress.kubernetes.io/https-forwarding-rule: k8s2-fs-fq3ng2uk-asm-ingress-gke-ingress-qm3qqdor ingress.kubernetes.io/ssl-cert: mcrt-306c779e-8439-408a-9634-163664ca6ced networking.gke.io/managed-certificates: gke-ingress-cert kubernetes.io/ingress.global-static-ip-name: ingress-ip ingress.gcp.kubernetes.io/pre-shared-cert: mcrt-306c779e-8439-408a-9634-163664ca6ced ingress.kubernetes.io/backends: {"k8s-be-31610--07bdde06b914144a":"HEALTHY","k8s1-07bdde06-asm-ingress-asm-ingressgateway-443-228c1881":"HEALTHY"} ingress.kubernetes.io/forwarding-rule: k8s2-fr-fq3ng2uk-asm-ingress-gke-ingress-qm3qqdor ingress.kubernetes.io/https-target-proxy: k8s2-ts-fq3ng2uk-asm-ingress-gke-ingress-qm3qqdor ingress.kubernetes.io/target-proxy: k8s2-tp-fq3ng2uk-asm-ingress-gke-ingress-qm3qqdor ingress.kubernetes.io/url-map: k8s2-um-fq3ng2uk-asm-ingress-gke-ingress-qm3qqdor ...
Ingress リソースは、
ingress.kubernetes.io/backends
アノテーションでバックエンドがHEALTHY
と示されている場合に使用できます。アノテーションには、バックエンド サービス、SSL 証明書、HTTPS ターゲット プロキシなど、プロビジョニングされたさまざまな Google Cloud リソースの名前も表示されます。
自己署名 Ingress ゲートウェイ証明書をインストールする
次の手順では、GFE がサービス メッシュの Ingress ゲートウェイへの TLS 接続を確立できるようにする証明書を(Kubernetes secret
リソースとして)生成し、インストールします。Ingress ゲートウェイ証明書の要件の詳細については、セキュア バックエンド プロトコルに関する検討事項ガイドをご覧ください。
Cloud Shell で、
openssl
を使用して秘密鍵と証明書を作成します。openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \ -subj "/CN=frontend.endpoints.${PROJECT}.cloud.goog/O=Edge2Mesh Inc" \ -keyout frontend.endpoints.${PROJECT}.cloud.goog.key \ -out frontend.endpoints.${PROJECT}.cloud.goog.crt
asm-ingress
名前空間にSecret
を作成します。kubectl -n asm-ingress create secret tls edge2mesh-credential \ --key=frontend.endpoints.${PROJECT}.cloud.goog.key \ --cert=frontend.endpoints.${PROJECT}.cloud.goog.crt
外部ロード バランシング用 Ingress ゲートウェイを構成する
次の手順では、asm-ingress
Namespace に共有 Gateway
リソースを作成します。ゲートウェイは通常、プラットフォーム管理者か、ネットワーク管理者チームが所有します。そのため、Gateway
リソースは、プラットフォーム管理者が所有する asm-ingress
Namespace に作成され、独自の VirtualService
エントリを介して他の Namespace で使用できます。
Cloud Shell で次のコマンドを実行して、
Gateway
マニフェストをingress-gateway.yaml
として作成します。cat <<EOF > ingress-gateway.yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: asm-ingressgateway namespace: asm-ingress spec: selector: asm: ingressgateway servers: - port: number: 443 name: https protocol: HTTPS hosts: - "*" # IMPORTANT: Must use wildcard here when using SSL, see note below tls: mode: SIMPLE credentialName: edge2mesh-credential EOF
Gateway
のhosts
フィールドではワイルドカード*
エントリを使用する必要があります。GCLB はバックエンドに対する SNI 拡張機能を使用しません。ワイルドカード エントリを使用すると、(GCLB から)暗号化されたパケットが ASM Ingress ゲートウェイに送信されます。ASM Ingress ゲートウェイはパケットを復号し、(復号されたパケット内の)HTTP ホストヘッダーを使用して(VirtualService
エントリに基づいて)ルーティングを決定します。クラスタに
ingress-gateway.yaml
をデプロイします。kubectl apply -f ingress-gateway.yaml
出力は次のようになります。
gateway.networking.istio.io/asm-ingressgateway created
Online Boutique サンプル アプリケーションをインストールする
Cloud Shell で、専用の
onlineboutique
Namespace を作成します。kubectl create namespace onlineboutique
onlineboutique
Namespace に名前空間ラベルを追加します。kubectl label namespace onlineboutique istio-injection=enabled
出力は次のようになります。
namespace/onlineboutique labeled
onlineboutique
名前空間にistio-injection=enabled
というラベルを付けると、アプリケーションのデプロイ時に Envoy サイドカー プロキシを自動挿入するよう Anthos Service Mesh が指示されます。Online Boutique のサンプルアプリの Kubernetes YAML ファイルをダウンロードします。
curl -LO \ https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/release/kubernetes-manifests.yaml
Online Boutique アプリをデプロイします。
kubectl apply -f kubernetes-manifests.yaml -n onlineboutique
出力は次のようになります。
deployment.apps/frontend created service/frontend created service/frontend-external created ...
すべてのデプロイが稼働していることを確認します。
kubectl get pods -n onlineboutique
出力は次のようになります。
NAME READY STATUS RESTARTS AGE adservice-d854d8786-fjb7q 2/2 Running 0 3m cartservice-85b5d5b4ff-8qn7g 2/2 Running 0 2m59s checkoutservice-5f9bf659b8-sxhsq 2/2 Running 0 3m1s ...
次のコマンドを実行して、
VirtualService
マニフェストをfrontend-virtualservice.yaml
として作成します。cat <<EOF > frontend-virtualservice.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: frontend-ingress namespace: onlineboutique spec: hosts: - "frontend.endpoints.${PROJECT}.cloud.goog" gateways: - asm-ingress/asm-ingressgateway http: - route: - destination: host: frontend port: number: 80 EOF
なお、
VirtualService
は、アプリケーションの Namespace(onlineboutique
)に作成されることに注意してください。通常、アプリケーション オーナーは、frontend
アプリケーションにルーティングするトラフィックとその方法を決定して構成し、VirtualService
がアプリケーション オーナーによってデプロイされるようにします。クラスタに
frontend-virtualservice.yaml
をデプロイします。kubectl apply -f frontend-virtualservice.yaml
出力は次のようになります。
virtualservice.networking.istio.io/frontend-virtualservice created
次のリンクにアクセスします。
echo "https://frontend.endpoints.${PROJECT}.cloud.goog"
Online Boutique のフロントエンドが表示されます。
証明書の詳細を表示するには、ブラウザのアドレスバーの
[サイト情報を表示]、[Certificate (Valid)] の順にクリックします。証明書ビューアには、証明書の有効期限や証明書の発行者など、マネージド証明書の詳細が表示されます。
これで、サービス メッシュでホストされるアプリケーションのフロントエンドとして機能するグローバル HTTPS ロードバランサが作成されました。
クリーンアップ
チュートリアルが完了したら、Google Cloud で作成したリソースをクリーンアップして、今後料金が発生しないようにします。プロジェクトを完全に削除するか、クラスタ リソースを削除してからクラスタを削除できます。
プロジェクトの削除
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
個々のリソースの削除
このチュートリアルで使用した Cloud プロジェクトを残しておく場合は、個々のリソースを削除します。
Ingress リソースを削除します。
kubectl delete -f ingress.yaml
マネージド証明書を削除します。
kubectl delete -f managed-cert.yaml
Endpoints DNS エントリを削除します。
gcloud endpoints services delete "frontend.endpoints.${PROJECT}.cloud.goog"
出力は次のようになります。
Are you sure? This will set the service configuration to be deleted, along with all of the associated consumer information. Note: This does not immediately delete the service configuration or data and can be undone using the undelete command for 30 days. Only after 30 days will the service be purged from the system.
続行を確認するメッセージが表示されたら、「Y」と入力します。
出力は次のようになります。
Waiting for async operation operations/services.frontend.endpoints.edge2mesh.cloud.goog-5 to complete... Operation finished successfully. The following command can describe the Operation details: gcloud endpoints operations describe operations/services.frontend.endpoints.edge2mesh.cloud.goog-5
静的 IP アドレスを削除します。
gcloud compute addresses delete ingress-ip --global
出力は次のようになります。
The following global addresses will be deleted: - [ingress-ip]
続行を確認するメッセージが表示されたら、「Y」と入力します。
出力は次のようになります。
Deleted [https://www.googleapis.com/compute/v1/projects/edge2mesh/global/addresses/ingress-ip].
GKE クラスタを削除します。
gcloud container clusters delete $CLUSTER_NAME --zone $CLUSTER_LOCATION
次のステップ
- サービス メッシュで使用できる GKE Ingress によって提供されるその他の機能について学習する。
- GKE で使用できるさまざまなタイプの Cloud Load Balancing について学習する。
- Anthos Service Mesh の特徴や提供される機能について学ぶ。
- マルチリージョン負荷分散用に複数の GKE クラスタに Ingress をデプロイする方法を確認する。
- Google Cloud に関するリファレンス アーキテクチャ、図、ベスト プラクティスを確認する。Cloud Architecture Center をご覧ください。