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 3 years have passed since last update.

東京・大阪のRed Hat OpenShift on IBM CloudをSubmarinerでIPsec VPN接続する

Posted at

目的

KubernetesやOpenShiftクラスターが2つあり、クラスタをまたがってPodどうしが通信したい場合、通常はそれぞれのクラスターでRouterやIngressを使ってServiceを公開し、それを利用してアクセスをすることになります。Submarinerを使うと、クラスタ間でIPsec VPNが張られ、あたかもクラスター内でServiceやPodにアクセスしているかのように、リモートのクラスター内のServiceやPodにアクセスが可能になります。

今回はRed Hat OpenShift on IBM Cloud(ROKS)を東京リージョンと大阪リージョンそれぞれに建てて、Submarinerを検証してみます。

手順

ROKSクラスターのオーダー(東京・大阪)

東京と大阪でROKSクラスターをオーダーします。このときの注意点として、次の3点があります。

  • VPCサブネットが重複しないこと
  • Podサブネットが重複しないこと
  • Serviceサブネットが重複しないこと

VPCサブネットは設定時に東京・大阪のVPCで重複しないようにしてください。

PodサブネットとServiceサブネットは、IBM Cloudコンソールからオーダーするとデフォルト値が適用されて重複する可能性があります。CLIからオーダーするとレンジを明示できますので、少なくとも片方のクラスターはCLIでレンジを指定して重複しないようにしてください。

東京にすでにクラスターが存在している場合、次のコマンドでPodサブネットとServiceサブネットを確認することができます。

$ oc get networks.config.openshift.io cluster -o yaml
...
spec:
  clusterNetwork:
  - cidr: 172.17.128.0/18  # Podサブネット
    hostPrefix: 23
  networkType: Calico
  serviceNetwork:
  - 172.21.0.0/16          # Serviceサブネット
...

例えば、大阪のクラスターは次のように作成します。

$ ibmcloud oc cluster create vpc-gen2 --flavor bx2.16x64 --name ${大阪クラスタ名} --subnet-id ******** --vpc-id ******** --zone jp-osa-1 --cos-instance ********  --pod-subnet 172.17.192.0/18 --service-subnet 172.22.0.0/16 --version 4.8
.11_openshift --workers 2
$ ibmcloud oc zone add vpc-gen2 -c ${大阪クラスタ名} --subnet-id ******** --worker-pool default --zone jp-osa-2
$ ibmcloud oc zone add vpc-gen2 -c ${大阪クラスタ名} --subnet-id ******** --worker-pool default --zone jp-osa-3
$ ibmcloud oc worker-pool resize -c ${大阪クラスタ名} --size-per-zone 1 --worker-pool default

ROKSをCLIでオーダーする場合、各ゾーン最低2台を指定しないとエラーになります。今回は各ゾーン1台3ゾーンにしたかったので、上記のように一旦23=6台構成にした後で1*3=3台構成に縮小しています。

私の環境では次のようになります。

|東京|大阪
---|---|---
VPCサブネット|10.244.2.0/24|10.248.0.0/24
Podサブネット|172.17.128.0/18|172.17.196.0/18
Serviceサブネット|172.21.0.0/16|172.22.0.0/16

東京・大阪間Transit Gatewayの有効化

東京・大阪間のVPCがIBM Cloudのプライベートネットワークで通信できるよう、Transit Gatewayを有効化します。

image.png

image.png

image.png

作業用kubeconfigの作成(作業PC)

ここから先は東京・大阪でそれぞれ作業をしますので、自分がどちらのクラスタで作業をしているか間違わないようにする必要があります。それぞれkubeconfigを生成して都度指定しながら作業をすると間違いにくいです。

gen-kubeconfig.sh
# !/usr/bin/env bash

export IBMCLOUD_API_KEY=********

TOK_RG=*****
TOK_CLUSTER=********
OSA_RG=*****
OSA_CLUSTER=********

function get-cluster-id {
  ibmcloud oc cluster get -c ${1} --output json | jq -r .id
}

