全然理解できなかったVirtualServiceがどのように動いてくれるのか、自分が理解した範囲で書いておきます。
VirtualServiceのyaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews.prod.svc.cluster.local
http:
- name: "reviews-v2-routes"
match:
- uri:
prefix: "/wpcatalog"
- uri:
prefix: "/consumercatalog"
rewrite:
uri: "/newcatalog"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v2
- name: "reviews-v1-route"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v1
Istio1.5の公式からそのままコピペしたものですね。
一行ずつ自分の解釈を書いていきます。
apiVersion:
apiVersion: networking.istio.io/v1alpha3
「istioのAPIを叩きますよ」という宣言。
そうえいばIstio1.5になってからMixerやGalleyやPilotなどバラバラだったPodは全てIstiod
に統合されました。
これはIstioのリリースノートにも書いてあるのでバージョンアップしたら読んだほうがいいですね。
kind:
kind: VirtualService
これで「IstioのVirtualServiceとして設定するよ」と宣言します。
metadata:
metadata:
name: reviews-route
もう既に一行じゃないですね。すみません。
VirtualServiceをreviews-route
という名前で作ります。
ここで指定する名前は他のserviceなどと一緒になっていても問題無いようです。
kubectl get virtualservice
を実行すると出力される名前になります。
nameの他にnamespace:hogehoge
でhogehoge
というNameSpaceに適用することが可能です。
hosts:
spec:
hosts:
- reviews.prod.svc.cluster.local
出ました。
ここでは、トラフィックの宛先がどこなのか
を指定します。
言い換えればVirtualSerivceさんがどこ宛のトラフィックを見るか。です。
上記の例ではreviews.prod.svc.cluster.local
でよくわからんです状態になりますが、
この書き方は簡単に言うとフルパスみたいな物で、prod
というNamespaceの
reviews
というServiceを表しています。Serviceはkubectl get svc
で表示されるServiceです。
Service名.Namespace名.svc.cluster.local
とすることで明示的に書いているんですね。
おそらく、複数のNamespaceに同じような構成を作った時に
誤った設定をしないようにこういう書き方ができるんだと思います。
「もっと簡単に書きたい!まともに使っているNamespaceは一個だ!」
そういう場合は以下のように書けるようです。
spec:
hosts:
- reviews
この場合はVirtualServiceを適用するNamespace内に
reviews
というSerivceが存在することが条件です。
動作について既にご存知の方もいらっしゃるかと思いますが、
基本的にVirtualServiceはServiceに向かって流れていくトラフィックを
横から掴んで自分のルールに従ってルーティングしてくれるんですね。
回転寿司でタッチパネルから注文すると自動で自分のところに向かってくるシステムがあるじゃないですか。
それで例えれば、Aさんが注文をした時に、本来ならAさんに届くはずのお寿司を、
勝手に横取りして自分の隣の人に渡してあげるんです。
ここのAさんがKubernetesのServiceとして、横取りするのがVirtualService。
隣の人がルーティング先。ということになります。
ルールの書き方によっては、Aさん宛のお寿司をVirtualServiceが横取りして、結局Aさんに届ける。みたいなのもできます。
match:
- name: "reviews-v2-routes"
match:
- uri:
prefix: "/wpcatalog"
- uri:
prefix: "/consumercatalog"
ああもう完全に一行解説じゃなくなってしまいました。
ここで定義しているのは「何が来たら横取りするか」です。
match:
はそのままの意味で、「横取りする条件を以下に書きますよ」という宣言。
その後につらつらと条件を書いてあげます。
prefix:
として指定すると、アクセス先が/wpcatalog
だったら。という条件になります。
rewrite:
rewrite:
uri: "/newcatalog"
これは上記のprefix:
にマッチしたトラフィックの宛先を/newcatalog
という名前で上書き(rewrite)しちゃいます。
回転寿司でAさんが注文し、そこに向かっていくお寿司の新幹線をリモコンで操作し、
Bさんのところに届けるような感じですね。
悪質極まりない。
destination:
- destination:
host: reviews.prod.svc.cluster.local
subset: v2
やっとdestination
まで来ました。
ここのhost:
でトラフィックの宛先を指定します。
先程のお寿司横取り事件で、VirtualServiceさんが隣の人に渡した時の、その「隣の人」をここで指定してあげます。
ここもhosts:
と同じような書き方ができて、
prod
というNamespaceにあるreviews
というServiceを宛先にしています。
VirtualServiceと宛先のServiceが同じNamespaceであればhost: reviews
と書くことができます。
ここまでで簡単におさらいしておきます。
spec:
hosts:
- reviews.prod.svc.cluster.local
http:
- name: "reviews-v2-routes"
match:
- uri:
prefix: "/wpcatalog"
- uri:
prefix: "/consumercatalog"
rewrite:
uri: "/newcatalog"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v2
Namespaceprod
にあるreviews
というServiceに対し、
/wpcatalog
と/consumercatalog
それぞれが先頭に付いたアドレスでアクセスがあったら
/newcatalog
というアドレスに置き換えて、Namespaceprod
のreviews
というServiceの
v2
とラベリングされたサブセットにアクセスさせる。
と言い換えることができます。
subset:
はごめんなさい。これから調べます。
DestinationRuleで頻繁に使われるようなのであとで調べます。
あれ?残りの定義は?
- name: "reviews-v1-route"
route:
- destination:
host: reviews.prod.svc.cluster.local
subset: v1
上記のいずれかにマッチしなかったらここにルーティングされます。(と思います)
VirtualServiceって分かってくるとそんなに複雑じゃない
Kubernetes自体がもう新しい言葉ばかりで頭おかしくなると思います。
実際私も頭おかしくなってます。
でもこうして一つずつ紐解いて行ければきっとKubernetesさん(Istioさん)と仲良くなれる気がします。
もし上記内容に間違いがありましたら、修正リクエストお気軽に!私も勉強中の身です!