Anthos Service Mesh を使用した Anthos clusters 間の通信の保護と暗号化

Last reviewed 2021-04-30 UTC

このドキュメントでは、Kubernetes クラスタを管理するネットワーク、プラットフォーム、セキュリティのエンジニアが、Anthos Service Mesh の上り(内向き)ゲートウェイと下り(外向き)ゲートウェイを使用して、外部のクラスタ間通信を処理する方法を示します。このドキュメントでは、Anthos Service Mesh を使用して、ある Kubernetes クラスタにデプロイされたワークロードから別の Kubernetes クラスタで実行されているワークロードへの下り(外向き)の送信トラフィックを暗号化し、保護する方法について説明します。ここで説明する手順では、相互の、暗号化されたクラスタ間の通信に、個別の証明書を使用する方法を示します。

このドキュメントのガイダンスは、クラスタ内通信に特定のルート認証局(CA)を使用するというお客様の要件に基づいています。このような要件は、金融サービスや医療など、規制の厳しい市場で使用される場合があります。ここで紹介するガイダンスでは、Kubernetes クラスタ以外のエンドポイント(金融クリアランス プロバイダや機密データ用の API インターフェースなど)も使用できます。このガイダンスは、厳格なセキュリティ ポリシーと監査ポリシーに準拠する必要がある組織に特に適しています。

クラスタで実行されているワークロードにアクセスすることなく、暗号化された通信を運用および処理できます。独自のクラスタを構成する方法に関するガイダンスについては、付属のチュートリアルをご覧ください。

はじめに

多くの企業が Kubernetes の導入を開始した最初の時点で、ほとんどの通信がクラスタ内部で完結する 1 つのクラスタで運用を開始します。まもなくして、名前空間をまたぐインタラクションの重要性が増大します。この段階では、Calico または Cillium などのネットワーク ポリシー プロバイダがサポートできます。しかし、コンテナ環境が拡大するにつれて、外部サービスと Kubernetes クラスタ内で実行されているコンテナとの間で安全な通信を実現することの重要性が高まります。

ネットワーク ポリシーは、クラスタ内部のファイアウォール ルールの作成など、従来のセキュリティ コンセプトに対処するには優れた手法ですが、クラスタ外での使用は限定的です。特定の IP アドレスのみにアクセスできるように設定できますが、コンテンツや ID は制御できません。したがって、より汎用性の高いコンセプトが必要となります。これにより、他の外部サービスへのトラフィックも暗号化できるようになります。次の図に、その方法の 1 つを示します。

公開証明書と限定公開(シークレット)証明書を使用してトラフィックを暗号化。

アプリケーション環境では通常、TLS(Transport Layer Security)を使用して暗号化が行われます。つまり、前の図に示すように、公開証明書と限定公開(シークレット)証明書を使用してトラフィックを暗号化しています。受信側は公開証明書を保持します。この証明書は、情報の発信元が信頼できるものであることを確認するために使用されます。HTTPS ウェブ トラフィックは TLS を使用して、クライアントとウェブサーバーの間で安全で暗号化された通信を確保します。この場合、公開証明書は信頼できる発行元(Google Trust Service など)から発行されています。これは、CA と呼ばれるもので、公開鍵基盤(PKI)の一部です。TLS はサーバーの ID を確認しますが、クライアントの ID は確認しません。

クライアント自体も検証する必要がある場合は、相互認証(mTLS)が必要です。mTLS を使用するのは、次の図に示すように、送信者と受信者の両方が相手に対して自身を識別しなければならない場合です。

相互認証(mTLS)を使用したトラフィックの暗号化。

この方法は多くの場合に、追加のセキュリティ レイヤを必要とするアプリケーションで使用されます。金融業界や個人を特定できる情報(PII)を扱う規制当局は、多くの場合 mTLS を必要とします。

Anthos Service Mesh

