0
1

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.

GemFire for KubernetesでTKGを使ってマルチサイト構成(WAN構成)で接続する。

Last updated at Posted at 2023-11-19

'23/11現在、GemFire for Kubernetesでマルチサイト構成(WAN構成)を組もうとしても、ドキュメントの記載がGKEに関するものしかなく、イマイチやり方が分からない。
実際、作ろうとした時にハマり箇所があったのでメモを残す。

GemFireの前提知識

GemFireで相手方と接続する場合、DNSの逆引きが動いて名前解決できる必要がある。
この辺の仕組みはよく分からないのだが、接続先IPの逆引きしたDNS名が接続元からも参照できる必要がある。
以下の図のケースで考える。
1700373542673.png
LocatorのPodに繋がるServiceをExternalIPで公開してgfshで繋ごうとしても、gfshのコマンド側でlocator.gem.svc.cluster.localが解決できないと、以下のようなエラーになる。

gfsh>connect --locator 10.20.30.40[10334]
Connecting to Locator at [host=10.20.30.40, port=10334] ..
Connecting to Manager at [host=locator.gem.svc.cluster.local, port=1099] ..
Could not connect to : [host=locator.gem.svc.cluster.local, port=1099]. Failed to retrieve RMIServer stub: javax.naming.ConfigurationException [Root exception is java.rmi.UnknownHostException: Unknown host: locator.gem.svc.cluster.local; nested exception is:
    java.net.UnknownHostException: locator.gem.svc.cluster.local]

なので、接続元で相手方クラスタ内のサービスに紐づく名前を解決できるようにする必要がある。

事前準備

GemFireClusterの構築

今回、ここではTKGクラスタを2面用意し、それぞれにGemFireClusterを作成した。
1700375787692.png
各GemFireClusterはLocator1台、Server2台を持つ構成とし、以下のManifestで作成した。

cluster1
apiVersion: gemfire.vmware.com/v1
kind: GemFireCluster
metadata:
  name: gemfire1
  namespace: gemfire-cluster-1
spec:
  serialization:
    pdx:
      readSerialized: true
  image: registry.tanzu.vmware.com/pivotal-gemfire/vmware-gemfire:10.0.1
  security:
    tls: {}
  locators:
    overrides:
      gemFireProperties:
      - name: "distributed-system-id"
        value: "10"
      - name: "remote-locators"
        value: "gemfire2-locator-0.gemfire2-locator.gemfire-cluster-2.svc.cluster.local[10334]"
cluster2
apiVersion: gemfire.vmware.com/v1
kind: GemFireCluster
metadata:
  name: gemfire2
  namespace: gemfire-cluster-2
spec:
  serialization:
    pdx:
      readSerialized: true
  image: registry.tanzu.vmware.com/pivotal-gemfire/vmware-gemfire:10.0.1
  security:
    tls: {}
  locators:
    overrides:
      gemFireProperties:
      - name: "distributed-system-id"
        value: "11"
      - name: "remote-locators"
        value: "gemfire1-locator-0.gemfire1-locator.gemfire-cluster-1.svc.cluster.local[10334]"

Remote Locatorは相手のServiceを指定している(後述するが実際は若干異なる経路で繋ぐ)。

また、クラスタ外から繋げられるようにExternalIPでServiceを公開する。これはGemFireClusterが作成するServiceとは別に作成する。

cluster1
apiVersion: v1
kind: Service
metadata:
  name: locator-lb
spec:
  ports:
  - name: locator
    port: 10334
    protocol: TCP
  - name: locator-management-api
    port: 7070
    protocol: TCP
  - name: locator-metrics
    port: 4321
    protocol: TCP
  - name: manager
    protocol: TCP
    port: 1099
  type: LoadBalancer
  selector:
    statefulset.kubernetes.io/pod-name: gemfire1-locator-0
cluster2
apiVersion: v1
kind: Service
metadata:
  name: locator-lb
