LoginSignup
5
1

More than 1 year has passed since last update.

Kubernetes Service Hatoba上でIstioを使用したMultiCluster Service Meshを構築してみた

Last updated at Posted at 2022-12-22

この記事はニフクラ等を提供している富士通クラウドテクノロジーズ Advent Calendar 2022の22日目の記事です。

前日はnatsumoさんの続・Scratchにデータベースが使える拡張ブロックを追加して活用してみた話でした。ニフクラ mobile backendを使用してゲームを作ってみたいけど、プログラムやったことないから不安です。という方にはピッタリのコンテンツかと思います。そうではない方も、カニさんゲームが面白いので是非やってみてください。

ちなみにですが、私は無事ランキング1位をとれました! よければ記録に挑戦してみてください。

image.png

それでは本題に入っていきます。目次はこんな感じです。

ToC

はじめに

富士通クラウドテクノロジーではKubernetes as a ServiceであるKubernetes Service Hatoba(以下、Hatoba)を提供しています。本記事ではHatobaで構築したクラスター上でIstioを使用したMultiClsuter Service Meshを構築してみます。クラスターはEastリージョンとWestリージョンに分散させ、アプリケーションはBookInfoを使用します。

いろいろ省略してますが、構築するシステムのイメージ図はこんな感じです。最終的にはWest側のProduct PageからReviewsへの通信をWest側とEast側に負荷分散させてみます。

image.png

MultiCluster ServiceMeshとは

MultiCluster Service MeshはIstioを使用することで構築できます。IstioはオープンソースのServiceMeshになります。通常Istioをインストールする際には下記のような設定要素があり、さまざまな種類のDeployment Modelが存在します。

  • Clusterの数
  • Networkの数
  • Control planeの数
  • Meshの数

Deployment Model毎の特徴についてはDeployment Modelsにまとまっています。MultiCluster Service Meshとは、複数のClusterが単一のMeshに接続するDeployment Modelであり、単一のClusterで構成するMeshと比較して以下のような利点があります。

  • 障害の分離
  • 位置情報を考慮したルーティング
  • Controle plane modelの選択肢の増加
  • チームやプロジェクトでClusterを分離可能

環境

詳細は割愛しますが、下記環境で構築作業を進めていきます。

  • Hatobaを使用しEastリージョンとWestリージョンにそれぞれkubernetesクラスターを構築済み
    • クラスターの構築手順はKubernetes Service Hatoba:クイックスタート参照
    • 一方のクラスター上のpodから他方のAPI Serverにアクセス可能な状態に設定しておいてください
      • 基本的にニフクラではIPベースの制御となるので、KubernetesクラスターのWorker NodeのグローバルIPをFWで許可しておけば良いです
  • 使用するコマンド等のバージョン
    • istioctl: v1.16.0
    • kubectl: v1.25.4
    • helm: v3.10.2
    • kubernetes: v1.24.3
  • istio v1.16.0のAssetsの取得
    curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.16.0 sh -
    
  • aliasの設定
    alias kw='kubectl --kubeconfig=${WEST_KUBECONFIG_PATH}'
    alias ke='kubectl --kubeconfig=${EAST_KUBECONFIG_PATH}'
    alias iw='istioctl --kubeconfig=${WEST_KUBECONFIG_PATH}'
    alias ie='istioctl --kubeconfig=${EAST_KUBECONFIG_PATH}'
    alias hw='helm --kubeconfig=${WEST_KUBECONFIG_PATH}'
    alias he='helm --kubeconfig=${EAST_KUBECONFIG_PATH}'
    

Let's 構築

まずはEast側とWest側のクラスターそれぞれにIstioをインストールします。その後、West側のクラスターにBookInfoをインストールしSingleClusterでMeshを作成します。イメージ図は下記です。

image.png

次にEast側のクラスターにもBookInfoをインストールします。West側にはProductPage/Reviews-v2/Ratingsをインストールしましたが、East側にはReviews-v3のみをインストールします。そして、West側のMeshとEast側のMeshを連結しMultiCluster Service Meshを構築します。Meshを連結するために下記設定を行います。

  • Cluster間の信頼関係(Trust)の設定
  • East-West Gatewayの構築
  • Endpoint Discoveryの有効化

