今回はService Meshについて概要を調べ、Service Meshを提供するプロダクトの一つであるIstioに触れてみました。
Service Meshとは
マイクロサービスの課題
Service Meshを考えるうえでまず必要になるのが、マイクロサービスアーキテクチャの抱えるいくつかの課題です。
マイクロサービスを導入・構築するうえでの課題として、ネットワークに関連する事項が挙げられます。マイクロサービスはお互いネットワークを通じて連携するため、ネットワークに関する機能(Load Balancing、Traffic Routingなど)を実装する必要があります。また、アプリケーションを構成するマイクロサービスの数が多くなるほど、マイクロサービス間の接続数は増加し、通信断の発生する確率やパフォーマンス低下など、ネットワーク関連の問題が発生する可能性も増加します。
これまで複数のグローバルな大企業では、信頼のできないネットワークに関連した課題を解決するため、様々な取り組みを行いました。当初はマイクロサービスの内部に埋め込むフレームワークでの解決を目指すことが多かったようですが(例:Ribbon、Hystrixなど)、それらは開発言語やプラットフォームに依存しており、既存のアプリケーションに組み込むことも難しい場面がありました。またフレームワークがアップデートされた場合、それを利用するアプリケーション側もアップデートをして追従する必要があり、さらにフレームワークが各言語に対応していても、各言語間で一貫した機能を利用するには大きな労力が必要となっていました。
一方で、アプリケーションの実行基盤としてコンテナやKubernetesが進化・発展してきました。異なる開発言語で書かれたマイクロサービスは、コンテナという箱の中で起動し、それらはKubernetesなどのコンテナプラットフォーム上へデプロイすることで、共通基盤上で動作し、複数のマイクロサービスが連携するアプリケーションを提供することができます。しかし、基盤上の複数のマイクロサービスが、どのように通信を行うか、連携するか、といった機能は、Service Meshが登場するまでは提供されませんでした。
Service Meshの特徴
Service Meshの特徴としては以下のようなものが挙げられます。Service Meshを導入することで、これらの機能を「アプリケーションコードに改変を加えることなく」利用することができます。アプリケーションと独立して導入できることで、開発者は自分たちのマイクロサービスが担う機能の開発に集中することができます。
Traffic Control: 特定のサービス間でのルーティングに加え、ネットワーク全体のトラフィックフローを変更(traffic shaping)したり、トラフィックを別のロケーションに移行(traffic shifting)する機能も提供する。
Service Discovery: 各サービスの存在や送信先を動的に検出・更新し、サービス間の通信を実現する。KubernetesはService Discoveryの機能を備えているため、こちらを利用する場合もある。
Load Balancing: Kubernetesでは
kube-proxy
によりデフォルトでRound-Robinな負荷分散が提供されるが、Service Meshにより複数のアルゴリズム(Random / Weighted least connectなど)を利用可能となる。Resilience: マイクロサービス間の通信の信頼性を向上する機能を提供する。ヘルスチェック、タイムアウト、リトライなどに加え、サービス間障害の影響が拡大しないよう、サービス間を切り離す仕組み(Circuit Breaker)などがある。
Observability: マイクロサービスでは大量のコンポーネントが動的に変化するため各サービスの状況や通信状況などを可視化することが必須になります。Service Meshにより、メトリクスの取得や分散トレーシング、ロギングなどを利用できます。
Security: サービス間の通信をセキュアにするため、相互TLS(mTLS)、ポリシーベースのアクセスコントロール(ACL)などの機能を提供する。
Service Meshのアーキテクチャは、大きくData PlaneとControl Planeに分けられます。Data Planeは各マイクロサービスのProxyとして実装されることが多く、サービスのエンドポイントを通過する全てのトラフィックを対象に、パケットの変換や転送、モニタリングなどを行います。特にKubernetesなどコンテナ基盤ではSidecar Proxyコンテナとして、マイクロサービスの外部Proxyとして実現されます。
Control Planeは各Data Planeの情報を集約した可視化、各Data Planeのポリシーや設定の管理などを行い、複数のData Planeを分散システムとして構成することを実現します。
※画像:Envoy Blogより
Data Plane
Control Plane
Service Meshを実現するプロダクト
Service Meshを実現するプロダクトには、現在複数の選択肢が用意されています。
Istio: Service Meshプロダクトの中でもっとも有名なもの。EnvoyをSidecar Proxyとして利用し、豊富な機能と拡張性を備えている。
Linkerd: Service Meshプロダクトとして最初に登場したもの。独自のData Plane Proxyを利用し、軽量・高性能を実現。
Kuma: 2019年にKong社が発表した、比較的新しいプロダクト。一つのControl Planeから複数のメッシュを管理することができる。またVMなどKubernetes以外のプラットフォームでも利用できる。
Consul Connect: Consulの提供するService Discovery機能を利用し、SIdecar Proxyを追加することで、サービス間の認証・mTLSによる通信を実現する。また各サービスのトラフィックを集約し、Prometheus等のモニタリングツールへ送信することも可能。
Traefik Mesh (Maesh): Cloud-NativeなReverse Proxy / Load Balancingを提供するTraefikの配下でService Meshの機能を提供する、軽量・シンプルなプロダクト。
AWS App Mesh: AWSの提供するマネージド型のService Mesh。Control PlaneはAWSが管理し、Fargate / ECS / EKS / EC2等にsidecar proxyを注入することで利用することが可能。
Open Service Mesh: Microsoftがリリース、Service Mesh Interface(SMI)に準拠したもの。Envoyをベースに利用し、軽量・拡張性を備えている。
※各Service Meshプロダクトの比較はこちらのページなどをご確認ください。
今回はこの中からもっとも有名なIstioを触ってみました
Istioとは
Istioの公式ページでは、以下のような特徴を持つと紹介されています。
- HTTP / gRPC / WebSocket / TCPといった複数のプロトコルに対応した自動ロードバランス
- Routingルール・Retry・Failover・Fault Injectionといった機能による詳細なトラフィックコントロール
- Pluggableなポリシーレイヤと、Access Control / Rate Limit・QuotaをサポートするConfiguration API
- Ingress / Egress方向を含む、クラスター内の全トラフィックのメトリクス・ログ・トレースを自動的に取得する
- 強力なIDベースの認証認可によるセキュアなサービス間通信の実現
またIstioは拡張性と多様なデプロイ要求に合わせて設計されており、それらはメッシュトラフィックに対するInjectionとConfigurationにより実現しています。
※Istioアーキテクチャ(画像はIstio公式ドキュメントより)
ここからは実際にIstioを触ってみます。今回は公式ドキュメントにあるGetting Startedのページにある内容をなぞってみました。
検証環境
- Kubernetesマネージドサービス: Amazon EKS (v1.18)
- 構築方法: eksctlによる構築
- ローカル環境: WSL (Ubuntu 18.04.4)
Istioのダウンロード
まずはIstioctl
CLIをインストールします。Istioを利用するには、istioctl
を用いる、Operatorを利用する、CLIによりマニフェストファイルを生成する、Helmを利用する、などの方法がありますが、ここではistioctl
によるインストールを採用しています。
※各インストール方法のPros/Consはこちらに記載されています。
istioctl
をインストールするため、以下の通りコマンドを実行します。
# ダウンロード $ curl -L https://istio.io/downloadIstio | sh - % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 102 100 102 0 0 290 0 --:--:-- --:--:-- --:--:-- 292 100 4579 100 4579 0 0 7631 0 --:--:-- --:--:-- --:--:-- 154k Downloading istio-1.8.1 from https://github.com/istio/istio/releases/download/1.8.1/istio-1.8.1-linux-amd64.tar.gz ... Istio 1.8.1 Download Complete! Istio has been successfully downloaded into the istio-1.8.1 folder on your system. Next Steps: See https://istio.io/latest/docs/setup/install/ to add Istio to your Kubernetes cluster. To configure the istioctl client tool for your workstation, add the /mnt/c/Users/user/Desktop/istio-1.8.1/bin directory to your environment path variable with: export PATH="$PATH:/mnt/c/Users/user/Desktop/istio-1.8.1/bin" Begin the Istio pre-installation check by running: istioctl x precheck Need more information? Visit https://istio.io/latest/docs/setup/install/
ここでダウンロードしたファイルにはistioctl
以外にもマニフェストファイルなどが含まれています。istioctl
をパスが通っているフォルダにコピーしてコマンドを実行できるようにします。
$ cd istio-1.8.1/ $ ll total 24 drwxrwxrwx 1 testuser testuser 512 Dec 8 06:58 ./ drwxrwxrwx 1 testuser testuser 512 Dec 21 11:12 ../ -rwxrwxrwx 1 testuser testuser 11348 Dec 8 06:58 LICENSE* -rwxrwxrwx 1 testuser testuser 5866 Dec 8 06:58 README.md* drwxrwxrwx 1 testuser testuser 512 Dec 8 06:58 bin/ -rwxrwxrwx 1 testuser testuser 853 Dec 8 06:58 manifest.yaml* drwxrwxrwx 1 testuser testuser 512 Dec 8 06:58 manifests/ drwxrwxrwx 1 testuser testuser 512 Dec 8 06:58 samples/ drwxrwxrwx 1 testuser testuser 512 Dec 8 06:58 tools/ $ sudo cp -p bin/istioctl /usr/local/bin # コマンド実行確認 $ istioctl version no running Istio pods in "istio-system" 1.8.1
Istioのインストール
次にクラスターにIstioをインストールします。ここではデモ用のConfiguration Profileを利用します。Configuration Profileはistioctl
ダウンロード直後に利用できる、ビルトインのインストールオプションのことで、このうちdemo
には、リソースが少ない環境下でもIstioの機能を見ることのできるような設定が含まれています。
demo.yaml
apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: meshConfig: accessLogFile: /dev/stdout components: egressGateways: - name: istio-egressgateway enabled: true k8s: resources: requests: cpu: 10m memory: 40Mi ingressGateways: - name: istio-ingressgateway enabled: true k8s: resources: requests: cpu: 10m memory: 40Mi service: ports: ## You can add custom gateway ports in user values overrides, but it must include those ports since helm replaces. # Note that AWS ELB will by default perform health checks on the first port # on this list. Setting this to the health check port will ensure that health # checks always work. https://github.com/istio/istio/issues/12503 - port: 15021 targetPort: 15021 name: status-port - port: 80 targetPort: 8080 name: http2 - port: 443 targetPort: 8443 name: https - port: 31400 targetPort: 31400 name: tcp # This is the port where sni routing happens - port: 15443 targetPort: 15443 name: tls pilot: k8s: env: - name: PILOT_TRACE_SAMPLING value: "100" resources: requests: cpu: 10m memory: 100Mi values: global: proxy: resources: requests: cpu: 10m memory: 40Mi pilot: autoscaleEnabled: false gateways: istio-egressgateway: autoscaleEnabled: false istio-ingressgateway: autoscaleEnabled: false
# Profileの配置場所 $ ll manifests/profiles/ total 24 drwxrwxrwx 1 testuser testuser 512 Dec 8 06:58 ./ drwxrwxrwx 1 testuser testuser 512 Dec 8 06:58 ../ -rwxrwxrwx 1 testuser testuser 862 Dec 8 06:58 PROFILES.md* -rwxrwxrwx 1 testuser testuser 8255 Dec 8 06:58 default.yaml* -rwxrwxrwx 1 testuser testuser 1836 Dec 8 06:58 demo.yaml* -rwxrwxrwx 1 testuser testuser 317 Dec 8 06:58 empty.yaml* -rwxrwxrwx 1 testuser testuser 216 Dec 8 06:58 minimal.yaml* -rwxrwxrwx 1 testuser testuser 481 Dec 8 06:58 openshift.yaml* -rwxrwxrwx 1 testuser testuser 664 Dec 8 06:58 preview.yaml* -rwxrwxrwx 1 testuser testuser 67 Dec 8 06:58 remote.yaml* # Install $ istioctl install --set profile=demo -y ✔ Istio core installed ✔ Istiod installed ✔ Egress gateways installed ✔ Ingress gateways installed ✔ Installation complete # Install後の確認 $ kubectl get ns NAME STATUS AGE default Active 5d17h istio-system Active 72s kube-node-lease Active 5d17h kube-public Active 5d17h kube-system Active 5d17h $ kubectl get all -n istio-system NAME READY STATUS RESTARTS AGE pod/istio-egressgateway-69fc79d576-zldvs 1/1 Running 0 64s pod/istio-ingressgateway-bc9b55659-9bldh 1/1 Running 0 63s pod/istiod-67f5756967-7b7rf 1/1 Running 0 80s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/istio-egressgateway ClusterIP 172.20.239.202 <none> 80/TCP,443/TCP,15443/TCP 63s service/istio-ingressgateway LoadBalancer 172.20.42.254 a2c0d8b0138ac4c0283e0bab1f35d904-1021565130.ap-northeast-1.elb.amazonaws.com 15021:30711/TCP,80:32657/TCP,443:30422/TCP,31400:30596/TCP,15443:32315/TCP 63s service/istiod ClusterIP 172.20.58.162 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 80s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/istio-egressgateway 1/1 1 1 64s deployment.apps/istio-ingressgateway 1/1 1 1 64s deployment.apps/istiod 1/1 1 1 80s NAME DESIRED CURRENT READY AGE replicaset.apps/istio-egressgateway-69fc79d576 1 1 1 64s replicaset.apps/istio-ingressgateway-bc9b55659 1 1 1 64s replicaset.apps/istiod-67f5756967 1 1 1 80s
クラスター上にIstioをインストールすることができたので、次にテスト用アプリケーションをデプロイするNamespaceにistio-injection=enabled
というラベルを付与します。このラベルを付与することで、指定のNamespaceにアプリケーションPodがデプロイされると、Istioがそれを検知し、Envoyを含むSidecar Proxyを自動的に追加します。
$ kubectl label namespace default istio-injection=enabled namespace/default labeled $ kubectl get ns --show-labels NAME STATUS AGE LABELS default Active 5d17h istio-injection=enabled istio-system Active 4m49s istio-injection=disabled kube-node-lease Active 5d17h <none> kube-public Active 5d17h <none> kube-system Active 5d17h <none>
サンプルアプリケーションのデプロイ
次にサンプル用アプリケーションをデプロイします。今回はBookInfoというアプリケーションを利用します。Bookinfo
はランタイムの異なる4つのマイクロサービスからなるアプリケーションです。
※Bookinfo
構成図(画像はIstioドキュメントより)
デプロイに利用するbookinfo.yaml
というマニフェストファイルを見ると、ここにはSidecar Proxyの設定はされていないことが確認できます。
boolinfo.yaml
# Copyright Istio Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################################## # This file defines the services, service accounts, and deployments for the Bookinfo sample. # # To apply all 4 Bookinfo services, their corresponding service accounts, and deployments: # # kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml # # Alternatively, you can deploy any resource separately: # # kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l service=reviews # reviews Service # kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l account=reviews # reviews ServiceAccount # kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l app=reviews,version=v3 # reviews-v3 Deployment ################################################################################################## ################################################################################################## # Details service ################################################################################################## apiVersion: v1 kind: Service metadata: name: details labels: app: details service: details spec: ports: - port: 9080 name: http selector: app: details --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-details labels: account: details --- apiVersion: apps/v1 kind: Deployment metadata: name: details-v1 labels: app: details version: v1 spec: replicas: 1 selector: matchLabels: app: details version: v1 template: metadata: labels: app: details version: v1 spec: serviceAccountName: bookinfo-details containers: - name: details image: docker.io/istio/examples-bookinfo-details-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 --- ################################################################################################## # Ratings service ################################################################################################## apiVersion: v1 kind: Service metadata: name: ratings labels: app: ratings service: ratings spec: ports: - port: 9080 name: http selector: app: ratings --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-ratings labels: account: ratings --- apiVersion: apps/v1 kind: Deployment metadata: name: ratings-v1 labels: app: ratings version: v1 spec: replicas: 1 selector: matchLabels: app: ratings version: v1 template: metadata: labels: app: ratings version: v1 spec: serviceAccountName: bookinfo-ratings containers: - name: ratings image: docker.io/istio/examples-bookinfo-ratings-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 --- ################################################################################################## # Reviews service ################################################################################################## apiVersion: v1 kind: Service metadata: name: reviews labels: app: reviews service: reviews spec: ports: - port: 9080 name: http selector: app: reviews --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-reviews labels: account: reviews --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v1 labels: app: reviews version: v1 spec: replicas: 1 selector: matchLabels: app: reviews version: v1 template: metadata: labels: app: reviews version: v1 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v1:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v2 labels: app: reviews version: v2 spec: replicas: 1 selector: matchLabels: app: reviews version: v2 template: metadata: labels: app: reviews version: v2 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v2:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v3 labels: app: reviews version: v3 spec: replicas: 1 selector: matchLabels: app: reviews version: v3 template: metadata: labels: app: reviews version: v3 spec: serviceAccountName: bookinfo-reviews containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v3:1.16.2 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- ################################################################################################## # Productpage services ################################################################################################## apiVersion: v1 kind: Service metadata: name: productpage labels: app: productpage service: productpage spec: ports: - port: 9080 name: http selector: app: productpage --- apiVersion: v1 kind: ServiceAccount metadata: name: bookinfo-productpage labels: account: productpage --- apiVersion: apps/v1 kind: Deployment metadata: name: productpage-v1 labels: app: productpage version: v1 spec: replicas: 1 selector: matchLabels: app: productpage version: v1 template: metadata: labels: app: productpage version: v1 spec: serviceAccountName: bookinfo-productpage containers: - name: productpage image: docker.io/istio/examples-bookinfo-productpage-v1:1.16.2 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: {} ---
# Bookinfoデプロイ $ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml service/details created serviceaccount/bookinfo-details created deployment.apps/details-v1 created service/ratings created serviceaccount/bookinfo-ratings created deployment.apps/ratings-v1 created service/reviews created serviceaccount/bookinfo-reviews created deployment.apps/reviews-v1 created deployment.apps/reviews-v2 created deployment.apps/reviews-v3 created service/productpage created serviceaccount/bookinfo-productpage created deployment.apps/productpage-v1 created # デプロイ後の確認 $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE details ClusterIP 172.20.77.57 <none> 9080/TCP 33s kubernetes ClusterIP 172.20.0.1 <none> 443/TCP 5d17h productpage ClusterIP 172.20.186.50 <none> 9080/TCP 32s ratings ClusterIP 172.20.1.42 <none> 9080/TCP 33s reviews ClusterIP 172.20.31.107 <none> 9080/TCP 33s $ kubectl get pods NAME READY STATUS RESTARTS AGE details-v1-558b8b4b76-vsg5d 2/2 Running 0 82s productpage-v1-6987489c74-lkkp7 2/2 Running 0 81s ratings-v1-7dc98c7588-kn2nd 2/2 Running 0 82s reviews-v1-7f99cc4496-tv2xw 2/2 Running 0 81s reviews-v2-7d79d5bd5d-7vtb6 2/2 Running 0 81s reviews-v3-7dbcdcbc56-npl2r 2/2 Running 0 81s # 以下のコマンドにより、全てのマイクロサービスが正常に起動していることを確認 $ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -s productpage:9080/productpage | grep -o "<title>.*</title>" <title>Simple Bookstore App</title>
またこの時点で各PodにSidecar Proxyが含まれていることが確認できます。
kubectl describe pod
実行結果
$ kubectl describe pod details-v1-558b8b4b76-vsg5d Name: details-v1-558b8b4b76-vsg5d Namespace: default Priority: 0 Node: ip-10-0-3-254.ap-northeast-1.compute.internal/10.0.3.254 Start Time: Mon, 21 Dec 2020 11:25:46 +0900 Labels: app=details istio.io/rev=default pod-template-hash=558b8b4b76 security.istio.io/tlsMode=istio service.istio.io/canonical-name=details service.istio.io/canonical-revision=v1 version=v1 Annotations: kubernetes.io/psp: eks.privileged prometheus.io/path: /stats/prometheus prometheus.io/port: 15020 prometheus.io/scrape: true sidecar.istio.io/status: {"version":"e2cb9d4837cda9584fd272bfa1f348525bcaacfadb7e9b9efbd21a3bb44ad7a1","initContainers":["istio-init"],"containers":["istio-proxy"]... Status: Running IP: 10.0.3.200 IPs: IP: 10.0.3.200 Controlled By: ReplicaSet/details-v1-558b8b4b76 Init Containers: istio-init: Container ID: docker://671332eb17f770507ea2c03abc0b7e63adaef1cfe4cd71194d1a35bee84ab7b8 Image: docker.io/istio/proxyv2:1.8.1 Image ID: docker-pullable://istio/proxyv2@sha256:0a407ecee363d8d31957162b82738ae3dd09690668a0168d660044ac8fc728f0 Port: <none> Host Port: <none> Args: istio-iptables -p 15001 -z 15006 -u 1337 -m REDIRECT -i * -x -b * -d 15090,15021,15020 State: Terminated Reason: Completed Exit Code: 0 Started: Mon, 21 Dec 2020 11:26:00 +0900 Finished: Mon, 21 Dec 2020 11:26:00 +0900 Ready: True Restart Count: 0 Limits: cpu: 2 memory: 1Gi Requests: cpu: 10m memory: 40Mi Environment: DNS_AGENT: Mounts: /var/run/secrets/kubernetes.io/serviceaccount from bookinfo-details-token-6qxvx (ro) Containers: details: Container ID: docker://d61b82d5a1383486be70492be5ed1dd63271cbe7935db7942b74edd21077b117 Image: docker.io/istio/examples-bookinfo-details-v1:1.16.2 Image ID: docker-pullable://istio/examples-bookinfo-details-v1@sha256:18e54f81689035019e1ac78f6d2e6483fcf1d94072d047315ab193cb2ab89ae5 Port: 9080/TCP Host Port: 0/TCP State: Running Started: Mon, 21 Dec 2020 11:26:44 +0900 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from bookinfo-details-token-6qxvx (ro) istio-proxy: Container ID: docker://19613b8fee7c77c2a2436824e6a33832e7758752c425add6b762da851faaccd7 Image: docker.io/istio/proxyv2:1.8.1 Image ID: docker-pullable://istio/proxyv2@sha256:0a407ecee363d8d31957162b82738ae3dd09690668a0168d660044ac8fc728f0 Port: 15090/TCP Host Port: 0/TCP Args: proxy sidecar --domain $(POD_NAMESPACE).svc.cluster.local --serviceCluster details.$(POD_NAMESPACE) --proxyLogLevel=warning --proxyComponentLogLevel=misc:error --concurrency 2 State: Running Started: Mon, 21 Dec 2020 11:26:48 +0900 Ready: True Restart Count: 0 Limits: cpu: 2 memory: 1Gi Requests: cpu: 10m memory: 40Mi Readiness: http-get http://:15021/healthz/ready delay=1s timeout=3s period=2s #success=1 #failure=30 Environment: JWT_POLICY: third-party-jwt PILOT_CERT_PROVIDER: istiod CA_ADDR: istiod.istio-system.svc:15012 POD_NAME: details-v1-558b8b4b76-vsg5d (v1:metadata.name) POD_NAMESPACE: default (v1:metadata.namespace) INSTANCE_IP: (v1:status.podIP) SERVICE_ACCOUNT: (v1:spec.serviceAccountName) HOST_IP: (v1:status.hostIP) CANONICAL_SERVICE: (v1:metadata.labels['service.istio.io/canonical-name']) CANONICAL_REVISION: (v1:metadata.labels['service.istio.io/canonical-revision']) PROXY_CONFIG: {"proxyMetadata":{"DNS_AGENT":""}} ISTIO_META_POD_PORTS: [ {"containerPort":9080,"protocol":"TCP"} ] ISTIO_META_APP_CONTAINERS: details ISTIO_META_CLUSTER_ID: Kubernetes ISTIO_META_INTERCEPTION_MODE: REDIRECT ISTIO_METAJSON_ANNOTATIONS: {"kubernetes.io/psp":"eks.privileged"} ISTIO_META_WORKLOAD_NAME: details-v1 ISTIO_META_OWNER: kubernetes://apis/apps/v1/namespaces/default/deployments/details-v1 ISTIO_META_MESH_ID: cluster.local TRUST_DOMAIN: cluster.local DNS_AGENT: Mounts: /etc/istio/pod from istio-podinfo (rw) /etc/istio/proxy from istio-envoy (rw) /var/lib/istio/data from istio-data (rw) /var/run/secrets/istio from istiod-ca-cert (rw) /var/run/secrets/kubernetes.io/serviceaccount from bookinfo-details-token-6qxvx (ro) /var/run/secrets/tokens from istio-token (rw) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: bookinfo-details-token-6qxvx: Type: Secret (a volume populated by a Secret) SecretName: bookinfo-details-token-6qxvx Optional: false istio-envoy: Type: EmptyDir (a temporary directory that shares a pod's lifetime) Medium: Memory SizeLimit: <unset> istio-data: Type: EmptyDir (a temporary directory that shares a pod's lifetime) Medium: SizeLimit: <unset> istio-podinfo: Type: DownwardAPI (a volume populated by information about the pod) Items: metadata.labels -> labels metadata.annotations -> annotations istio-token: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 43200 istiod-ca-cert: Type: ConfigMap (a volume populated by a ConfigMap) Name: istio-ca-root-cert Optional: false QoS Class: Burstable Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 5m5s default-scheduler Successfully assigned default/details-v1-558b8b4b76-vsg5d to ip-10-0-3-254.ap-northeast-1.compute.internal Normal Pulling 5m4s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Pulling image "docker.io/istio/proxyv2:1.8.1" Normal Pulled 4m55s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Successfully pulled image "docker.io/istio/proxyv2:1.8.1" Normal Created 4m51s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Created container istio-init Normal Started 4m51s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Started container istio-init Normal Pulling 4m50s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Pulling image "docker.io/istio/examples-bookinfo-details-v1:1.16.2" Normal Pulled 4m10s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Successfully pulled image "docker.io/istio/examples-bookinfo-details-v1:1.16.2" Normal Created 4m7s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Created container details Normal Started 4m7s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Started container details Normal Pulling 4m7s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Pulling image "docker.io/istio/proxyv2:1.8.1" Normal Pulled 4m3s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Successfully pulled image "docker.io/istio/proxyv2:1.8.1" Normal Created 4m3s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Created container istio-proxy Normal Started 4m3s kubelet, ip-10-0-3-254.ap-northeast-1.compute.internal Started container istio-proxy
アプリケーションを外部に公開
次にBookinfo
を外部からアクセスできるようにします。Istioの機能で外部からアプリケーションへアクセスできるようにするには、Istio Ingress Gatewayを作成し、アプリケーションへのルーティングを追加する必要があります。ここではIstioのCRDであるGateway
とVirtualService
をデプロイすることで、外部からのアクセスを実現します。
IstioのCRDの一つであるGatewayを作成すると、Gateway
に含まれる設定は、メッシュのエッジ部分で起動するEnvoy Proxyへと反映されます。Istio gatewayは、外部に公開するポートやTLSの設定など、Layer 4-6のLoad Balancingに関する機能を設定することができます。それに加え、IstioのVirtual ServiceというCRDを利用することも可能です。Virtual Service
はトラフィックのRoutingの機能を提供し、HTTPやgRPCといったプロトコルのルーティング設定を定義することができます。これをGateway
組み合わせることで、Layer 7のルーティングをGateway
に追加することができます。
bookinfo-gateway.yaml
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: bookinfo-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: bookinfo spec: hosts: - "*" gateways: - 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 port: number: 9080
# gateway / virtual serviceのデプロイ $ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml gateway.networking.istio.io/bookinfo-gateway created virtualservice.networking.istio.io/bookinfo created # デプロイ後の確認 $ kubectl get gateway NAME AGE bookinfo-gateway 20s $ kubectl get virtualservice NAME GATEWAYS HOSTS AGE bookinfo [bookinfo-gateway] [*] 30s
またistioctl
コマンドには、Istioクラスターの設定を確認するためのistioctl analyzeというオプションが存在します。
$ istioctl analyze ✔ No validation issues found when analyzing namespace: default.
外部からのアクセス
次にクラスター外からのアクセスが可能かを確認します。
まずは以下のコマンドによりアクセス先のIPアドレスとポート番号を確認します。
# Serviceの確認 $ kubectl get svc -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-egressgateway ClusterIP 172.20.239.202 <none> 80/TCP,443/TCP,15443/TCP 31m istio-ingressgateway LoadBalancer 172.20.42.254 a2c0d8b0138ac4c0283e0bab1f35d904-1021565130.ap-northeast-1.elb.amazonaws.com 15021:30711/TCP,80:32657/TCP,443:30422/TCP,31400:30596/TCP,15443:32315/TCP 31m istiod ClusterIP 172.20.58.162 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 31m # istio-ingressgatewayのIPアドレス(ここではhostname)を確認 $ kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' a2c0d8b0138ac4c0283e0bab1f35d904-1021565130.ap-northeast-1.elb.amazonaws.com # istio-ingressgatewayのポートを確認 $ kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}' 80
アクセス先が判明したので、以下の通りコマンドを実行し、クラスター外からアクセスできることを確認します。
$ curl -s a2c0d8b0138ac4c0283e0bab1f35d904-1021565130.ap-northeast-1.elb.amazonaws.com/productpage | grep -o "<title>.*</title>" <title>Simple Bookstore App</title>
また、Webブラウザから上記URLにアクセスすると、以下のようなページへアクセスできることが確認できます。
Dashboardからアプリケーションの状況を確認する
IstioはGrafanaやKialiなど様々なプロダクトのDashboardと統合されています。Dashboardから見ることで、Service Meshの構造を視覚的に見ることが出来たり、メッシュのヘルスチェックを行うこともできます。ここではKialiのDashboardからIstioのメッシュの状況を確認します。
# Kiali(とその他アドオン)のインストール $ ll samples/addons/ total 300 drwxrwxrwx 1 testuser testuser 512 Dec 8 06:58 ./ drwxrwxrwx 1 testuser testuser 512 Dec 8 06:58 ../ -rwxrwxrwx 1 testuser testuser 5186 Dec 8 06:58 README.md* drwxrwxrwx 1 testuser testuser 512 Dec 8 06:58 extras/ -rwxrwxrwx 1 testuser testuser 240054 Dec 8 06:58 grafana.yaml* -rwxrwxrwx 1 testuser testuser 2317 Dec 8 06:58 jaeger.yaml* -rwxrwxrwx 1 testuser testuser 35080 Dec 8 06:58 kiali.yaml* -rwxrwxrwx 1 testuser testuser 13250 Dec 8 06:58 prometheus.yaml* # インストールに失敗することがある $ kubectl apply -f samples/addons serviceaccount/grafana created configmap/grafana created service/grafana created deployment.apps/grafana created configmap/istio-grafana-dashboards created configmap/istio-services-grafana-dashboards created deployment.apps/jaeger created service/tracing created service/zipkin created service/jaeger-collector created customresourcedefinition.apiextensions.k8s.io/monitoringdashboards.monitoring.kiali.io created serviceaccount/kiali created configmap/kiali created clusterrole.rbac.authorization.k8s.io/kiali-viewer created clusterrole.rbac.authorization.k8s.io/kiali created clusterrolebinding.rbac.authorization.k8s.io/kiali created service/kiali created deployment.apps/kiali created serviceaccount/prometheus created configmap/prometheus created clusterrole.rbac.authorization.k8s.io/prometheus created clusterrolebinding.rbac.authorization.k8s.io/prometheus created service/prometheus created deployment.apps/prometheus created unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" unable to recognize "samples/addons/kiali.yaml": no matches for kind "MonitoringDashboard" in version "monitoring.kiali.io/v1alpha1" # 失敗した場合、もう一度同じコマンドを実行する $ kubectl apply -f samples/addons serviceaccount/grafana unchanged configmap/grafana unchanged service/grafana unchanged deployment.apps/grafana configured configmap/istio-grafana-dashboards configured configmap/istio-services-grafana-dashboards configured deployment.apps/jaeger unchanged service/tracing unchanged service/zipkin unchanged service/jaeger-collector unchanged customresourcedefinition.apiextensions.k8s.io/monitoringdashboards.monitoring.kiali.io unchanged serviceaccount/kiali unchanged configmap/kiali unchanged clusterrole.rbac.authorization.k8s.io/kiali-viewer unchanged clusterrole.rbac.authorization.k8s.io/kiali unchanged clusterrolebinding.rbac.authorization.k8s.io/kiali unchanged service/kiali unchanged deployment.apps/kiali unchanged monitoringdashboard.monitoring.kiali.io/envoy created monitoringdashboard.monitoring.kiali.io/go created monitoringdashboard.monitoring.kiali.io/kiali created monitoringdashboard.monitoring.kiali.io/micrometer-1.0.6-jvm-pool created monitoringdashboard.monitoring.kiali.io/micrometer-1.0.6-jvm created monitoringdashboard.monitoring.kiali.io/micrometer-1.1-jvm created monitoringdashboard.monitoring.kiali.io/microprofile-1.1 created monitoringdashboard.monitoring.kiali.io/microprofile-x.y created monitoringdashboard.monitoring.kiali.io/nodejs created monitoringdashboard.monitoring.kiali.io/quarkus created monitoringdashboard.monitoring.kiali.io/springboot-jvm-pool created monitoringdashboard.monitoring.kiali.io/springboot-jvm created monitoringdashboard.monitoring.kiali.io/springboot-tomcat created monitoringdashboard.monitoring.kiali.io/thorntail created monitoringdashboard.monitoring.kiali.io/tomcat created monitoringdashboard.monitoring.kiali.io/vertx-client created monitoringdashboard.monitoring.kiali.io/vertx-eventbus created monitoringdashboard.monitoring.kiali.io/vertx-jvm created monitoringdashboard.monitoring.kiali.io/vertx-pool created monitoringdashboard.monitoring.kiali.io/vertx-server created serviceaccount/prometheus unchanged configmap/prometheus unchanged clusterrole.rbac.authorization.k8s.io/prometheus unchanged clusterrolebinding.rbac.authorization.k8s.io/prometheus unchanged service/prometheus unchanged deployment.apps/prometheus configured # インストール後の確認 $ kubectl get pods -n istio-system NAME READY STATUS RESTARTS AGE grafana-94f5bf75b-ffqqc 1/1 Running 0 119s istio-egressgateway-69fc79d576-zldvs 1/1 Running 0 67m istio-ingressgateway-bc9b55659-9bldh 1/1 Running 0 67m istiod-67f5756967-7b7rf 1/1 Running 0 67m jaeger-5c7675974-vpzh2 1/1 Running 0 119s kiali-667b888c56-2tztk 1/1 Running 0 118s prometheus-7d76687994-rf49q 2/2 Running 0 118s $ kubectl get monitoringdashboard NAME AGE envoy 116s go 116s kiali 116s micrometer-1.0.6-jvm 116s micrometer-1.0.6-jvm-pool 116s micrometer-1.1-jvm 116s microprofile-1.1 116s microprofile-x.y 116s nodejs 116s quarkus 116s springboot-jvm 116s springboot-jvm-pool 116s springboot-tomcat 116s thorntail 116s tomcat 116s vertx-client 116s vertx-eventbus 116s vertx-jvm 116s vertx-pool 115s vertx-server 115s
インストールが完了したので、KialiのDashboardにアクセスします。istioctl
コマンドにはistioctl dashboard kialiというオプションがあり、これを実行することでkubectl port-forward
を実行したときのように、KialiのDashboardにアクセスできるようになります。
$ istioctl dashboard kiali
http://localhost:20001/kiali
Failed to open browser; open http://localhost:20001/kiali in your browser.
コマンド実行後にhttp://localhost:20001/kiali
にアクセスすると、以下のようにDashboardにアクセスできることが確認できます。
上記画面には、各Namespace毎のアプリケーションPodの個数、Istio Configの設定有無などの状況が表示されています。
ここではdefault
NamespaceからGraph
を選択し、Pod間の接続状況を示すGraphを表示します。
上記画面のGraph
をクリックすると、以下のようにアプリケーションの状況が図示されます。
上記画面中の三角形はService
、丸四角形はapp
を表しています。また画面中にはistio-ingressgateway
がいることも確認できます。
Kialiでは、実際のアクセス量やサービス間の通信発生個所をリアルタイムで表示します。ここでWebブラウザからBookinfo
アプリケーションへアクセスをしてみると、以下の画像のように、マイクロサービス間での通信の様子が、緑色の線で表示されることがわかります。
また、以下のコマンドでクラスター内部からアクセスをすると、istio-ingressgateway
からはアクセスしておらずproductpage
から矢印が伸びている様子も確認できます。
$ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -s productpage:9080/productpage | grep -o "<title>.*</title>" <title>Simple Bookstore App</title>
Sidecar Proxyログを眺めてみる
ここまでIstioの機能に触れてみましたが、実際にSidecar Proxyにトラフィックが流れているかを確認してみます。Istioでログを出力するには、IstioOperator
に以下のような設定を追加する必要があります。
spec: meshConfig: accessLogFile: /dev/stdout
今回利用するdemo
Configuration Profileは上記設定が最初からされているため、この操作は不要です。
上記設定を行った後、各マイクロサービスのistio-proxy
Sidecar Podのログを見ると、実際に転送するログが確認できます。
# productpageのSidecar Pod log $ kubectl logs productpage-v1-6987489c74-lkkp7 -c istio-proxy -f (中略) [2020-12-21T03:41:23.900Z] "GET /details/0 HTTP/1.1" 200 - "-" 0 178 5 4 "-" "curl/7.52.1" "3d44d9aa-1744-993a-9162-9bd800f1c872" "details:9080" "10.0.3.200:9080" outbound|9080||details.default.svc.cluster.local 10.0.4.151:41226 172.20.77.57:9080 10.0.4.151:38742 - default [2020-12-21T03:41:23.910Z] "GET /reviews/0 HTTP/1.1" 200 - "-" 0 379 31 31 "-" "curl/7.52.1" "3d44d9aa-1744-993a-9162-9bd800f1c872" "reviews:9080" "10.0.4.134:9080" outbound|9080||reviews.default.svc.cluster.local 10.0.4.151:39398 172.20.31.107:9080 10.0.4.151:35580 - default [2020-12-21T03:41:23.893Z] "GET /productpage HTTP/1.1" 200 - "-" 0 5183 60 60 "-" "curl/7.52.1" "3d44d9aa-1744-993a-9162-9bd800f1c872" "productpage:9080" "127.0.0.1:9080" inbound|9080|| 127.0.0.1:51420 10.0.4.151:9080 10.0.4.170:44506 outbound_.9080_._.productpage.default.svc.cluster.local default
ここで別のターミナルから以下のコマンドを実行すると、新しくログが表示されることも確認できます。
# 別ターミナルから実行 $ kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -s productpage:9080/productpage | grep -o "<title>.*</title>" <title>Simple Bookstore App</title> # productpage sidecar logs [2020-12-21T03:54:34.947Z] "GET /details/0 HTTP/1.1" 200 - "-" 0 178 5 4 "-" "curl/7.52.1" "0953f7fd-82aa-9de4-ac25-e1b6cc24c39c" "details:9080" "10.0.3.200:9080" outbound|9080||details.default.svc.cluster.local 10.0.4.151:59200 172.20.77.57:9080 10.0.4.151:46496 - default [2020-12-21T03:54:34.959Z] "GET /reviews/0 HTTP/1.1" 200 - "-" 0 379 34 34 "-" "curl/7.52.1" "0953f7fd-82aa-9de4-ac25-e1b6cc24c39c" "reviews:9080" "10.0.4.134:9080" outbound|9080||reviews.default.svc.cluster.local 10.0.4.151:48918 172.20.31.107:9080 10.0.4.151:43334 - default [2020-12-21T03:54:34.940Z] "GET /productpage HTTP/1.1" 200 - "-" 0 5183 66 66 "-" "curl/7.52.1" "0953f7fd-82aa-9de4-ac25-e1b6cc24c39c" "productpage:9080" "127.0.0.1:9080" inbound|9080|| 127.0.0.1:59174 10.0.4.151:9080 10.0.4.170:44506 outbound_.9080_._.productpage.default.svc.cluster.local default
Istioのアンインストール
一通り検証が終わったので、Istio、及びbookinfo
アプリケーションを削除します。
# “bookinfo”アプリケーションの削除 $ samples/bookinfo/platform/kube/cleanup.sh namespace ? [default] # “default” Namespaceを選択 using NAMESPACE=default (中略) Application cleanup successful # Kiali / Istioのアンインストール $ kubectl delete -f samples/addons $ istioctl manifest generate --set profile=demo | kubectl delete --ignore-not-found=true -f - $ kubectl get all -n istio-system No resources found in istio-system namespace. # “istio-system” Namespaceの削除 $ kubectl delete namespace istio-system namespace "istio-system" deleted # Namespaceに付与していたラベルの削除 $ kubectl label namespace default istio-injection- namespace/default labeled