0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Kumaでクラスタ跨ぎの通信を試す

Posted at

先日、KongのAPI Gatewayを触っていた時に、Kongが開発しているService MeshのKumaがあることを知った。
機能を見るとTanzu Service Mesh(以下TSM)のGlobal Namespaceのように全体を俯瞰するControlPlaneを置いてクラスタ間通信を制御するようでちょっと気になったので、触ってみた時のメモ。

Kumaとは

KumaはKongが中心となって開発されているService MeshのOSSで、CNCFのSandbox Projectにもなっている。
2022/5のCNCFの調査で「利用中、もしくは予定しているService Mesh製品は何か?」というアンケートではKumaの名前がなかったので、Service Mesh製品としてはマイナーな部類に入る。
アーキテクチャとしては以下のように複数のKubernetes/VMクラスタを跨いだマルチゾーン展開が出来、全体を見るControlPlaneが存在するようで、これがTanzu Service Meshにちょっと似ている。
1704246211063.png
Overview of Kumaより引用)

なおKumaではKubernetesにMeshを導入するKubernetes Modeと、非Kubernetes環境でもMeshを実現するUniversal Modeが用意されており、どちらの環境でもMeshが利用できるようになっている。
また、各ゾーン内のMeshはControlPlaneとDataPlaneで構成されていて、DataplaneにはEnvoyが利用されている。
1704247140770.png
Architectureより引用)

一般的なService MeshのSidecarパターンと同じと考えるとよさそう。

検証

事前準備

以下を用意して検証した。

  • K8sクラスタ3台(1台はGlobal ControlPlane用、2台はZone用)

ちなみに最初はVMも含めた構成でUniversal Modeも検証しようとしたのだが、検証を進めた結果、どうもDataPlaneごとにVMが必要っぽいように見えて用意するのが大変なので断念した。

インストール

Deploy a multi-zone global control planeを参考にインストールを進めていく。
やりたいのは以下の構成となる。

Global ControlPlaneの構築

まずKubernetes上にGlobal ControlPlaneを構築する。
インストール方法は独自のCLIであるkumactlを使った方法と、Helmによるインストール方法が用意されているが、ここでは慣れたHelmで進める。
インストール時、controlPlane.modeglobalを指定することで、Global ControlPlaneとしてKumaをデプロイ出来る。
Global ControlPlaneのUIに頻繁にアクセスするため、ここではServiceをtype: LoadBalancerで公開してデプロイした。

helm repo add kuma https://kumahq.github.io/charts
helm upgrade -i --create-namespace --namespace kuma-system \
  --set "controlPlane.mode=global" \
  --set "controlPlane.service.type=LoadBalancer" \
  kuma kuma/kuma

インストールが成功すると、ControlPlaneが展開される。

$ kubectl get pod -n kuma-system
NAME                                     READY   STATUS    RESTARTS   AGE
pod/kuma-control-plane-679574bbb-zk98x   1/1     Running   0          12s

ModeをGlobalにした場合にStandalone Modeと異なるのは、Serviceにkuma-global-zone-syncが作成され、External-IPでIPが公開される点である。
このIPを別のクラスタ上にKuma ControlPlaneを展開する際にcontrolPlane.kdsGlobalAddress=<IP:5686>で指定して、Global ControlPlaneと繋いでいく。
なお、通常DataPlaneはPodかNamespaceにkuma.io/sidecar-injection: enabledというラベルを付与するとサイドカーとして自動的に付加されるが、Global ControlPlaneで展開したクラスタではkuma.io/sidecar-injection: enabledをつけてもDataPlaneは展開されず、ControlPlane専用で動くようになっている。

マルチゾーン(クラスタ間通信)を利用するにはmTLSが必須なため、Global ControlPlaneのデプロイ後、以下を実行してdefaultのMesh設定を変更してmTLSを有効化する。

cat << EOF | kubectl apply -f -
apiVersion: kuma.io/v1alpha1
kind: Mesh
metadata:
  name: default
spec:
  routing:
    zoneEgress: true
  mtls:
    enabledBackend: ca-1
    backends:
      - name: ca-1
        type: builtin
        dpCert:
          rotation:
            expiration: 1d
        conf:
          caCert:
            RSAbits: 2048
            expiration: 10y
EOF

K8s ZoneのControlPlaneの構築

Global ControlPlaneが提供するkuma-global-zone-syncが公開しているIPを指定して、HelmでKubernetesクラスタに展開する。

GLOBAL_IP="10.220.35.73"
ZONE_NAME="tkgs-cluster-2"
helm install --create-namespace --namespace kuma-system \
  --set "controlPlane.mode=zone" \
  --set "controlPlane.zone=$ZONE_NAME" \
  --set "ingress.enabled=true" \
  --set "controlPlane.kdsGlobalAddress=grpcs://${GLOBAL_IP}:5685" \
  --set "controlPlane.tls.kdsZoneClient.skipVerify=true" \
  kuma kuma/kuma

