エッジからメッシュへ: GKE Ingress を介したサービス メッシュ アプリケーションの公開

このチュートリアルでは、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 ロードバランサをデプロイする点を除いて、このアーキテクチャと類似しています。

外部ロードバランサは、外部クライアントを Ingress ゲートウェイ プロキシ経由でメッシュにルーティングします。

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 サービス 外部 TCP/UDP ロードバランサ

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) バランサを中心に説明します。外部 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 よりも、パフォーマンス、信頼性、セキュリティ関連の大きな利点が得られます。これには、次のような利点があります。

この L7 負荷分散の外部レイヤは、Mesh Ingress で使用されるセルフホストのプロキシではなく、クラウド管理ロードバランサ上に構築されるため、「Cloud Ingress」と呼ばれます。Cloud Ingress と Mesh Ingress を組み合わせる場合、Google Cloud インフラストラクチャとメッシュの補完機能を活用します。次の図は、Cloud Ingress と Mesh Ingress を組み合わせて、インターネット トラフィックの 2 つの負荷分散レイヤとして機能する方法を示しています。

Cloud Ingress は、VPC ネットワーク経由でメッシュへの外部トラフィックのためのゲートウェイとして機能します。

このトポロジでは、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 は Mesh 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 クラスタにデプロイします。
  • インターネット上のクライアントに公開する GKE クラスタに Online Boutique アプリケーションをデプロイします。
  • パブリック HTTPS トラフィックを終了し、そのトラフィックをサービス メッシュでホストされるアプリケーションに転送するように GKE Ingress を構成します。

料金

このチュートリアルでは、課金対象である次の Google Cloud コンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。新しい Google Cloud ユーザーは無料トライアルをご利用いただけます。

このチュートリアルを終了した後、作成したリソースを削除すると、それ以上の請求は発生しません。詳しくは、クリーンアップをご覧ください。

始める前に

  1. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  2. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  3. Cloud Console で、Cloud Shell をアクティブにします。

    Cloud Shell をアクティブにする

    このチュートリアルでは、Cloud Shell からすべてのターミナル コマンドを実行します。

  4. デフォルトの Google Cloud プロジェクトを設定します。

    export PROJECT=$(gcloud info --format='value(config.project)')
    export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT} --format="value(projectNumber)")
    gcloud config set project ${PROJECT}
    
  5. このチュートリアル用のファイルを取得するコード リポジトリのクローンを作成し、作業ディレクトリを作成します。

    mkdir -p ${HOME}/edge-to-mesh
    cd ${HOME}/edge-to-mesh
    export WORKDIR=`pwd`
    

    チュートリアルを完了したら、作業ディレクトリを削除できます。

GKE クラスタの作成

このチュートリアルで説明されてる機能には、GKE クラスタ バージョン 1.16 以降が必要です。

  1. Cloud Shell で、新しい kubeconfig ファイルを作成します。この手順により、既存の(デフォルト)kubeconfig ファイルと競合しなくなります。

    touch edge2mesh_kubeconfig
    export KUBECONFIG=${WORKDIR}/edge2mesh_kubeconfig
    
  2. GKE クラスタの環境変数を定義します。

    export CLUSTER_NAME=edge-to-mesh
    export CLUSTER_LOCATION=us-west1-a
    
  3. GKE クラスタを作成する。

    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
    
  4. クラスタが実行されていることを確認します。

    gcloud container clusters list
    

    出力は次のようになります。

    NAME          LOCATION    MASTER_VERSION    MASTER_IP      MACHINE_TYPE   NODE_VERSION      NUM_NODES  STATUS
    edge-to-mesh  us-west1-a  1.21.4-gke.301    35.233.195.59  e2-standard-4  1.21.4-gke.301    4          RUNNING
    
  5. クラスタに接続します。

    gcloud container clusters get-credentials ${CLUSTER_NAME} --zone ${CLUSTER_LOCATION} --project ${PROJECT}
    