上記のTrustの設定ではIstioのCAの変更作業が発生します。通常、Istioで使用するCAを変更するとIstioの再インストールが必要となります。そのため、クラスター構築の前にまずTrustの設定を行う流れとします。

まとめるとこんな感じです。

  • Cluster間の信頼関係(Trust)の設定
  • Istioのインストール
  • SingleClusterでの動作確認
    • BookInfoのインストール
    • 動作確認
  • MultiClusterでの動作確認
    • ServiceMeshの連結
      • East-West Gatewaの構築
      • Endpoint Discoveryの有効化
    • BookInfoのインストール
    • 動作確認

Cluster間の信頼関係(Trust)の設定の構築

Mesh内の通信はIstioによってmTLS認証が適用されます。そのため、Meshを共有するClsuter間の通信にもmTLS認証を適用できるように信頼関係(Trust)を設定する必要があります。Trustの設定は、Istioの証明書管理で説明される下記のどちらかの方法を利用することで設定可能です。

  • Custom CA Integration using Kubernetes CSR
  • Plug in CA Certificates

今回はPlug in CA Certificatesに記載されている方法を利用してTrustの設定を行います。この方法では、まずRootCAを作成し、そのRootCAを使用して各クラスター用の中間CAを生成します。生成した中間CAはKubernetes上にSecretリソースとして配置します。この設定を行うことで、生成したCAでMesh内のWorkloadの証明書に署名が行われるようになります。

各CAはIstioのtoolで提供されているMakefileを利用することで簡単に生成可能です。

mkdir certs
cd certs
# Root CAの作成
make  -f ./../istio-1.16.0/tools/certs/Makefile.selfsigned.mk root-ca
# west-cluster用の中間CAの作成
make  -f ./../istio-1.16.0/tools/certs/Makefile.selfsigned.mk west-cluster-cacerts
# east-clsuter用の中間CAの作成
make  -f ./../istio-1.16.0/tools/certs/Makefile.selfsigned.mk east-cluster-cacerts
cd ..

certs配下に以下のようなファイル群が生成されてるかと思います。

$ tree certs
certs
├── east-cluster
│   ├── ca-cert.pem
│   ├── ca-key.pem
│   ├── cert-chain.pem
│   └── root-cert.pem
├── root-ca.conf
├── root-cert.csr
├── root-cert.pem
├── root-key.pem
└── west-cluster
    ├── ca-cert.pem
    ├── ca-key.pem
    ├── cert-chain.pem
    └── root-cert.pem

次に、作成した中間CAをSecretリソースとしてデプロイします。

# west cluster
kw create ns istio-system
kw create secret generic cacerts -n istio-system \
       --from-file=certs/west-cluster/ca-cert.pem \
       --from-file=certs/west-cluster/ca-key.pem \
       --from-file=certs/root-cert.pem \
       --from-file=certs/west-cluster/cert-chain.pem
# east cluster
ke create ns istio-system
ke create secret generic cacerts -n istio-system \
       --from-file=certs/east-cluster/ca-cert.pem \
       --from-file=certs/east-cluster/ca-key.pem \
       --from-file=certs/root-cert.pem \
       --from-file=certs/east-cluster/cert-chain.pem

これでTrustの設定は終わりです。

Istioのインストール

Kubernetes上にIstioをインストールする際の選択肢は基本的には下記の4種類になります。

各インストールのメリット・デメリットはWhich Istio installation method should I use?にまとめられています。今回は個人的な趣味でHelmを使用してインストールします。

Helmを利用したIstioのインストールについて
2022/12/22時点ではHelmを使用したインストールはalpha機能となっています。使用する際にはFeature Statusを一読しておいた方が良いかもしれません。

まずHelmにリポジトリを追加します。

hw repo add istio https://istio-release.storage.googleapis.com/charts
hw repo update
he repo add istio https://istio-release.storage.googleapis.com/charts
he repo update

最終的にはEast側とWest側のクラスターを単一のMeshに接続するため、下記設定でIstioのインストールを行います。

west cluster east cluster
meshID mesh mesh
cluster name west-cluster east-cluster
network name west-network east-network

