LoginSignup
3

posted at

IstioのAmbient Mesh について

はじめに

この記事ではIstioでサービスメッシュを実現する新たな仕組みである、Ambient Meshについて調べた内容を書いてみたいと思います。

Istioとは

Istioはオープンソースのサービスメッシュです。
Istioを利用することで、カナリアリリースなどの高度なルーティングやリクエストの再試行、フェイルオーバー、フォルトインジェクションによりトラフィックを細かく制御することが可能となります。
Istioにはその他にも多くの機能がありますので、詳細についてはIstioのドキュメントなどを参考としてください。

Kubernetes環境でIstioを利用する場合、各PodにサイドカーとしてEnvoy Proxyを実行し、トラフィックがサイドカーのEnvoy Proxyを経由することでサービスメッシュを構成します。
下記はIstioのブログから引用した図ですが、構成のイメージとしては下記です。
スクリーンショット 2022-12-11 15.38.01.png
参考:https://istio.io/latest/blog/2022/introducing-ambient-mesh/

サイドカーのEnvoy Proxyを利用することで、アプリケーションを変更せずともサービスメッシュを導入することが可能です。

サイドカーパターンによる問題

サイドカーとしてEnvoy Proxyを利用することで、アプリケーションを変更せずともサービスメッシュを導入することが可能ではありますが、これによりいくつかの制限が発生するとのことです。

  • サイドカーとしてEnvoy Proxyを注入する必要があるため、サイドカーのインストールやバージョンアップ時にアプリケーションのPodの再起動が必要となる。
  • サイドカーは関連するワークロード専用であるため、それぞれのPodが利用する可能性のある量のCPU とメモリ リソースをプロビジョニングする必要がある。それによりクラスター全体でリソースが効率的に利用されない可能性がある。
  • Istioのサイドカーで通常行われるトラフィックキャプチャとHTTP処理は、計算量が多く、HTTPの実装に準拠していない一部のアプリケーションを壊す可能性がある。

サイドカーには良い点があるものの、多くのサービスメッシュユーザーにとって、より負担の少ない、より簡単なオプションが必要であるとのことで、Ambient Meshという方法が考えられたようです。

Ambient Mesh について

Ambient Meshは上記のサイドカーを利用したパターンとは異なるアプローチを取っています。
Istioの機能を下記のように2つのレイヤーに分割し、Secure overlay Layer に記載されている機能は、各ワーカーノードで起動する共有のエージェント(ztunnel エージェント)が担当し、L7 Processing Layerの機能はwaypoint proxyというコンポーネントが担当する構成となります。
スクリーンショット 2022-12-11 19.50.35.png
参考:https://istio.io/latest/blog/2022/introducing-ambient-mesh/#slicing-the-layers

Secure Overlay Layer

上記の Secure Overlay Layer に記載された Ambient Mesh の機能を Kubernetesで利用する場合、ztunnelをDaemonSetとしてデプロイすることで、各ワーカーノードでPodを1つ起動する構成とします。

構成のイメージとしては下記です。
スクリーンショット 2022-12-16 10.10.56.png
参考: https://istio.io/latest/blog/2022/introducing-ambient-mesh/#building-an-ambient-mesh

L7 Processing Layer

L7 の機能を利用する場合、Ambient Mesh は Envoy ベースの waypoint proxy を経由する構成となります。
構成のイメージは下記です。

スクリーンショット 2022-12-25 17.01.26.png

参考: https://istio.io/latest/blog/2022/introducing-ambient-mesh/#building-an-ambient-mesh

L7 の処理を必要とする場合、ztunnel 間の通信は、上記のように waypoint proxy を経由する構成となります。
Kubernetes 環境で利用する場合、waypoint proxy は通常のアプリケーションの Pod のように Deployment を利用して複数起動実行します。
トラフィックの量に応じて waypoint proxy の Pod をスケールアウトすることができますので、サイドカーとして Envoy を利用する場合よりも、リソースを効率良く利用できることが期待されます。

試してみる

実際に Ambient Mesh を試してみたいと思います。
下記のような設定ファイルをもとに kind を利用してローカルの環境で Kubernetes クラスターを作成します。