サービス メッシュのインストール

  1. Cloud Shell にAnthos Service Mesh のインストール ファイルをダウンロードします。

    カスタム オーバーレイ ファイルを作成して、NEG アノテーションを付加した IstioOperator を構成します。

    cat <<EOF > ingress-backendconfig-operator.yaml
    ---
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    spec:
      components:
        ingressGateways:
          - name: istio-ingressgateway
            enabled: true
            k8s:
              service:
                type: ClusterIP
              serviceAnnotations:
                cloud.google.com/backend-config: '{"default": "ingress-backendconfig"}'
                cloud.google.com/neg: '{"ingress": true}'
                cloud.google.com/app-protocols: '{"https":"HTTP2"}' # HTTP/2 with TLS encryption
    EOF
    

    このカスタム オーバーレイでは、GKE Ingress が使用するカスタム アノテーションを使って istio-ingressgateway Service にパッチを適用します。

    この Service には、デプロイ時に Ingress ロードバランサのパラメータを設定する、次のアノテーションがあります。

    • cloud.google.com/backend-config は、BackendConfig というカスタム リソースの名前を指します。Ingress コントローラは、BackendConfig を使用して Google Cloud BackendService リソースにパラメータを設定します。このリソースは、次のステップで 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 に指示します。

    GKE への Anthos Service Mesh のインストールの手順に沿って、Google 提供のスクリプトを使用して Anthos Service Mesh をインストールします。スクリプトの実行時に、次のオプションを指定します。

    --custom_overlay ingress-backendconfig-operator.yaml
    

    例:

    ./install_asm \
        --project_id ${PROJECT} \
        --cluster_name ${CLUSTER_NAME} \
        --cluster_location ${CLUSTER_LOCATION} \
        --mode install \
        --enable_all \
        --custom_overlay ingress-backendconfig-operator.yaml
    
  2. すべてのデプロイが稼働していることを確認します。

    kubectl wait --for=condition=available --timeout=600s deployment --all -n istio-system
    

    出力は次のようになります。

    deployment.apps/istio-ingressgateway condition met
    deployment.apps/istiod-asm-1104-14 condition met
    

自己署名 Ingress ゲートウェイ証明書の生成とインストール

次の手順では、GFE がサービス メッシュの Ingress ゲートウェイへの TLS 接続を確立できるようにする証明書を(Kubernetes secret リソースとして)生成し、インストールします。Ingress ゲートウェイ証明書の要件の詳細については、セキュア バックエンド プロトコルに関する検討事項ガイドをご覧ください。

  1. 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
    
  2. istio-system 名前空間に secret を作成します。

    kubectl -n istio-system create secret tls edge2mesh-credential \
     --key=frontend.endpoints.${PROJECT}.cloud.goog.key \
     --cert=frontend.endpoints.${PROJECT}.cloud.goog.crt
    