インストールコマンドはこちらです。

# west clsuter
kw label ns istio-system topology.istio.io/network=west-network
hw install -n istio-system  istio-base istio/base
hw install -n istio-system  istiod istio/istiod --set global.meshID=mesh --set global.multiCluster.clusterName=west-cluster --set global.network=west-network
hw install -n istio-ingress istio-ingress istio/gateway --create-namespace --set service.annotations."service\.beta\.kubernetes\.io/hatoba-load-balancer-name"=westingress --set labels.istio=ingressgateway
# east clsuter
ke label ns istio-system topology.istio.io/network=east-network
he install -n istio-system  istio-base istio/base
he install -n istio-system  istiod istio/istiod --set global.meshID=mesh --set global.multiCluster.clusterName=east-cluster --set global.network=east-network
he install -n istio-ingress istio-ingress istio/gateway --create-namespace --set service.annotations."service\.beta\.kubernetes\.io/hatoba-load-balancer-name"=eastingress --set labels.istio=ingressgateway

Type:LoadBalancerEXTERNAL-IPが割り当てられるまで待機です。

$ kw get svc -n istio-ingress -w
NAME             TYPE           CLUSTER-IP       EXTERNAL-IP       PORT(S)                                           AGE
istio-ingress    LoadBalancer   10.111.160.181   <pending>         15021:32079/TCP,80:32182/TCP,443:30333/TCP        17s
istio-ingress    LoadBalancer   10.111.160.181   222.158.213.21    15021:32079/TCP,80:32182/TCP,443:30333/TCP        106s

HatobaのType:LoadBalancerの名前について
HatobaのType:LoadBalancerには利用できる名前が英数字15文字以内という仕様があります。また、istio/gateway chartでインストールされるType:LoadBalancerの名前はリリース名となります。そのため、リリース名が英数字15文字以内でない場合、Type:LoadBalancerの作成処理はエラーとなります。この場合は、上記手順のようにannotationにservice.beta.kubernetes.io/hatoba-load-balancer-nameを付与し実際にインストールされるLoadBalancerの名前を変更することでエラーを回避できます。その他のannotationで設定可能な項目は技術仕様/Kubernetes Service Hatoba/ロードバランサーに記載があります。

SingleClusterでの動作確認

Westリージョンに構築したクラスターにBookinfoをインストールし動作確認を行います。

Bookinfoのインストール

Istioではさまざまな種類のサンプルアプリケーションが提供されており、今回はその中のBookInfoを使用します。BookInfoのReviewsアプリにはv1とv2、v3の3種類のバージョンが存在していますが、West側にはv2のみをインストールしたいと思います。

手順はこちらです。

kw create ns bookinfo
kw label ns bookinfo istio-injection=enabled
kw apply -n bookinfo -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/bookinfo/platform/kube/bookinfo.yaml
kw apply -n bookinfo -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/bookinfo/networking/bookinfo-gateway.yaml
# v1とv3の削除
kw delete -n bookinfo -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/bookinfo/platform/kube/bookinfo.yaml -l app=reviews,version=v1
kw delete -n bookinfo -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/bookinfo/platform/kube/bookinfo.yaml -l app=reviews,version=v3

全てのPodがRunningになることを確認します。

$ kw get pod -n bookinfo
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-7d4d9d5fcb-smdx6       2/2     Running   0          13s
productpage-v1-66756cddfd-tgcs4   2/2     Running   0          12s
ratings-v1-85cc46b6d4-wqxpc       2/2     Running   0          13s
reviews-v2-cdd8fb88b-89kvj        2/2     Running   0          12s

動作確認

West側のIngress GatewayのIPを取得します。

