マルチクラスタサービスメッシュにおけるバージョンルーティング
マルチクラスタサービスメッシュでのIstioルートルールの設定。
Istioを少しでも調べたことがある方は、単純なタスクや単一のKubernetesクラスタで実行されるサンプルでデモできる多くの機能が含まれていることに気づいたでしょう。ほとんどすべての実世界のクラウドおよびマイクロサービスベースのアプリケーションはそれほど単純ではなく、サービスを複数の場所に分散して実行する必要があるため、これらのことが実際のプロダクション環境でも同じようにシンプルになるのか疑問に思われるかもしれません。
幸いなことに、Istioには、アプリケーションが、複数のクラスタ、つまりマルチクラスタデプロイメントでサービスが実行されているメッシュの一部として、ほぼ透過的に動作するようにサービスメッシュを構成するいくつかの方法が用意されています。特別なネットワーク要件がないため、マルチクラスタメッシュを設定する最も簡単な方法は、レプリケートされたコントロールプレーンモデルを使用することです。この構成では、メッシュに参加する各Kubernetesクラスタは独自のコントロールプレーンを持っていますが、各コントロールプレーンは同期され、単一の管理制御下で実行されます。
この記事では、Istioの機能の1つであるトラフィック管理が、専用コントロールプレーントポロジを持つマルチクラスタメッシュでどのように機能するかを見ていきます。reviews
サービスのバージョンv1
を1つのクラスタで、バージョンv2
とv3
を2番目のクラスタで実行するBookinfoサンプルをデプロイすることで、マルチクラスタサービスメッシュでリモートサービスを呼び出すためのIstioルートルールの設定方法を示します。
クラスタの設定
まず、Istioの構成を少しカスタマイズした2つのKubernetesクラスタが必要です。
レプリケートされたコントロールプレーンの手順に従って、2つのIstioクラスタを持つマルチクラスタ環境をセットアップします。
kubectl
コマンドは、--context
フラグを使用して両方のクラスタにアクセスするために使用されます。次のコマンドを使用してコンテキストをリストします$ kubectl config get-contexts CURRENT NAME CLUSTER AUTHINFO NAMESPACE * cluster1 cluster1 user@foo.com default cluster2 cluster2 user@foo.com default
構成のコンテキスト名を持つ次の環境変数をエクスポートします
$ export CTX_CLUSTER1=<cluster1 context name> $ export CTX_CLUSTER2=<cluster2 context name>
cluster1
にbookinfo
アプリケーションのバージョンv1をデプロイします
cluster1
でproductpage
および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
cluster2
にbookinfo
v2およびv3サービスをデプロイします
cluster2
でratings
サービスと、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
アプリケーションにアクセスします。
cluster1
にbookinfo
ゲートウェイを作成します$ kubectl apply --context=$CTX_CLUSTER1 -f @samples/bookinfo/networking/bookinfo-gateway.yaml@
Bookinfoサンプルの手順に従って、ingress IPとポートを決定し、ブラウザを
http://$GATEWAY_URL/productpage
に向けてください。
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サービス用に両方のクラスタに宛先ルールを作成します
技術的には、各クラスタで使用されているローカルサービスのサブセット(つまり、cluster1
のv1
、cluster2
のv2
とv3
)のみを定義する必要がありますが、簡単にするために、実際にデプロイされていないバージョンのサブセットを定義しても問題ないため、両方のクラスタですべての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
バージョンv2
とv3
(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
としてログインします。ページを数回リフレッシュすると、評価の星が黒と赤(v2
とv3
)で交互に表示されるはずです。ログアウトすると、評価なしのレビュー(v1
)のみが表示されます。
まとめ
この記事では、レプリケートされたコントロールプレーンモデルを持つマルチクラスタサービスメッシュで、Istioルートルールを使用してサービスバージョンをクラスタ間で分散する方法を見てきました。この例では、1つのリモートサービスreviews
への接続を提供するために必要な.global
サービスエントリと宛先ルールを手動で構成しました。ただし、一般に、サービスがローカルまたはリモートで実行できるようにするには、すべてのサービスに対して.global
リソースを作成する必要があります。幸いなことに、このプロセスは自動化でき、おそらく将来のIstioリリースで実現されるでしょう。