ibmcloud login -r jp-tok -g ${TOK_RG}
KUBECONFIG=./tok.config ibmcloud oc cluster config -c ${TOK_CLUSTER}
KUBECONFIG=./tok.config oc login -u apikey -p ${IBMCLOUD_API_KEY}
KUBECONFIG=./tok.config oc config delete-context ${TOK_CLUSTER}/$(get-cluster-id ${TOK_CLUSTER})

ibmcloud login -r jp-osa -g ${OSA_RG}
KUBECONFIG=./osa.config ibmcloud oc cluster config -c ${OSA_CLUSTER}
KUBECONFIG=./osa.config oc login -u apikey -p ${IBMCLOUD_API_KEY}
KUBECONFIG=./osa.config oc config delete-context ${OSA_CLUSTER}/$(get-cluster-id ${OSA_CLUSTER})

Submarinerのインストールと構成

Submariner CLIのインストール(作業PC)

作業PCにCLIをインストールします。

$ curl -Ls https://get.submariner.io | bash
Installing subctl version latest
  OS detected:           linux
  Architecture detected: amd64
  Download URL:          https://github.com/submariner-io/releases/releases/download/v0.10.1/subctl-v0.10.1-linux-amd64.tar.xz

Downloading...
subctl-v0.10.1-linux-amd64 has been installed as /home/teruq/.local/bin/subctl
This provides subctl version: v0.10.1

$ subctl completion bash | sudo tee /etc/bash_completion.d/subctl >/dev/null
$ source /etc/bash_completion.d/subctl

Calico CLIのインストール(作業PC)

$ curl -o calicoctl -O -L  "https://github.com/projectcalico/calicoctl/releases/download/v3.20.2/calicoctl" 
$ sudo cp calicoctl /usr/local/bin/
$ sudo chmod 755 /usr/local/bin/calicoctl

Calico

IPPoolの作成

東京と大阪それぞれのIPレンジを下記のように記述します。

ippool-tok.yaml
---
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: service-tok
spec:
  cidr: 172.21.0.0/16
  natOutgoing: false
  disabled: true

---
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: pod-tok
spec:
  cidr: 172.17.128.0/18
  natOutgoing: false
  disabled: true
ippool-osa.yaml
---
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: service-osa
spec:
  cidr: 172.22.0.0/16
  natOutgoing: false
  disabled: true

---
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: pod-osa
spec:
  cidr: 172.17.192.0/18
  natOutgoing: false
  disabled: true

それぞれのクラスタに相手のIPPoolを登録します。つまり、東京のクラスタには大阪のレンジを、大阪のクラスタには東京のレンジを登録します。

$ DATASTORE_TYPE=kubernetes KUBECONFIG=./tok.config calicoctl create -f ippool-osa.yaml --allow-version-mismatch
Successfully created 2 'IPPool' resource(s)
$ DATASTORE_TYPE=kubernetes KUBECONFIG=./osa.config calicoctl create -f ippool-tok.yaml --allow-version-mismatch
Successfully created 2 'IPPool' resource(s)

ノードにラベル付与

競合が発生するとsubmariner-operatorに次のログが出力されます。
E1014 15:09:03.590563 1 submariner_controller.go:204] controller_submariner "msg"="failed to update the Submariner status" "error"="Operation cannot be fulfilled on submariners.submariner.io "submariner": the object has been modified; please apply your changes to the latest version and try again" "Request.Name"="submariner" "Request.Namespace"="submariner-operator"

$ KUBECONFIG=./tok.config oc label nodes --all submariner.io/gateway=true
node/10.244.130.28 labeled
node/10.244.2.36 labeled
node/10.244.66.34 labeled

$ KUBECONFIG=./osa.config oc label nodes --all submariner.io/gateway=true
node/10.248.0.10 labeled
node/10.248.128.10 labeled
node/10.248.64.11 labeled

Submariner Brokerのインストール(東京)

東京クラスターにSubmariner Brokerをインストールします。

