はじめに
Istioのトラフィック制御関連のカスタムリソースについて、ざっくり解説していきます。
また、その中からよく使うものを実際に動かしながら理解していきたいと思います。
Istioの基礎については、こちらで解説しています。

トラフィック制御に関するカスタムリソース
Istioでのトラフィック制御関連のカスタムリソースは下記の通りです。
リソース | 説明 |
---|---|
VirtualService | サービスメッシュ内のトラックのルーティングを設定 |
DestinationRule | 実際に届くトラフィックのルールを設定 |
Gateway | 外部とのトラフィックの出入口を定義 |
ServiceEntry | サービスレジストリに宛先を追加 |
Sidecar | サイドカーのEnvoyプロキシの設定 |
基本的には、Gateway
でサービスの出入口を定義して、VirtualService
でどのAPIにトラフィックを届けるか決め、DestinationRule
で実際にトラフィックが届くAPIが決定するという流れになります。
ServiceEntry
とSidecar
は適宜使うようなイメージです。
ローカルで試す
今回は、Istioのサンプルアプリを使って、Gateway
、VirtualSerive
、DestinationRule
を実際に動かしていきます。
Istioのインストール
まずは、istioctl
でIstioのコンポーネントをインストールします。
istioctl install --set profile=demo -y
インストールされたコンポーネントを確認します。
❯ kubectl get all -n istio-system
NAME READY STATUS RESTARTS AGE
pod/istio-egressgateway-5765b65799-2frz8 1/1 Running 0 20s
pod/istio-ingressgateway-5ff4b47bb7-7w589 1/1 Running 0 20s
pod/istiod-57c5d796fc-98md9 1/1 Running 0 27s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/istio-egressgateway ClusterIP 10.109.101.79 <none> 80/TCP,443/TCP 20s
service/istio-ingressgateway LoadBalancer 10.102.72.120 localhost 15021:32617/TCP,80:32710/TCP,443:32299/TCP,31400:32356/TCP,15443:31325/TCP 20s
service/istiod ClusterIP 10.97.105.18 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 26s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/istio-egressgateway 1/1 1 1 20s
deployment.apps/istio-ingressgateway 1/1 1 1 20s
deployment.apps/istiod 1/1 1 1 27s
NAME DESIRED CURRENT READY AGE
replicaset.apps/istio-egressgateway-5765b65799 1 1 1 20s
replicaset.apps/istio-ingressgateway-5ff4b47bb7 1 1 1 20s
replicaset.apps/istiod-57c5d796fc 1 1 1 27s
今回重要になるのはistio-ingressgateway
です。Envoyコンテナを含むPodとLoadBalancerタイプのServiceからなるコンポーネントで、クラスタ外からのトラフィックを受け付ける入口になります。ここでは、EXTERNAL-IPがlocalhostになっています。
ingressgateway
とありますが、カスタムリソースのGatewayとは異なります。
サイドカーの有効化
PodにEnvoyコンテナがサイドカーとして追加されるように、ラベルの設定を有効化します。
kubectl label namespace default istio-injection=enabled
アプリのデプロイ
Istioのサンプルアプリ(bookinfo)をデプロイします。
kubectl apply -f bookinfo/platform/kube/bookinfo.yaml
サンプルアプリの構成は下記の通りです。
Istioのドキュメントより
デプロイしたリソースを確認してみます。
❯ kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/details-v1-586577784f-tpmr2 2/2 Running 0 12s
pod/productpage-v1-589b848cc9-wb47g 2/2 Running 0 11s
pod/ratings-v1-679fc7b4f-pfmt9 2/2 Running 0 12s
pod/reviews-v1-7b76665ff9-5xkk4 2/2 Running 0 12s
pod/reviews-v2-6b86c676d9-nk562 2/2 Running 0 12s
pod/reviews-v3-b77c579-xc4lr 2/2 Running 0 12s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/details ClusterIP 10.104.173.141 <none> 9080/TCP 12s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3m11s
service/productpage ClusterIP 10.102.202.100 <none> 9080/TCP 12s
service/ratings ClusterIP 10.99.99.43 <none> 9080/TCP 12s
service/reviews ClusterIP 10.96.13.117 <none> 9080/TCP 12s
ingress-gatewayに対するGatewayとVirtualServiceの作成
トラフィック制御関連のリソースを作成していきます。
まずは、istio-ingressgateway
に対して、Gateway
とVirtualService
を作成します。
Gateway
というリソースは、istio-ingressgateway
のようなIngress Gatewayに対して入口を定義するリソースと言えます。
Gateway
とVirtualService
のマニュアルは下記の通りです。説明用のコメントを入れています。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
selector:
istio: ingressgateway # istio-ingressgatewayに付与されているラベル(どのIngress Gatewayに対してか)
servers:
- port:
number: 80 # Port80で受け付ける(Ingress Gatewayのどのポートか)
name: http
protocol: HTTP
hosts:
- "*" # 全ての宛先へのトラフィックを受け付ける
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*" # 全ての宛先へのトラフィックに対してルーティングを適用(どの宛先向けのトラフィックにルーティングを適用するか)
gateways:
- bookinfo-gateway # bookinfo-gatewayに対してルーティングを適用(どこに適用するか)
http:
- match: # マッチするルールの定義
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination: # マッチした場合の宛先
host: productpage # productpageというServiceへトラフィックを送る
port:
number: 9080
Gateway
とVirtualService
を作成します。
kubectl apply -f bookinfo/networking/bookinfo-gateway.yaml
これで、アプリへの入口が定義できました。
アプリの動作確認
Ingress GatewayのポートやIPアドレスを環境変数として設定して、動作確認します。
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
export INGRESS_HOST=127.0.0.1
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
Ingress GatewayへのURLを確認します。
❯ echo $GATEWAY_URL
127.0.0.1:80
設定した変数を使って、動作確認します。
❯ curl -s "http://${GATEWAY_URL}/productpage" | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
DestinationRuleの作成
次にDestinationRule
を作成します。
bookinfo/networking/destination-rule-all.yaml
では、各バージョンへトラフィックを流すためのルールが定義されています。
...
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1 # ルールの名前
labels:
version: v1 # ラベルがついているPodへトラフィックを流す
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
...
DestinationRule
を作成します。
kubectl apply -f bookinfo/networking/destination-rule-all.yaml
各APIのVirtualServiceの作成
DestinationRule
を使って、トラフィックを流すPodを決定するVirtualService
を作成します。
bookinfo/networking/virtual-service-all-v1.yaml
では、サービスメッシュ内でのルーティングが定義されています。
...
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews # reviewsというServiceが宛先のトラフィックに対するルーティング
# gatewaysがない場合はサービスメッシュ内の全てのサイドカーにルールが適用される
http:
- route:
- destination:
host: reviews # reviewsというServiceにトラフィックを流す
subset: v1 # DestinationRuleで定義したルールに従ってトラフィックを流す
...
VirtualService
を作成します。
kubectl apply -f bookinfo/networking/virtual-service-all-v1.yaml
動作確認
ダッシュボードを確認しながら、実際にどう動作しているか確認します。
まずはダッシュボードをデプロイします。
kubectl apply -f addons
kubectl rollout status deployment/kiali -n istio-system
ダッシュボードにアクセスします。
istioctl dashboard kiali
トラフィックを流して、どのようにトラフィックが流れるか確認します。
for i in $(seq 1 100); do curl -s -o /dev/null "http://$GATEWAY_URL/productpage"; done
istio-ingressgateway
にGateway
が、各APIにVirtualService
が定義されていることが確認できます。特に、productpageへのVirtualService
は、Gateway
の設定によりistio-ingressgateway
からのトラフィックに対してルーティングしていることがわかります。
また、reviewsはDestinationRule
とVirtualService
で定義したようにv1のPodにのみトラフィックが流れています。
Virtual Serviceの変更
reviewのトラフィックをv3のPodに流れるように変更してみます。
bookinfo/networking/virtual-service-reviews-v3.yaml
で、VirtualService
のルーティング設定を変更できます。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v3 # DestinationRuleで定義したv3のルールに従ってトラフィックを流す
reviewsのVirtualService
を更新します。
kubectl apply -f bookinfo/networking/virtual-service-reviews-v3.yaml
再度、トラフィックを流して確認します。
for i in $(seq 1 100); do curl -s -o /dev/null "http://$GATEWAY_URL/productpage"; done
トラフィックがv3に流れるようになりました。