マルチクラスタサービスメッシュにおけるバージョンルーティング

マルチクラスタサービスメッシュでのIstioルートルールの設定。

2019年2月7日 | Frank Budinsky - IBM

Istioを少しでも調べたことがある方は、単純なタスクや単一のKubernetesクラスタで実行されるサンプルでデモできる多くの機能が含まれていることに気づいたでしょう。ほとんどすべての実世界のクラウドおよびマイクロサービスベースのアプリケーションはそれほど単純ではなく、サービスを複数の場所に分散して実行する必要があるため、これらのことが実際のプロダクション環境でも同じようにシンプルになるのか疑問に思われるかもしれません。

幸いなことに、Istioには、アプリケーションが、複数のクラスタ、つまりマルチクラスタデプロイメントでサービスが実行されているメッシュの一部として、ほぼ透過的に動作するようにサービスメッシュを構成するいくつかの方法が用意されています。特別なネットワーク要件がないため、マルチクラスタメッシュを設定する最も簡単な方法は、レプリケートされたコントロールプレーンモデルを使用することです。この構成では、メッシュに参加する各Kubernetesクラスタは独自のコントロールプレーンを持っていますが、各コントロールプレーンは同期され、単一の管理制御下で実行されます。

この記事では、Istioの機能の1つであるトラフィック管理が、専用コントロールプレーントポロジを持つマルチクラスタメッシュでどのように機能するかを見ていきます。reviewsサービスのバージョンv1を1つのクラスタで、バージョンv2v3を2番目のクラスタで実行するBookinfoサンプルをデプロイすることで、マルチクラスタサービスメッシュでリモートサービスを呼び出すためのIstioルートルールの設定方法を示します。

クラスタの設定

まず、Istioの構成を少しカスタマイズした2つのKubernetesクラスタが必要です。

cluster1bookinfoアプリケーションのバージョンv1をデプロイします

cluster1productpageおよびdetailsサービスと、reviewsサービスのバージョンv1を実行します

$ kubectl label --context=$CTX_CLUSTER1 namespace default istio-injection=enabled
$ kubectl apply --context=$CTX_CLUSTER1 -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: productpage
  labels:
    app: productpage
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: productpage
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: productpage-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: productpage
        version: v1
    spec:
      containers:
      - name: productpage
        image: istio/examples-bookinfo-productpage-v1:1.10.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
apiVersion: v1
kind: Service
metadata:
  name: details
  labels:
    app: details
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: details
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: details-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: details
        version: v1
    spec:
      containers:
      - name: details
        image: istio/examples-bookinfo-details-v1:1.10.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
apiVersion: v1
kind: Service
metadata:
  name: reviews
  labels:
    app: reviews
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: reviews
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: reviews-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: reviews
        version: v1
    spec:
      containers:
      - name: reviews
        image: istio/examples-bookinfo-reviews-v1:1.10.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
EOF

cluster2bookinfo v2およびv3サービスをデプロイします

cluster2ratingsサービスと、reviewsサービスのバージョンv2およびv3を実行します

$ kubectl label --context=$CTX_CLUSTER2 namespace default istio-injection=enabled
$ kubectl apply --context=$CTX_CLUSTER2 -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: ratings
  labels:
    app: ratings
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: ratings
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: ratings-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: ratings
        version: v1
    spec:
      containers:
      - name: ratings
        image: istio/examples-bookinfo-ratings-v1:1.10.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
apiVersion: v1
kind: Service
metadata:
  name: reviews
  labels:
    app: reviews
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: reviews
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: reviews-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: reviews
        version: v2
    spec:
      containers:
      - name: reviews
        image: istio/examples-bookinfo-reviews-v2:1.10.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: reviews-v3
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: reviews
        version: v3
    spec:
      containers:
      - name: reviews
        image: istio/examples-bookinfo-reviews-v3:1.10.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
EOF

bookinfoアプリケーションへのアクセス

他のアプリケーションと同様に、Istioゲートウェイを使用してbookinfoアプリケーションにアクセスします。

reviewsサービスのv1のみがcluster1で実行されており、cluster2へのアクセスをまだ構成していないため、レビューが表示されたproductpageが表示されますが、評価は表示されません。

リモートreviewsサービス用にcluster1にサービスエントリと宛先ルールを作成します

