Istioは、複雑なマイクロサービスアーキテクチャのためのサービスメッシュプラットフォームです。
Istioとは
Istioは、マイクロサービスにおける通信やセキュリティ、監視、トラフィック制御を監視します。具体的にはサービス間の通信制御をサービスごとに実装するのではなく、すべてプロキシ経由の通信にすることで、マイクロサービスの複雑性を解決するサービスメッシュを実現しています。サービスのプロキシにはEnvoyが配置されており、Envoyについては前回解説した記事があるのでよければそちらもご覧ください。
Istioの機能
Traffic Management
特定のサービス間でのルーティングに加え、ネットワーク全体のトラフィックフローを変更(traffic shaping)したり、トラフィックを別のロケーションに移行(traffic shifting)する機能があります。
Observability
マイクロサービスでは大量のコンポーネントが動的に変化するため、各サービスの状況や通信状況などを可視化することが必須になります。サービスメッシュにより、メトリクスの取得や分散トレーシング、ロギングなどの機能があります。
Security
サービス間の通信をセキュアにするため、クライアントとサーバー間の相互認証のためのプロトコルなどの機能があります。
Istioの構成要素
Istioではコントロールプレーンとデータプレーンが相互に動作することでサービス間の通信を制御しています。
Control plane
Istioの本体でサービスディスカバリや証明書の管理などを行います。
Data plane
アプリケーションのロジックと関係のない処理を独立させるためにプロキシ(Envoy)をサイドカーコンテナとして配置します。これによってサービス間のルーティング制御を行ったりします。
Image Source: https://istio.io/latest/docs/ops/deployment/architecture/
IstioのControl planeはIstiodによって動作します。Istiodは以下の機能を持ちます。
Pilot
プロキシサーバのトラフィックを管理するコンポーネントで、Kubernetesなどに応じたサービスディスカバリを担当します。
Citadel
証明書管理、エンドユーザとアプリケーション間の認証や、コンポーネント間の相互認証など、サービスメッシュのセキュリティを担当します。
Galley
Envoyプロキシの構成管理、収集したデータをもとに、アクセス制御などを担当します。
デモ
公式ドキュメントにあるGetting Startedに沿ってサンプルアプリケーションをデプロイしてみます。
動作環境
OS : WSL2 – Ubuntu 22.04.2 LTS
Minikube : version: v1.30.1
Minikubeを使って構築したいと思います。
Minikubeを起動します。
$ minikube start
Istioをダウンロード
Istioをダウンロードします。
$ curl -L https://istio.io/downloadIstio | sh -
Istio パッケージ ディレクトリに移動します。
$ cd istio-1.18.2 istioctl
クライアントをパスに追加します(Linux または macOS)。
$ export PATH=$PWD/bin:$PATH
Istioのインストール
Istioのインストールではdemo構成プロファイルを使用します。
$ istioctl install --set profile=demo -y
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete
Making this installation the default for injection and validation.
名前空間ラベルを追加して、後でアプリケーションをデプロイするときに Envoy サイドカー プロキシを自動的に挿入するように Istio に指示します。Podにistio-proxyというEnvoyコンテナが追加される設定を有効化します。
$ kubectl label namespace default istio-injection=enabled
namespace/default labeled
サンプル アプリケーションをデプロイ
$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
アプリケーションが起動します。各ポッドの準備が整うと、Istio サイドカーもそれとともにデプロイされます。
$ kubectl get services
$ kubectl get pods
コマンドを再実行してすべてのPodが READY2/2と STATUS Runningになってから次のステップに進みます。数分かかる場合があります。
次のコマンドを実行して、応答内のページ タイトルを確認することで、アプリがクラスター内で実行され、HTML ページを表示しているかどうかを確認します。
$ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>”
<title>Simple Bookstore App</title>
アプリケーションを外部トラフィックに対して開く
Bookinfo アプリケーションはデプロイされていますが、外部からはアクセスできません。アクセス可能にするには、Istio Ingress Gatewayを作成する必要があります 。
このアプリケーションを Istio ゲートウェイに関連付けます。
$ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created
構成に問題がないことを確認します。
$ istioctl analyze
✔ No validation issues found when analyzing namespace: default.
イングレス IP とポートの決定
ゲートウェイにアクセスするためのINGRESS_HOSTおよび変数を設定します。
新しいターミナル ウィンドウで以下のコマンドを実行して、ロードバランサーに接続します。
$ minikube tunnel
ロードバランサの確認
$ kubectl get svc istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.109.132.66 127.0.0.1 15021:31073/TCP,80:32328/TCP,443:31833/TCP,31400:30564/TCP,15443:30613/TCP 19m
イングレスホストとポートを設定します。
$ 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}')
IP アドレスとポートが各環境変数に正常に割り当てられていることを確認します。
$ echo "$INGRESS_HOST"
127.0.0.1
$ echo "$INGRESS_PORT"
80
$ echo "$SECURE_INGRESS_PORT"
443
GATEWAY_URLを設定
$ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
IP アドレスとポートが環境変数に正常に割り当てられていることを確認します。
echo "$GATEWAY_URL"
127.0.0.1:80
外部アクセスを検証
ブラウザを使用して Bookinfo ページを表示し、外部から Bookinfo アプリケーションにアクセスできることを確認します。
次のコマンドを実行して、Bookinfo アプリケーションの外部アドレスを取得します。
$ echo "http://$GATEWAY_URL/productpage
http://127.0.0.1:80/productpage
前のコマンドの出力を Web ブラウザーに貼り付け、Bookinfo ページが表示されることを確認します。
ダッシュボードを見る
Prometheus、Grafana、JaegerとともにKialiダッシュボードをデプロイします。
Kiali と他のアドオンをインストールし、展開されるまで待ちます。
$ kubectl apply -f samples/addons
$ kubectl rollout status deployment/kiali -n istio-system
Waiting for deployment "kiali" rollout to finish: 0 of 1 updated replicas are available...
deployment "kiali" successfully rolled out
アドオンのインストール中にエラーが発生した場合は、コマンドを再度実行してください。いくつかのタイミングの問題が発生する可能性がありますが、コマンドを再度実行すると解決されます。
Kiali ダッシュボードにアクセスします。
$ istioctl dashboard kiali
左側のナビゲーション メニューで[graph]を選択し、[namespace]ドロップダウンで[default]を選択します。
トレース データを表示するには、サービスにリクエストを送信する必要があります。リクエストの数は Istio のサンプリング レートによって異なり、[Telemetry API]を使用して構成できます。デフォルトのサンプリング レート 1% では、最初のトレースが表示されるまでに少なくとも 100 回のリクエストを送信する必要があります。100 個のリクエストをproductpageサービスに送信するには、次のコマンドを使用します。
for i in $(seq 1 100); do curl -s -o /dev/null "http://$GATEWAY_URL/productpage"; done
リクエストが送られてくるとトラフィックがどのように流れているかが可視化されているのがわかります。
まとめ
Istioは複雑なマイクロサービスアーキテクチャのためのサービスメッシュプラットフォームです。サービス間の通信制御をサービスごとに実装するのではなく、すべてプロキシ経由の通信にすることでサービスメッシュを実現しています。複数のサービスが連携して動作する現代のアプリケーション開発において、Istioはその連携をスムーズにする役割を果たします。
参考文献
https://cloud.google.com/learn/what-is-istio?hl=ja
https://www.ibm.com/jp-ja/topics/istio
https://techblog.zozo.com/entry/zozotown-istio-production-ready#What-is-Istio
https://engineering.mercari.com/blog/entry/20220210-how-istio-solved-our-problems/