$ subctl deploy-broker --kubeconfig ./tok.config
 ✓ Setting up broker RBAC
 ✓ Deploying the Submariner operator
 ✓ Created operator CRDs
 ✓ Created operator namespace: submariner-operator
 ✓ Created operator service account and role
 ✓ Updated the privileged SCC
 ✓ Created lighthouse service account and role
 ✓ Updated the privileged SCC
 ✓ Created Lighthouse service accounts and roles
 ✓ Deployed the operator successfully
 ✓ Deploying the broker
 ✓ The broker has been deployed
 ✓ Creating broker-info.subm file
 ✓ A new IPsec PSK will be generated for broker-info.subm

Podが起動したことを確認します。

$ KUBECONFIG=./tok.config oc get pods -n submariner-operator
NAME                                   READY   STATUS    RESTARTS   AGE
submariner-operator-7987f7ccfb-8fdml   1/1     Running   0          49s
[teruz@t14s20 odf]$

クラスターの参加(東京)

東京クラスターをSubmarinerに参加させます。--clusteridtokとします。

$ subctl join --clusterid tok broker-info.subm --cable-driver vxlan --kubeconfig ./tok.config
* broker-info.subm says broker is at: https://c100-e.jp-tok.containers.cloud.ibm.com:*****
* There are 3 labeled nodes in the cluster:
  - 10.244.130.28
  - 10.244.2.36
  - 10.244.66.34
        Network plugin:  Calico
        Service CIDRs:   [172.21.0.0/16]
        Cluster CIDRs:   [172.17.128.0/18]
 ✓ Discovering network details
 ✓ Validating Globalnet configurations
 ✓ Discovering multi cluster details
 ✓ Deploying the Submariner operator
 ✓ Created Lighthouse service accounts and roles
 ✓ Creating SA for cluster
 ✓ Deploying Submariner
 ✓ Submariner is up and runnin
$ subctl join --clusterid tok broker-info.subm --kubeconfig ./tok.config
* broker-info.subm says broker is at: https://c100-e.jp-tok.containers.cloud.ibm.com:30677
? Which node should be used as the gateway? 10.244.2.36
        Network plugin:  Calico
        Service CIDRs:   [172.21.0.0/16]
        Cluster CIDRs:   [172.17.128.0/18]
 ✓ Discovering network details
 ✓ Validating Globalnet configurations
 ✓ Discovering multi cluster details
 ✓ Deploying the Submariner operator
 ✓ Created Lighthouse service accounts and roles
 ✓ Creating SA for cluster
 ✓ Deploying Submariner
 ✓ Submariner is up and running

Podを確認すると、submariner-lighthouse-agentがErrorになっています。

$ KUBECONFIG=./tok.config oc get pods -n submariner-operator
NAME                                             READY   STATUS    RESTARTS   AGE
submariner-gateway-29qtp                         1/1     Running   0          26s
submariner-gateway-9l52q                         1/1     Running   0          26s
submariner-gateway-hcgr5                         1/1     Running   0          26s
submariner-lighthouse-agent-6898c46575-5bssg     0/1     Error     2          22s
submariner-lighthouse-coredns-74bfcb6f65-99njs   1/1     Running   0          19s
submariner-lighthouse-coredns-74bfcb6f65-m2x5p   1/1     Running   0          19s
submariner-operator-7987f7ccfb-2dfb6             1/1     Running   0          74m
submariner-routeagent-4js8k                      1/1     Running   0          22s
submariner-routeagent-9lzg4                      1/1     Running   0          22s
submariner-routeagent-p6fmf                      1/1     Running   0          22s

ログを確認すると、APIサーバのTLS証明書の検証に失敗しているようです。

