Verrazzanoで実現するマルチKubernetesクラスタ管理

# はじめに
この記事は、[Oracle Cloud Infrastructure Advent Calendar 2021 その2](https://qiita.com/advent-calendar/2021/oci) Day 6 の記事として書かれています。

みなさんはVerazzanoという製品をご存知でしょうか？
実は1年以上前になりますが、[Cloud Native Days Tokyo 2020](https://event.cloudnativedays.jp/cndt2020)の場をお借りしまして、[スポンサーセッション](https://event.cloudnativedays.jp/cndt2020/talks/55)として、Verazzanoのご紹介をさせて頂きました。
この時は、まだアルファ版だったのですが、今夏に正式リリースされています。

この記事では、このVerrazzanoで構築できるマルチクラスタ環境を作ってみたいと思います。

# そもそもVerrazzanoって何？

まずは、Verrazzanoの概要だけご紹介しておきます。

概要資料は[こちら](https://oracle-japan.github.io/ocidocs/solutions/cloud%20native/verrazzano-overview/)に置いてありますが、この資料から、Verrazzanoを1枚で説明するとすると以下のスライドが適切かなと思います。
![スクリーンショット 2021-12-06 10.27.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/c00f0a62-46ed-dac9-ff24-92ffd4f9616b.png)

中身はオープンソースのプロダクトの集合体になっており、これらのプロダクトをユーザが使いやすいように統合管理できるようになっているのがVerrazzanoです。
それぞれのプロダクトを見て頂ければ一目瞭然ですが、マルチクラスタ管理からアプリケーションのライフサイクル管理を一括で行えるサービススタックが含まれています。

今回は、このVerrazzanoを利用してマルチクラスタ環境を構築してみます。

環境は、Oracle Cloud Infrastructure Advent Calendarということで、もちろんOracle Cloud Infrastructure(以下、OCI)上のマネージドKubernetesサービスであるOracle Container Engine for Kubernetes(以下、OKE)上に構築します。
Verrazzano自体は、ハイブリッドな仕組み（将来的にはマルチクラウドも予定）なので、他にもkindや一般的なKubernetes環境にも構築することができます。
各環境のインストール手順については、[こちら](https://verrazzano.io/docs/setup/platforms/)に記載があります。

#OKEクラスタの準備

今回利用するOKEクラスタを準備していきます。  

今回は、マルチクラスタ環境なので、2つのクラスタを準備します。  

OKEの構築手順は、[こちら](https://oracle-japan.github.io/ocitutorials/cloud-native/oke-for-commons/)のチュートリアルを参考に構築してください。
今回は、マルチクラスタ管理なので、2つのOKEクラスタを構築します。

* Adminクラスタ
    * VM.Standard2.4 × 3 Node
* 管理対象クラスタ
    * VM.Standard.E3.Flex 1oCPU/8GB RAM × 3 Node

# Verrazzanoのインストール

ここからは、OKEクラスタが構築されているものとして進めていきます。  

まずは、OKEクラスタにVerrazzanoをインストールしていきます。  

最初にVerrazzano Operatorをインストールします。

```sh
kubectl apply -f https://github.com/verrazzano/verrazzano/releases/download/v1.0.3/operator.yaml
```

インストール完了するまで待機します。

```sh
kubectl -n verrazzano-install get pods -w
NAME                                            READY   STATUS     RESTARTS   AGE
verrazzano-platform-operator-54cf56884f-kvdfk   0/1     Init:0/1   0          12s
verrazzano-platform-operator-54cf56884f-kvdfk   0/1     PodInitializing   0          18s
verrazzano-platform-operator-54cf56884f-kvdfk   0/1     Running           0          19s
verrazzano-platform-operator-54cf56884f-kvdfk   0/1     Running           0          24s
verrazzano-platform-operator-54cf56884f-kvdfk   1/1     Running           0          85s
```

続いて、カスタムリソースを作成していきます。
現時点では、Verrazzanoには`prod`、`dev`、`managed-cluster`の3つのプロファイルを設定できます。
それぞれプロファイルの違いについては、[こちら](https://verrazzano.io/docs/setup/install/profiles/)を確認してください。
この記事では、`dev`で作成します。

```sh
kubectl apply -f - <<EOF
apiVersion: install.verrazzano.io/v1alpha1
kind: Verrazzano
metadata:
  name: my-verrazzano
spec:
  profile: ${VZ_PROFILE:-dev}
EOF
```

インストール中のログは以下のコマンドで確認できます。

```sh
kubectl logs -n verrazzano-install \
    -f $(kubectl get pod \
    -n verrazzano-install \
    -l job-name=verrazzano-install-my-verrazzano \
    -o jsonpath="{.items[0].metadata.name}")
```

```sh
---
[2021-12-06 04:24:53 UTC] 
[2021-12-06 04:24:53 UTC] Installation Complete.
[2021-12-06 04:24:53 UTC] 
[2021-12-06 04:24:53 UTC] Verrazzano provides various user interfaces.
[2021-12-06 04:24:53 UTC] 
[2021-12-06 04:24:53 UTC] Grafana - https://grafana.vmi.system.default.xxx.xxx.xxx.xxx.nip.io
[2021-12-06 04:24:53 UTC] Prometheus - https://prometheus.vmi.system.default.xxx.xxx.xxx.xxx.nip.io
[2021-12-06 04:24:53 UTC] Kibana - https://kibana.vmi.system.default.xxx.xxx.xxx.xxx.nip.io
[2021-12-06 04:24:53 UTC] Elasticsearch - https://elasticsearch.vmi.system.default.xxx.xxx.xxx.xxx.nip.io
[2021-12-06 04:24:53 UTC] Verrazzano Console - https://verrazzano.default.xxx.xxx.xxx.xxx.nip.io
[2021-12-06 04:24:53 UTC] 
[2021-12-06 04:24:53 UTC] You will need the credentials to access the preceding user interfaces. They are all accessed by the same username/password.
[2021-12-06 04:24:53 UTC] User: verrazzano
[2021-12-06 04:24:53 UTC] Password: kubectl get secret --namespace verrazzano-system verrazzano -o jsonpath={.data.password} | base64 --decode; echo
[2021-12-06 04:24:53 UTC] 
[2021-12-06 04:24:53 UTC] Rancher - https://rancher.default.xxx.xxx.xxx.xxx.nip.io
[2021-12-06 04:24:53 UTC] User: admin
[2021-12-06 04:24:53 UTC] Password: kubectl get secret --namespace cattle-system rancher-admin-secret -o jsonpath={.data.password} | base64 --decode; echo
[2021-12-06 04:24:53 UTC] 
[2021-12-06 04:24:53 UTC] Keycloak - https://keycloak.default.xxx.xxx.xxx.xxx.nip.io
[2021-12-06 04:24:53 UTC] User: keycloakadmin
[2021-12-06 04:24:53 UTC] Password: kubectl get secret --namespace keycloak keycloak-http -o jsonpath={.data.password} | base64 --decode; echo
```

`Installation Complete.`が出力されていればインストールは完了しています。

また、Verrazzanoに包含されている各コンポーネントのURLとパスワード(Secretを出力するコマンド)も出力されているので、メモしておいてください。

念の為、Verrazzanoのリソース状態も確認します。

```sh
kubectl get pods -n verrazzano-system
```

この状態になっていれば、Verrazzanoのインストールは完了です。
数コマンドだけなので、簡単ですね！

```sh
NAME                                              READY   STATUS    RESTARTS   AGE
coherence-operator-5cb8cd9f76-47bnt               1/1     Running   1          18m
fluentd-8ckfm                                     2/2     Running   1          13m
fluentd-wsfrz                                     2/2     Running   1          15m
fluentd-wtg4c                                     2/2     Running   2          14m
oam-kubernetes-runtime-56cdb56c98-7kzc8           1/1     Running   0          16m
verrazzano-api-5d9c776954-4jjnd                   2/2     Running   0          18m
verrazzano-application-operator-d57bd4f59-lrgbh   1/1     Running   0          15m
verrazzano-console-6bcb597dbb-xqtdw               2/2     Running   0          18m
verrazzano-monitoring-operator-69cc594b9b-mbhzp   1/1     Running   0          18m
verrazzano-operator-5b96664f9-lrpxs               1/1     Running   0          18m
vmi-system-es-master-0                            3/3     Running   0          18m
vmi-system-grafana-88dd99bb6-l8t7x                3/3     Running   0          18m
vmi-system-kibana-6cd469b9b7-2xqrm                3/3     Running   0          18m
vmi-system-prometheus-0-5f7fd8cd9c-7f7k5          4/4     Running   0          13m
weblogic-operator-f46cb6fd4-thhp4                 2/2     Running   0          17m
```

#管理対象Kubernetesクラスタの登録

ここでは、管理対象とするKubernetesクラスタ(今回はOKEクラスタ)を登録します。  
VerrazzanoにおけるマルチKubernetesクラスタ構成は以下のようなイメージです。
(今回は、Managed Clusterは一つです)

![スクリーンショット 2021-12-06 13.39.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/a6686145-ce16-0619-7f86-74bbb5a9fbe3.png)

##事前準備

ここでは、複数のKubernetesクラスタを操作しやすくするために、ちょっとだけ工夫をします。

まずは、kubeconfigに登録されているクラスタを確認します。

```sh
kubectl config get-contexts -o=name
```

例えば以下のように出力されます。

```sh
context-c2xd2htprdq
context-c4477dr5lca
```

今回の私の環境では、以下のように設定していきたいと思います。

* context-c2xd2htprdq：Adminクラスタ
* context-c4477dr5lca：管理対象クラスタ

後々の手順で分かりやすくなるように、環境変数をつけます。

```sh
export KUBECONTEXT_ADMIN=context-c2xd2htprdq
export KUBECONTEXT_MANAGED=context-c4477dr5lca
```

これで、以下のようにアクセスできます。

- Adminクラスタ

```sh
kubectl --context $KUBECONTEXT_ADMIN get pods
```

- 管理対象クラスタ

```sh
kubectl --context $KUBECONTEXT_MANAGED get pods
```

これで、事前準備は完了です。

## 管理対象クラスタへのVerrazzanoのインストール

ここでは、管理対象クラスタにおいて、`managed-cluster`プロファイルを利用してVerrazzanoをインストールします。
インストール手順は、プロファイルの指定以外、Adminクラスタと同様です。

```sh
kubectl --context $KUBECONTEXT_MANAGED apply -f https://github.com/verrazzano/verrazzano/releases/download/v1.0.3/operator.yaml
```

```sh
kubectl --context $KUBECONTEXT_MANAGED apply -f - <<EOF
apiVersion: install.verrazzano.io/v1alpha1
kind: Verrazzano
metadata:
  name: my-verrazzano
spec:
  profile: managed-cluster
EOF
```

Verrazzanoのカスタムリソースが展開されるのを待機します。

```sh
kubectl --context $KUBECONTEXT_MANAGED get pods -n verrazzano-system -w
```

このようになれば問題ありません。
Adminクラスタと比較すると、インストールされるコンポーネントが少しだけ違います。

```sh
NAME                                              READY   STATUS    RESTARTS   AGE
coherence-operator-5cb8cd9f76-bdfkn               1/1     Running   1          4m35s
fluentd-ftfmm                                     2/2     Running   1          68s
fluentd-lrdnl                                     2/2     Running   1          115s
fluentd-tzf97                                     2/2     Running   1          32s
oam-kubernetes-runtime-56cdb56c98-c6nt4           1/1     Running   0          3m8s
verrazzano-api-646d446cc6-2p28d                   2/2     Running   0          4m47s
verrazzano-application-operator-d57bd4f59-6jvs8   1/1     Running   0          2m47s
verrazzano-monitoring-operator-69cc594b9b-nk4lc   1/1     Running   0          4m47s
verrazzano-operator-585cdbcbcd-rhlqs              1/1     Running   0          4m47s
vmi-system-prometheus-0-c468974b5-gsdst           4/4     Running   0          2m55s
weblogic-operator-f46cb6fd4-4n9j9                 2/2     Running   0          3m58s
```

これで、事前準備は完了です。

## 管理対象Kubernetesクラスタの登録の事前準備

ここでは、管理対象KubernetesクラスタをAdminクラスタに登録するための事前準備を行います。

まずは、管理対象Kubernetesクラスタにインストールされている登録に必要な証明書を出力します。  

```sh
kubectl --context $KUBECONTEXT_MANAGED \
     -n verrazzano-system get secret system-tls -o jsonpath='{.data.ca\.crt}'
```

このような結果が表示されます。(セキュリティのためマスクします)

```sh
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lRWjRMekFpMnJzODllL245RnFsbm~~~~~~~~~~~~~~~~
```

この証明書を利用して、管理対象サーバを登録するためのManifestを作成します。

```sh
MGD_CA_CERT=$(kubectl --context $KUBECONTEXT_MANAGED \
>      get secret system-tls \
>      -n verrazzano-system \
>      -o jsonpath="{.data.ca\.crt}" | base64 --decode)
kubectl --context $KUBECONTEXT_MANAGED \
```
```sh
kubectl --context $KUBECONTEXT_MANAGED \
  create secret generic "ca-secret-managed1" \
  -n verrazzano-mc \
  --from-literal=cacrt="$MGD_CA_CERT" \
  --dry-run=client \
  -o yaml > managed1.yaml
```

問題なければ、`managed1.yaml`というManifestが出力されます。  

出力されたManifestをAdminクラスタに登録します。 

```sh
kubectl --context $KUBECONTEXT_ADMIN \
     apply -f managed1.yaml
```

次に、AdminクラスタのAPI ServerのIPアドレスを取得します。

```sh
kubectl --context $KUBECONTEXT_ADMIN config view --minify
```

以下のように出力されます。

```sh
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://xxx.xxx.xxx.xxx:6443
  name: cluster-c2xd2htprdq
contexts:
-------
```

`https://xxx.xxx.xxx.xxx:6443`の部分がAdminクラスタのAPI ServerのIPアドレスになります。

これを環境変数にしておきます。

```sh
export ADMIN_K8S_SERVER_ADDRESS=https://xxx.xxx.xxx.xxx:6443
```

最後に、上記IPアドレスを含むConfigMapをAdminクラスタに作成します。

```sh
kubectl --context $KUBECONTEXT_ADMIN \
    apply -f <<EOF -
apiVersion: v1
kind: ConfigMap
metadata:
  name: verrazzano-admin-cluster
  namespace: verrazzano-mc
data:
  server: "${ADMIN_K8S_SERVER_ADDRESS}"
EOF
```

これで、管理対象Kubernetesクラスタの登録の事前準備は完了です。

# 管理対象Kubernetesクラスタの登録

ここでは、いよいよ、管理対象Kubernetesクラスタの登録を行います。
登録手順は、Adminクラスタ、管理対象クラスタにそれぞれ分かれます。

## Adminクラスタでの手順

AdminクラスタにVerrazzanoManagedClusterリソースを作成します。

```sh
kubectl --context $KUBECONTEXT_ADMIN \
    apply -f <<EOF -
apiVersion: clusters.verrazzano.io/v1alpha1
kind: VerrazzanoManagedCluster
metadata:
  name: managed1
  namespace: verrazzano-mc
spec:
  description: "Test VerrazzanoManagedCluster object"
  caSecret: ca-secret-managed1
EOF
```

VerrazzanoManagedClusterリソースの展開が完了するまで、待機します。

```sh
kubectl --context $KUBECONTEXT_ADMIN \
    wait --for=condition=Ready \
    vmc managed1 -n verrazzano-mc
```

最後に、管理対象クラスターを登録するために作成されたManifestファイルをエクスポートします。

```sh
kubectl --context $KUBECONTEXT_ADMIN \
    get secret verrazzano-cluster-managed1-manifest \
    -n verrazzano-mc \
    -o jsonpath={.data.yaml} | base64 --decode > register.yaml
```

## 管理対象クラスタでの手順

管理対象クラスタでは、先ほど出力したManifestファイルを適用するだけです。

```sh
kubectl --context $KUBECONTEXT_MANAGED apply -f register.yaml
```

これで、管理対象クラスタの登録は完了です！

# 管理対象クラスタの登録確認

最後に、管理対象クラスタが正常に登録されていることを確認します。

Verrazzanoには、Verrazzano UIと呼ばれるコンソール画面があるので、こちらを利用して確認していきます。

[Verrazzanoのインストール](#verrazzanoのインストール)にて、インストール後に確認した`Verrazzano Console`のURLにアクセスします。

コンソールにログインする際にユーザ名とパスワードが聞かれますが、以下のようになります。

* ユーザ名：verrazzano
* パスワード：`kubectl get secret --namespace verrazzano-system verrazzano -o jsonpath={.data.password} | base64 --decode; echo`の出力結果

ログインすると以下のような画面が表示されます。

左のメニューにある`Cluster`をクリックします。

![スクリーンショット 2021-12-06 14.59.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/537ae007-b2a8-cab2-7fee-3e61bead8fd4.png)

このように`managed1`という名前の管理対象クラスタが`Running`状態で登録されていれば、問題なく登録されています。

![スクリーンショット 2021-12-06 14.59.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/949e31f3-9229-6ddc-53e9-f05a593830aa.png)

ついでに、Rancherでも確認します。

[Verrazzanoのインストール](#verrazzanoのインストール)にて、インストール後に確認した`Rancher`のURLにアクセスします。

コンソールにログインする際にユーザ名とパスワードが聞かれますが、以下のようになります。

* ユーザ名：admin

* パスワード：`kubectl get secret --namespace cattle-system rancher-admin-secret -o jsonpath={.data.password} | base64 --decode; echo`の出力結果

ログインすると以下のような画面が表示されます。

![スクリーンショット 2021-12-06 15.08.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40392/1ad79bfd-8cc0-4c40-d007-5ddd97a3e3f2.png)


`local`はAdminクラスタ、`managed1`が管理対象クラスタになります。
Rancherを使って、Adminクラスタ/管理対象クラスタの操作を行うこともできます。

#まとめ

今回は、VerrazzanoでのマルチKubernetesクラスタ管理ということで環境を構築してみました。

これだけだとつまらないので、次回の記事で今回のマルチクラスタ環境にサンプルアプリケーションなどをデプロイしてみようと思います。

#参考記事

https://verrazzano.io/docs/

https://github.com/verrazzano