spec:
  ports:
  - name: locator
    port: 10334
    protocol: TCP
  - name: locator-management-api
    port: 7070
    protocol: TCP
  - name: locator-metrics
    port: 4321
    protocol: TCP
  - name: manager
    protocol: TCP
    port: 1099
  type: LoadBalancer
  selector:
    statefulset.kubernetes.io/pod-name: gemfire2-locator-0

Manager用にPort1099を公開する必要がある点に注意。

また、WAN構成を取った場合、GatewaySenderとGatewayReceiverはServer上で動くため、最終的にはServer間で通信できる=ServerもExternalIP等で公開する必要がある。そのため、Locatorと同様に、Serverも公開する。

cluster1
apiVersion: v1
kind: Service
metadata:
  name: server-lb-0
spec:
  type: LoadBalancer
  ports:
  - name: server
    port: 40404
  - name: server-dev-rest-api
    port: 7070
  - name: server-metrics
    port: 4321
  - name: receiver
    port: 8888
  selector:
    statefulset.kubernetes.io/pod-name: gemfire1-server-0
---
apiVersion: v1
kind: Service
metadata:
  name: server-lb-1
spec:
  type: LoadBalancer
  ports:
  - name: server
    port: 40404
  - name: server-dev-rest-api
    port: 7070
  - name: server-metrics
    port: 4321
  - name: receiver
    port: 8888
  selector:
    statefulset.kubernetes.io/pod-name: gemfire1-server-1
cluster2
apiVersion: v1
kind: Service
metadata:
  name: server-lb-0
spec:
  type: LoadBalancer
  ports:
  - name: server
    port: 40404
  - name: server-dev-rest-api
    port: 7070
  - name: server-metrics
    port: 4321
  - name: receiver
    port: 8888
  selector:
    statefulset.kubernetes.io/pod-name: gemfire2-server-0
---
apiVersion: v1
kind: Service
metadata:
  name: server-lb-1
spec:
  type: LoadBalancer
  ports:
  - name: server
    port: 40404
  - name: server-dev-rest-api
    port: 7070
  - name: server-metrics
    port: 4321
  - name: receiver
    port: 8888
  selector:
    statefulset.kubernetes.io/pod-name: gemfire2-server-1

なお、Receiverで使うポートを明示的に書く必要がある点に注意。

CoreDNSの設定変更

相手のServiceの名前解決が出来るよう、CoreDNSに設定変更を行う。
各クラスタでkubectl edit cm -n kube-system corednsを実行し、以下のように相手のServiceのFQDNとExternalIPを追記する。

cluster1
@@ -7,6 +7,12 @@
            lameduck 5s
         }
         ready
+        hosts {
+           10.220.28.88 gemfire2-locator-0.gemfire2-locator.gemfire-cluster-2.svc.cluster.local
+           10.220.28.92 gemfire2-server-0.gemfire2-server.gemfire-cluster-2.svc.cluster.local
+           10.220.28.93 gemfire2-server-1.gemfire2-server.gemfire-cluster-2.svc.cluster.local
+           fallthrough
+        }
         kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
cluster2
@@ -7,6 +7,12 @@
            lameduck 5s
         }
         ready
+        hosts {
+           10.220.28.87 gemfire1-locator-0.gemfire1-locator.gemfire-cluster-1.svc.cluster.local
+           10.220.28.90 gemfire1-server-0.gemfire1-server.gemfire-cluster-1.svc.cluster.local
+           10.220.28.91 gemfire1-server-1.gemfire1-server.gemfire-cluster-1.svc.cluster.local
+           fallthrough
+        }
         kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa

保存後、CoreDNSを再起動して設定をリロードする。

kubectl delete pod -n kube-system -l k8s-app=kube-dns

WAN構成の動作確認

ここでは以下のような作業用Podを立ち上げて、そこから各クラスタのLocatorに繋いで作業していく。

