【超基礎】Istioでのトラフィック制御

スポンサーリンク

はじめに

Istioのトラフィック制御関連のカスタムリソースについて、ざっくり解説していきます。

また、その中からよく使うものを実際に動かしながら理解していきたいと思います。

Istioの基礎については、こちらで解説しています。

【Istio】実際に動かしてざっくり理解するIstio
はじめにIstioとはどんなものなのか実際に使ってみて、ざっくり理解したいと思います。IstioとはIstionとは、サービスメッシュを実装するためのオープンソースです。Istioには以下のような機能があります。ネットワークトラフィック管理...

トラフィック制御に関するカスタムリソース

Istioでのトラフィック制御関連のカスタムリソースは下記の通りです。

リソース説明
VirtualServiceサービスメッシュ内のトラックのルーティングを設定
DestinationRule実際に届くトラフィックのルールを設定
Gateway外部とのトラフィックの出入口を定義
ServiceEntryサービスレジストリに宛先を追加
SidecarサイドカーのEnvoyプロキシの設定

基本的には、Gatewayでサービスの出入口を定義して、VirtualServiceでどのAPIにトラフィックを届けるか決め、DestinationRuleで実際にトラフィックが届くAPIが決定するという流れになります。

ServiceEntrySidecarは適宜使うようなイメージです。

ローカルで試す

今回は、Istioのサンプルアプリを使って、GatewayVirtualSeriveDestinationRuleを実際に動かしていきます。

istio/samples/bookinfo at master · istio/istio
Connect,secure,control,andobserveservices.Contributetoistio/istiodevelopmentbycreatinganaccountonGitHub.

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)をデプロイします。

istio/samples/bookinfo at master · istio/istio
Connect,secure,control,andobserveservices.Contributetoistio/istiodevelopmentbycreatinganaccountonGitHub.
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に対して、GatewayVirtualServiceを作成します。

Gatewayというリソースは、istio-ingressgatewayのようなIngress Gatewayに対して入口を定義するリソースと言えます。

GatewayVirtualServiceのマニュアルは下記の通りです。説明用のコメントを入れています。

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

GatewayVirtualServiceを作成します。

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-ingressgatewayGatewayが、各APIにVirtualServiceが定義されていることが確認できます。特に、productpageへのVirtualServiceは、Gatewayの設定によりistio-ingressgatewayからのトラフィックに対してルーティングしていることがわかります。

また、reviewsはDestinationRuleVirtualServiceで定義したように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に流れるようになりました。

参考

タイトルとURLをコピーしました