Online Boutique サンプル アプリケーションをインストールする

  1. Cloud Shell で、default 名前空間に名前空間ラベルを追加します。

    kubectl label namespace default istio-injection- istio.io/rev=asm-1104-14 --overwrite
    

    namespace 名前空間にラベルを付けると、アプリケーションのデプロイ時に Envoy サイドカー プロキシを自動挿入するよう Istio に指示します。適用する istio.io/rev ラベルが、ASM インストール ガイドで説明されているように、インストールした ASM のバージョンと一致していることを確認してください。出力は次のようになります。

    label "istio-injection" not found.
    namespace/default labeled
    
  2. Online Boutique のサンプルアプリの Kubernetes および Istio YAML ファイルをダウンロードします。

    curl -LO \
        https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/master/release/kubernetes-manifests.yaml
    curl -LO \
        https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/master/release/istio-manifests.yaml
    
  3. Online Boutique アプリをデプロイします。

    kubectl apply -f kubernetes-manifests.yaml
    

    出力は次のようになります。

    deployment.apps/frontend created
    service/frontend created
    service/frontend-external created
    ...
    
  4. すべてのデプロイが稼働していることを確認します。

    kubectl get pods
    

    出力は次のようになります。

    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
    ...
    
  5. Istio マニフェストでは、Kustomize を使用して、Ingress ゲートウェイで TLS を有効にするために、さらにいくつかの変更が必要です。

    mkdir istio-kustomization
    mv istio-manifests.yaml ./istio-kustomization
    
    cat <<EOF > istio-kustomization/https-gateway.yaml
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
        name: frontend-gateway
    spec:
      selector:
        istio: ingressgateway # use Istio default gateway implementation
      servers:
      - port:
          number: 443
          name: https
          protocol: HTTPS
        hosts:
        - "*"
        tls:
          mode: SIMPLE
          credentialName: edge2mesh-credential
    EOF
    
    cat <<EOF > istio-kustomization/kustomization.yaml
    resources:
    - istio-manifests.yaml
    patchesStrategicMerge:
    - https-gateway.yaml
    EOF
    
  6. Istio マニフェストをデプロイします。

    kubectl apply -k istio-kustomization/
    

    出力は次のようになります。

    virtualservice.networking.istio.io/frontend created
    gateway.networking.istio.io/frontend-gateway created
    virtualservice.networking.istio.io/frontend-ingress created
    serviceentry.networking.istio.io/allow-egress-googleapis created
    serviceentry.networking.istio.io/allow-egress-google-metadata created
    

GKE Ingress をデプロイする

次の手順では、GKE の Ingress コントローラを介して外部 HTTP(S) ロードバランサをデプロイします。Ingress リソースは、ロードバランサ、TLS 証明書、バックエンド ヘルスチェックのプロビジョニングを自動化します。また、Cloud Endpoints を使用して、アプリケーションのパブリック DNS 名が自動的にプロビジョニングされます。

バックエンド サービスの設定を適用

  1. Cloud Shell で、istio-ingressgateway サービスを確認し、カスタマイズを適用する前にデプロイされているかどうかを確認します。

    kubectl get svc -n istio-system istio-ingressgateway
    

    出力に、デフォルトのインストールの Service アノテーションが表示されます。

    NAME                   TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                                        AGE
    istio-ingressgateway   ClusterIP   10.44.15.44   <none>        15021/TCP,80/TCP,443/TCP,31400/TCP,15443/TCP   5m57s
    

    このチュートリアルの前半では、Anthos Service Mesh または Istio のインストール プロファイルを使用して、istio-ingressgatewayClusterIP サービスとしてデプロイしました。このカスタマイズされたプロファイルでは、サービス メッシュ デプロイの一部として TCP/UDP ロードバランサをデプロイしません。このチュートリアルでは、HTTP(S) ベースの Ingress リソースを通じてアプリが公開されるためです。チュートリアルのこの時点ではアプリケーションは公開されていないため、クラスタ外部からアプリケーションにアクセスすることはできません。

  2. 次の BackendConfig マニフェストを ingress-backendconfig.yaml として保存します。

    cat <<EOF > ingress-backendconfig.yaml
    apiVersion: cloud.google.com/v1
    kind: BackendConfig
    metadata:
      name: ingress-backendconfig
      namespace: istio-system
    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 セキュリティ ポリシーの名前です。
  3. クラスタに ingress-backendconfig.yaml をデプロイして BackendConfig リソースを作成します。

    kubectl apply -f ingress-backendconfig.yaml
    

    出力は次のようになります。

    backendconfig.cloud.google.com/ingress-backendconfig created
    

    Ingress リソースがデプロイされるまで、BackendConfig パラメータと istio-ingressgateway Service アノテーションは Google Cloud ロードバランサには適用されません。Ingress デプロイは、これらのすべてのリソースを結び付けます。

セキュリティ ポリシーの定義