$ KUBECONFIG=./tok.config oc logs submariner-lighthouse-agent-6898c46575-5bssg -n submariner-operator
I1013 01:31:57.083392       1 main.go:70] Arguments: [/usr/local/bin/lighthouse-agent -alsologtostderr -v=2]
I1013 01:31:57.083442       1 main.go:71] AgentSpec: {tok submariner-operator false}
W1013 01:31:57.083499       1 client_config.go:608] Neither --kubeconfig nor --master was specified.  Using the inClusterConfig.  This might not work.
I1013 01:31:57.442060       1 main.go:98] Starting submariner-lighthouse-agent {tok submariner-operator false}
F1013 01:31:57.505801       1 main.go:115] Failed to create lighthouse agent: cannot access the API server "https://c100-e.jp-tok.containers.cloud.ibm.com:******": Get "https://c100-e.jp-tok.containers.cloud.ibm.com:30677/apis/multicluster.x-k8s.io/v1alpha1/namespaces/submariner-k8s-broker/serviceimports/any": x509: certificate signed by unknown authority

恐らくは2021年10月にLet's Encryptのルート証明書が変更になったことが原因な気がします。仕方がないので今回はPodのCA証明書を手動で差し替えます。

APIサーバの証明書を調べます。issuerがDigiCertのようです。

$ openssl s_client -connect c100-e.jp-tok.containers.cloud.ibm.com:****** -showcerts
...
issuer=C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
...

DigiCertのサイトでDigiCert TLS RSA SHA256 2020 CA1を調べると、ルート証明書が公開されていますので、PEMをダウンロードします。

https://www.digicert.com/kb/digicert-root-certificates.htm#roots

image.png

$ wget https://cacerts.digicert.com/DigiCertTLSRSASHA2562020CA1-1.crt.pem

Base64エンコードします。

$ cat DigiCertTLSRSASHA2562020CA1-1.crt.pem | base64 -w 0
LS0tLS1CRUdJTiBDRVJUSUZJ.....

CustomResourceのキーbrokerK8sCAをエンコードした値に書き換えます。

$ KUBECONFIG=./tok.config oc edit submariners.submariner.io submariner -n submariner-operator
...
spec:
  broker: k8s
  brokerK8sApiServer: c100-e.jp-tok.containers.cloud.ibm.com:******
  brokerK8sApiServerToken: ********
  brokerK8sCA: LS0tLS1CRUdJTiBDRVJUSUZJ.....(先ほどエンコードしたルート証明書)
...

保存すると、Podが無事起動しました。

$ KUBECONFIG=./tok.config oc get pods -n submariner-operator | grep lighthouse-agent
submariner-lighthouse-agent-85b9c48df8-rgjbl     1/1     Running   0          33s

クラスターの参加(大阪)

大阪クラスターをSubmarinerに参加させます。--clusteridosaとします。

$ subctl join --clusterid osa broker-info.subm --kubeconfig ./osa.config
* broker-info.subm says broker is at: https://c100-e.jp-tok.containers.cloud.ibm.com:*****
* There are 3 labeled nodes in the cluster:
  - 10.248.0.10
  - 10.248.128.10
  - 10.248.64.11
        Network plugin:  Calico
        Service CIDRs:   [172.22.0.0/16]
        Cluster CIDRs:   [172.17.192.0/18]
 ✓ Discovering network details
 ✓ Validating Globalnet configurations
 ✓ Discovering multi cluster details
 ✓ Deploying the Submariner operator
 ✓ Created operator CRDs
 ✓ Created operator namespace: submariner-operator
 ✓ Created operator service account and role
 ✓ Updated the privileged SCC
 ✓ Created lighthouse service account and role
 ✓ Updated the privileged SCC
 ✓ Created Lighthouse service accounts and roles
 ✓ Deployed the operator successfully
 ✓ Creating SA for cluster
 ✓ Deploying Submariner
 ✓ Submariner is up and running

or

$ subctl join --clusterid osa broker-info.subm --kubeconfig ./osa.config
* broker-info.subm says broker is at: https://c100-e.jp-tok.containers.cloud.ibm.com:30677
? Which node should be used as the gateway? 10.248.0.10
        Network plugin:  Calico
        Service CIDRs:   [172.22.0.0/16]
        Cluster CIDRs:   [172.17.192.0/18]
 ✓ Discovering network details
 ✓ Validating Globalnet configurations
 ✓ Discovering multi cluster details
 ✓ Deploying the Submariner operator
 ✓ Created operator namespace: submariner-operator
 ✓ Created operator service account and role
 ✓ Created lighthouse service account and role
 ✓ Created Lighthouse service accounts and roles
 ✓ Deployed the operator successfully
 ✓ Creating SA for cluster
 ✓ Deploying Submariner
 ✓ Submariner is up and running