Anthos Service Mesh は、OSS Istio に基づく Google 管理のサービス メッシュ ソリューションです。つまり、Istio API と 100% 互換性があります。Anthos Service Mesh は、アプリケーション コード内ではなくプラットフォーム レベルで mTLS 機能を提供できます。つまり、すべてのサービスを再コーディングすることなくサービスに適用できます。証明書のローテーションなどのオペレーションも Anthos Service Mesh の一部です。このドキュメントでは、mTLS と Anthos Service Mesh の外部通信機能を中心に説明します。フォールト インジェクション、高度なロード バランシング、エラー処理など、その他の機能は多数あります。

すべてのトラフィックをサイドカー プロキシ(Envoy)経由でルーティングすることで、Anthos Service Mesh などのサービス メッシュは、暗号化や証明書の処理などの煩雑な(ただし重要な)タスクについてのデベロッパーの負担を軽減します。透過的プロキシを使用すると、サービス メッシュで、ヘッダー情報に基づいて HTTP および HTTPS 呼び出しをルーティングするなどの、強力な L7 機能を有効にできます。ただし、Anthos Service Mesh はトラフィックのカプセル化と暗号化も有効にできるため、セキュリティが強化されます。

構成例: クラスタ間での MySQL の通信

このシナリオは、異なるクラスタ内のサービス間で安全かつ信頼できる通信が必要な場合に使用できます。この例では、次の図に示すように、MySQL クライアント アプリケーションが、別の Kubernetes クラスタで実行されている MySQL サーバーの DB ワークロードと通信します。

異なる Kubernetes クラスタで実行されている MySQL サーバー DB ワークロードと通信する MySQL クライアント アプリケーション。

多くの場合、サービス メッシュは OSI L7 で動作しますが、その一部を使用して L4 通信を制御することもできます。

コンセプトの機能を有効にする際の要件を以下に記載します。

  • アプリケーションとクラスタ間の通信は暗号化する必要があります。
  • クライアントとサーバー間の通信を相互検証(mTLS)する必要があります。
  • クライアント ワークロードとサーバー ワークロードを変更する必要はありません。

暗号化された接続のみを受け入れるように MySQL データベースをセットアップできますが、このセットアップではデータベース クライアントを変更する必要があります。このデータベース クライアントを完全に制御することはできません。

Anthos Service Mesh を使用して、これらの要件に対応するための複数の方法が存在します。1 つの方法は、クラスタ間で Istio の共有コントロール プレーンを作成し、1 つの論理サービス メッシュに属していることによって、複数のサービスが相互に通信するように設定することです。この設定は、Anthos 対応の GKE クラスタに対して、1 つのプロジェクトまたはマルチプロジェクトのセットアップで Anthos Service Mesh を使用して行うことができます。

ただし、クラスタ間通信には個別の信頼チェーンが必要であるため、mTLS を使用した下り(外向き)ゲートウェイ <–> 上り(内向き)ゲートウェイのアプローチを使用できます。

下り(外向き)ゲートウェイと上り(内向き)ゲートウェイは、メッシュの境界に存在する Envoy プロキシです。

サービス メッシュとの間のトラフィック フローを制御するように、それらを構成できます。これは Kubernetes 以外のエンドポイントでも機能し、暗号化された通信に異なる証明書を使用できるようにします。

Anthos Service Mesh の下り(外向き)と上り(内向き)を構成する

前述のシナリオでは、それぞれのクラスタ間で下り(外向き)ゲートウェイと上り(内向き)ゲートウェイを使用して、安全なクラスタ間通信を処理します。

下り(外向き)ゲートウェイとは

下り(外向き)とは、サービス メッシュから外部に送信されるトラフィックを指します。下り(外向き)ゲートウェイは、対象のトラフィックに対して制御された終了ポイントとしての役割を果たします。

追加の構成なしでサイドカー プロキシが挿入された Pod の場合、メッシュの外部にあるサービス(公開 API サービスなど)を宛先とするトラフィックは、Pod からサイドカー プロキシにルーティングされます。GKE クラスタ(およびその他のほとんどの Kubernetes クラスタ)では、ノードの IP アドレスが NAT を使用してサイドカー プロキシのトラフィックを変換し、直接サービスの外部アドレスに向かいます。以下の図に、この構成を示します。

クライアントが、外部サービスを表すサーバーサイドを呼び出します。

