この投稿はFujitsu Advent Calendar 2019の10日目の記事です。
なお、記事は全て個人の見解です。会社・組織を代表するものではありません。
概要
現在サービスメッシュの認知の広まりとともに、その代表的なOSSであるIstioが注目されています。
Istioを使ってみたいという声を聴く一方で、Istioはコンポーネントが多すぎてわからないといった声も聴きます。
確かにIstio全体としてはとても巨大です。
しかし、各コンポーネントは疎結合なため、必要なもののみインストールすることも可能なのです。
この記事ではひとつずつインストールしながら、コンポーネントについて解説していきます。
環境
- MacBook Air
- CPU: 3, Memory: 8GiB
- Docker Version: 19.03.5
- Kubernetes Version: v1.15.5
- Istio Version: 1.4.1
- Helm Version: v2.12.0
※KubernetesはDocker for Kubernetesを使用しています。
Istioの全体像
まずはIstioの全体像について解説します。
Istioにはざっと上記のようなコンポーネントが存在します。
大まかな動作としてはサービス通信の間にEnvoyが存在し、それがプロキシとしてすべての通信(Inbound, Outbound両方)の仲介をします。
そのEnvoyがサービス間通信の際に考えなければならないめんどくさいこと(timeoutや流動制御など)を肩代わりしてくれます。
その他のコンポーネントはこのあと解説しますが、主にEnvoyの制御や情報収集などEnvoyをControlするコンポーネントたちです。
それでは、実際にインストールしながら解説していきます。
参考: https://istio.io/docs/ops/deployment/architecture/
Istioインストールの前準備
今回はhelmコマンドを使ってコンポーネントをインストールしていこうと思います。
helmのインストールとistio用のtemplateの準備方法は以下の通りです。
$ brew install helm
$ helm version
$ curl -L https://istio.io/downloadIstio | sh -
$ sudo cp istio-1.4.1/bin/istioctl /usr/local/bin
$ istioctl version
その後、コンポーネントをインストールするための前段階のNamespsceやCRD(Custom Resource Definition)をインストールします
$ kubectl create namespace istio-system
$ helm template istio-1.4.1/install/kubernetes/helm/istio-init --name istio-init --namespace istio-system | k apply -f -
参考:
- helmでのセットアップ: https://istio.io/docs/setup/install/helm/
Core Components
Pilot
PilotはユーザーがKubernetesのCRD(Custom Resource Definition)として設定した値をEnvoyに伝えるためのコンポーネントです。
このコンポーネントによってDestinationRuleやVirtualServiceなどのリソースを解釈してEnvoyの設定として反映してやることができます。
Pilotのインストールによってできるようになる操作
Load Balancingや特定バージョンのみリクエストを送るなどTraffic Managementが行えるようになります。
- Traffic Management一覧
- 特定のバージョンのみへのルーティング
- Fault Injection(強制的にInternal Server Errorを返すなど)
- リクエストにtimeoutを設定
- Circuit Breaking
デプロイコマンド
今回はhelmのvalueファイルを用意し、そこからkubernetesのyamlファイルをtemplateコマンドで作成していきます。
$ vi values-pilot.yaml
# ※下記参照
$ helm template istio-1.4.1/install/kubernetes/helm/istio --name istio --namespace istio-system --values values-pilot.yaml > pilot.yaml
$ kubectl apply -f pilot.yaml
pilot:
enabled: true
sidecar: false
gateways:
enabled: false
security:
enabled: false
sidecarInjectorWebhook:
enabled: false
galley:
enabled: false
mixer:
policy:
enabled: false
telemetry:
enabled: false
prometheus:
enabled: false
# Common settings.
global:
proxy:
envoyStatsd:
enabled: false
useMCP: false
テスト
テストアプリはBookInfoを使用します。
今回は全てのリクエストをv1のみに送るようにしたいと思います。
$ vi istio-1.4.1/samples/bookinfo/platform/kube/bookinfo.yaml
# とりあえずアクセスするためにProductpageのServiceをNodePortにします(下記参照)
$ istioctl kube-inject -f istio-1.4.1/samples/bookinfo/platform/kube/bookinfo.yaml | kubectl apply -f -
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-5c76c87c6-5w2pr 2/2 Running 0 4m53s
productpage-v1-7bc5cb86bd-9srfr 2/2 Running 0 4m50s
ratings-v1-5597f5d56d-zr225 2/2 Running 0 4m51s
reviews-v1-67b6db665d-48968 2/2 Running 0 4m52s
reviews-v2-5f78d5fdf9-zvcff 2/2 Running 0 4m52s
reviews-v3-69f68ff8bd-fxsfc 2/2 Running 0 4m52s
# 動作しているかブラウザから確認(http://localhost:30000/productpage)
# 何度か更新するとレビューの星が黒や赤や無くなったりするはずです
$ kubectl apply -f istio-1.4.1/samples/bookinfo/networking/destination-rule-all.yaml
$ kubectl apply -f istio-1.4.1/samples/bookinfo/networking/virtual-service-all-v1.yaml
# ブラウザからアクセスするとreviewの星がない状態しか表示されなくなる
# ・・・(省略)
# 240行目付近
apiVersion: v1
kind: Service
metadata:
name: productpage
labels:
app: productpage
service: productpage
spec:
type: NodePort
ports:
- port: 9080
name: http
nodePort: 30000
selector:
app: productpage
---
# ・・・(省略)
PodがEnvoy付きで起動したのでREADYが2/2となっているのが確認できると思います。
また、特定バージョンのみへのルーティングしかできないようになっているのが確認できると思います。
参考:
- Traffic Management: https://istio.io/docs/tasks/traffic-management/
- BookInfoアプリ: https://istio.io/docs/examples/bookinfo/
Policy
PolicyはMixerの一部で、流動制御やブラックリスト(ホワイトリスト)でのアクセス制御などEnvoyに対してアクセスポリシーを設定するためのコンポーネントです。
デプロイコマンド
先ほどのvalues-pilot.yamlからpolicyの項目をenableにします。
また、disablePolicyChecksをfalseにします。
# ・・・(省略)
mixer:
policy:
enabled: true
telemetry:
enabled: false
# ・・・(省略)
global:
disablePolicyChecks: false
# ・・・(省略)
$ helm template istio-1.4.1/install/kubernetes/helm/istio --name istio --namespace istio-system --values values-policy.yaml > policy.yaml
$ kubectl apply -f policy.yaml
テスト
今回はブラックリストによってhelloworldサービスのv3(reviewsの星が赤色)にアクセスできないようにしてみます。
# all-v1のルールは削除しておきます
$ kubectl delete -f istio-1.4.1/samples/bookinfo/networking/virtual-service-all-v1.yaml
$ kubectl apply -f istio-1.4.1/samples/bookinfo/policy/mixer-rule-deny-label.yaml
# ブラウザを更新し続けると以下のようにアクセスできなくなっているのが確認できると思います
# Ratings service is currently unavailable
Telemetry
Telemetryも同じくMixerの一部で、Envoyからメトリクスやログ情報を収集するコンポーネントです。
収拾したデータはバックエンドにつながっているPrometheusやDatadogなどにMixer Adapterを通して送信されます。
Adapterとはistioの持つデータ形式を各バックエンドのデータ形式に変換するもので、例えばPrometheus Adapterの場合、Envoyから収集したメトリクスをPrometheusの形式に変更して送信してくれます。
このAdapterは自作することも可能なので、任意のバックエンドに送信することができます。
デプロイコマンド
今回も同様にvaluesファイルを作成していきます。
※TelemetryはデフォルトのResource Requestが多いので減らしています。
# ・・・(省略)
mixer:
policy:
enabled: true
telemetry:
enabled: true
resources:
requests:
cpu: 200m
memory: 500Mi
# ・・・(省略)
$ helm template istio-1.4.1/install/kubernetes/helm/istio --name istio --namespace istio-system --values values-telemetry.yaml > telemetry.yaml
$ kubectl apply -f telemetry.yaml
テスト
最もわかりやすい使い方はPrometheusに情報を送ることだと思うので、ついでにPrometheusもインストールしてみます。
values-telemetry.yamlを次のように修正してPrometheusをONにします。
# ・・・(省略)
prometheus:
enabled: true
service:
nodePort:
enabled: true
security:
enabled: false
# ・・・(省略)
http://localhost:32090にアクセスするとPrometheusのUI画面が見えて、メトリクス情報が取得できるのが確認できると思います。
Ingress/Egress Gateway
まず、Ingress Gatewayは外部からCluster内への通信を制御するためのコンポーネントです。
KubernetesのIngress Controllerと似たようなもの(どちらもL7の通信を制御)ですが、Istio Ingress Gatewayはより細かい設定ができます。
Egress Gatewayはその逆でCluster内から外部への通信を制御するためのコンポーネントです。
今回はIngress Gatewayについてのみ紹介したいと思います。
デプロイコマンド
先ほどのvalues-telemetry.yamlからgatewaysの項目を設定していきます。
# ・・・(省略)
gateways:
istio-ingressgateway:
autoscaleEnabled: false
resources:
requests:
cpu: 10m
memory: 40Mi
istio-egressgateway:
enabled: false
# ・・・(省略)
$ helm template istio-1.4.1/install/kubernetes/helm/istio --name istio --namespace istio-system --values values-gateways.yaml > gateways.yaml
$ kubectl apply -f gateways.yaml
テスト
まず、先ほど設定したbookinfoのNodePortの設定はもう用がないので外します。
その後、Istio IngressGateway用のリソースをデプロイします。
$ vi istio-1.4.1/samples/bookinfo/platform/kube/bookinfo.yaml
# ※下記参照
$ istioctl kube-inject -f istio-1.4.1/samples/bookinfo/platform/kube/bookinfo.yaml | kubectl apply -f -
$ kubectl apply -f istio-1.4.1/samples/bookinfo/networking/bookinfo-gateway.yaml
# ・・・(省略)
# 240行目付近
apiVersion: v1
kind: Service
metadata:
name: productpage
labels:
app: productpage
service: productpage
spec:
ports:
- port: 9080
name: http
selector:
app: productpage
---
# ・・・(省略)
最後にブラウザからhttp://localhost/productpage(istio-ingressgatewayのServiceのアドレス)にアクセスします。
Citadel
CitadelはIstioのセキュリティを担う部分です。
Istioにはセキュリティ機能として以下の2つがあります。
- Mutual TLS(相互認証)
- Istio RBAC(Role Based Access Control)
相互認証
通常のhttpsのサービスなどの認証はクライアントがサーバがだれなのか
というのを認証します。
相互認証ではクライアントがサーバを認証すると同時にサーバがクライアントがだれなのか
ということを認証します。
これによりサービス間で正しいサービス同士が安全に通信できるようになります。
認証には通常SSL証明書が必要になります。
証明書は発行や管理など扱いは大変なのですが、IstioではCitadelがこの証明書をすべて管理してくれます。
Istio RBAC
Istio RBACはIstioのアクセスコントロール機能の一つです。
KubernetesのRBACと同じ様な使い方でService間の通信のアクセス制御できます。(k8sはリソースのアクセス制御)
例としてserviceAのGET /pathにはuserAだけアクセスを許可するというような設定が可能になります。
Citadelがやってくれること
- サービス間(Envoy間)通信の暗号化
- 通信先の認証(※k8s Cluster外サービスを除く)
- Roleによる通信の認可
※より詳しくk8s, istioのセキュリティについて知りたい方はぜひ私のGitHub(https://github.com/sh-miyoshi/sectest )を参照してください
デプロイ手順
先ほどのvalues-gateways.yamlからcitadel周りの項目をONにしていきます
# ・・・(省略)
security:
enabled: true
# ・・・(省略)
global:
disablePolicyChecks: false
proxy:
envoyStatsd:
enabled: false
useMCP: false
mlts:
enabled: true
# ・・・(省略)
$ helm template istio-1.4.1/install/kubernetes/helm/istio --name istio --namespace istio-system --values values-citadel.yaml > citadel.yaml
$ kubectl apply -f citadel.yaml
テスト
今回は見た目的には変わらないので省略します。
なお、security OFF時に作成したbookinfoアプリを削除してから再度デプロイし直してください。
テスト方法などは私のGitHub(https://github.com/sh-miyoshi/sectest )に載せています。
Sidecar Injector
Sidecar InjectorはPodの起動を検知し、自動でEnvoy(istio-proxy)を挿入してくれるコンポーネントです。
今まではistioctl kube-inject
コマンドでEnvoy(istio-proxy)を挿入したyamlファイルを作成し、それをkubectl apply
コマンドでデプロイしていました。
このコンポーネントがあると自動で挿入してくれるのでとても便利です。
デプロイコマンド
先ほどのvalues-citadel.yamlからsidecarInjectorWebhookの項目をenableにします。
※私の環境だとCitadelを有効にした状態でないと起動できませんでした。
# ・・・(省略)
sidecarInjectorWebhook:
enabled: true
# ・・・(省略)
$ helm template istio-1.4.1/install/kubernetes/helm/istio --name istio --namespace istio-system --values values-injector.yaml > injector.yaml
$ kubectl apply -f injector.yaml
使い方
auto injectするnamespaceにラベルをつけて、kubectlコマンドでデプロイするだけです。
# 一旦削除
$ ./istio-1.4.1/samples/bookinfo/platform/kube/cleanup.sh
$ kubectl label namespace default istio-injection=enabled
$ kubectl apply -f istio-1.4.1/samples/bookinfo/platform/kube/bookinfo.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
details-v1-74f858558f-krpqv 2/2 Running 0 3m36s
productpage-v1-8554d58bff-2l57q 2/2 Running 0 3m33s
ratings-v1-7855f5bcb9-xzcvc 2/2 Running 0 3m36s
reviews-v1-59fd8b965b-7nm8r 2/2 Running 0 3m34s
reviews-v2-d6cfdb7d6-kdmg2 2/2 Running 0 3m35s
reviews-v3-75699b5cfb-86tqh 2/2 Running 0 3m35s
Galley
ユーザが定義したIstio設定のvalidationを実施してくれるコンポーネントらしいです。
すみません、私もあまりGalleyについて詳しくわかってなくて具体的に何がどうなるのかが説明できないです・・・
Addons
最後にistioのCoreの部分ではありませんが、役に立ちそうなコンポーネントを紹介します。
Tracing
簡単に言うとJaegerやzipkinといった分散トレーシングツールを導入してくれます。
複数サービスの通信においてどこにどれだけ時間がかかっているのかを知ることができます。
デプロイコマンド
今までと同様にvaluesファイルを修正し、helmコマンドでデプロイします。
# ・・・(省略)
tracing:
enabled: true
service:
type: LoadBalancer
# ・・・(省略)
$ helm template istio-1.4.1/install/kubernetes/helm/istio --name istio --namespace istio-system --values values-tracing.yaml > tracing.yaml
$ kubectl apply -f tracing.yaml
確認方法
http://localhost:(node-port) にアクセスするとJaegerのダッシュボードが見えます。
※node-portはkubectl get svc -n istio-system tracing -o json | jq .spec.ports[0].nodePort
などのコマンドで調べられます。
適当にリクエストしてみてデータを見てみてください。
Kiali
Kialiはマイクロサービスで何が起こっているかを可視化するGUIコンポーネントです。
どのサービスが通信していて今どういう状態なのかということをWeb UI画面から視覚的に確認することができます。
デプロイコマンド
今までと同様にvaluesファイルを修正し、helmコマンドでデプロイします。
# ・・・(省略)
kiali:
enabled: true
createDemoSecret: true
# ・・・(省略)
$ helm template istio-1.4.1/install/kubernetes/helm/istio --name istio --namespace istio-system --values values-kiali.yaml > kiali.yaml
$ kubectl apply -f kiali.yaml
確認方法
kialiはNodePortやLoadBalancerでアクセスする方法がないので、kubectl port-forward
コマンドでアクセスできるようにします。
$ kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=kiali -o jsonpath='{.items[0].metadata.name}') 20001:20001
これでhttp://localhost:20001にアクセスすると様々なグラフが見えるようになります。
なお、ログイン情報はadmin/adminです。(※createDemoSecret: trueの場合)
まとめ
Istioは全体としては巨大ですが、各コンポーネントが独立しており、必要な分だけインストールすることができます。
今回は1コンポーネントずつ確認しながらインストールする手順を紹介しました。
この記事が少しでもみなさまのIstio理解の手助けになれば幸いです。
おまけ
最終的なvalues.yamlファイル
pilot:
enabled: true
sidecar: false
gateways:
istio-ingressgateway:
autoscaleEnabled: false
resources:
requests:
cpu: 10m
memory: 40Mi
istio-egressgateway:
enabled: false
security:
enabled: true
sidecarInjectorWebhook:
enabled: true
galley:
enabled: false
mixer:
policy:
enabled: true
telemetry:
enabled: true
resources:
requests:
cpu: 200m
memory: 500Mi
prometheus:
enabled: true
service:
nodePort:
enabled: true
security:
enabled: true
# Common settings.
global:
disablePolicyChecks: false
proxy:
envoyStatsd:
enabled: false
useMCP: true
mlts:
enabled: true
tracing:
enabled: true
service:
type: NodePort
kiali:
enabled: true
createDemoSecret: true