こちらもlighthouse-agentが起動に失敗するので、CustomResourceを書き換えます。

$ KUBECONFIG=./osa.config oc get pods -n submariner-operator | grep lighthouse-agent
submariner-lighthouse-agent-66fc4dfd47-rxswt    0/1     CrashLoopBackOff   1          34s

$ KUBECONFIG=./osa.config oc edit submariners.submariner.io submariner -n submariner-operator
→brokerK8sCAを東京と同じ値に変更

$ KUBECONFIG=./osa.config oc get pods -n submariner-operator | grep lighthouse-agent
submariner-lighthouse-agent-6749795b6f-rw6j5    1/1     Running   0          28s

接続確認

oc edit cm rook-ceph-operator-config -n openshift-storage

CSI_ENABLE_OMAP_GENERATOR", "value": "true"
apiVersion: v1
data:
  ROOK_CSI_KUBELET_DIR_PATH: /var/data/kubelet
  CSI_ENABLE_OMAP_GENERATOR: "true"
kind: ConfigMap
metadata:
  creationTimestamp: "2021-10-12T14:09:39Z"
  name: rook-ceph-operator-config
  namespace: openshift-storage
  resourceVersion: "22743"
  uid: 4ca20351-9f4f-4be3-b0f6-dea95c37a107
$ oc get pods -n openshift-storage -l app=csi-rbdplugin-provisioner -o jsonpath={.items[*].spec.containers[*].name}
csi-provisioner csi-resizer csi-attacher csi-snapshotter csi-omap-generator csi-rbdplugin liveness-prometheus csi-provisioner csi-resizer csi-attacher csi-snapshotter csi-omap-generator csi-rbdplugin liveness-prometheus

oc get pods -n openshift-storage -l app=csi-rbdplugin-provisioner -o jsonpath={.items[].spec.containers[].name}

東京・大阪それぞれでSTATUSconnectedになっていることを確認します。

$ subctl show connections --kubeconfig ./tok.config
Cluster "c100-e-jp-tok-containers-cloud-ibm-com:30677"
 ✓ Showing Connections
GATEWAY                          CLUSTER  REMOTE IP      NAT  CABLE DRIVER  SUBNETS                         STATUS     RTT avg.
kube-c5j0dfuo0fmosdq1d1pg-roksd  osa      10.248.128.10  no   vxlan         172.22.0.0/16, 172.17.192.0/18  connected  8.455507ms

$ subctl show connections --kubeconfig ./osa.config
Cluster "c101-e-jp-osa-containers-cloud-ibm-com:31014"
 ✓ Showing Connections
GATEWAY                          CLUSTER  REMOTE IP    NAT  CABLE DRIVER  SUBNETS                         STATUS     RTT avg.
kube-c5g3vset0jaip0r1pmkg-rokso  tok      10.244.2.36  no   vxlan         172.21.0.0/16, 172.17.128.0/18  connected  8.395445ms

動作確認

サービス公開の仕組み

ServiceExport

ここまでの手順で東京・大阪のクラスタは接続されていますが、まだお互いのサービスにアクセスすることはできません。公開したいサービスを登録する必要があります。それをServiceExportと呼びます。

ServiceExportはマニフェストで登録します。

apiVersion: multicluster.x-k8s.io/v1alpha1
kind: ServiceExport
metadata:
  name: hello       # Service名
  namespace: qiita  # Serviceがあるネームスペース名

subctlで登録もできます。

$ subctl export service hello -n qiita --kubeconfig ./xxx.config

公開したサービスは、${サービス名}.${ネームスペース名}.svc.clusterset.localという特殊なFQFNで解決できるようになります。

サービス名重複時の動作