設定手順で説明されているように、リモートサービスには.global DNS名を使用してアクセスします。この場合、reviews.default.globalなので、そのホストのサービスエントリと宛先ルールを作成する必要があります。サービスエントリは、サービスにアクセスするためのエンドポイントアドレスとしてcluster2ゲートウェイを使用します。ゲートウェイにDNS名がある場合はDNS名を使用するか、次のようにパブリックIPを使用できます。

$ export CLUSTER2_GW_ADDR=$(kubectl get --context=$CTX_CLUSTER2 svc --selector=app=istio-ingressgateway \
    -n istio-system -o jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}")

次のコマンドを使用して、サービスエントリと宛先ルールを作成します

$ kubectl apply --context=$CTX_CLUSTER1 -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: reviews-default
spec:
  hosts:
  - reviews.default.global
  location: MESH_INTERNAL
  ports:
  - name: http1
    number: 9080
    protocol: http
  resolution: DNS
  addresses:
  - 240.0.0.3
  endpoints:
  - address: ${CLUSTER2_GW_ADDR}
    labels:
      cluster: cluster2
    ports:
      http1: 15443 # Do not change this port value
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews-global
spec:
  host: reviews.default.global
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v2
    labels:
      cluster: cluster2
  - name: v3
    labels:
      cluster: cluster2
EOF

サービスエントリのアドレス240.0.0.3は、任意の未割り当てのIPにすることができます。クラスEアドレス範囲240.0.0.0/4のIPを使用するのが良い選択です。詳細については、ゲートウェイ接続マルチクラスタの例を参照してください。

宛先ルールのサブセットのラベルが、cluster2ゲートウェイに対応するサービスエントリエンドポイントラベル(cluster: cluster2)にマップされることに注意してください。リクエストが宛先クラスタに到達すると、ローカル宛先ルールが、要求されたサブセットに対応する実際のポッドラベル(version: v1またはversion: v2)を識別するために使用されます。

ローカルreviewsサービス用に両方のクラスタに宛先ルールを作成します

技術的には、各クラスタで使用されているローカルサービスのサブセット(つまり、cluster1v1cluster2v2v3)のみを定義する必要がありますが、簡単にするために、実際にデプロイされていないバージョンのサブセットを定義しても問題ないため、両方のクラスタですべての3つのサブセットを定義します。

$ kubectl apply --context=$CTX_CLUSTER1 -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews.default.svc.cluster.local
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3
EOF
$ kubectl apply --context=$CTX_CLUSTER2 -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews.default.svc.cluster.local
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3
EOF

reviewsサービストラフィックをルーティングするための仮想サービスを作成します

この時点で、reviewsサービスへのすべての呼び出しは、ローカルのreviewsポッド(v1)に送られます。これは、ソースコードを見ると、productpageの実装が単にhttp://reviews:9080(ホストreviews.default.svc.cluster.localに展開される)へのリクエストを行っているため、ローカルバージョンのサービスです。対応するリモートサービスはreviews.default.globalという名前なので、グローバルホストにリクエストをリダイレクトするにはルートルールが必要です。

次の仮想サービスを適用して、ユーザーjasonのトラフィックをcluster2で実行されているreviewsバージョンv2v3(50/50)に転送します。他のユーザーのトラフィックはreviewsバージョンv1に送られます。

$ kubectl apply --context=$CTX_CLUSTER1 -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews.default.svc.cluster.local
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews.default.global
        subset: v2
      weight: 50
    - destination:
        host: reviews.default.global
        subset: v3
      weight: 50
  - route:
    - destination:
        host: reviews.default.svc.cluster.local
        subset: v1
EOF

ブラウザに戻り、ユーザーjasonとしてログインします。ページを数回リフレッシュすると、評価の星が黒と赤(v2v3)で交互に表示されるはずです。ログアウトすると、評価なしのレビュー(v1)のみが表示されます。

まとめ

この記事では、レプリケートされたコントロールプレーンモデルを持つマルチクラスタサービスメッシュで、Istioルートルールを使用してサービスバージョンをクラスタ間で分散する方法を見てきました。この例では、1つのリモートサービスreviewsへの接続を提供するために必要な.globalサービスエントリと宛先ルールを手動で構成しました。ただし、一般に、サービスがローカルまたはリモートで実行できるようにするには、すべてのサービスに対して.globalリソースを作成する必要があります。幸いなことに、このプロセスは自動化でき、おそらく将来のIstioリリースで実現されるでしょう。

この記事を共有