column

コラム

Ciliumを使ってマルチクラウドのKubernetes間でService Discoveryしてみた

こんにちは。クラウドCoEの竹中です。

今回は、Amazon Elastic Kubernetes Service (EKS)とAzure Kubernetes Service (AKS)の間でService Discoveryを有効化し、透過的に通信する方法について記載していこうと思います。

マルチクラスタのService Discovery

KubernetesではService Discoveryを利用することで、Podに対して透過的に通信することができます。
例えばアプリケーションからnginx-serviceというマイクロサービスに対してリクエストを送信するようなケースを考えます。
下記のようにServiceリソースを用いることで、Service Discoveryを用いた透過的な通信が可能になります。

これにより、例えばPodがスケールアウトした場合や、他のNodeにフェールオーバーした場合でも、クライアントはそれを意識せずにマイクロサービスと通信できます。

上記はシングルクラスタの例でしたが、Service Discoveryをマルチクラスタに拡張することで、クラスタの違いさえも意識しない通信が可能になります。

 
マルチクラスタのService Discoveryを実現する方法はいくつかあります。
有名なのは以下のようなものだと思います。
 
 
今回は、この中でCilium Cluster Meshを利用してマルチクラスタかつマルチクラウドの通信を実現してみます。
 

Cilium Cluster Meshによるマルチクラウド通信の概要

Ciliumは、KubernetesにおいてPod間の通信を行うためのCNI Pluginです。

EKS、AKSの双方にCiliumを導入し、Cluster Meshと呼ばれる機能を用いて連携させることで、マルチクラウドでの通信を可能にします。
上記の図のような環境を構築していきます。

なお、今回使用したEKS, AKS, Ciliumのバージョンは以下の通りです。

  • EKS: kubernetes 1.26
  • AKS: kubernetes 1.26
  • Cilium: 1.15.1

事前準備: Site-to-Site VPNの接続

Ciliumの公式ドキュメントに記載の通り、Cluster Meshの利用のためにはそれぞれのノードがプライベートIPで通信できる必要があります。

この条件を満たすために、AWSとAzureの間でSite to Site VPN接続を確立します。

リンクに記載の手順に従って構築するだけなので、詳細は割愛します。

AWS側の作業

1. EKSクラスタの作成
 
まず、EKSのクラスタを作成します。

公式ドキュメントの記載通りに作成するだけなので、詳細は割愛します。
 
 
2. AWSのネットワークリソースの設定
 
Security Groupを設定して、以下のように設定します。
 
 
① クラスターセキュリティグループ
 
クラスタ作成時に自動で作られます。特に設定変更はしません。
 
 
②追加のセキュリティグループ
 
ワーカーノードにはカスタムセキュリティグループを適用するので、このセキュリティグループはコントロールプレーンにのみ適用されます。
 
したがって、ドキュメントのMaster Nodes (master-sg) のルールを設定します。
 
 
③ワーカーノードのセキュリティグループ
 
このセキュリティグループはマネージドノードの起動設定に紐づけます。
 
ドキュメントのWorker Nodes (worker-sg) のルールを設定します。
 
 
3. EKSへのCiliumの導入
 
EKSクラスタからVPC CNIを取り除いて、Ciliumを導入していきます。
 
 
①aws-nodeの適用を除外(=VPC CNIの除外)
 
kubectl patch ds aws-node -n kube-system -p '{"spec":{"template":{"spec":{"nodeSelector":{"no-such-node": "true"}}}}}'

 

②kube-proxyをCiliumに置き換える(=ルーティングにeBPFを利用)ため、kube-proxyの適用を除外
 
kubectl patch ds kube-proxy -n kube-system -p '{"spec":{"template":{"spec":{"nodeSelector":{"no-such-node": "true"}}}}}'

 

③Ciliumのインストール
 
インストールにはHelmを用いました。
 
Cluster Mesh利用時のパラメータ設定例は公式ドキュメントに載っていないので、やや試行錯誤が必要でした。
 
設定の詳細は割愛しますが、ポイントは以下の5つです。

ⅰ. Cluster Meshを利用する場合にはクラスタのidとnameの指定が必須
ⅱ. 前提条件から、Cluster Meshで接続するクラスタは、同じdatapath modeを採用する必要がある
※今回はEncapsulation(VXLAN)を設定します。
ⅲ. Ciliumがカプセル化したネットワーク上で通信するので、ENIを使わない設定(=overlayモード)にする
ⅳ. EKSとAKSのPodのIPアドレス範囲が衝突しないように、明示的にIPアドレス範囲を設定する
ⅴ. kube-proxyをCiliumに置き換えるよう設定する
※参考: https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/

 
Cluster Meshの有効化
 
cilium clustermesh enable

以上でAWS側の設定は完了です。

 

Azure側の作業

1. AKSクラスタの作成
 
AKSの場合、EKSとは違って何も考えずに進めると罠にはまるため、手順を記載します。
 
 
Cloud Shellで以下のように入力し、AKSクラスタを作成します。
 