Ingressを有効にすることで、type: LoadBalancerkuma-ingressというServiceが作成され、外部から接続可能となる。

$ kubectl get svc -n kuma-system
NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)                                                AGE
kuma-control-plane   ClusterIP      10.97.3.51       <none>         5680/TCP,5681/TCP,5682/TCP,443/TCP,5676/TCP,5678/TCP   2d6h
kuma-ingress         LoadBalancer   10.103.209.149   10.220.35.74   10001:30597/TCP                                        2d6h

なお、ModeをZoneにしているため、こちらではNamespaceかPodのラベルにkuma.io/sidecar-injection: enabledがあればDataPlaneがサイドカーとしてInjectされるので試してみる。
以下のサンプルのManifestを動かしてみる。

cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
        kuma.io/sidecar-injection: enabled
    spec:
      containers:
      - image: nginx
        name: nginx
EOF

確認する。

$ kubectl get pod
NAME                     READY   STATUS        RESTARTS   AGE
nginx-67c9776b8b-bvqhs   2/2     Running       0          13s

コンテナ数が2となっており、サイドカー入りのPodが作成されることが確認できた。

次にもう1つのZone用クラスタにコンテキストを切り替え、同じように展開する。
なお、こちらでは動作確認用にEgressを有効にし、こちらのクラスタから先程のクラスタへの通信が行えるようにする。

ZONE_NAME="tkgs-cluster-3"
helm upgrade -i --create-namespace --namespace kuma-system \
  --set "controlPlane.mode=zone" \
  --set "controlPlane.zone=$ZONE_NAME" \
  --set "ingress.enabled=true" \
  --set "egress.enabled=true" \
  --set "controlPlane.kdsGlobalAddress=grpcs://${GLOBAL_IP}:5685" \
  --set "controlPlane.tls.kdsZoneClient.skipVerify=true" \
  kuma kuma/kuma

展開後、Global ControlPlaneのServicekuma-control-planeの5681ポートにブラウザで接続すると、それぞれのクラスタが確認できる。
1704441962254.png

動作確認

マルチゾーンでの通信確認のため、最初のK8sのZoneで立ち上げたnginxに対し、2番目のZoneから通信する。
最初のZoneのnginxのServiceを作成する。

kubectl expose deploy nginx --port 80

次に2番めのZoneでアクセス元となるPodを起動する。mTLSで通信しないと接続できないため、アクセス元の方もサイドカーをInjectionするようにラベルにkuma.io/sidecar-injection: enabledを設定して起動する。

cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: centos
  name: centos
spec:
  replicas: 1
  selector:
    matchLabels:
      app: centos
  template:
    metadata:
      labels:
        app: centos
        kuma.io/sidecar-injection: enabled
    spec:
      containers:
      - command:
        - sleep
        - infinity
        image: centos
        name: centos
EOF

Podが起動したら、早速アクセスする。
アクセス先についてはkind: ServiceInsightというリソースを確認することで確認できる。

$ kubectl get serviceinsight -o yaml all-services-default
apiVersion: kuma.io/v1alpha1
kind: ServiceInsight
mesh: default
:(省略)
    nginx_default_svc_80:
      dataplanes:
        online: 1
      issuedBackends:
        ca-1: 1
      status: online

ここだとnginx_default_svc_80がアクセス先となる。
これに.meshをつけて、対応ポートを指定すればアクセスできる。

$ kubectl exec -it centos-6d7594d4c9-445rl  -- curl nginx_default_svc_80.mesh:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

クラスタを跨いでアクセスすることが出来た。
なお、アクセス先はUIからも確認できる。
1704445571697.png

なお、メトリクスに関しては別途Prometheusなどをインストールする必要がある
kumactlを使うことでKuma向けに設定されたPrometheus、Jaeger、Loki、Grafanaが簡単にインストール出来るようになっている。

kumactl install observability | kubectl apply -f -

ただ、インストールするだけではメトリクスが見えず、この辺などの設定を入れてメトリクスを公開する必要がある模様。
今回は時間の都合上断念した。

感想

簡単にクラスタ跨ぎのService Meshが作成でき、かつUIが最初から提供され、各クラスタの状態が確認できるのは便利だった。
一方で、TSMに慣れてるとそれでも導入が少し面倒と感じたり、UIもKialiみたいなネットワークトポロジーを表示する機能はなく、ダッシュボードも別途用意する必要がある点ではOOTBなTSMが流石だなと感じた。
Istioの面倒さとTSMの簡単さの中間にあるService Meshというところだろうか。
OSSとしては十分良かったので、お金を掛けず楽してService Meshを使いたい人は選択肢としてあっていいと思う。

0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?