WEST_INGRESS=$(kw get svc istio-ingress -n istio-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

curlコマンドでWest側にアクセスし、文字列reviews-v2を含む応答が返ってくればOKです。

$ curl -s "http://${WEST_INGRESS}/productpage" | grep reviews
        <u>reviews-v2-cdd8fb88b-89kvj</u>

ちなみにですが、productpage podのEndpointを確認してみると、outbound|9080||reviews.bookinfo.svc.cluster.local通信が10.233.0.75:9080に送られ、そのIPアドレスがReviews-v2 podのものであることが分かります。

$ iw pc -n bookinfo endpoints deploy/productpage-v1 --cluster 'outbound|9080||reviews.bookinfo.svc.cluster.local' -o json | jq '[.[].hostStatuses[] | { socketAddress: .address.socketAddress } ]'
[
  {
    "socketAddress": {
      "address": "10.233.0.79",
      "portValue": 9080
    },
    "locality": {
      "region": "jp-west-1",
      "zone": "west-13"
    }
  }
]
$ kw get pod -n bookinfo -o wide -l app=reviews
NAME                        READY   STATUS    RESTARTS   AGE     IP            NODE         NOMINATED NODE   READINESS GATES
reviews-v2-cdd8fb88b-89kvj   2/2     Running   0          2m27s   10.233.0.79   pool-zis5n   <none>           <none>

MultiClusterでの動作確認

本題のMultiCluster Service Meshを構築します。East側とWest側に作成したMeshを結合します。Meshを結合するためには下記の設定を行います。

  • East-West Gatewayの構築
  • Endpoint Discoveryの有効化
  • SerivceのExporse

最後にBookinfoをインストールし、Product PageからEastリージョンとWestリージョンに配置したReviewsへ負荷分散が行われていることを確認します。

Meshの結合

East-West Gatewayの構築

各クラスター間のIngress PointとなるEast-West Gatewayをインストールします。East-West GatewayもIngress gatewayと同じようにistio/gateway chartを利用することでインストールできます。

インストールの前に使用するvalueファイルを下記コマンドで生成します。

for REGION in west east
do
cat << EOF > ${REGION}-values.yaml
labels:
  topology.istio.io/network: "${REGION}-network"
  istio: "eastwestgateway"
env:
  ISTIO_META_REQUESTED_NETWORK_VIEW: "${REGION}-network"
service:
  annotations:
    service.beta.kubernetes.io/hatoba-load-balancer-name: "eastwest"
  ports:
  - name: status-port
    port: 15021
    targetPort: 15021
  - name: tls
    port: 15443
    targetPort: 15443
  - name: tls-istiod
    port: 15012
    targetPort: 15012
EOF
done

次にHelmを使用してインストールします。

he install -n istio-ingress istio-eastwest istio/gateway -f east-values.yaml
hw install -n istio-ingress istio-eastwest istio/gateway -f west-values.yaml

HatobaのType:LoadBalancerの利用可能ポート数について
本来であればistio/gateway chartnetworkGatewayを設定することでEast-West Gatewayを簡単に構築することができます。このnetworkGatewayの設定を使用した場合、Type:LoadBalancerのポートは4つ設定される動作となります(service.yaml参照)。しかし、HatobaのType:LoadBalancerでは利用できるポートが3つまでという制限があり、ポートを4つ確保する設定はエラーとなります。そのため、networkGateway経由ではなく、上記のようなvalue.yamlでユースケースに応じた設定を行う必要があります。

Endpoint Discoveryの有効化

クラスターからピアクラスターへのアクセスを可能にするため、サービスアカウントトークンと証明書を含む情報をsecretとして設定します。

ie create-remote-secret --name="east-cluster" | kw apply -f -
iw create-remote-secret --name="west-cluster" | ke apply -f -
SerivceのExporse

East West Gatewayで公開したいServiceをGatewayリソースとして作成します。下記は.localで終わるサービスを公開する設定になります。

cat <<EOF > cross-network-gateway.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: cross-network-gateway
  namespace: istio-ingress
spec:
  selector:
    istio: eastwestgateway
  servers:
    - port:
        number: 15443
        name: tls
        protocol: TLS
      tls:
        mode: AUTO_PASSTHROUGH
      hosts:
        - "*.local"  
EOF
ke apply -f cross-network-gateway.yaml
kw apply -f cross-network-gateway.yaml

これでMultiCluster Service Meshを構築することができました。
次にBookinfoを使用して動作確認を行ってみます。

Bookinfoのインストール

EastリージョンにはReviews-v3のみをインストールしたいと思います。

ke create ns bookinfo
ke label ns bookinfo istio-injection=enabled
ke apply -n bookinfo -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/bookinfo/platform/kube/bookinfo.yaml -l app=reviews,version=v3
ke apply -n bookinfo -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/bookinfo/platform/kube/bookinfo.yaml -l service=reviews
ke apply -n bookinfo -f https://raw.githubusercontent.com/istio/istio/release-1.16/samples/bookinfo/platform/kube/bookinfo.yaml -l account=reviews

PodがRunningになることを確認します。

$ ke get pod -n bookinfo
NAME                        READY   STATUS    RESTARTS   AGE
reviews-v3-58b6479b-jc92w   2/2     Running   0          25s

動作確認

curlコマンドでWest側にアクセスし、reviews-v2reviews-v3の文字列を含む応答が返ってくればOKです。これでEast側にあるReviews v2とWest側にあるReviews v3に分散してアクセスが行われていることが分かります。

$ curl -s "http://${WEST_INGRESS}/productpage" | grep reviews
        <u>reviews-v3-58b6479b-jc92w</u>
$ curl -s "http://${WEST_INGRESS}/productpage" | grep reviews
        <u>reviews-v2-cdd8fb88b-89kvj</u>

ちなみにproductpage-v1のendpointを確認してみると、111.64.95.151:15443が新たなEndpointとして設定されてあり、East側のEast-West GatewayのIPアドレスが設定されています。

$ iw pc -n bookinfo endpoints deploy/productpage-v1 --cluster 'outbound|9080||reviews.bookinfo.svc.cluster.local' -o json | jq '[.[].hostStatuses[] | { socketAddress: .address.socketAddress, locality: .locality} ]'
[
  {
    "socketAddress": {
      "address": "111.64.95.151",
      "portValue": 15443
    },
    "locality": {
      "region": "jp-east-1",
      "zone": "east-14"
    }
  },
  {
    "socketAddress": {
      "address": "10.233.0.79",
      "portValue": 9080
    },
    "locality": {
      "region": "jp-west-1",
      "zone": "west-13"
    }
  }
]
$ ke get svc -n istio-ingress -l istio=eastwestgateway
NAME             TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                           AGE
istio-eastwest   LoadBalancer   10.100.138.193   111.64.95.151   15021:31761/TCP,15443:30224/TCP,15012:30564/TCP   3h13m

また、East-West Gatewayではoutbound|9080||reviews.bookinfo.svc.cluster.localの宛先としてReviews-v2 podのIPアドレスが設定されています。

$ ie pc endpoints -n istio-ingress deploy/istio-eastwest --cluster 'outbound|9080||reviews.bookinfo.svc.cluster.local' -o json | jq '[.[].hostStatuses[] | { socketAddress: .address.socketAddress, locality: .locality } ]'
[
  {
    "socketAddress": {
      "address": "10.233.0.27",
      "portValue": 9080
    },
    "locality": {
      "region": "jp-east-1",
      "zone": "east-14"
    }
  }
]
$ ke get pod -n bookinfo -o wide -l app=reviews
NAME                        READY   STATUS    RESTARTS   AGE     IP            NODE         NOMINATED NODE   READINESS GATES
reviews-v3-58b6479b-jc92w   2/2     Running   0          2m11s   10.233.0.27   pool-8tt3u   <none>           <none>

つまり、productpage pod内のoutbound|9080||reviews.bookinfo.svc.cluster.localの通信はWest内のReviews-v2 podかEast側のEast-West Gatewayにルーティングされ、East側のEast-West GatewayでEast側のReviews-v3 podにルーティングされることが分かります。

最後に

Hatoba上でMultiCluster Service Meshを構築してみました。また、Bookinfoを使用して簡単な負荷分散も試してみました。今回は簡単な動作確認のみでDeployment Modelに記載されているようなMultiClusterの利点の検証まではできなかったので、別途時間を作って試してみようかなと思います。また、通信経路の確認をistioctlコマンドで行いましたが、KialiJaegerを使って視覚的に見ても面白そうですね。

明日はAuthnsさんで、「TauriでSVGのグラフ生成・描画・保存をしてくれるデスクトップアプリ作成」です。よろしくお願いいたします :bow:

5
1
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
5
1