この図でクライアントは、外部サービスを表すサーバーサイドを呼び出しています。このトラフィックはメッシュに送信されるため、クライアントサイド(例: MySQL クライアント)で下り(外向き)ゲートウェイを構成する必要があります。

呼び出しを外部サービスに転送するように下り(外向き)ゲートウェイを構成します。外部サービスがリクエストを処理してレスポンスを返すと、下り(外向き)ゲートウェイを介して再びクライアント プロキシに戻り、最終的に呼び出しを行っている Pod(MySQL クライアントなど)に戻ります。

上り(内向き)ゲートウェイとは

上り(内向き)とは、サービス メッシュに向かうトラフィックのことです。上り(内向き)ゲートウェイは、サービスを外部(つまり、サービス メッシュの外部)に公開し、これらのサービスにアクセスする方法を処理します。Kubernetes Ingress オブジェクトと同等です。

上り(内向き)ゲートウェイを使用すると、トラフィックがメッシュに入る単一の制御されたエントリ ポイントを定義できます。最初にトラフィックがロードバランサを経由します。これは、上り(内向き)ゲートウェイ サービスを定義することで作成されます。そこからリクエストはサイドカー プロキシに転送され、プロキシから Pod に転送されます。Pod はリクエストを処理し、同じルートを逆に使用してレスポンスを返します。以下の図に、この構成を示します。

トラフィックはロードバランサを経由し、リクエストがサイドカー プロキシと Pod に転送されます。

このトラフィックは、他のクラスタ(VPC 2)のメッシュへのインバウンド トラフィックです。したがって、これらの呼び出しを処理するように、サーバーサイドで上り(内向き)ゲートウェイを構成する必要があります。

上り(内向き)ゲートウェイのサーバーサイドの構成により、呼び出しが内部サービスに転送されます。内部サービスがリクエストを処理した後、返されたレスポンスは上り(内向き)ゲートウェイを介してクライアントに返送されます。

下り(外向き)機能と上り(内向き)機能の併用により相互 TLS を実現する

前述のように、クライアントサイドでは、サービス メッシュの制御された終了ポイントとして機能する下り(外向き)ゲートウェイを定義する必要があります。ゲートウェイを通過してメッシュから送信されるトラフィックが mTLS によって暗号化されるようにするには、TLS 発信と呼ばれる手法を使用できます。外部サービスへのトラフィックで TLS 発信を行うように下り(外向き)ゲートウェイを構成します。

クライアントサイドのサービス メッシュから発信されたトラフィックが暗号化された際に、サーバーサイドがクライアントに対して自身を識別し、暗号化されたトラフィックを解読できるようにする必要があります。

そのためには、上り(内向き)ゲートウェイをメッシュへの単一のエントリ ポイントとして使用します。相互に暗号化されたトラフィックを受け入れるように上り(内向き)ゲートウェイを構成します。

メッシュ アーキテクチャの概要

次の図は、MySQL シナリオでこのコンセプトを実装するための要件を示したものです。アプリケーションまたはサーバーについては、何も変更する必要はありません。

VPC 1 では、MySQL クライアントを実行しているクライアント クラスタがサーバーにアクセスしていることを確認できます。サーバーは VPC 2 に配置されています。

クライアントサイドでは、トラフィックのマッチングとルーティングに関してより多くの処理を行う必要があることから、アプリケーションが下り(外向き)ゲートウェイを使用するようにするために、サーバーサイドよりも構成の重みが大きくなります。ただし、この構成について毎日行う必要のある作業は存在しません。すなわち、構成を行う必要があるのは 1 回のみです。実装後は保守が大幅に簡易化されます。

このコンセプトを Kubernetes を使用して実装することの利点は、すべての構成項目が YAML ファイルに格納されることです。つまり、ビルド全体をバージョン管理されたリポジトリで使用して変更を追跡し、必要に応じて簡単に元に戻すことができます。

クライアントサイド

このサブセクションでは、クライアントサイドの構成について説明します。図の各要素は、下り(外向き)ゲートウェイ経由で宛先である MySQL サーバーにトラフィックをルーティングする際の方法を制御するメッシュ内の個別の機能を備えています。