Google Cloud Armor の DDoS 防御とカスタマイズ可能なセキュリティ ポリシーは、Ingress リソースを介してロードバランサに接続できます。次の手順では、事前構成されたルールを使用してクロスサイト スクリプティング(XSS)攻撃をブロックするセキュリティ ポリシーを作成します。このルールは、既知の攻撃の署名と一致するトラフィックをブロックしますが、他のすべてのトラフィックを許可します。ワークロードに応じて、環境に異なるルールが適用される場合があります。

  1. Cloud Shell で、edge-fw-policy という名前のセキュリティ ポリシーを作成します。

    gcloud compute security-policies create edge-fw-policy \
        --description "Block XSS attacks"
    
  2. 事前構成された XSS フィルタを使用するセキュリティ ポリシー ルールを作成します。

    gcloud compute security-policies rules create 1000 \
        --security-policy edge-fw-policy \
        --expression "evaluatePreconfiguredExpr('xss-stable')" \
        --action "deny-403" \
        --description "XSS attack filtering"
    

edge-fw-policy は前のセクションの ingress-backendconfig によって参照されました。Ingress リソースがデプロイされると、このセキュリティ ポリシーをロードバランサにバインドして、istio-ingressgateway Service のバックエンドを保護します。

IP アドレス指定と DNS の設定

  1. Cloud Shell で、Google Cloud ロードバランサのグローバル静的 IP を作成します。

    gcloud compute addresses create ingress-ip --global
    

    この静的 IP は Ingress リソースによって使用され、外部ロードバランサが変更されても、IP を同じままにできます。

  2. 静的 IP アドレスを取得します。

    export GCLB_IP=$(gcloud compute addresses describe ingress-ip --global --format=json | jq -r '.address')
    echo ${GCLB_IP}
    

    Ingress IP との安定した理解しやすいマッピングを作成するには、パブリック DNS レコードが必要です。任意の DNS プロバイダと自動化を使用できます。このチュートリアルでは、マネージド DNS ゾーンを作成する代わりに Endpoints を使用します。Endpoints は、パブリック IP 用に無料の Google 管理 DNS レコードを提供します。

  3. 次の YAML 仕様を dns-spec.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} は一意のプロジェクト番号です。

  4. 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 [2020-04-28r0] uploaded for service [frontend.endpoints.edge2mesh.cloud.goog]
    

    IP と DNS が構成されたので、Ingress フロントエンドを保護するための公開証明書を生成できます。GKE Ingress は Kubernetes リソースとして Google マネージド証明書をサポートしており、宣言型の方法でプロビジョニングできます。

TLS 証明書をプロビジョニングする

  1. Cloud Shell で、次の YAML マニフェストを managed-cert.yaml として保存します。

    cat <<EOF > managed-cert.yaml
    apiVersion: networking.gke.io/v1
    kind: ManagedCertificate
    metadata:
      name: gke-ingress-cert
      namespace: istio-system
    spec:
      domains:
        - "frontend.endpoints.${PROJECT}.cloud.goog"
    EOF
    

    この YAML ファイルでは、Endpoints を通じて作成された DNS 名が公開証明書をプロビジョニングするように指定します。Google がこれらの公開証明書のライフサイクルを完全に管理するため、ユーザーの直接介入なしに、定期的に自動生成およびローテーションされます。

  2. GKE クラスタに managed-cert.yaml ファイルをデプロイします。

    kubectl apply -f managed-cert.yaml
    

    出力は次のようになります。

    managedcertificate.networking.gke.io/gke-ingress-cert created
    
  3. ManagedCertificate リソースを調べて、証明書の生成の進行状況を確認します。

    kubectl describe managedcertificate gke-ingress-cert -n istio-system
    

    出力は次のようになります。

    Name:         gke-ingress-cert
    Namespace:    istio-system
    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/v1b/namespaces/istio-system/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 StatusActive になります。