export NODE_SUBNET_ID=$(az network vnet subnet show \
    --resource-group "<resource-group>" \
    --vnet-name "<vnet-name>" \
    --name "cilium-subnet" \
    --query id \
    -o tsv)
 
az aks create \
    --resource-group "<resource-group>" \
    --name "cilium-mesh-cluster" \
    --network-plugin none \
    --pod-cidr "10.200.0.0/16" \
    --service-cidr "10.201.0.0/16" \
    --dns-service-ip "10.201.0.10" \
    --vnet-subnet-id "${NODE_SUBNET_ID}" \
    --kubernetes-version 1.26.10
 
このとき、ポイントは以下の通りです。
 

ⅰ. クラスタはBYOCNIモードで作成する
ⅱ. Pod, ServiceのIP範囲を指定する(AWS側のものと被らないように!)

 
2. AzureへのCiliumの導入
 
AKS側にもCiliumを導入していきます。AWSでの手順とほとんど同じです。
 
①kube-proxyをCiliumに置き換える(=ルーティングにeBPFを利用)ため、kube-proxyの適用を除外
 
kubectl patch ds kube-proxy -n kube-system -p '{"spec":{"template":{"spec":{"nodeSelector":{"no-such-node": "true"}}}}}'

 

②Ciliumのインストール
 
AWSのときと同様の点に注意して、HelmでCiliumをインストールしていきます。手順は割愛します。
 
③Cluster Meshの有効化
 
cilium clustermesh enable

以上でAzure側の設定は完了です。

 

Cluster Mesh接続作業(AWS, Azure共通)

1. ネットワーク設定の修正
 
Worker Nodeのセキュリティグループで、VXLAN通信がAWS, Azureのお互いのノードで疎通できるように、Firewall Ruleに従ってルールを追加します。
 
以下の例では、AzureのvNet(10.224.0.0/12)からの通信をAWSのWorker Nodeで受け取れるようにしています。
 
 
2. Cluster Meshの接続
 
①EKSとAKSのCertificate Authorityを共有
 
# EKS
export CLUSTER1=arn:aws:eks:ap-northeast-1:<account-id>:cluster/multicloud-cluster
# AKS
export CLUSTER2=multi-cilium-cluster
kubectl delete secret cilium-ca --context $CLUSTER2 -n kube-system
kubectl --context=$CLUSTER1 get secret -n kube-system cilium-ca -o yaml | \ 
kubectl --context $CLUSTER2 create -f -
 
②Cluster Meshを接続
 
cilium clustermesh connect --destination-context multi-cilium-cluster
 
③Connectivity testを実行し、成功することを確認
 
cilium connectivity test --context $CLUSTER1 --multi-cluster $CLUSTER2
 

マルチクラウドのクラスタ間でService Discovery

ここまでで、準備は整いました。この環境を使って、AKS上のPodからEKS上のPodへのService Discoveryが可能であることを確認します。
 
kubectl run test-nginx --image=nginx:alpine --context=$CLUSTER1
 
次に、Global Serviceを作成し、EKSとAKSの両方からこのnginxにアクセスできるようにします。
 
EKS側のServiceの設定は以下の通りです。EKSにtest-nginxを作成するので、Global Service Affinityの設定でlocalを指定します。
 
apiVersion: v1
kind: Service
metadata:
  labels:
    run: test-nginx
  name: test-nginx
  annotations:
    service.cilium.io/global: "true"
    service.cilium.io/affinity: "local" # Global Service Affinity
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    run: test-nginx
  type: ClusterIP
 
続いて、AKS側のServiceの設定は以下の通りです。AKSに存在しないtest-nginxに接続しに行くので、Global Service Affinityの設定でremoteを指定します。
 
apiVersion: v1
kind: Service
metadata:
  labels:
    run: test-nginx
  name: test-nginx
  annotations:
    service.cilium.io/global: "true"
    service.cilium.io/affinity: "remote" # Global Service Affinity
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    run: test-nginx
  type: ClusterIP
 
EKSにテスト用のPodを立てて、上記のnginxにアクセスできることを確認します。
 
同じクラスタ上にあるアプリケーションなので、当然問題なく疎通できます。
 
kubectl --context=$CLUSTER1 run tmp -i --tty --rm --restart=Never --image=nginx:alpine -- ash
If you don't see a command prompt, try pressing enter.
/ #
If you don't see a command prompt, try pressing enter.
/ # curl test-nginx:8080
<!DOCTYPE html>
<html>
 
同じようにAKSにもPodを立てて、EKS上にあるnginxにアクセスできることを確認します。
 
その結果、異なるクラスタにあるnginxですが、問題なく接続できました。
 
kubectl --context=$CLUSTER2 run tmp -i --tty --rm --restart=Never --image=nginx:alpine -- ash
If you don't see a command prompt, try pressing enter.
/ # curl test-nginx:8080
<!DOCTYPE html>
<html> 

 

まとめ

以上の通り、EKSとAKSのマルチクラウドでのService Discoveryが実現できました。
 
今後は運用や認可の制御等に注目して、Cluster Meshの使い勝手を検証していきます。

RECOMMEND

おすすめ記事一覧