トラフィックのルーティングは、必要な機能の一部にすぎません。他の要素によってもトラフィックの暗号化が制御され、完全に透過的なため、常に通信の安全性が確保されます。次のセクションでは、このシナリオでのロールと機能について説明します。

下り(外向き)ゲートウェイ経由で MySQL サーバーにトラフィックがルーティングされる方法を示すクライアントサイドの構成。

サービス エントリ

サービス メッシュでは、Kubernetes クラスタに対して独自のサービス レジストリが作成されます。コントロール プレーンはこのレジストリを使用して、サイドカー プロキシをルーティング テーブルとして構成します。Kubernetes で実行されているサービスは自動的に検出され、サービス メッシュ レジストリに追加されます。Kubernetes クラスタ内で実行されていないサービスは自動的に検出できませんが、ServiceEntry を使用して定義できます。これにより、クライアントはエントリをホスト名として使用して外部サービスに接続できます。

Anthos Service Mesh では、完全修飾ドメイン名(FQDN)を使用してすべてのサービスが識別されます。証明書はホスト名に基づいているため、FQDN はこの構成で最も重要な部分です。FQDN は変更できますが、その場合は必要な証明書をすべて再生成する必要があります。

通信を有効にするには、トラフィックを適切にルーティングするために、外部サービスに対する呼び出しをリッスンするようにサービス メッシュを構成する必要があります。このメッシュを使用すると、その外部サービスを指すサービス エントリを定義できます。

