マルチテナントにおけるOpenShift Service MeshによるRoute公開を検証してみた

マルチテナント環境において、OpenShift Service Meshを利用する場合の外部公開はどうすればいいか疑問を感じたので、OpenShift Service Meshを利用した場合の外部公開を検証しました。

  • OpenShiftのマルチテナント環境における外部公開(想定)
  • OpenShift Service Meshのマルチテナント環境における外部公開(想定)
  • OpenShift Service Meshの検証
    • メンバーロールの作成
    • Routeの作成
    • Gatewayの作成
  • 注意点

OpenShiftのマルチテナント環境における外部公開(想定)


マルチテナントプラットフォームにOpenShiftを採用する場合、Routeリソースを使って、それぞれのシステムを外部に公開することが想定されます。

マルチテナント管理チームがProjectリソースを作成・管理し、プロジェクトチームが各自でRouteリソースを作成することが考えられます。

※ベストプラクティスではなく、あくまでも想定です。要件・環境に応じて設計は変わることご認識いただければ幸いです。

OpenShift Service Meshのマルチテナント環境における外部公開(想定)


OpenShift Service Meshを利用する場合、Istio外部から受け付けるServiceリソースがService MeshのコントロールプレーンProjectにあります。Routeを利用して外部に公開するには、そのServiceに紐づいたRouteを作成する必要があります。

従って、RouteリソースをService MeshのコントロールプレーンProject内に作成し、各ProjectでService Meshのリソース(Gateway・VirtualService・DestinationRule)を作成する形が想定されます。

※ベストプラクティスではなく、あくまでも想定です。要件・環境に応じて設計は変わることご認識いただければ幸いです。

OpenShift Service Meshの検証


上記で想定した役割を踏まえて、実装してみました。

※VertualService/DestinationRule/Service/アプリケーションの作成は、通常のIstioと変わらないので省略しています。istio関連の操作については、Istio関連記事に投稿しています。
※OpenShift Service Meshのインストールは省略しています。インストール方法については、OpenShift Service Meshをインストールする方法に記載しています。

メンバーロールの作成


OpenShift Service Meshでは、ServiceMeshMemberRollというリソースに、Service Meshの対象プロジェクトを定義する必要があります。

以下のように、membersブロックにプロジェクト名を定義します。

apiVersion: maistra.io/v1
kind: ServiceMeshMemberRoll
metadata:
  name: default
  namespace: istio-system
  ownerReferences:
    - apiVersion: maistra.io/v1
      kind: ServiceMeshControlPlane
      name: basic-install
  finalizers:
    - maistra.io/istio-operator
spec:
  members:
    - project-a
    - project-b

Routeの作成


OpenShift Service MeshをOperatorHubからインストールすると、Istioが外部からの通信を受け付けるためのistio-ingressgateway Serviceリソースが作成されます。このServiceをRouteで外部に公開することで、クラスター外のユーザーからアクセスできるようになります。

以下のコマンドで、istio-ingressgateway に紐づくProjectAとProjectBのRouteリソースを作成します。

$ oc expose svc istio-ingressgateway --hostname=example-a.test.com --port=8080 --name=project-a --generator=route/v1
route.route.openshift.io/project-a exposed
$ oc expose svc istio-ingressgateway --hostname=example-b.test.com --port=8080 --name=project-b --generator=route/v1
route.route.openshift.io/project-b exposed

当然ながらhostnameは外部から名前解決できる必要があります。本記事ではローカルホストにexample-a.test.com, example-b.test.comを登録しました。

Gatewayの作成


各Projectで作成するGatewayを作成します。

project-aにexample-a.test.comの80番ポートで受け付けるa-gwを作成します。

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: a-gw
  namespace: project-a
spec:
  selector:
    istio: ingressgateway # use Istio default gateway implementation
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "example-a.test.com"

同様にproject-bにexample-b.test.comの80番ポートで受け付けるb-gwを作成します。

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: b-gw
  namespace: project-b
spec:
  selector:
    istio: ingressgateway # use Istio default gateway implementation
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "example-b.test.com"

example-a.test.com, example-b.test.comの名前でhttpリクエストを飛ばすと、それぞれのプロジェクトのアプリケーションに割り振られることが確認できました。

注意点


Gatewayリソースにおけるhostnameをワイルドカードにすると、期待していないアプリケーションに通信が飛んでしまうのでご注意ください。

名前解決や証明書のコントロールを考慮すると、RouteやGatewayはマルチテナント管理チームで作成・管理するのがいいのかもしれないなと感じました。

以上です。