# 202-service-mesh
Istioも0.8がリリースされたので、Istioの公式ドキュメントからサンプルアプリケーションを動かしたほうがよいです。 それでは続きをしていきます。
Service Mesh integration with Kubernetes
Service MeshコンポーネントをKubernetesクラスタに統合する方法を示します。 Service Meshは、マイクロサービス間の通信を管理するレイヤーで、クラウドネイティブアプリケーションにとって普及している サービス検出、負荷分散、自動再試行、回路遮断器、収集要求/応答メトリック、トレース情報などの重要な機能があります。
2つのよく知られているサービスメッシュ統合について検討します。
- Linkerd
- Istio
こちらもあわせて読みたいです。 Service meshとは何か
LinkerdとKubernetesの使用
Linkerdは、HTTP、Thrift、Mux、HTTP/2、およびgRPC経由でトラフィックをルーティングおよびロードバランスするレイヤ5/7のプロキシです。 それはFinagle(Twitterで構築)に基づいており、2017年1月にlinkerdがKubernetesとともにCNCFのメンバーになりました。
Linkerdは、回路破壊、待ち時間を考慮したロードバランシング、最終的に一貫した(「アドバイザリ」)サービス発見、デッドライン伝播、トレーシングと計測など、幅広い強力なテクニックを使用して、可視性、制御、および信頼性をアプリケーションに追加します。 今回Kubernetesクラスターで実行されているサービスの可視性に焦点を当てます。 k8sクラスタにlinkerdをインストールし、いくつかの簡単なマイクロサービスを実行し、linkerdが成功率、要求量、待ち時間などのトップラインサービスメトリクスをどのように取得するかを行います。 Linkerdの次のような機能をいくつか見ていきます。
Kubernetesクラスタを作成する
3つのマスターノードと5つのワーカーノードを持つクラスタを用意
Linkerdをインストールする
kubectl
でインストールします。
デフォルトのKubernetes名前空間で動作するDaemonSet(つまり、ホストごとに1つのインスタンス)としてlinkerdがインストールされます。
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/\ k8s-daemonset/k8s/linkerd.yml configmap "l5d-config" created daemonset "l5d" created service "l5d" created
linkerd(l5dという名前の)ポッドが実行されていることを確認します。
$ kubectl get pods NAME READY STATUS RESTARTS AGE l5d-b8pht 2/2 Running 0 48s l5d-jlpcl 2/2 Running 0 48s l5d-kl98n 2/2 Running 0 48s l5d-mp4vn 2/2 Running 0 48s l5d-nnxqz 2/2 Running 0 48s
これは、5ワーカーノードクラスタからの出力です。 linkerdサービスが実行されていることを確認します。
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 5m l5d LoadBalancer 100.67.155.17 a8ac6926260d4... 4140:32573/TCP,4141:31565/TCP,9990:30298/TCP 2m
linkerdサービスの詳細もみてみます。
$ kubectl describe svc/l5d Name: l5d Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"l5d","namespace":"default"},"spec":{"ports":[{"name":"outgoing","port":4140},{... Selector: app=l5d Type: LoadBalancer IP: 100.70.56.141 LoadBalancer Ingress: abf44db7dbe1211e7a7d00220684043f-1319890531.eu-central-1.elb.amazonaws.com Port: outgoing 4140/TCP TargetPort: 4140/TCP NodePort: outgoing 30108/TCP Endpoints: 100.96.3.2:4140,100.96.4.2:4140,100.96.5.4:4140 + 2 more... Port: incoming 4141/TCP TargetPort: 4141/TCP NodePort: incoming 31209/TCP Endpoints: 100.96.3.2:4141,100.96.4.2:4141,100.96.5.4:4141 + 2 more... Port: admin 9990/TCP TargetPort: 9990/TCP NodePort: admin 32117/TCP Endpoints: 100.96.3.2:9990,100.96.4.2:9990,100.96.5.4:9990 + 2 more... Session Affinity: None External Traffic Policy: Cluster Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal CreatingLoadBalancer 3m service-controller Creating load balancer Normal CreatedLoadBalancer 3m service-controller Created load balancer
Linkerdの管理ページ(ELB:9990)に行ってインストールを確認することができます。 ELB DNSが利用可能になるには、1〜2分かかります。 ロードバランサエンドポイントにアクセスする際に問題が発生した場合は、ファイアウォールまたはVPNがポート9990へのアクセスを妨げている可能性があります。
LINKERD_ELB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}") open http://$LINKERD_ELB:9990
openコマンドがだめだったらブラウザからURLを入力していけます。
ダッシュボードを確認しましょう。
サンプルのmicroservicesアプリケーションをインストールする
linkerd examplesリポジトリに「hello」と「world」という2つのマイクロサービスアプリがあります。 それらはお互いに通信してリクエストを完了します。このコマンドを実行すると、デフォルトの名前空間にこれらのアプリがインストールされます。
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/\ k8s-daemonset/k8s/hello-world.yml replicationcontroller "hello" created service "hello" created replicationcontroller "world-v1" created service "world-v1" created
次のコマンドを実行してトラフィックを生成します。
http_proxy=$LINKERD_ELB:4140 curl -s http://hello
Linkerdは、提供されているリクエスト数、接続数、豊富なデータを表示します。
Install linkerd-viz
linkerd-vizは、PrometheusとGrafanaに基づく監視アプリケーションです。 k8sクラスタにインストールされているリンカーインスタンスとサービスを自動的に検索できます。
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-viz/master/k8s/linkerd-viz.yml replicationcontroller "linkerd-viz" created service "linkerd-viz" created
linkerd-viz ELBを開いてダッシュボードを表示できます
LINKERD_VIZ_ELB=$(kubectl get svc linkerd-viz -o jsonpath="{.status.loadBalancer.ingress[0].*}") open http://$LINKERD_VIZ_ELB
前の例と同様に、ELB DNSが利用可能になるには1〜2分かかることがあります。
リクエストごとのルーティング
上記の例で使用したのと同じ「hello-world」アプリケーションを使用しますが、今回は「world」マイクロサービスのバージョン2をデプロイし、要求ごとにリクエストでv1かv2を使用するかどうかを指定します 「hello-world」アプリケーションをまだ配備していない場合は、今すぐデプロイしてください。
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/ \ k8s-daemonset / k8s / hello-world.yml
以前のリンカーのDaemonsetを削除してください。ConfigMapを更新して新しいものをインストールします
$ kubectl delete ds/l5d
アプリケーションに外部からアクセスできるようにlinkerd ingressをデプロイします。
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/\ k8s-daemonset/k8s/linkerd-ingress.yml configmap "l5d-config" configured daemonset "l5d" configured service "l5d" configured
今、バージョン2の「world」マイクロサービスを導入してください。
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/\ k8s-daemonset/k8s/world-v2.yml replicationcontroller "world-v2" created service "world-v2" created
サービスのv1にリクエストを送信します。それは 'Hello world'と返信する必要があります。
INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}") curl -H 'Host: www.hello.world' $INGRESS_LB
1〜2分後、次のHello worldように返信する必要があります。
Hello (100.96.1.12) world (100.96.1.14)
要求のヘッダーを変更して、サービスのv2に要求を送信します。
Hello (100.96.1.11) earth (100.96.2.14)
次のように「Hello Earth」と返信する必要があります
Hello (100.96.1.11) earth (100.96.2.14)
これは、worldサービスのv1とv2がクラスタ内で実行されていることを示しています。 また、要求ヘッダーに個々の要求をルーティングするサービスのバージョンを指定できます。 これでおしまい! linkerdの設定ファイルをlinkerdの例で見ることができます。
Cleanup
インストールしたコンポーネントの削除
kubectl delete -f install/kubernetes/addons/servicegraph.yaml kubectl delete -f install/kubernetes/addons/prometheus.yaml kubectl delete -f install/kubernetes/istio-auth.yaml kubectl delete -f install/kubernetes/istio.yaml ./samples/bookinfo/kube/cleanup.sh
kubectl get all kubectl get all --namespace istio-system
IstioとKubernetesの併用
Istioは、HTTP、WebSocket、HTTP/2、gRPC経由でトラフィックのルーティングとロードを行い、MongoDBやRedisなどのアプリケーションプロトコルをサポートするレイヤ4/7プロキシです。 IstioはEnvoyプロキシを使用して、サービスメッシュ内のすべての着信/発信トラフィックを管理します。 EnvoyはLyftによって建設され、2017年9月EnvoyはKubernetesと共にCNCFのメンバーになった。 Istioは、Google、IBM、Lyftの共同開発です。
Istioには、A/Bテスト、段階的/カナリ・ロールアウト、障害回復、回路遮断器、レイヤー7ルーティング、ポリシー施行(すべてEnvoyプロキシによって提供される)など、アプリケーションコードの外にあるさまざまなトラフィック管理機能があります。 また、IstioはMixerコンポーネントを使用して、ACL、レート制限、クォータ、認証、要求トレース、テレメトリ収集をサポートしています。 Istioプロジェクトの目標は、アプリケーションの変更を必要とせずにトラフィック管理とマイクロサービスのセキュリティをサポートすることです。 これは、すべてのネットワーク通信を処理するside-carをポッドに注入することで行います。
この演習では、Istioが提供する次のような機能をいくつか見ていきます。
- 加重ルーティング
- 分散トレース
- 相互TLS認証
Kubernetesクラスタを作成
3つのマスターノードと5つのワーカーノードを持つクラスタを使用
Istioをインストールする
Istioは、Envoy(side-car proxy)のサイドカーをポッドに挿入するためにマシンにバイナリをインストールする必要があります。 つまり、Istioをダウンロードする必要があります。Istioは自動的にside-carを注入することもできます。 詳細はIstioクイックスタートをご覧ください
curl -L https://git.io/getLatestIstio | sh - cd istio-* export PATH=$PWD/bin:$PATH
これで、istioctl
CLI を実行できるはずです
$ istioctl version Version: 0.8.0 GitRevision: 6f9f420f0c7119ff4fa6a1966a6f6d89b1b4db84 User: root@48d5ddfd72da Hub: docker.io/istio GolangVersion: go1.10.1 BuildStatus: Clean
kubectlを使用してIstioをインストールします。
これにより、Istioが独自の名前空間 istio-system
にインストールされます。
上記の手順でIstioをダウンロードしたディレクトリに移動します。
side-car 間の相互TLS認証を有効にせずにIstioをインストールします。
既存のアプリケーションを持つクラスタ、Istioside-carを持つサービスが他の非Istio Kubernetesサービスと通信できる必要があるアプリケーション、生存度と準備性のプローブ、ヘッドレスサービス、またはStatefulSet を使用するアプリケーションには、このオプションを選択します。
kubectl apply -f install/kubernetes/istio-demo.yaml
Istioがインストールされていることを確認します。 Istioは独自の名前空間にインストールされています。
$ kubectl get all --namespace istio-system NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deploy/istio-ca 1 1 1 1 1m deploy/istio-egress 1 1 1 1 1m deploy/istio-ingress 1 1 1 1 1m deploy/istio-mixer 1 1 1 1 2m deploy/istio-pilot 1 1 1 1 1m NAME DESIRED CURRENT READY AGE rs/istio-ca-2651333813 1 1 1 1m rs/istio-egress-2836352731 1 1 1 1m rs/istio-ingress-2873642151 1 1 1 1m rs/istio-mixer-1999632368 1 1 1 2m rs/istio-pilot-1811250569 1 1 1 1m NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deploy/istio-ca 1 1 1 1 1m deploy/istio-egress 1 1 1 1 1m deploy/istio-ingress 1 1 1 1 1m deploy/istio-mixer 1 1 1 1 2m deploy/istio-pilot 1 1 1 1 1m NAME READY STATUS RESTARTS AGE po/istio-ca-2651333813-pcr1f 1/1 Running 0 1m po/istio-egress-2836352731-sfj7j 1/1 Running 0 1m po/istio-ingress-2873642151-vzfxr 1/1 Running 0 1m po/istio-mixer-1999632368-nz0mw 2/2 Running 0 2m po/istio-pilot-1811250569-mmfdg 1/1 Running 0 1m
サンプルアプリケーションのデプロイ
私たちは、Istioチームが開発したサンプルアプリケーションを使用して、Istioの機能をチェックします。
Envoy(side-car proxy)をアプリケーションに手動で注入する方法を使用しているので、以下のように istioctl
を使用する必要があります。
kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/kube/bookinfo.yaml)
これによりBookInfoアプリケーションが展開されます。 これは4つのマイクロサービスで構成され、それぞれが異なる言語で書かれており、共同して書籍の製品情報、書籍の詳細、書籍のレビューを表示します。 各マイクロサービスは専用ポッドに配置され、エンボイプロキシはポッドに注入されます。 Envoyは、ポッド間のすべてのネットワーク通信を引き継ぐようになります。 すべてのコンポーネントがインストールされていることを確認しましょう
$ kubectl get all NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deploy/details-v1 1 1 1 1 3h deploy/productpage-v1 1 1 1 1 3h deploy/ratings-v1 1 1 1 1 3h deploy/reviews-v1 1 1 1 1 3h deploy/reviews-v2 1 1 1 1 3h deploy/reviews-v3 1 1 1 1 3h NAME DESIRED CURRENT READY AGE rs/details-v1-39705650 1 1 1 3h rs/productpage-v1-1382449686 1 1 1 3h rs/ratings-v1-3906799406 1 1 1 3h rs/reviews-v1-2953083044 1 1 1 3h rs/reviews-v2-348355652 1 1 1 3h rs/reviews-v3-4088116596 1 1 1 3h NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deploy/details-v1 1 1 1 1 3h deploy/productpage-v1 1 1 1 1 3h deploy/ratings-v1 1 1 1 1 3h deploy/reviews-v1 1 1 1 1 3h deploy/reviews-v2 1 1 1 1 3h deploy/reviews-v3 1 1 1 1 3h NAME READY STATUS RESTARTS AGE po/details-v1-39705650-vc2x0 2/2 Running 0 3h po/productpage-v1-1382449686-b7frw 2/2 Running 0 3h po/ratings-v1-3906799406-11pcn 2/2 Running 0 3h po/reviews-v1-2953083044-sktvt 2/2 Running 0 3h po/reviews-v2-348355652-xbbbv 2/2 Running 0 3h po/reviews-v3-4088116596-pkkjk 2/2 Running 0 3h
すべてのコンポーネントが正常にインストールされている場合は、製品ページを表示できるはずです。 これには、最初にIngressが作成されるのに1〜2分かかる場合があります。 また、Ingressが公開するサービスに接続する場合もあります。 予約商品ページが表示されるまでブラウザを更新してください。
ISTIO_INGRESS=$(kubectl get -n istio-system svc istio-ingressgateway -o jsonpath="{.status.loadBalancer.ingress[0].*}") open http://$ISTIO_INGRESS/productpage
加重ルーティング
サンプルアプリケーションは非常に便利です。
上記のコマンドkubectl get all
では、複数の「レビュー」マイクロサービスのバージョンが展開されていることがわかります。
重み付けされたルーティングを使用して、トラフィックの50%をレビューマイクロサービスのv3にルーティングします。
v3ではレビューごとに星が表示されますが、v1では表示されません。
次に、bookinfoの商品ページに数回問い合わせを行い、評価のために星を含むレビューページが表示された回数を数えます。
これは、レビューページのv3にルーティングされていることを示します。
$ kubectl create -f samples/bookinfo/kube/route-rule-all-v1.yaml routerule "productpage-default" created routerule "reviews-default" created routerule "ratings-default" created routerule "details-default" created $ kubectl replace -f samples/bookinfo/kube/route-rule-reviews-50-v3.yaml routerule "reviews-default" replaced
エンボイプロキシは、異なるバージョンのマイクロサービスへのルーティングをラウンドロビンしません。 したがって、製品ページに2回アクセスすると、1つのリクエストでレビューのv1が使用される可能性は低くなり、2回目のリクエストではv3が使用されます。 しかし、100件を超えるリクエストのうち50%はレビューページのv3にルーティングする必要があります。以下のスクリプトを使用してこれをテストできます。 mfileこれを実行する前に、現在のフォルダで呼び出されているファイルがないことを確認してください。 このスクリプトcurlはbookinfo製品ページに100回のリクエストを送信します。 約30秒かかる場合があり、レスポンスに星があるものを数えます。製品ページhtmlには2人のレビューアが含まれているため、2人で区切られています。 curlsレビューページで「完全な星」を返しました。100本のカールのうち、50本は「完全な星」を含むと予想しています。
ISTIO_INGRESS=$(kubectl get -n istio-system svc istio-ingressgateway -o jsonpath="{.status.loadBalancer.ingress[0].*}") for((i=1;i<=100;i+=1));do curl -s http://$ISTIO_INGRESS/productpage >> mfile; done; a=$(grep 'full stars' mfile | wc -l) && echo Number of calls to v3 of reviews service "$(($a / 2))"
出力は次のように表示されます。
Number of calls to v3 of reviews service 72
最後に、一時ファイルを削除します。
rm mfile
この重み付きルーティングは、Istioがバージョン間のトラフィックをルーティングし、トラフィックの負荷に対応するためにレビューマイクロサービスをスケーリングすることによって処理されました。
分散トレース
Istioは各サイドポッドにside-car proxyとして配備されています。 つまり、マイクロサービス間のすべてのトラフィックフローを表示および監視し、メッシュトラフィックのグラフィカルな表現を生成できます。 前の手順でデプロイしたbookinfoアプリケーションを使用してこれを実演します。
まず、Prometheusをインストールします。 これはIstioから必要なメトリクスを取得します
$ kubectl apply -f install/kubernetes/addons/prometheus.yaml configmap "prometheus" created service "prometheus" created deployment "prometheus" created
Prometheusが動作していることを確認してください.
$ kubectl -n istio-system get svc prometheus NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE prometheus ClusterIP 100.69.199.148 <none> 9090/TCP 47s
Servicegraphアドオンをインストールします。 Servicegraphは、Istioからのメッシュトラフィックフローの詳細を取得するPrometheusをクエリします。
$ kubectl apply -f install/kubernetes/addons/servicegraph.yaml deployment "servicegraph" created service "servicegraph" created
Servicegraphが展開されたことを確認します。
$ kubectl -n istio-system get svc servicegraph NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE servicegraph ClusterIP 100.65.77.1 <none> 8088/TCP 5m
bookinfoアプリケーションへのトラフィックを生成。
ISTIO_INGRESS=$(kubectl get ingress gateway -o jsonpath="{.status.loadBalancer.ingress[0].*}") open http://$ISTIO_INGRESS/productpage
サービスグラフUIを表示する - ポートフォワーディングを使用してこれにアクセスします。
kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=servicegraph -o jsonpath='{.items[0].metadata.name}') 8088:8088 & open http://localhost:8088/dotviz
このような形の分散トレースが表示されます。 Servicegraphが利用可能になるまで数秒かかる場合がありますので、応答がない場合はブラウザを更新してください。
side-car 間の相互TLS認証を有効にする
Istio-auth は、サイドキャストプロキシ間の相互TLS通信を強制することによって、マイクロサービス間の安全な通信を可能にします。 これを実装するのは簡単です。 相互TLSを有効にしてIstioをインストールするだけです。
上記の例を実行した場合は、Istioをアンインストールします。
kubectl delete -f install/kubernetes/istio.yaml
Authモジュールを有効にして再インストールする. デフォルトでは、Istioをインストールし、side-car 間で相互TLS認証を実施します。 このオプションは、新しく展開されたワークロードでIstio-side-car がインストールされていることが保証されている新しいkubernetesクラスタでのみ使用してください。
kubectl apply -f install/kubernetes/istio-demo-auth.yaml
マイクロサービス間のすべてのトラフィックが暗号化されます。
Cleanup
インストールされているコンポーネントを削除する
kubectl delete -f install/kubernetes/addons/servicegraph.yaml kubectl delete -f install/kubernetes/addons/prometheus.yaml kubectl delete -f install/kubernetes/istio-auth.yaml kubectl delete -f install/kubernetes/istio.yaml ./samples/bookinfo/kube/cleanup.sh
default
上記のクリーンアップスクリプトの名前空間を受け入れます。
Istioを削除すると、出力にエラーが表示されることがあります。 これらはインストールしていないIstioコンポーネントに関連しているので、これらについては心配する必要はありません。 すべてがアンインストールされたことを確認するには、次のようにします。 IstioまたはBookinfoのコンポーネントは残る必要はありません。
kubectl get all kubectl get all --namespace istio-system