この構造は MESH_EXTERNAL と呼ばれ、このようなユースケースに最適です。また、探しているものを指定することもできます。これは L4 のユースケースで、IP アドレスとポートのみを制御できるため、プロトコルと特定のポートをメッシュに伝える必要があります。(この場合、TCP とポート 3306(標準 MySQL プロトコル ポート)です。また、サーバーサイドの対応するコンポーネント(上の図を参照)は、ポート 13306(サーバー クラスタの下り(外向き)ゲートウェイ)でリッスンしています。最後に、サービス エントリに対し、このポートタグでトラフィックをキャプチャするように指示する必要があります。

次の YAML サービス エントリの例は、この構成を示しています。

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
 name: mysql-external
spec:
 hosts:
   - mysql.fqdn.example
 location: MESH_EXTERNAL
 ports:
   - number: 3306
     name: tcp
     protocol: TCP
   - number: 13306
     name: tls
     protocol: TLS
 resolution: DNS
 endpoints:
   - address: mysql.fqdn.example
     ports:
       tls: 13306

hosts フィールドを使用して外部サービスの FQDN を設定するか、location フィールドを MESH_EXTERNAL に指定できます。また、外部サービスで使用される ports 値(この場合は 133063306)も指定する必要があります。13306 は、サーバーサイドの上り(内向き)ゲートウェイから公開されるポートです。このサービス エントリで両方を指定することが重要です。この接続は L4 ベースの TLS 通信を提供するため、プロトコルには TLS を指定する必要があります。

サービス エントリを定義すると、メッシュはこれらのルールに基づいて呼び出しをリッスンし、ルーティングを変更できます。

サービス エントリは、既存の DNS エントリまたは IP アドレス エントリに基づいている必要があります。つまり、DNS 名はすでに DNS サーバーで解決可能である必要があります。たとえば、Kubernetes 内でコア DNS サービスを使用し、まだ kube-dns に存在しないエントリを Kubernetes サービスに追加できます。サービス エントリを使用して DNS エントリを作成することはできません。

仮想サービス

仮想サービスは、トラフィック ルーティング パターンに影響するために使用する定義です。仮想サービスを使用して、MySQL クライアントからサービス エントリへの呼び出しが下り(外向き)ゲートウェイに確実にルーティングされるようにします。したがって、まったく異なる要因に基づいてトラフィックをルーティングするように仮想サービスを設定できます。L7 のユースケースでは、これらの要因はトラフィック ルーティングに優先します。たとえば、ターゲットに到達できない場合の対処方法を仮想サービスに指示できます。この例では、一致トラフィックのみを今後の処理のために下り(外向き)ゲートウェイにルーティングするために、この機能のサブセットを使用します。

仮想サービスを使用して、Pod からプロキシを経由して下り(外向き)ゲートウェイにトラフィックをルーティングし、下り(外向き)ゲートウェイから外部サービスにルーティングします。

前の図は、仮想サービスを使用して、トラフィックを Pod からプロキシ経由で下り(外向き)ゲートウェイに、下り(外向き)ゲートウェイから外部サービスにルーティングする方法を示しています。

下り(外向き)ゲートウェイのポートも指定する必要があります。これはデフォルトで 15443 です。このポートは、作成された際に下り(外向き)ゲートウェイで設定されます。他の任意のフリーポートを選択できますが、選択したポートを開くにはゲートウェイにパッチを適用する必要があります。

次のコード スニペットは、そのような仮想サービスの定義を示しています。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: direct-mysql-through-egress-gateway
spec:
 hosts:
   - mysql.fqdn.example
 gateways:
   - istio-egressgateway-mysql
   - mesh
 tcp:
   - match:
       - gateways:
           - mesh
         port: 3306
     route:
       - destination:
           host: istio-egressgateway.istio-system.svc.cluster.local
           subset: mysql
           port:
             number: 15443
         weight: 100
   - match:
       - gateways:
           - istio-egressgateway-mysql
         port: 15443
     route:
       - destination:
           host: mysql.fqdn.example
           port:
             number: 13306
         weight: 100

FQDN URL を保持する hosts フィールドは、指定された URL のみに一致ルールを適用するために使用されます。最初の match 句はメッシュで定義されます。これは予約済みのキーワードであり、メッシュ内のすべてのゲートウェイに適用されます。最初の route ブロックは、一致が true の場合に行う処理をメッシュに伝えるために定義されています。この場合、一致したトラフィックを下り(外向き)ゲートウェイに送信します。ここでは、ルートの重み付けに加えて、下り(外向き)ポートが定義されます。このブロックには、後で定義する subset 値も指定されています。

2 番目の match 句が下り(外向き)ゲートウェイに適用されます。2 番目の match 句に付加された 2 番目の route ブロックは、上り(内向き)FQDN で host フィールドを使用して、ポート 13306 を指定して、トラフィックを上り(内向き)サーバー クラスタに送信するようにメッシュを構成します。

次のステップでは、mTLS 通信が機能するように、証明書の挿入をゲートウェイにプログラムする必要があります。

宛先ルール

トラフィックが適切に識別され(サービス エントリ)、Pod からプロキシ経由でゲートウェイ(仮想サービス)にルーティングされたので、次のステップではトラフィックを暗号化します。トラフィックを暗号化するには、宛先ルールを使用します。サービス メッシュ内のこのようなルールは、ルーティングの後にトラフィックに適用され、ロード バランシングやその他のトラフィック管理機能を導入するために使用されます。

宛先ルールをルーティング後のトラフィックに適用する。

このケースでは、宛先ルールを使用して標準のロード バランシング パターンを定義し、mTLS 通信を使用してエンドポイントを有効にする証明書も追加します。この手順は、サーバー クラスタの上り(内向き)ゲートウェイを介して公開される MySQL サーバーの FQDN をマッチングし、mTLS ルールを定義することによって実行されます。

次の定義は、そのような宛先ルールの例です。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: egressgateway-for-mysql
spec:
  host: istio-egressgateway.istio-system.svc.cluster.local
  subsets:
    - name: mysql
      trafficPolicy:
        loadBalancer:
          simple: ROUND_ROBIN
        portLevelSettings:
          - port:
              number: 15443
            tls:
              mode: ISTIO_MUTUAL
              sni: mysql.fqdn.example

host フィールドは、下り(外向き)ゲートウェイのクラスタ FQDN に設定されます。最初の宛先ルールは、下り(外向き)ゲートウェイの FQDN を使用する ISTIO_MUTUAL モードを使用して、トラフィックの内部メッシュの暗号化を行います。コード スニペットでは、subset を定義します。これは、ラウンドロビン ロード バランシングの作成、15443 へのポートの設定(上書き)に使用されます。下り(外向き)ゲートウェイは、このポートを使用してトラフィックを送信します。

内部メッシュのポリシー(ISTIO_MUTUAL)を定義する tls フィールドを正しく設定することが重要です。sni(サービス名表示)フィールドに、サーバー クラスタからの上り(内向き)ゲートウェイの FQDN を追加します。

2 番目の宛先ルールは、カスタムで指定されたルート CA 証明書でトラフィックを暗号化してから、下り(外向き)ゲートウェイを介して送信します。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: originate-mtls-for-mysql
spec:
 host: mysql.fqdn.example
 trafficPolicy:
   loadBalancer:
     simple: ROUND_ROBIN
   portLevelSettings:
   - port:
       number: 13306
     tls:
       mode: MUTUAL
       credentialName: client-credential
       sni: mysql.fqdn.example

host フィールドが外部 FQDN に再び設定されます。trafficPolicy フィールドでは、ロードバランサ モードが ROUND_ROBIN に設定されます。また、カスタムルート CA 証明書を使用しているため、ポートが 13306 に、tls モードが MUTUAL に設定されます。対応する上り(内向き)ゲートウェイでは tls MUTUAL も使用するため、同じ署名付きルート CA 証明書を使用してそれ自体を識別する必要があります。このポートを使用すると、トラフィックは上り(内向き)ゲートウェイ経由でサーバー クラスタを通過して MySQL データベースに到達できます。

カスタムルート CA 証明書を使用する暗号化は、通常、証明書を保持している Kubernetes のシークレットを使用して Envoy Secret Discovery Service(SDS)を介して実行されます。宛先ルールにシークレット名を追加するには、credentialName フィールドを使用します。

この時点でのトラフィックの動作を要約すると、次のとおりです。

  • これは、MySQL が外部 FQDN に対して透過的に発行します。この FQDN はメッシュ登録に存在します。
  • 内部メッシュ証明書を使用して宛先ルールによって暗号化されます。
  • 仮想サービスによってゲートウェイにルーティングされます。
  • 宛先ルールによってカスタムルート CA を使用して暗号化されます(これは、メッシュ証明書に使用されるメッシュ CA とは異なります)。
  • mTLS モードで下り(外向き)ゲートウェイを通して転送されます。

サーバーサイド

このシナリオでは、クライアントサイドよりもサーバーサイドの構成を容易に行うことができます。次の図に示すように、必要とされるのは、上り(内向き)ゲートウェイとトラフィックを MySQL DB サーバーにルーティングするための仮想サービス エントリのみです。

上り(内向き)ゲートウェイとトラフィックを MySQL サーバーにルーティングする仮想サービス エントリが配置されたサーバーサイドの構成。

サーバー クラスタの上り(内向き)ゲートウェイ

上り(内向き)ゲートウェイがポート 13306 を公開しています。任意のポートを指定できますが、この例では、標準の MySQL ポートの前に「1」を追加して、簡単に識別できるようにしています。セキュリティ上の理由から、標準の MySQL ポート(3306)をインターネットに直接公開することはおすすめしません。

デフォルトの Istio 上り(内向き)ゲートウェイはポート 13306 をリッスンしていないため、この機能を追加する必要があります。次のコード スニペットの例では、ポート 13306 をゲートウェイにパッチ適用しています。

[{
  "op": "add",
  "path": "/spec/ports/0",
  "value": {
    "name": "tls-mysql",
    "protocol": "TCP",
    "targetPort": 13306,
    "port": 13306
  }
}]

このコードを JSON ファイルに格納し、kubectl patch コマンドとともに使用して、上り(内向き)ゲートウェイ サービスに適用できます。

トラフィックを正しく処理するには、MUTUAL モードで上り(内向き)ゲートウェイを設定する必要があります。

この時点で、上り(内向き)ゲートウェイは認証情報ストアから取得した証明書を使用して受信トラフィックを復号し、トラフィックをメッシュに送信します。ここで、メッシュの内部証明書を使用してトラフィックが再暗号化されます。次のコード スニペットの例は、その構成方法を示しています。

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: gateway-mysql
spec:
 selector:
   istio: ingressgateway # Istio default gateway implementation
 servers:
 - port:
     number: 13306
     name: tls-mysql
     protocol: TLS
   tls:
     mode: MUTUAL
     credentialName: mysql-credential
   hosts:
   - "mysql.fqdn.example"

この例では、標準の Istio 上り(内向き)ゲートウェイが selector フィールドで使用されています。servers フィールドを使用して、上り(内向き)で想定されるポート number13306)と protocolTLS)の値を設定できます。ポートに一意の名前を付けることが重要です。