apiVersion: v1
kind: Pod
metadata:
  name: debug-gemfire
spec:
  containers:
    - name: gemfire
      image: registry.tanzu.vmware.com/pivotal-gemfire/vmware-gemfire:10.0.0
  imagePullSecrets:
    - name: image-pull-secret

また構成は以下とする。
1700379502149.png

作業用Podに接続し、gfshを立ち上げる。

kubectl exec -it debug-gemfire -- bash
gfsh

Cluster1のLocatorに接続する。

connect --locator 10.220.28.87[10334]

GatewaySenderを作成する。

create gateway-sender --id=gemfire-cluster-1 --parallel=true --remote-distributed-system-id=11

Regionを作成する。

create region --name=regionA --type=PARTITION --gateway-sender-id=gemfire-cluster-1

GatewayReceiverを作成する。デフォルト値で作ると待受ポートが一意にならないため、Serviceで公開したPortを指定する。

create gateway-receiver --start-port 8888 --end-port 8888

確認用のデータを入れておく。

put --region=regionA --key="1" --value="one"
put --region=regionA --key="2" --value="two"

Cluster1側の作業は以上なので、Cluster1から切断する。

disconnect

次にCluster2の方でもGatewaySender、GatewayReceiverを作成する。
Cluster2のLocatorに接続する。

connect --locator 10.220.28.88[10334]

Cluster1と同じようにGatewaySender、Region、GatewayReceiverを作成する。

create gateway-sender --id=gemfire-cluster-2 --parallel=true --remote-distributed-system-id=10
create region --name=regionA --type=PARTITION --gateway-sender-id=gemfire-cluster-2
create gateway-receiver --start-port 8888 --end-port 8888

ここでstatus gateway-senderでGatewaySenderの設定を確認する。

Cluster-11 gfsh>status gateway-sender --id gemfire-cluster-2
                     Member                      |   Type   | Status
------------------------------------------------ | -------- | ---------------------
gemfire2-server-1(gemfire2-server-1:1)<v1>:59668 | Parallel | Running and Connected
gemfire2-server-0(gemfire2-server-0:1)<v1>:58072 | Parallel | Running and Connected

StatusConnectedになっているため、相手のクラスタと繋がっていることが分かる。
また、クエリを発行してデータが取れるか確認する。

query --query="select * from /regionA"
Result : true
Limit  : 100
Rows   : 2

Result
------
two
one

無事、Cluster1でputした内容が確認できた。

まとめ

一応WAN構成自体は作れることを確認できた。
ただ、スケールイン・アウトには対応出来ないし、IPが変わった場合も追従出来ない。
この辺はOperatorで実装して欲しい部分であり、GemFire for Kubernetesが将来的に改善されることを期待したい。

失敗談

CoreDNSのStubDomain

CoreDNSのStubDomainで解決できないか、CoreDNSのConfigMapに以下を追加して試してみた。

  Corefile: |
+   gemfire-cluster-2.svc.cluster.local:53 {
+     forward . 10.220.28.89
+   }
    .:53 {

この場合、PodのIPは引けるようになるが、Private IPを返してくるため上手く動かない。
接続は以下のような感じでタイムアウトとなる。

gfsh>connect --locator 10.220.28.88[10334]
Connecting to Locator at [host=10.220.28.88, port=10334] ..
Connecting to Manager at [host=gemfire2-locator-0.gemfire2-locator.gemfire-cluster-2.svc.cluster.local, port=1099] ..
Could not connect to : [host=gemfire2-locator-0.gemfire2-locator.gemfire-cluster-2.svc.cluster.local, port=1099]. Failed to retrieve RMIServer stub: javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException: Connection refused to host: gemfire2-locator-0.gemfire2-locator.gemfire-cluster-2.svc.cluster.local; nested exception is:
    java.net.ConnectException: Connection timed out (Connection timed out)]
0
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?