はじめに
Istioでどのようにトラフィックを制御しているのかについて、公式チュートリアルをローカル環境で実験した際に学んだ事のメモ。
■公式チュートリアル
https://istio.io/docs/examples/bookinfo/
前提
Kubernetes上にデプロイするのは、BookInfoというサンプルアプリケーションで構成は以下の通り。
EnvoyプロキシをPodにインジェクトすると下図のように、各PodにEnvoyがサイドカーとして内包され、全トラフィックをEnvoy経由でやり取りする事でサービスメッシュを構築する。
Istio IngressGateway周りの流れ
- クラスタ外部からトラフィックが来る
- トラフィックをロードバランサーが受ける
- ロードバランサーが転送するポートで待ち受けてるIstio-IngressGateway Serviceにルーティングされる
- Istio-IngressGateway Serviceは、リクエストをIstio-IngressGateway Podに転送
- VirtualServiceリソースの設定を元に、Istio-IngressGateway PodはリクエストをアプリケーションのServiceへ送る
のような流れだと思われる
■下記参考
https://blog.jayway.com/2018/10/22/understanding-istio-ingress-gateway-in-kubernetes/
IngressGateway
Istioをセットアップすると、serviceリソースとしてnamespace=istio-systemにistio-ingressgatewayがクラスタ内にセットアップされる。
$ kubectl get service istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.99.217.20 localhost 15020:31305/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:32722/TCP,15030:30551/TCP,15031:30212/TCP,15032:31148/TCP,15443:32476/TCP 4h
上記ServiceからIstio-IngressGateway Podにリクエストを転送し、後述のVirtualServiceの設定を元にトラフィックを制御している。
$ kubectl get pod istio-ingressgateway-5966c86d4-sb9cb -n istio-system
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-5966c86d4-sb9cb 1/1 Running
Gateway
Kubernetesクラスタの外部からトラフィックを受け付けるために、サービスメッシュの境界に存在するistio-ingessgatewayの設定を行うためのリソース。
下記は80番ポートでHTTPリクエストを待ち受ける設定。
Gatewayリソースはトラフィックを受ける設定をするだけで、どこにどうやって流すかはVirtualServiceリソースが担当する。
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:
- "*"
hostsは「*」で全てを受け入れるように設定されているが、例えば下記のように設定すると、dev.example.comやprod.example.comを持つVirtualServiceが該当する事になる。
hosts:
- "*.example.com"
VirtualService
istio-ingressgatewayで受けたトラフィックをどこにどうやって流すかのルールを設定するためのリソース。
後述のDestinationRuleリソースで定義するsubsetsと合わせる事でトラフィック分割を実現する事が可能。
尚、subsetsを定義しなくても異なるサービスにトラフィックを分割することも可能な模様(実験してないけど)
※参考:Istio-HTTPRouteDestination
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
トラフィック分割の例
■DestinationRule
DestinationRuleリソースは、トラフィックに適応されるポリシーを定義する。
reviewsという名前のServiceに3つのバージョンが存在し、それぞれv1、v2、v3というLabelで識別可能である事を設定している。
Service = reviews配下のPodはversionラベルを持っており、それぞれv1〜v3まで設定されている状態⬇️こんな感じ
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
■VirtualService
DestinationRuleで設定したバージョンに対して、それぞれv1に5%、v2に5%、v3に90%の割合でトラフィック分散させるようにVirtualServiceリソースで設定している例。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 5
- destination:
host: reviews
subset: v2
weight: 5
- destination:
host: reviews
subset: v3
weight: 90
destination.host(string) = Service名を指定
destination.subset(string) = DestinationRuleで定義されたsubset名を指定
参考:Istio/VirtualService
実行してみると、確かにほぼv3が反映されるようになった(Book Reviews部分)
ハマった事
DestinationRuleリソースに相互TLSの設定(trafficPolicy)を何も記述していなかった(Default=DISABLE)のだが、DestinationRuleをApplyした瞬間にupstream connect error or disconnect/reset before headers
と言われて一瞬詰んだ・・・†
下記を参考に相互TLSについて把握し、trafficPolicy.tls.modeを設定。
参考:TLSSettings.TLSmode
参考:503 errors after setting destination rule
所感
Istio初心者ですがチュートリアルを進める事で、Istio IngressGateway周りでどんな挙動をしているのか、雰囲気理解する事ができた気がします。
まだ試せていないの機能だらけなので、実際に動かしてIstioに対する理解を深めると共に、次は自分のアプリケーションをKubernetesにデプロイしてIstioを適応してみようと思いましたまる
< Fight!!