tls を定義し、credentialName フィールドを使用して下り(外向き)ゲートウェイで使用されているものと同じルート CA によって署名された証明書を格納するシークレットを指定します。証明書は Kubernetes シークレットに保存されている必要があります。

最後に、MySQL DB FQDN を指すトラフィックを照合します。hosts で設定されたこの FQDN の名前解決は、上り(内向き)ゲートウェイのパブリック IP アドレスに設定する必要があります。

サーバー クラスタの仮想サービス

トラフィックがクライアント クラスタ(送信元)の下り(外向き)ゲートウェイからポート 13306 を介してメッシュに入ったら、このトラフィックを識別して、MySQL DB サーバーに確実に到達するようにする必要があります。そのためには、仮想サービスを定義します。

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: mysql-virtual-service
spec:
 hosts:
   - "mysql.fqdn.example"
 gateways:
   - gateway-mysql
 tcp:
   - route:
     - destination:
         port:
           number: 3306
         host: mysql.default.svc.cluster.local

MySQL DB サービスにトラフィックを送信するには、hosts フィールドを使用して FQDN ホストを再度確認する必要があります。また、この仮想サービス定義の適用先を構成するには、gateways フィールドを使用する必要があります。これは、上記の YAML ファイルで定義したゲートウェイ オブジェクトです。これは L4 トラフィックであるため、tcp フィールドを設定し、また MySQL DB Kubernetes Service を指すように route フィールドを設定します。Kubernetes クラスタ内部 FQDN を使用して、host フィールドにサービス名を指定する必要があります。