Ingress リソースをデプロイする

  1. Cloud Shell で、次の Ingress マニフェストを ingress.yaml として保存します。

    cat <<EOF > ingress.yaml
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gke-ingress
      namespace: istio-system
      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: istio-ingressgateway
          port:
            number: 443
      rules:
      - http:
          paths:
          - path: /*
            pathType: ImplementationSpecific
            backend:
              service:
                name: istio-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: "${GCLB_IP}" は、以前に作成した IP アドレスをロードバランサにリンクします。このリンクを使用すると、IP アドレスをロードバランサとは別に作成でき、ロードバランサのライフサイクルとは別に再利用できます。
    • networking.gke.io/managed-certificates: "gke-ingress-cert" はこのロードバランサを、以前に Google が管理する SSL 証明書リソースにリンクします。
    • host: frontend.endpoints.${project}.cloud.google.com には、このロードバランサ IP がリッスンする HTTP ホストヘッダーを指定します。アプリケーションのアドバタイズに使用する DNS 名が使用されます。
  2. クラスタに ingress.yaml をデプロイします。

    kubectl apply -f ingress.yaml
    
  3. Ingress リソースを調べて、ロードバランサのデプロイの進行状況を確認します。

    kubectl describe ingress gke-ingress -n istio-system
    

    出力は次のようになります。

    ...
    Annotations:
      ingress.kubernetes.io/https-forwarding-rule:       k8s2-fs-fq3ng2uk-istio-system-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-istio-system-istio-ingressgateway-443-228c1881":"HEALTHY"}
      ingress.kubernetes.io/forwarding-rule:        k8s2-fr-fq3ng2uk-istio-system-gke-ingress-qm3qqdor
      ingress.kubernetes.io/https-target-proxy:     k8s2-ts-fq3ng2uk-istio-system-gke-ingress-qm3qqdor
      ingress.kubernetes.io/target-proxy:           k8s2-tp-fq3ng2uk-istio-system-gke-ingress-qm3qqdor
      ingress.kubernetes.io/url-map:                k8s2-um-fq3ng2uk-istio-system-gke-ingress-qm3qqdor
    ...
    

    Ingress リソースは、ingress.kubernetes.io/backends アノテーションでバックエンドが HEALTHY と示されている場合に使用できます。アノテーションには、バックエンド サービス、SSL 証明書、HTTPS ターゲット プロキシなど、プロビジョニングされたさまざまな Google Cloud リソースの名前も表示されます。

    証明書がプロビジョニングされ、Ingress の準備ができたら、アプリケーションにアクセスできます。

  4. 次のリンクにアクセスします。

    echo "https://frontend.endpoints.${PROJECT}.cloud.goog"
    

    Online Boutique のフロントエンドが表示されます。

    Online Boutique のホームページに表示される商品。

  5. 証明書の詳細を表示するには、ブラウザのアドレスバーの [サイト情報を表示]、[Certificate (Valid)] の順にクリックします。

    証明書ビューアには、証明書の有効期限や証明書の発行者など、マネージド証明書の詳細が表示されます。

これで、サービス メッシュでホストされるアプリケーションのフロントエンドとして機能するグローバル HTTPS ロードバランサが作成されました。

クリーンアップ

チュートリアルが完了したら、Google Cloud で作成したリソースをクリーンアップして、今後料金が発生しないようにします。プロジェクトを完全に削除するか、クラスタ リソースを削除してからクラスタを削除できます。

プロジェクトの削除

  1. Cloud Console で [リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

個々のリソースの削除

このチュートリアルで使用した Cloud プロジェクトを残しておく場合は、個々のリソースを削除します。

  1. Ingress リソースを削除します。

    kubectl delete -f ingress.yaml
    
  2. マネージド証明書を削除します。

    kubectl delete -f managed-cert.yaml
    
  3. 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.
    
  4. 続行を確認するメッセージが表示されたら、「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
    
  5. 静的 IP アドレスを削除します。

    gcloud compute addresses delete ingress-ip --global
    

    出力は次のようになります。

    The following global addresses will be deleted:
    
     - [ingress-ip]
    
  6. 続行を確認するメッセージが表示されたら、「Y」と入力します。

    出力は次のようになります。

    Deleted
    [https://www.googleapis.com/compute/v1/projects/edge2mesh/global/addresses/ingress-ip].
    
  7. GKE クラスタを削除します。

    gcloud container clusters delete $CLUSTER_NAME --zone $CLUSTER_LOCATION
    

次のステップ