Istioを入れてサービスメッシュなサンプルアプリ(BookInfo)を動かすところまで。
環境
こっちで構築したMetalLBでtype:LoadBalancer Serviceが使えるオンプレK8sです。
[zaki@cloud-dev ~]$ kubectl version Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:47:41Z", GoVersion:"go1.13.9", Com piler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:39:24Z", GoVersion:"go1.13.9", Com piler:"gc", Platform:"linux/amd64"} [zaki@cloud-dev ~]$ kubectl get node NAME STATUS ROLES AGE VERSION k8s-master01.esxi.jp-z.jp Ready master 22d v1.18.5 k8s-worker01.esxi.jp-z.jp Ready <none> 22d v1.18.5 k8s-worker02.esxi.jp-z.jp Ready <none> 22d v1.18.5
デフォルトでtype:LoadBalancer Serviceを使って外部アクセス用のIngressgatewayが作成されるので、使えるようにしておくこと。
ちなみにOpenShiftのサービスメッシュの場合は、インストール(OperatorHubを使用)もサイドカーインジェクション(namespaceのラベルでなくCRMでnamespace指定してアノテーション指定する)も外部アクセス(デフォルトではrouteが提供される)若干異なるのでドキュメントをよく確認すること。
アノテーション等の変更点に関連してBookInfoのマニフェストも若干異なる。
Istio
単純な構成なKubernetesにIstioを入れるには、現バージョンでは
- istioctlを使用
- Operatorを使用
の2パターンが提供されている。
(以前はHelmを使ったインストールもあったが、現在はdeprecated)
今回はGetting Startedに沿ってやっていくので、istioctlを使用したインストールについて。
以下、2020.07.26時点の、Istio 1.6.5について記載。
インストール
流れとしては、まずistioctl
を操作用ノード(kubectl
など叩くノードであればよく、K8sのノードである必要はない)にインストール。そしてistioctl install
を実行してK8sクラスタへIstioをインストールする。
download istioctl
[zaki@cloud-dev ~]$ mkdir -p local/istio [zaki@cloud-dev ~]$ cd local/istio/ [zaki@cloud-dev istio]$ curl -L https://istio.io/downloadIstio | sh - % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 107 100 107 0 0 169 0 --:--:-- --:--:-- --:--:-- 169 100 3896 100 3896 0 0 3741 0 0:00:01 0:00:01 --:--:-- 3804k Downloading istio-1.6.5 from https://github.com/istio/istio/releases/download/1.6.5/istio-1.6.5-linux.tar.gz ...Failed. Trying with TARGET_ARCH. Downloading istio-1.6.5 from https://github.com/istio/istio/releases/download/1.6.5/istio-1.6.5-linux-amd64.tar.gz ... Istio 1.6.5 Download Complete! Istio has been successfully downloaded into the istio-1.6.5 folder on your system. Next Steps: See https://istio.io/docs/setup/kubernetes/install/ to add Istio to your Kubernetes cluster. To configure the istioctl client tool for your workstation, add the /home/zaki/local/istio/istio-1.6.5/bin directory to your environment path variable with: export PATH="$PATH:/home/zaki/local/istio/istio-1.6.5/bin" Begin the Istio pre-installation verification check by running: istioctl verify-install Need more information? Visit https://istio.io/docs/setup/kubernetes/install/
ダウンロードが完了すると
[zaki@cloud-dev istio]$ istio-1.6.5/bin/istioctl version no running Istio pods in "istio-system" 1.6.5 [zaki@cloud-dev istio]$ ls -F istio-1.6.5/
このとおり。
一時的にPATH設定(あとでちゃんと~/.bashrc
とかに書きましょう)
[zaki@cloud-dev istio-1.6.5]$ export PATH=$PWD/bin:$PATH [zaki@cloud-dev istio-1.6.5]$ istioctl version no running Istio pods in "istio-system" 1.6.5
install Istio
Istio本体をK8sクラスタへデプロイする。
使用するプロファイルはdemo
。
[zaki@cloud-dev istio-1.6.5]$ time istioctl install --set profile=demo Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/docs/ops/best-practices/security/#configure-third-party-service-acc ount-tokens for details. ✔ Istio core installed ✔ Istiod installed - Processing resources for Addons, Egress gateways, Ingress gateways. Waiting for Deployment/istio-system/grafana, Deployment/istio-system/istio-egressgateway, Deployment/istio-system/istio-ingressgateway, ...
インストール処理が完了するとこんな感じ。
[zaki@cloud-dev istio-1.6.5]$ time istioctl install --set profile=demo Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/docs/ops/best-practices/security/#configure-third-party-service-acc ount-tokens for details. ✔ Istio core installed ✔ Istiod installed ✔ Egress gateways installed ✔ Ingress gateways installed ✔ Addons installed ✔ Installation complete real 4m3.635s user 0m7.524s sys 0m0.934s [zaki@cloud-dev istio-1.6.5]$
クラスタのpodとserviceの状態は以下の通り。
[zaki@cloud-dev istio-1.6.5]$ kc get pod,svc -n istio-system NAME READY STATUS RESTARTS AGE pod/grafana-b54bb57b9-nl4zn 1/1 Running 0 10m pod/istio-egressgateway-7486cf8c97-l5mtk 1/1 Running 0 10m pod/istio-ingressgateway-6bcb9d7bbf-4sg9p 1/1 Running 0 10m pod/istio-tracing-9dd6c4f7c-cl2cf 1/1 Running 0 10m pod/istiod-788f76c8fc-q4bws 1/1 Running 0 12m pod/kiali-d45468dc4-jlshb 1/1 Running 0 10m pod/prometheus-6477cfb669-xwc6d 2/2 Running 0 10m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/grafana ClusterIP 10.99.190.212 <none> 3000/TCP 10m service/istio-egressgateway ClusterIP 10.102.52.210 <none> 80/TCP,443/TCP,15443/TCP 10m service/istio-ingressgateway LoadBalancer 10.108.43.69 192.168.0.182 15020:32605/TCP,80:30286/TCP,443:32689/TCP,31400:32053/TCP,15443:31536/TCP 10m service/istiod ClusterIP 10.103.63.200 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP,853/TCP 12m service/jaeger-agent ClusterIP None <none> 5775/UDP,6831/UDP,6832/UDP 10m service/jaeger-collector ClusterIP 10.108.183.184 <none> 14267/TCP,14268/TCP,14250/TCP 10m service/jaeger-collector-headless ClusterIP None <none> 14250/TCP 10m service/jaeger-query ClusterIP 10.106.205.30 <none> 16686/TCP 10m service/kiali ClusterIP 10.104.53.76 <none> 20001/TCP 10m service/prometheus ClusterIP 10.98.172.87 <none> 9090/TCP 10m service/tracing ClusterIP 10.96.197.30 <none> 80/TCP 10m service/zipkin ClusterIP 10.106.80.121 <none> 9411/TCP 10m
表示されている通り、istio-ingressgateway
がtype:LoadBalancer Serviceとしてデプロイされており、このIngressサービスがクラスタ外からのトラフィックをIstioで動くpodへルーティングしてくれるようになる。
サンプルアプリケーションのデプロイ
IstioにはBookInfoというアプリがあり、Pythonで動作するフロントエンドのProductpage
、Java/Ruby/Node.jsで動作するバックエンドのReviews
/Details
/Ratings
という構成になっていて、それぞれIstioを使ってpod間通信が行われる構成になっている。
namespace作成
Istioを使用したアプリケーションのデプロイは、デプロイするnamespaceのラベルにistio-injection=enabled
を付与する。
これを行うことで、自動的にpodにistio-proxyサイドカーがインジェクションされ、これがpod間通信を肩代わりする。
例としてbookinfo-sample
を手動で作成するには
$ kubectl create namespace bookinfo-sample $ kubectl label namespaces bookinfo-sample istio-injection=enabled
マニフェストを作るならこんな感じ。
apiVersion: v1 kind: Namespace metadata: labels: istio-injection: enabled name: bookinfo-sample
describe
してlabelが設定されてあればOK
$ kc describe ns bookinfo-sample Name: bookinfo-sample Labels: istio-injection=enabled Annotations: Status: Active No resource quota. No LimitRange resource.
デプロイ
といっても、istioctlにマニフェストが同梱されているのでapply
すればOK。
ファイルの場所は、istioctlを展開したディレクトリのsamples/bookinfo/platform/kube/bookinfo.yaml
にある。
現在のv1.16バージョンはGitHubのここのはず。
[zaki@cloud-dev istio-1.6.5]$ kc apply -f samples/bookinfo/platform/kube/bookinfo.yaml -n bookinfo-sample 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
[zaki@cloud-dev istio-1.6.5]$ kc get pod -n bookinfo-sample NAME READY STATUS RESTARTS AGE details-v1-6c9f8bcbcb-7rx6s 0/2 PodInitializing 0 7s productpage-v1-7df7cb7f86-8zf6b 0/2 Init:0/1 0 6s ratings-v1-65cff55fb8-pw42c 0/2 Init:0/1 0 7s reviews-v1-7bccdbbf96-dhpgr 0/2 Init:0/1 0 7s reviews-v2-7c9685df46-wcm7r 0/2 Init:0/1 0 7s reviews-v3-58fc46b64-jqls6 0/2 PodInitializing 0 7s
この通り、コンテナ数が2/2
となっており、1pod2コンテナとなっている。
マニフェストを見ればわかるけど、Deploymentの定義には複数のコンテナの記述はなく、namespaceのistio-injection=enabled
のラベルによって、Istioが自動的にコンテナを追加していることがわかる。
しばらく待てばこの通り。
[zaki@cloud-dev istio-1.6.5]$ kc get pod -n bookinfo-sample NAME READY STATUS RESTARTS AGE details-v1-6c9f8bcbcb-7rx6s 2/2 Running 0 2m25s productpage-v1-7df7cb7f86-8zf6b 2/2 Running 0 2m24s ratings-v1-65cff55fb8-pw42c 2/2 Running 0 2m25s reviews-v1-7bccdbbf96-dhpgr 2/2 Running 0 2m25s reviews-v2-7c9685df46-wcm7r 2/2 Running 0 2m25s reviews-v3-58fc46b64-jqls6 2/2 Running 0 2m25s
[zaki@cloud-dev istio-1.6.5]$ kc logs productpage-v1-7df7cb7f86-8zf6b -n bookinfo-sample error: a container name must be specified for pod productpage-v1-7df7cb7f86-8zf6b, choose one of: [productpage istio-proxy] or one of the init containers: [istio-init]
このように、istio-proxy
というコンテナが追加されている。
podへの外部からのアクセス設定
デプロイされたBookInfoアプリケーションに外部からアクセスするには、前にも少し書いたIstio Ingressgateway。
[zaki@cloud-dev istio-1.6.5]$ kc get svc -n istio-system istio-ingressgateway NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.108.43.69 192.168.0.182 15020:32605/TCP,80:30286/TCP,443:32689/TCP,31400:32053/TCP,15443:31536/TCP 36m
ただし、まだBookInfoのアプリケーションをデプロイしただけで、Istio IngressgatewayからBookInfoへトラフィックを転送する設定関連はまだ何もないので、これをデプロイする必要がある。
Istioの外部からのトラフィックコントロールには、Gateway
, VirtualService
というリソースがあり、この定義内容によってIstio Ingressgatewayへのアクセスが各アプリケーション(今回はBookInfo)へ転送される動きになる。
BookInfo用の定義ファイルはsamples/bookinfo/networking/bookinfo-gateway.yaml
にある。
GitHubだとこちら。
[zaki@cloud-dev istio-1.6.5]$ kc apply -f samples/bookinfo/networking/bookinfo-gateway.yaml -n bookinfo-sample gateway.networking.istio.io/bookinfo-gateway created virtualservice.networking.istio.io/bookinfo created
デプロイすると、gateway
,virtualservice
リソースが作成される。
[zaki@cloud-dev istio-1.6.5]$ kc get gateway,virtualservice -n bookinfo-sample NAME AGE gateway.networking.istio.io/bookinfo-gateway 3s NAME GATEWAYS HOSTS AGE virtualservice.networking.istio.io/bookinfo [bookinfo-gateway] [*] 3s
設定におかしいところがないか確認
[zaki@cloud-dev istio-1.6.5]$ istioctl analyze -n bookinfo-sample ✔ No validation issues found when analyzing namespace: bookinfo-sample.
外部からのアクセス
じゃあ外部からアクセスしてみましょう。
先の答えを書いておくと、istio-ingressgateway
のEXTERNAL-IPのホストに対して、/productpage
というパスにアクセスすれば以下のようにBookInfoアプリが表示されるはずです。
アクセス設定について
(以下、自分の解釈を書いてるので間違ってるかも)
まず、アクセス先のホストはistio-system
ネームスペースのistio-ingressgateway
のEXTERNAL-IPのアドレス。
[zaki@cloud-dev istio-1.6.5]$ kc get svc -n istio-system istio-ingressgateway NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.108.43.69 192.168.0.182 15020:32605/TCP,80:30286/TCP,443:32689/TCP,31400:32053/TCP,15443:31536/TCP 36m
Gateway
ただし、どのポートのどのパスにアクセスするかは、アプリケーション次第。
まず確認するのはGatewayリソース
[zaki@cloud-dev istio-1.6.5]$ kc get gw -n bookinfo-sample bookinfo-gateway -o yaml : : spec: selector: istio: ingressgateway servers: - hosts: - '*' port: name: http number: 80 protocol: HTTP
これはIstio Ingressgatewayに対して『「ホスト名は*
でワイルドカード指定で任意」「ポートは80/TCP」「プロトコルはHTTP」のアクセスであれば自分(この場合BookInfo)がトラフィックを貰うよ』という定義になっている。
VirtualService
そしてVirtualServiceリソース
[zaki@cloud-dev istio-1.6.5]$ kc get vs -n bookinfo-sample bookinfo -o yaml : : spec: gateways: - bookinfo-gateway hosts: - '*' 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リソースのbookinfo-gateway
の定義を使用しつつ、ホスト名は任意・プロトコルはhttp
で、更に特定のHTTPリクエストパスであれば、productpage
の9080/TCPへトラフィックを転送するよ、という定義になっている。
productpage
の9080/TCPというのは、このServiceのこと。
[zaki@cloud-dev ~]$ kc get svc -n bookinfo-sample NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE details ClusterIP 10.105.9.42 <none> 9080/TCP 59m productpage ClusterIP 10.98.40.227 <none> 9080/TCP 59m ratings ClusterIP 10.96.130.215 <none> 9080/TCP 59m reviews ClusterIP 10.110.12.172 <none> 9080/TCP 59m
これで、「Istio Ingressgatewayが80/TCPで受けたトラフィック(細かく言うと、更にHTTPリクエストパスが/productpage
,/api/v1/products
など特定の場合)」を「productpageの9080/TCPへ転送する」という流れになる。
Istio IngressgatewayのService?pod?
ちなみにこの構成の場合、Istio Ingressgatewayのtype:LoadBalancer Serviceは80/TCPで外部からのトラフィックを受けているけど、
spec: clusterIP: 10.108.43.69 externalTrafficPolicy: Cluster ports: - name: http2 nodePort: 30286 port: 80 protocol: TCP targetPort: 8080
こんな定義になっているので、このServiceによるトラフィックはまずIngressGatewayのpod自体は8080/TCPで受けてるので、Gatewayの設定は本来は80じゃなくて8080じゃないのかなーと思ったり…
$ kubectl edit gateway -n bookinfo-sample bookinfo-gateway
でポートを8080に変更しても動く。
ホストのワイルドカード
現状BookInfoしか動かしてないので特に問題ないけど、Gateway/VirtualServiceのhosts: '*'
は「どのホスト名でもBookInfoが横取り」してしまうので、複数アプリケーションを(異なるFQDNで)動かす場合は、きちんと設定する必要がある。
とりあえずIstioで(期待するアプリケーションのアクセスできずに)最初にハマるところのようなきがする。