MySQL DB は、ポート「3306」でクライアントからのリクエストを取得します。トラフィックは、MySQL DB サーバーのサイドカー プロキシを通過します。

MySQL DB は、ポート 3306 でクライアントからのリクエストを取得できます。トラフィックは MySQL DB サーバーのサイドカー プロキシを通過します。MySQL DB サーバーに対しては、これはデータベースにアクセスするための暗号化されていないローカル リクエストのように見えます。

サーバーが呼び出しに応答すると、トラフィックは同じルートを使用してクライアントに返されます。クライアントでは、ローカル DB が呼び出しに応答したものとして認識されます。

トラフィックは、クライアントからサーバーへ移動する間に異なる証明書を使用して 3 回暗号化されます。これにより、クライアントとサーバー間の通信を保護できます。

トラフィックの最初の暗号化または復号は、クライアントサイドのメッシュ内でメッシュ CA を使用して証明書を用いて行われます。

2 回目のトラフィックの暗号化は、カスタムルート CA の証明書を使用して下り(外向き)ゲートウェイからメッシュ外部へ送信される際に行われます。その後、同じカスタムルート CA によって署名された証明書を使用して、上り(内向き)ゲートウェイでトラフィックが認証および復号されます。

最後(3 回目)については、トラフィックは上り(内向き)ゲートウェイを通過して MySQL サーバーに向かう際にメッシュ内で暗号化または復号されます。ここでも、メッシュ内部であるため、メッシュ CA の証明書が使用されます。

このシナリオでは、2 つのクラスタ間の通信を、前述のルート CA を使用して暗号化する必要がありました。この構成を適用することで、メッシュの内部証明書やアプリケーション自体から、この部分を独立して処理することが可能になります。

この追加のステップを行うことによって、この構成では、各 Kubernetes クラスタのメッシュ CA を変更することなく、これらの証明書を定期的かつ容易にローテーションすることもできます。

次のステップ