もし同じ名称同じネームスペースのサービスを複数クラスターが同時に公開した場合は、すこし特殊な動きをします。この状態で例えばhello.qiita.svc.clusterset.localにアクセスしようとした場合、次の動きになります。

  • 自クラスターにサービスが存在していればそのIPを返す
  • 自クラスターにサービスが存在していなければ、他の存在しているクラスターからラウンドロビン的にIPを返す(今回は2クラスタなのでこれはありえないですが、Submarinerは本来は3つ以上のクラスターにも対応しています)

1点目がポイントです。リモートのクラスターにアクセスしているつもりが、実はローカルのクラスターにアクセスしていたという間違いを犯しやすくなります。ですので、明示的に相手のクラスターのサービスにアクセスしたい場合は、サービス名またはネームスペース名を別にする必要があります。

大阪のサービスを東京からアクセス

大阪にHelloアプリをデプロイします。

$ KUBECONFIG=./osa.config oc new-project qiita
$ KUBECONFIG=./osa.config oc new-app --name hello-osa --docker-image docker.io/ibmcom/hello
$ KUBECONFIG=./osa.config oc get svc hello-osa
NAME        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
hello-osa   ClusterIP   172.22.70.152   <none>        8080/TCP   24s

サービスを公開します。

$ subctl export service hello-osa -n qiita --kubeconfig ./osa.config
Service exported successfully

東京から大阪にアクセスします。サービスのIPを指定することも、FQDN名を指定することもできます。

  • Submarinerでは、相手方のサービスを${サービス名}.${ネームスペース}.svc.clusterset.localで解決することができます。
  • ServiceのClusterIPで直接アクセスする場合はServiceExportは不要です。が、実運用上現実的ではないでしょう。
  • もし公開側でServiceを作成してClusterIPが変わった場合でも、自動的にServiceImportは新しいIPに変更されます。
$ KUBECONFIG=./tok.config oc run centos8 --image centos:8 --command -- tail -f /dev/null
$ KUBECONFIG=./tok.config oc rsh centos8 curl http://hello-osa.qiita.svc.clusterset.local:8080/
Hello World

東京のサービスを大阪からアクセス

逆も同様です。東京にHelloアプリをデプロイします。

$ KUBECONFIG=./tok.config oc new-project qiita
$ KUBECONFIG=./tok.config oc new-app --name hello-tok --docker-image docker.io/ibmcom/hello
$ KUBECONFIG=./tok.config oc get svc hello-tok
NAME    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
hello   ClusterIP   172.21.57.229    <none>        8080/TCP   5s

東京のHelloを公開します。subctlで公開することもできます。

$ subctl export service hello -n qiita --kubeconfig ./tok.config
Service exported successfully

$ oc get serviceexport hello -n qiita -o yaml
apiVersion: multicluster.x-k8s.io/v1alpha1
kind: ServiceExport
metadata:
  name: hello
  namespace: qiita
...

大阪から東京にアクセスします。

$ KUBECONFIG=./osa.config oc run centos8 --image centos:8 --command -- tail -f /dev/null

# IP直接
$ KUBECONFIG=./osa.config oc rsh centos8 curl http://172.21.57.229:8080/
Hello World

# サービス名
$ KUBECONFIG=./osa.config oc rsh centos8 curl http://hello.qiita.svc.clusterset.local:8080/
Hello World

クリーンアップ

$ KUBECONFIG=./tok.config oc delete ns submariner-k8s-broker submariner-operator
$ KUBECONFIG=./tok.config oc label nodes -l submariner.io/gateway=true submariner.io/gateway-

$ KUBECONFIG=./osa.config oc delete ns submariner-operator
$ KUBECONFIG=./osa.config oc label nodes -l submariner.io/gateway=true submariner.io/gateway-

残作業

  • Transit Gateway断時の挙動
  • Gatewayの冗長化検証
  • Submarinerのバージョンアップ
  • ノードのバージョンアップ、リプレイス時の挙動
  • ROKSのエンドポイントのプライベート化
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?