cluster.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: ambient
nodes:
- role: control-plane
- role: worker
- role: worker

Kubernetes クラスターを作成します。

$ kind create cluster --config=cluster.yaml

こちらのページ から ambient mesh をサポートしているプレビューバージョンの istioctl をダウンロードします。

ダウンロードした istioctl を利用して、作成した Kubernetes クラスターに istio をインストールします。

./istioctl install --set profile=ambient

インストールが完了すると、下記のコマンドで Istiod、ingress gateway、ztunnel、CNI plugin などが起動していることを確認できるかと思います。

$ kubectl get pod -n istio-system

istio をインストールしたクラスターに bookinfo アプリケーションをデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/bookinfo/platform/kube/bookinfo.yaml

上記のアプリケーションにアクセスするための Client 側のアプリケーションをデプロイします。

$ kubectl apply -f https://raw.githubusercontent.com/linsun/sample-apps/main/sleep/sleep.yaml

istio の Authorization Policy の機能を利用してアクセスの制限を試してみます。

下記のようなマニフェストファイルを作成します。
下記の例の場合、app: productpage ラベルが設定されたワークロードへのアクセスを制限します。
合わせて rules の設定により、sleep サービスアカウントからのアクセスを許可しています。

authorization-policy.yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: productpage-viewer
 namespace: default
spec:
 selector:
   matchLabels:
     app: productpage
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns/default/sa/sleep"]

上記のマニフェストをファイルを apply します。

$ kubectl apply -f authorization-policy.yaml

先ほどデプロイした Client の Pod からアクセスを試してみます。
Client の Pod は sleep サービスアカウントが設定されているため、アクセスすることが可能です。

$ kubectl describe deployment sleep                                                                                                                                                                                  
Name:                   sleep
Namespace:              default
CreationTimestamp:      Sun, 25 Dec 2022 15:55:40 +0900
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=sleep
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:           app=sleep
  Service Account:  sleep
  Containers:
   sleep:
    Image:      curlimages/curl
(略)
$ kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | head -n1                                 

異なるサービスアカウントが設定された Pod からはアクセスができないことが確認できます。

$ kubectl apply -f https://raw.githubusercontent.com/linsun/sample-apps/main/sleep/notsleep.yaml
$ kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ | head -n1

次に L7 の Authorization Policy の機能を試してみます。
上記の機能を利用するには waypoint proxy が必要となるため、下記のマニフェストをデプロイします。

waypoint-proxy.yaml
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: Gateway
metadata:
 name: productpage
 annotations:
   istio.io/service-account: bookinfo-productpage
spec:
 gatewayClassName: istio-mesh
$ kubectl apply -f waypoint-proxy.yaml

私の環境の場合、下記のように bookinfo-productpage-waypoint-proxy-6f88c55d59-h26qt という Pod が起動します。

$ kubectl get pods                                                                                           
NAME                                                   READY   STATUS    RESTARTS   AGE
bookinfo-productpage-waypoint-proxy-6f88c55d59-h26qt   1/1     Running   0          142m
(略)

AuthorizationPolicy のマニフェストファイルを下記のように修正して apply します。

authorization-policy.yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: productpage-viewer
 namespace: default
spec:
 selector:
   matchLabels:
     app: productpage
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns/default/sa/sleep"]
   to:
   - operation:
       methods: ["GET"]

GET メソッドのアクセスだけが許可されているため、sleep サービスアカウントが設定されている Pod からのアクセスであっても GET メソッド以外のアクセスは失敗することが確認できるかと思います。

$ kubectl exec deploy/sleep -- curl -s http://productpage:9080/ -X DELETE | head -n1
$ kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | head -n1

さいごに

確認が完了して、検証用の Kubernetes クラスタが不要になりましたら下記のコマンドでクラスタを削除してください。

$ kind delete cluster --name ambient

まとめ

簡単に試してみただけの内容となってしまいましたが、Ambient Mesh について調べた内容を書いてみました。
今回は動作の詳細などについては踏み込んで調査できませんでしたが、今後、機会があればより詳細について調査してみたいと思います。

参考資料

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3