Tanzu Mission Control Self-Managed をデプロイしてみた

2023年6月29日、以下のブログが公開され、`VMware Tanzu Mission Control Self-Managed` (以下、TMC-SM と呼ぶ)が利用可能になりました。
- [Beyond SaaS: Multi-cluster Kubernetes Management for Regulated Industries and Sovereign Clouds](https://tanzu.vmware.com/content/blog/vmware-tanzu-mission-control-self-managed-announcement)

私のおうちクラウドにTMC-SM を導入してみましたので、ポイントを紹介します。
※. 実際に業務利用するにはTMC-SM 用のライセンスが必要です

# TL;DR
難易度Max!
この記事のスクロールの長さが大変さを物語っていますｗ
私のドキュメントを見ずにTMC-SMを構築できた方は、なかなかのTanzu＆おうちクラウドマスターです。

# TMC-SMの要件と準備
以下のドキュメントに掲載されている内容をまとめます。（都度変わる可能性があるので、最新の情報はオリジナルのドキュメントをチェックして下さい）

- [Preparing your cluster for Tanzu Mission Control Self-Managed](https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/1.0/tanzumc-sm-install/prepare-cluster.html)

## TMC-SM の要件

### 対応するTanzu環境
現時点ではvSphereのみが対象(AWS等は未対応)であり、以下の組み合わせで導入が可能なようです。

| vSphere version | Kubernetes 環境 | 備考 |
|:-:|:-:|:-:|
| vSphere (Version指定なし) | TKG(Standalone) 1.6/2.1/2.2 上の TKG Cluster |   |
| vSphere 7.0U3l以降 | vSphere with Tanzu 上の Workload cluster |   |
| vSphere8 | vSphere with Tanzu 上の TKG2 workload cluster| ※. tech preview |

今回私は、一番上のTKG (Standalone) 2.2でデプロイしたTKCを使って試していきたいと思います。

### Component 要件
目ぼしいところをピックアップすると、以下を満たす必要があります。

| 項目 | 要件 |
|:-:|:-|
| Kubernetes Version | v1.23/1.24/1.25 |
| Controlplane スペック | 1Node / 4vCPU / 8gb mem / 40gb disk |
| Workers スペック | 3Nodes / 4vCPU / 8gb mem / 40gb disk |
| Load Balancer | Port 443受け付けるLB (※なんでも良い)を用意しておく  |
| Container Registry | Harbor 2.xを事前に用意<br>- 10gb以上の領域<br>- Public project(認証は未サポート)  |
| OIDC準拠のIDP | 例<br>- Okta<br>- Dex<br>- 一部の Active Directory への ID フェデレーションを持つ UAA(User Account and Authentication Service) |
| cert-manager | 1.10.2: ※アップストリームではサポート終了しているバージョンなので、将来変更予定 |
| kapp-controller | 0.45.1 or later: ※Tanzu CLIに準拠 |

はい、これらを用意するだけでも大変ですね。。今回私は、以下の構成を用意しました。
- Kubernetes v1.25.7 (TKG 2.2の最新版)
- Controlplane: 3Node / 2vCPU /8gb mem/ 40gb disk
- Workers: 3Nodes / 4vCPU / 8gb mem / 40gb disk
- ALB (v22.1.3)
- Harbor: v2.7.1(Tanzu package最新版) / 50gb disk
- IDP: Okta

### クライアント要件
先に、ページ下方にある [Bootstrap machine](https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/1.0/tanzumc-sm-install/prepare-cluster.html#bootstrap-machine-5) を読んでおくと良いでしょう。自分のノートPCでもなんでも構いませんが、TMC-SMをK8sクラスタにインストール際に使用するマシンの要件です。

- A Linux x86_64 build
- Kubernetes clusterにアクセス可能
- glibcベースの Linux ディストロ (Ubuntu, Fedora, CentOS, Debian) ※. Alpine はサポート対象外
- tar command / tmc CLI / kubectl CLI が使えること

ここまで厳格にクライアント側の要件を指定しているのは珍しいですね。。恐らく、この後のステップで登場する`tmc-sm` というセットアップ用CLIが上記の環境用にビルドされているからでしょう。ただimgpkg copyしてるだけのようにも見えますが・・・。

私はUbuntuの踏み台VMを用意し、そこからTKG環境を立てました。

## 事前準備
ここからは、TMC-SMのセットアップを開始する前に、前提条件を満たすための準備をするフェーズです。

### Kubernetesクラスタの準備
ドキュメントには特に明記していませんが、順番的には最初にTanzu環境を用意するのが良いでしょう。私と同等の構成にする場合、以下のドキュメントを順番に参照すると良いでしょう。

1. Bootstrap VMの準備([OVF または OVA テンプレートの展開](https://docs.vmware.com/jp/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-17BEDA21-43F6-41F4-8FB2-E01D275FE9B4.html))
    - ※. Ubuntu 22.04 OVA( https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.ova )を使うと良いでしょう。
1. [スタンドアローン管理クラスタで使用する Tanzu CLI およびその他のツールのインストール](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/2.2/tkg-deploy-mc-22/install-cli.html)
1. [NSX Advanced Load Balancer のインストールと構成](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/2.2/tkg-deploy-mc-22/mgmt-reqs-network-nsx-alb-install.html)
1. [インストーラ インターフェイスを使用した管理クラスタの展開](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/2.2/tkg-deploy-mc-22/mgmt-deploy-ui.html)
1. [ワークロード クラスタの作成](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/2.2/using-tkg-22/workload-clusters-deploy.html)

このWorkload Clusterを、今回のTMC-SMのインストール対象とします。また、この後の手順でHarborの用意が必要ですが、Tanzu packagesを使ってK8sクラスタにHarborを導入する場合は、もう一つクラスタをデプロイしておくとよいでしょう。

私は、以下の2つのクラスタを用意しました。
```
$ tanzu cluster list
  NAME      NAMESPACE  STATUS   CONTROLPLANE  WORKERS  KUBERNETES        ROLES   PLAN  TKR
  shared    default    running  1/1           2/2      v1.25.7+vmware.2  <none>  dev   v1.25.7---vmware.2-tkg.1
  tmclocal  default    running  3/3           3/3      v1.25.7+vmware.2  <none>  dev   v1.25.7---vmware.2-tkg.1
```
sharedはharborを入れるために用意したクラスタであり、tmclocalがTMC-SM を入れるために用意したクラスタです。注意点として、tmclocalの方のクラスタには、要件を満たすためにノードサイズを`4 vCPU / 8GB mem`となるようカスタマイズしてクラスタを作成しましょう。

### DNSの用意
まずは、`DNSドメイン` と `DNSプロバイダ` を用意しましょう。

DNSドメインは、基本的にはレジストラ(ドメイン登録業者)から購入するのがオススメです。世界シェアだと[GoDaddy](https://jp.godaddy.com)が最もシェアが高く、日本だと[お名前.com](https://www.onamae.com/)が有名です([参考](https://nlog.jp/domein-ranking-global/))。.com(ドットコム)ドメインであれば、年間千数百円位でドメインを維持できます。ただし、DNSドメインについては特に制約がないので、一時的な利用であれば、[Freenom](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwiezcDZwJOAAxUeR2wGHdjcBqYQFnoECBkQAQ&url=https%3A%2F%2Fwww.freenom.com%2Fja%2Findex.html&usg=AOvVaw1r19GZ5FDrfJGMR1vnTJUY&opi=89978449) の無料ドメインを活用するのも良いでしょう。(※. 詳しい作り方は、Google先生に訪ねて下さい。)
DNSプロバイダについても特に制限はありませんが、オススメは `cert-manager` の [DNS01 Challenge](https://cert-manager.io/docs/configuration/acme/dns01/) に対応しているものを選ぶと、`パブリック証明書` を手軽に作成できて便利です。つまり、[Supported DNS01 providers](https://cert-manager.io/docs/configuration/acme/dns01/#supported-dns01-providers)に記載の以下のものがオススメです。

- ACMEDNS
- Akamai
- AzureDNS
- CloudFlare
- Google
- Route53
- DigitalOcean
- RFC2136

※. ここで注意点として、Freenom と CloudFlare の組み合わせは避けましょう。[既知のエラー](https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/#cloudflare-api-error-for-post-zonesiddns_records-generic-error)として、この組み合わせだとDNS 01 Challengeに失敗することが分かっています。

今回は、Freenomを使って取得した `vmwt.gq` ドメインを利用して、GoogleのCloud DNSをDNS Providerとして利用した例を紹介しようと思います。（なお、CloudDNSは、マネージド ゾーンあたり月額 0.20ドル、クエリ 100 万件ごとに 0.40ドル/月 位かかります。つまり、月に $0.6 ほど微課金してます。DigitalOceanあたりを使えば無料で済むかもしれないので、どなたか試して教えてもらえると助かります ^ ^）


[Configure a DNS Zone](https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/1.0/tanzumc-sm-install/prepare-cluster.html#configure-a-dns-zone-1)のところを見ると、用意すべきドメイン名一覧が掲載されています。このように多数のドメインを用意する必要がある場合、ワイルドカードサブドメイン（サブドメインのところを `*` で表記する）を利用することで、一括指定することができます。これを活用すると、DNS 登録する必要があるものは、以下の4パターンになります。

- (my-tmc-dns-zone)
- *.(my-tmc-dns-zone)
- s3.(my-tmc-dns-zone)
- *.s3.(my-tmc-dns-zone)

(my-tmc-dns-zone)のところは、厳密にはゾーンではなくサブドメインでも大丈夫です。私は`vmwt.gq`のDNSゾーンに作成する`tmclocal`というサブドメインをベースとして、以下の4つのDNSレコードを登録します。

- tmclocal.vmwt.gq
- *.tmclocal.vmwt.gq
- s3.tmclocal.vmwt.gq
- *.s3.tmclocal.vmwt.gq

次に、このドメインに向けるIPアドレスを決めます。基本的にはLoad BalancerのIPとして払い出されるVIPのレンジの中で未使用のIPを決め打ちで指定する形となります。このIPは外部に公開されないプライベートIPでも構いません。私は今回ALBを使用していて、VIPのレンジに`172.16.1.100-172.16.1.199`と設定しているため、この中で未使用であった`172.16.1.100`を使用することにしました。これを先ほどの4つのドメインの`Aレコード`として登録します。

以下、Google CloudDNSで登録する際のポイントを説明します。基本的にはどのDNSプロバイダでも同様のステップで登録するので、参考にして下さい。

1. Freenomで取得したDNS名(今回は`vmwt.gq`)を使ってDNSゾーンを作成。ゾーン名は何でも良い。
    ![スクリーンショット 2023-07-17 11.25.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/a01704ad-3177-3755-24b7-9540a40e173c.png)

1. 作成されたDNSゾーンのNSレコードに記載されたName Serverの値を取得する。(Google CloudDNSの場合は必ず `ns-cloud-c[1-4].googledomains.com.` の４つが記載されているはずです。)
    ![スクリーンショット 2023-07-17 11.32.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/a564c347-f9e9-12df-03d5-d84b18ce34c6.png)

1. DNSドメイン側で取得したNSレコードを登録します。Freenomの場合、以下のステップを行います。
    3-1. サインイン後、メニューから`Services` -> `My Domains`と辿り、`Manage Domain`をクリックして、ドメイン管理画面に移ります。
        ![スクリーンショット 2023-07-17 11.51.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/cf4c224b-a827-bdde-dc6c-14e3a85d83d2.png)
    3-2. 上部のタブで`Manage Freenom DNS`を選択すると、DNS管理画面に移るので、ここで`Edit Nameservers`をクリック
        ![スクリーンショット 2023-07-17 11.51.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/c3b9c822-e8fe-17b9-5215-6917a3c0523a.png)
    3-3. 先ほど取得したGoogle CloudDNSのNSサーバの値を入力して保存します。
        ![スクリーンショット 2023-07-17 11.50.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/7a0bc821-4fa2-6976-a0b6-f85c23539c86.png)
1. 再びCloudDNSに戻り、先ほどの4つのドメインとIPを利用して、4つのAレコードを登録します。
    ![スクリーンショット 2023-07-17 1.08.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/6bfef2bf-b8ce-80d4-ad0b-9bf133bf8be9.png)
1. 最終的に、以下の画像のように4つのドメインと指定したIPの組み合わせで登録されたら完了です。
![スクリーンショット 2023-07-17 1.07.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/698489a0-32b3-6943-c243-b45889db332c.png)

数分すると、全世界に登録したレコードが配信されるので、`nslookup`でチェックしてみましょう。
```
$ nslookup gts-rest.tmclocal.vmwt.gq
Server:		127.0.0.53
Address:	127.0.0.53#53

Non-authoritative answer:
Name:	gts-rest.tmclocal.vmwt.gq
Address: 172.16.1.100
```

また、Public証明書でHarborを用意したい場合は、ここでShared Cluster用のDNSも用意しましょう。
私の場合、空いていた`172.16.1.105`のIPを使うよう、以下のレコードを追加で登録しました。
- shared.vmwt.gq / 172.16.1.105
- *.shared.vmwt.gq / 172.16.1.105
- harbor.shared.vmwt.gq / 172.16.1.105
- *.harbor.shared.vmwt.gq / 172.16.1.105

### tanzu package CLI と cert-manager のセットアップ
次は、[Set up a cluster issuer for TLS certificates](https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/1.0/tanzumc-sm-install/prepare-cluster.html#set-up-a-cluster-issuer-for-tls-certificates-2)に記載の要件を満たすために、cert-managerをセットアップしていきます。Tanzu環境を使っているので、tanzu packageを使うのが良いでしょう。

[コチラ](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/2.2/using-tkg-22/workload-packages-ref.html) を参照しながら作業します。まずはtmclocalクラスタのkubeconfigを取得し、コンテキストを切り替えます
```
$ tanzu cluster kubeconfig get tmclocal --admin
Credentials of cluster 'shared' have been saved
You can now access the cluster by running 'kubectl config use-context tmclocal-admin@shared'

$ kubectl config use-context tmclocal-admin@shared
Switched to context "tmclocal-admin@shared".
```

次に、packageをインストールするためのnamespaceを用意します。名前は任意で構いませんが、ここでは`tanzu-packages`としました。
```
$ kubectl create ns tanzu-packages
namespace/tanzu-packages created
```

作成したnamespaceを指定して、tanzu-standard`レポジトリを登録します。
```
$ tanzu package repository add tanzu-standard --url projects.registry.vmware.com/tkg/packages/standard/repo:v2.2.0 --namespace tkg-system
(途中省略)
8:36:16AM: Deploy succeeded

$ tanzu package available list -A
  NAMESPACE   NAME                                          DISPLAY-NAME
  tkg-system  cert-manager.tanzu.vmware.com                 cert-manager
(以下、省略)
```
次は、[コチラ](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/2.2/using-tkg-22/workload-packages-cert-mgr.html)を参考にcert-managerをインストールします。これはサクッと入るはずです。
```
$ tanzu package available list cert-manager.tanzu.vmware.com -A
  NAMESPACE   NAME                           VERSION                RELEASED-AT
  tkg-system  cert-manager.tanzu.vmware.com  1.1.0+vmware.1-tkg.2   2020-11-24 18:00:00 +0000 UTC
  tkg-system  cert-manager.tanzu.vmware.com  1.1.0+vmware.2-tkg.1   2020-11-24 18:00:00 +0000 UTC
  tkg-system  cert-manager.tanzu.vmware.com  1.10.2+vmware.1-tkg.1  2023-01-11 12:00:00 +0000 UTC
(以下省略)
# 上記により、最新バージョンの値 (1.10.2+vmware.1-tkg.1) を確認

$ tanzu package install cert-manager -p cert-manager.tanzu.vmware.com -n tanzu-packages -v 1.10.2+vmware.1-tkg.1
(途中省略)
8:45:59AM: Deploy succeeded
```

ここからがちょっと特殊です。要件によると、`Regardless of which cluster issuer you choose, save the root CA certificate` 、つまり、`どのcluster issuerを選んでもroot CAを保存しておいて下さい`とあります。ここはドキュメントの指示に従い、Root CA(自己署名証明書)を用意して、[コチラ](https://cert-manager.io/docs/configuration/ca/)を見ながら`CA`のcluster issuer typeを発行します。

:::note warn
私は一度これを無視して、`DNS 01 Challenge`することで`Well-known CA`による信頼を得られるかなと思ってましたが、インストール後半で`authentication handshake failed`と出てしまい、失敗しました。TMC-SMコンポーネントの信頼を得られなかったようです。
:::

まずは、Root CAの用意です。`openssl`コマンドを使って適当な鍵を作ります。Subjectには最低限CN(Common Name)の指定が必要なので、今回のベースドメインを入れておくと良いでしょう。
```
$ openssl genrsa -out ca.key 4096
$ openssl req -x509 -new -nodes -sha512 -days 3650 -key ca.key -out ca.crt -subj "/CN=tmclocal.vmwt.gq"
```

これにより、`ca.key`と`ca.crt`ができたので、Secretに登録します。注意点として、cert-managerがインストールされたnamespace（標準では`cert-manager` namespace）に格納する必要があります。

```
$ B64KEY=`cat ca.key | base64 -w 0`
$ B64CRT=`cat ca.crt | base64 -w 0`
$ cat << EOF > ca-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: internal-ca
  namespace: cert-manager
data:
  tls.crt: $B64CRT
  tls.key: $B64KEY
EOF
```

このSecretを指定したClusterIssuerリソースを作成すれば、準備フェースは完了です。
```
cat << EOF | kubectl apply -f -
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: ca-issuer
  namespace: cert-manager
spec:
  ca:
    secretName: internal-ca
EOF
```

(パブリック証明書でTMC-SMを構築できた人がいれば、私にやり方を教えて下さいｗ)

### Harbor のセットアップ
HarborもTMC-SM用に用意するには一癖あります。最大の難関は、後のフェーズで出てくる`tmc-sm` というセットアップ用CLIで、HarborへのTLS認証が通った状態じゃないと、セットアップに失敗します。現時点ではSkip TLS verifyオプションも無いようです。これを回避するには、以下の2通りの選択肢が考えられます。
1. パブリック証明書でHarborがアクセス可能
1. HarborのRoot CAをクライアント側に設定

そして、現在Harborは、tanzu packageによってK8sにインストールする方法と、OVAによる提供の2種類が選択可能です。上記の要件を考えると、以下のユースケースで使い分けると良いでしょう。
1. tanzu package 版 Harbor (本番運用向き) : cert-managerと連携できるので、パブリック証明書の用意が楽で、証明書更新も自動でしてくれる
1. OVA Harbor (お試し向き) : 少ないリソースで手軽にセットアップしたい場合はこちら。証明書更新が手動なのと、クライアント毎にRoot CAを配布する必要があるのが悩みのタネ

今回は、前者のtanzu package版Harborのセットアップ方法を紹介します。OVA版Harborを使いたい場合は、[コチラ](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/2.2/tkg-deploy-mc-22/mgmt-reqs-prep-offline.html) を参照すると良いでしょう。

1. まずはsharedの方のクラスタのkubeconfigを取得して、コンテキストを切り替えます
    ```
    $ tanzu cluster kubeconfig get shared --admin
    Credentials of cluster 'shared' have been saved
    You can now access the cluster by running 'kubectl config use-context shared-admin@shared'
    
    $ kubectl config use-context shared-admin@shared
    Switched to context "shared-admin@shared".
    ```
1. 先ほどの`tanzu package CLI と cert-manager のセットアップ`を参考に、cert-managerのインストールまでを終わらせて下さい

ここで、パブリック証明書を発行するため、cert-managerを使って `DNS01 Challenge` を行う方法を紹介します。これは要は、`指定したDNSの名前引きにチャレンジして成功したら、ACME認証局と連動してそのDNS名を使った証明書を発行`する一連の作業を自動化してくれます。cert-managerがDNSレコードを操作するため、cert-managerにDNS providerの操作権限の一部を付与する必要があります。

今回は cert-manager の [google CloudDNS](https://cert-manager.io/docs/configuration/acme/dns01/google/) を参考に作業をしていきます。前提として、操作端末（今回はUbuntu VM）に`gcloud`コマンドを入れておきましょう。

1. まずは、CloudDNSの操作権限を持つ`gcloudのService Account`(※K8sのSAではない)を作成します。
    ```
    $ PROJECT_ID=(gcloudのproject ID)
    $ gcloud iam service-accounts create dns01-solver --display-name "dns01-solver"
    $ gcloud projects add-iam-policy-binding $PROJECT_ID \
   --member serviceAccount:dns01-solver@$PROJECT_ID.iam.gserviceaccount.com \
   --role roles/dns.admin
    $ gcloud iam service-accounts keys create key.json \
   --iam-account dns01-solver@$PROJECT_ID.iam.gserviceaccount.com
    ```
1. 上記により、gcloudの操作を行うための認証キー(key.json)が生成されたので、これをK8s Secretに格納します。注意点として、cert-manager namespaceに入れるようにしましょう。
    ```
    kubectl create secret generic clouddns-dns01-solver-sa \
   --from-file=key.json -n cert-manager
    ```
1. DNS01 Challenge用のClusterIssuerを作成します。上述のSecretを使うことで、CloudDNSへの操作が可能になります。
    ```
    $ cat cluster-issuer.yaml
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-prod
    spec:
      acme:
        server: https://acme-v02.api.letsencrypt.org/directory
        email: email@example.com
        privateKeySecretRef:
          name: letsencrypt-prod-account-key
        solvers:
        - dns01:
            cloudDNS:
              project: (あなたのproject ID)
              serviceAccountSecretRef:
                name: clouddns-dns01-solver-sa
                key: key.json

    $ k apply -f cluster-issuer.yaml
    clusterissuer.cert-manager.io/letsencrypt-prod created
    ```
1. Certificateリソースを用意して適用します。dnsNamesには複数のドメインが入れられるので、今回の対象DNS名を全て入れるようにしましょう。また、今回Harborをインストールする予定の`tanzu-system-registry`を作成し、そちらにCertificateを発行しましょう。
    ```
    $ kubectl create namespace tanzu-system-registry
    $ cat certificate.yaml
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: le-crt
      namespace: tanzu-system-registry
    spec:
      secretName: vmwt-gq-tls
      issuerRef:
        name: letsencrypt-prod
        kind: ClusterIssuer
      commonName: "*.shared.vmwt.gq"
      dnsNames:
      - "*.shared.vmwt.gq"
      - "*.harbor.shared.vmwt.gq"

    $ kubectl apply -f certificate.yaml
    ```
1. 適用後5−10分ほどして、certificateのReady状態がTrueとなればチャレンジ成功です。今回の場合、`vmwt-gq-tls` Secretに証明書が格納されます。これは、後述のHarborのインストール時に使用します。
    ```
    $ k get certificate
    NAME     READY   SECRET        AGE
    le-crt   True    vmwt-gq-tls   36m
    ```

次は、[コチラ](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/2.2/using-tkg-22/workload-packages-contour.html)を参考に、Contourをインストールしていきます。

1. ContourのVersionを取得。
    ```
    $ tanzu package available list -n tanzu-packages contour.tanzu.vmware.com
      NAME                      VERSION                RELEASED-AT
      contour.tanzu.vmware.com  1.23.5+vmware.1-tkg.1  2023-04-05 00:00:00 +0000 UTC
    ```
1. ドキュメントのvSphere向け構成例を参考にしながら、以下の様にカスタマイズ。ポイントは、`type: LoadBalancer`にするのと、`loadBalancerIP`に事前に用意したIPアドレスを指定することです。
    ```
    $ cat contour-data-values.yaml
    infrastructure_provider: vsphere
    namespace: tanzu-system-ingress
    loadBalancerIP: 172.16.1.105
    envoy:
      service:
        type: LoadBalancer
        externalTrafficPolicy: Cluster
        disableWait: false
      hostPorts:
        enable: true
        http: 80
        https: 443
      pspNames: null
    ```
1. Contourのインストール
    ```
    $ tanzu package install contour -p contour.tanzu.vmware.com -v 1.23.5+vmware.1-tkg.1 --values-file contour-data-values.yaml -n tanzu-packages
    (途中省略)
    3:47:53PM: Deploy succeeded
    ```

いよいよ、[コチラ](https://docs.vmware.com/jp/VMware-Tanzu-Kubernetes-Grid/2.2/using-tkg-22/workload-packages-harbor.html)を参考に、Haarborのインストールします。

1. Harborのバージョンを取得
    ```
    $ tanzu package available list harbor.tanzu.vmware.com -A
      NAMESPACE   NAME                     VERSION               RELEASED-AT
      (途中省略)
      tkg-system  harbor.tanzu.vmware.com  2.7.1+vmware.1-tkg.1  2021-09-28 06:05:00 +0000 UTC
    ```
1. Harbor設定用ファイル群を/tmp以下にダウンロード
    ```
    $ image_url=$(kubectl -n tkg-system get packages harbor.tanzu.vmware.com.2.7.1+vmware.1-tkg.1 -o jsonpath='{.spec.template.spec.fetch[0].imgpkgBundle.image}')
    $ imgpkg pull -b $image_url -o /tmp/harbor-package-2.7.1
    ```
1. パスワード生成スクリプトを実行。これにより、いくつかのパスワード設定が必要な項目に、ランダムなパスワードが注入されます。
    ```
    $ cd /tmp/harbor-package-v2.7.1_vmware.1-tkg.1/config/scripts
    $ bash generate-passwords.sh harbor-data-values.yaml
    ```
1. パラメータを編集
    ```
    $ vi harbor-data-values.yaml
    ```
    以下の項目をカスタマイズ。私は以下の項目を書き換えました。
    - hostname: harbor.shared.vmwt.gq (※あなたの用意したドメインを指定)
    - persistence.persistentVolumeClaim.registry.size: 50Gi (※10GBでは心許ないので。。)
    - harborAdminPassword: (※ここは頻繁に使うので、ランダムではなく覚えられるものに変えたい)
    - tlsCertificateSecretName: vmwt-gq-tls (※先程cert-managerで生成したSecret)
1. yqコマンドをインストールして、yqコマンドでコメント行を削除
    ```
    $ wget https://github.com/mikefarah/yq/releases/download/v4.34.1/yq_linux_amd64
    (途中省略)
    2023-07-08 15:44:22 (24.6 MB/s) - ‘yq_linux_amd64’ saved [8941568/8941568]

    $ sudo install yq_linux_amd64 /usr/local/bin/yq
    $ yq -i eval '... comments=""' harbor-data-values.yaml
    ```
1. Harborのインストール
    ```
    $ tanzu package install harbor -p harbor.tanzu.vmware.com -v 2.7.1+vmware.1-tkg.1 --values-file harbor-data-values.yaml -n tanzu-packages
    ```
1. FQDNが設定通りになっていて、とTLS SECRETがvalidになっていることを確認
    ```
    $ k get httpproxies.projectcontour.io -A
    NAMESPACE               NAME                      FQDN                           TLS SECRET   STATUS   STATUS DESCRIPTION
    tanzu-system-registry   harbor-httpproxy          harbor.shared.vmwt.gq          harbor-tls   valid    Valid HTTPProxy
    tanzu-system-registry   harbor-httpproxy-notary   notary.harbor.shared.vmwt.gq   harbor-tls   valid    Valid HTTPProxy
    ```

それでは実際にブラウザでアクセスしてみましょう。
ちゃんと鍵マークが出てパブリック証明書が表示できれば成功です。
（ToDo: スクショ後で取る）


最後に、今回TMC-SMのコンポーネント・イメージを設置するためのprojectの作成が必要です。今回は、project名を`tanzumc`としました。注意点として、Access Levelは必ず`Public`にしましょう。
![スクリーンショット 2023-07-09 23.39.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/d7a21132-73f2-f0b8-9484-f6a4a2638d7e.png)


### IDPの設定
次は、[Set up authentication](https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/1.0/tanzumc-sm-install/prepare-cluster.html#set-up-authentication-3)を見ながら、今回はOktaを使って要件を満たしながら作業を進めていきます。なお、Oktaは`Developer Edition`であれば、テスト用途で一部の機能を無料で使用することができ、TMC-SMの検証には充分な機能を備えています([参考](https://developer.okta.com/signup/))。


1. tmc:admin および tmc:member グループを作成
    ![スクリーンショット 2023-07-11 13.02.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/25393292-46b6-8f70-26e1-ae5439fd03a3.png)
1. 自分のユーザ作成して、をtmc:adminグループに追加
    ![スクリーンショット 2023-07-11 13.03.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/5ea1359b-3bb7-24a1-47dc-1a231fe20c5f.png)
1. OIDCクライアントアプリケーションを作成

アプリケーションの作成は、操作順に紹介します。
1. Create a new app integration
    - Sign-in methodをOIDCにする
    - ユーザーがusernameとpasswordをOIDC tokensと交換可能な、resource-owner password flowをサポートする形式を指定（※Oktaの場合、Native Applicationを選択)
    ![スクリーンショット 2023-07-11 15.17.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/f24d106a-8a94-d6d8-3dd1-5bee95fc8033.png)
1. New Navigate App Integration
    - APP名はなんでもよい
    - Grant typeに以下の権限が必要
        - authorization code
        - refresh token
        - resource owner password (※オプション。これはusernameとpasswordを使用してCLIでログインする場合にのみ必要。未選択時は、TMC CLIはログインを完了するためにブラウザを要求)
    - Sign-in redirect URIsを、前述のdnsZoneを用いて以下のようにする
        - https://pinniped-supervisor.tmclocal.vmwt.gq/provider/pinniped/callback
    - Assignments未指定だと怒られたので、一旦 Skip group assignment for nowを選択
    ![スクリーンショット 2023-07-11 15.37.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/3d107cd9-fa52-8275-4ffe-1e09f36c285a.png)
1. ApplicationのGeneral設定
    - Client authenticationは、Client secretにする必要がある。デフォでは None であったので、Editを押して変える。
    - 要件では追加認証にPKCEを要求する必要があるが、デフォでそうなっていた
    ![スクリーンショット 2023-07-11 15.42.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/e343be24-337e-12fa-e301-217c0d130cd1.png)
1. ApplicationのAssignment設定
    - 先ほど作成した2つのグループをAssignしてみた
    ![スクリーンショット 2023-07-11 15.50.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/5518f362-da12-f891-4878-dff413819ae6.png)

TMC-SMは、Pinnipedを使用するので、Pinippedの[Okta設定ガイド](https://github.com/vmware-tanzu/pinniped/blob/v0.20.0/site/content/docs/howto/configure-supervisor-with-okta.md#create-an-okta-application)も併せて見ると良いでしょう。

これで、一通りの準備は完了です！ここまでが大変長かった・・・。

# TMC-SMのインストール

ここからはやっと、[Installing Tanzu Mission Control Self-Managed](https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/1.0/tanzumc-sm-install/install-tmc-sm.html)のドキュメントを見て、進めることになります。


## インストールイメージの準備

[コチラ](https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/1.0/tanzumc-sm-install/install-tmc-sm.html#download-and-stage-the-installation-images-0)のガイドに沿って進めていきます。

ただし、本来は[Customer Connect](https://customerconnect.vmware.com/en/downloads/info/slug/infrastructure_operations_management/vmware_tanzu_mission_control_self_managed/1_0_0)にログインしてダウンロードしてくるのですが、[VMware Customer Connect CLI](https://github.com/vmware-labs/vmware-customer-connect-cli)というもの使うと、直接Linux端末に取得できます。一見ステップ数が多く見えますが、CLIの方が慣れると断然早いのでオススメです。今回はこちらでダウンロードしてみます。

### vmware-customer-connect-cli (vcc) のインストール

1. [Rereasesページ](https://github.com/vmware-labs/vmware-customer-connect-cli/releases)からlinux用最新版のURLを取得してダウンロード
    ```
    $ wget https://github.com/vmware-labs/vmware-customer-connect-cli/releases/download/v1.1.5/vcc-linux-v1.1.5
    ```
2. インストール
    ```
    $ sudo install vcc-linux-v1.1.5 /usr/local/bin/vcc
    ```
    これで、`vcc`コマンドが使えるようになりました。
3. Customer Connectにログインする際に使用するユーザ名とパスワードをセット。(※.bashrc等に格納しておくと、毎回実行しなくて良くなるので便利です。)
    ```
    export VCC_USER='email@email.com'
    export VCC_PASS='##'
    ```
### vcc を使って TMC-SM インストーラーをダウンロードする方法
1. productコードの取得: `vcc get products` ※. ただし、これだけだと全製品が一気に出力されるので、その製品を表す特徴的な文字列で`grep`してあげましょう。
    ```
    $ vcc get products | grep -i mission
    vmware_tanzu_mission_control_self_managed                            	VMware Tanzu Mission Control (Self-Managed)
    ```
2. sub productコードの取得: `vcc get subproducts -p (productコード)`
    ```
    $ vcc get subproducts -p vmware_tanzu_mission_control_self_managed
    SUB-PRODUCT CODE	DESCRIPTION
    tmc-sm          	Tanzu Mission Control Self-Managed
    ```
3. バージョンの取得: `vcc get versions -p (productコード) -s (subコード)`
    ```
    $ vcc get versions -p vmware_tanzu_mission_control_self_managed -s tmc-sm
    '1.0'
    ```
4. ダウンロードしたいファイル名の取得: `vcc get files -p (productコード) -s (subコード) -v (version)` ※. ここからは適切なCustomer Connect権限がないと表示されない
    ```
    $ vcc get files -p vmware_tanzu_mission_control_self_managed -s tmc-sm -v 1.0
    Logging in...
    Getting DLG Details

    Version:               1.0
    Eula Accepted:         false
    Eligable to Download:  true

    FILENAME                  	SIZE   	BUILD NUMBER	DESCRIPTION
    tmc-self-managed-1.0.0.tar	4.74 GB	            	Tanzu Mission Control Self-Managed 1.0
    ```
    Eula(エンドユーザライセンス)の同意状況やダウンロードする権限を持っているかどうかもここで分かります。
1. ダウンロード: `vcc download -p (productコード) -s (subコード) -v (version) -f (ファイル名) --accepteula`
    ```
    ~$ vcc download -p vmware_tanzu_mission_control_self_managed -s tmc-sm -v 1.0 -f tmc-self-managed-1.0.0.tar --accepteula
    (途中、省略)
    Download started to /home/ubuntu/vcc-downloads/tmc-self-managed-1.0.0.tar
    Downloading... 5.1 GB complete
    Download finished
    ```
    上述の通り、ホームディレクトリ以下に`vcc-downloads`フォルダが作成され、その中に対象ファイルがダウンロードされます。

## インストーラーの展開とイメージの設置
基本的にドキュメントに記載の通りに進みます。
1. ダウンロードしたファイルを展開
    ```
    $ mkdir tanzumc
    $ tar xf vcc-downloads/tmc-self-managed-1.0.0.tar -C ./tanzumc
    ```
1. Harborがパブリック証明書ではない場合(OVA Harborを使用している場合)、クライアントにRoot CAを設置してあげる必要があります。証明書のダウンロード方法は [コチラ](https://docs.vmware.com/jp/VMware-vSphere/7.0/vmware-vsphere-with-tanzu/GUID-F98E7DAF-7AFF-4E3F-AB98-A026236CE5C8.html)が参考になります。
    - 今回作成した`tanzumc` projectに進み、[リポジトリ] タブを選択し、[レジストリ証明書] をクリックして、`ca.crt`を取得
    - /etc/ssl/certs以下に設置
        ```
        cat ca.crt >> /etc/pki/tls/certs/ca-bundle.crt
        ```
1. `tmc-sm` CLIを使って、用意したHarborのprojectにTMC-SMのイメージ郡を設置。
    ```
    $ ./tmc-sm push-images harbor --project harbor1.vmwt.gq/tanzumc --username admin --password VMware1!
    INFO[0000] Pushing image                                 progress=1/77 uri=harbor1.vmwt.gq/tanzumc/498533941640.dkr.ecr.us-west-2.amazonaws.com/extensions/agent-updater/agent-updater
    INFO[0000] Pushing image                                 progress=5/77 uri=harbor1.vmwt.gq/tanzumc/498533941640.dkr.ecr.us-west-2.amazonaws.com/extensions/agent-updater/supervisor/manifest
    (途中省略)
    Image Staging Complete. Next Steps:
    (途中省略)
    Update TMC Self Managed Package Repository:
    Run: tanzu package repository add tanzu-mission-control-packages --url "harbor.shared.vmwt.gq/tanzumc/package-repository:1.0.0" --namespace tmc-local

    Create a values based on the TMC Self Managed Package Schema:
    View the Values Schema: tanzu package available get "tmc.tanzu.vmware.com/1.0.0" --namespace tmc-local --values-schema
    Create a Values file named values.yaml matching the schema

    Install the TMC Self Managed Package:
    Run: tanzu package install tanzu-mission-control -p tmc.tanzu.vmware.com --version "1.0.0" --values-file values.yaml --namespace tmc-local
    ```
    ご丁寧に、次の手順が記載されているので、コピペに便利です。

## TMC-SM package repositoryの登録
まずは、コンテキストを切り替えましょう
```
$ kubectl config use-context tmclocal-admin@shared
Switched to context "tmclocal-admin@shared".
```
ドキュメントの指示通りにnamespaceを作り、先ほどの出力からRepositoryのコマンドを貼りましょう。
```
$ kubectl create namespace tmc-local
$ tanzu package repository add tanzu-mission-control-packages --url "harbor.shared.vmwt.gq/tanzumc/package-repository:1.0.0" --namespace tmc-local
```

## values.yaml の用意
こちらは[ドキュメント内容](https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/1.0/tanzumc-sm-install/install-tmc-sm.html#create-a-valuesyaml-file-2)をコピペして使うのが良いでしょう。私は以下のファイルを準備しました。
```
$ cat tmc-default-values.yaml
harborProject: harbor.shared.vmwt.gq/tanzumc
dnsZone: tmclocal.vmwt.gq
clusterIssuer: ca-issuer
postgres:
  userPassword: VMware1!
minio:
  username: root
  password: VMware1!
contourEnvoy:
  serviceType: LoadBalancer
  serviceAnnotations:
    ako.vmware.com/load-balancer-ip: "172.16.1.100"
trustedCAs:
  local-ca.pem: |
    -----BEGIN CERTIFICATE-----
    MIIFFzCCAv+gAwIBAgIUebBHl0c/cl4le4Uwg5nTg7a7Tp4wDQYJKoZIhvcNAQEN
    (途中省略)
    nP2VdggPwgSIPAeBWA3FIGLCiXtHc3a5FzHSQpqDJgijF427zsM6K/TOHmY0EuiY
    snKMvkrNvqO9klk=
    -----END CERTIFICATE-----
oidc:
  issuerType: pinniped
  issuerURL: https://dev-(your ID).okta.com/oauth2/default
  clientID: (your clientID)
  clientSecret: (your clientsecret)
```

ここでのカスタマイズポイントは、以下の通りです。
- harborProject : 用意したharborのURLおよびプロジェクトを入力
- dnsZone : 用意したDNSゾーンを入力
- ca-issuer : cert-managerのインストールの際に用意したClusterIssuerの名前を入力します
- 各ミドルウェアのパスワード : ただの例なので、ちゃんと自分のものに置き換えましょうｗ
- contourEnvoy.serviceAnnotations : 上記のようなアノテーションを入れることで、DNS登録したIPアドレスを指定してインストールすることができます。
- trustedCAs.local-ca.pem: ここにはcert-managerのインストールの際にopensslコマンドで生成した`ca.crt`の内容を入力します。注意点として、`local-ca.pem:`の直後に`|(パイプ)`を入れるのと、次の行からは全ての行にインデントを入れるようにしましょう。
- oidc : 自分の使用しているIDP（今回はOkta）側に情報があるので、拾ってきましょう。

## TMC-SMのデプロイ
ついに、、ここまで来た！先ほどの`tmc-sm`コマンド出力をコピペ実行し、しばらく待つだけです。
```
tanzu package install tanzu-mission-control -p tmc.tanzu.vmware.com --version "1.0.0" --values-file values.yaml --namespace tmc-local
```

ここまでの全てのセットアップが正しければ、、うまくいくはずなので祈りましょうｗ
最終的に全てのReconcileが成功していることを確認しましょう。
```
$ tanzu package installed list -A
  NAMESPACE       NAME                                        PACKAGE-NAME                                        PACKAGE-VERSION                STATUS
  tanzu-packages  cert-manager                                cert-manager.tanzu.vmware.com                       1.10.2+vmware.1-tkg.1          Reconcile succeeded
  tkg-system      tmclocal-antrea                             antrea.tanzu.vmware.com                             1.9.0+vmware.2-tkg.1-advanced  Reconcile succeeded
  tkg-system      tmclocal-capabilities                       capabilities.tanzu.vmware.com                       0.29.0+vmware.1                Reconcile succeeded
  tkg-system      tmclocal-load-balancer-and-ingress-service  load-balancer-and-ingress-service.tanzu.vmware.com  1.9.3+vmware.1-tkg.1           Reconcile succeeded
  tkg-system      tmclocal-metrics-server                     metrics-server.tanzu.vmware.com                     0.6.2+vmware.1-tkg.2           Reconcile succeeded
  tkg-system      tmclocal-pinniped                           pinniped.tanzu.vmware.com                           0.12.1+vmware.3-tkg.4          Reconcile succeeded
  tkg-system      tmclocal-secretgen-controller               secretgen-controller.tanzu.vmware.com               0.11.2+vmware.1-tkg.3          Reconcile succeeded
  tkg-system      tmclocal-tkg-storageclass                   tkg-storageclass.tanzu.vmware.com                   0.29.0+vmware.1                Reconcile succeeded
  tkg-system      tmclocal-vsphere-cpi                        vsphere-cpi.tanzu.vmware.com                        1.25.1+vmware.2-tkg.1          Reconcile succeeded
  tkg-system      tmclocal-vsphere-csi                        vsphere-csi.tanzu.vmware.com                        2.7.1+vmware.2-tkg.1           Reconcile succeeded
  tmc-local       contour                                     contour.bitnami.com                                 12.1.0                         Reconcile succeeded
  tmc-local       kafka                                       kafka.bitnami.com                                   22.1.3                         Reconcile succeeded
  tmc-local       kafka-topic-controller                      kafka-topic-controller.tmc.tanzu.vmware.com         0.0.21                         Reconcile succeeded
  tmc-local       minio                                       minio.bitnami.com                                   12.6.4                         Reconcile succeeded
  tmc-local       pinniped                                    pinniped.bitnami.com                                1.2.1                          Reconcile succeeded
  tmc-local       postgres                                    tmc-local-postgres.tmc.tanzu.vmware.com             0.0.46                         Reconcile succeeded
  tmc-local       postgres-endpoint-controller                postgres-endpoint-controller.tmc.tanzu.vmware.com   0.1.43                         Reconcile succeeded
  tmc-local       s3-access-operator                          s3-access-operator.tmc.tanzu.vmware.com             0.1.22                         Reconcile succeeded
  tmc-local       tanzu-mission-control                       tmc.tanzu.vmware.com                                1.0.0                          Reconcile succeeded
  tmc-local       tmc-local-monitoring                        monitoring.tmc.tanzu.vmware.com                     0.0.13                         Reconcile succeeded
  tmc-local       tmc-local-stack                             tmc-local-stack.tmc.tanzu.vmware.com                0.0.17161                      Reconcile succeeded
  tmc-local       tmc-local-stack-secrets                     tmc-local-stack-secrets.tmc.tanzu.vmware.com        0.0.17161                      Reconcile succeeded
  tmc-local       tmc-local-support                           tmc-local-support.tmc.tanzu.vmware.com              0.0.17161                      Reconcile succeeded
```

ご参考までに、空のクラスタの状態から今回のインストールだけで、これだけの数のPodが入ります。
```
$ kubectl get pod -A
NAMESPACE              NAME                                                     READY   STATUS      RESTARTS         AGE
avi-system             ako-0                                                    1/1     Running     17 (36m ago)     35h
cert-manager           cert-manager-5ff8d848c7-hmdfz                            1/1     Running     6 (25h ago)      2d1h
cert-manager           cert-manager-cainjector-549d9b45fc-4vsgv                 1/1     Running     4 (28h ago)      2d1h
cert-manager           cert-manager-webhook-6b9cb465f9-fkxsb                    1/1     Running     0                2d1h
kube-system            antrea-agent-2fbg2                                       2/2     Running     0                35h
kube-system            antrea-agent-42swg                                       2/2     Running     0                35h
kube-system            antrea-agent-87hwf                                       2/2     Running     0                35h
kube-system            antrea-agent-dnl9x                                       2/2     Running     3 (28h ago)      35h
kube-system            antrea-agent-gmbvz                                       2/2     Running     0                35h
kube-system            antrea-agent-gvccd                                       2/2     Running     0                35h
kube-system            antrea-controller-78cdb465b-9sm8w                        1/1     Running     6 (3d22h ago)    4d10h
kube-system            coredns-5d4666ccfb-8cd2n                                 1/1     Running     3 (3d22h ago)    4d10h
kube-system            coredns-5d4666ccfb-hlm92                                 1/1     Running     3 (3d22h ago)    4d10h
kube-system            etcd-tmclocal-496jc-4wpsx                                1/1     Running     2 (29h ago)      4d4h
kube-system            etcd-tmclocal-496jc-7wt92                                1/1     Running     6 (2d9h ago)     4d3h
kube-system            etcd-tmclocal-496jc-9kmhd                                1/1     Running     3 (3d22h ago)    4d10h
kube-system            kube-apiserver-tmclocal-496jc-4wpsx                      1/1     Running     40 (28h ago)     4d4h
kube-system            kube-apiserver-tmclocal-496jc-7wt92                      1/1     Running     17 (28h ago)     4d3h
kube-system            kube-apiserver-tmclocal-496jc-9kmhd                      1/1     Running     20 (28h ago)     4d10h
kube-system            kube-controller-manager-tmclocal-496jc-4wpsx             1/1     Running     25 (28h ago)     4d4h
kube-system            kube-controller-manager-tmclocal-496jc-7wt92             1/1     Running     43 (28h ago)     4d3h
kube-system            kube-controller-manager-tmclocal-496jc-9kmhd             1/1     Running     50 (28h ago)     4d10h
kube-system            kube-proxy-288n9                                         1/1     Running     6 (2d9h ago)     4d3h
kube-system            kube-proxy-46ml5                                         1/1     Running     0                2d2h
kube-system            kube-proxy-8dprv                                         1/1     Running     0                2d1h
kube-system            kube-proxy-khbgq                                         1/1     Running     3 (29h ago)      4d4h
kube-system            kube-proxy-zv6hr                                         1/1     Running     3 (3d22h ago)    4d10h
kube-system            kube-proxy-zz7ld                                         1/1     Running     0                2d2h
kube-system            kube-scheduler-tmclocal-496jc-4wpsx                      1/1     Running     27 (28h ago)     4d4h
kube-system            kube-scheduler-tmclocal-496jc-7wt92                      1/1     Running     35 (28h ago)     4d3h
kube-system            kube-scheduler-tmclocal-496jc-9kmhd                      1/1     Running     43 (28h ago)     4d10h
kube-system            metrics-server-7bddc49fd4-rwkdr                          1/1     Running     0                2d1h
kube-system            vsphere-cloud-controller-manager-jndml                   1/1     Running     49 (28h ago)     4d10h
kube-system            vsphere-cloud-controller-manager-lvn7x                   1/1     Running     38 (28h ago)     4d3h
kube-system            vsphere-cloud-controller-manager-x7xmv                   1/1     Running     42 (28h ago)     4d3h
pinniped-concierge     pinniped-concierge-57c5b7cf49-qz58b                      1/1     Running     0                2d1h
pinniped-concierge     pinniped-concierge-57c5b7cf49-rx7hx                      1/1     Running     0                2d1h
pinniped-concierge     pinniped-concierge-kube-cert-agent-56b7bd5775-xwzbl      1/1     Running     6 (2d9h ago)     4d3h
secretgen-controller   secretgen-controller-588966758f-vg9zp                    1/1     Running     0                2d1h
tkg-system             kapp-controller-5f57bfdcd4-w52d8                         2/2     Running     12 (28h ago)     4d10h
tkg-system             tanzu-capabilities-controller-manager-7675999c7f-fwp8n   1/1     Running     5 (3d22h ago)    4d10h
tmc-local              account-manager-server-5995989889-4j9sx                  1/1     Running     0                4m1s
tmc-local              account-manager-server-5995989889-jjjw8                  1/1     Running     0                4m1s
tmc-local              agent-gateway-server-5944c89fc8-jfqjj                    1/1     Running     0                4m1s
tmc-local              agent-gateway-server-5944c89fc8-p8f2k                    1/1     Running     3 (2m41s ago)    4m1s
tmc-local              alertmanager-tmc-local-monitoring-tmc-local-0            2/2     Running     0                91s
tmc-local              api-gateway-server-67c47bd4d6-c24zl                      1/1     Running     3 (2m40s ago)    4m
tmc-local              api-gateway-server-67c47bd4d6-ggjp2                      1/1     Running     2 (2m53s ago)    4m
tmc-local              audit-service-consumer-5fb8875cc5-bgtn5                  1/1     Running     0                4m
tmc-local              audit-service-consumer-5fb8875cc5-vztjd                  1/1     Running     0                4m
tmc-local              audit-service-server-7d58c85744-7z7f5                    1/1     Running     0                4m
tmc-local              audit-service-server-7d58c85744-dzf8g                    1/1     Running     0                4m
tmc-local              auth-manager-server-d486f57f5-6bkh2                      1/1     Running     1 (3m6s ago)     4m1s
tmc-local              auth-manager-server-d486f57f5-pks5s                      1/1     Running     0                4m1s
tmc-local              auth-manager-server-d486f57f5-vjqm4                      1/1     Running     0                4m1s
tmc-local              authentication-server-74bc4fccb5-bv92f                   1/1     Running     0                3m59s
tmc-local              authentication-server-74bc4fccb5-z9rp6                   1/1     Running     0                3m59s
tmc-local              cluster-agent-service-server-7858768c68-4ksbl            1/1     Running     0                3m59s
tmc-local              cluster-agent-service-server-7858768c68-tzxhn            1/1     Running     0                3m59s
tmc-local              cluster-config-server-bbddd8777-6xxbz                    1/1     Running     0                3m59s
tmc-local              cluster-config-server-bbddd8777-dwtcg                    1/1     Running     0                3m59s
tmc-local              cluster-object-service-server-88bcf8884-77whz            1/1     Running     0                3m59s
tmc-local              cluster-object-service-server-88bcf8884-8cxwf            1/1     Running     0                3m59s
tmc-local              cluster-reaper-server-64f65ccf6-jjdq2                    1/1     Running     0                3m59s
tmc-local              cluster-secret-server-777f6f9bbd-r5dqc                   1/1     Running     0                3m59s
tmc-local              cluster-secret-server-777f6f9bbd-v8s8v                   1/1     Running     0                3m58s
tmc-local              cluster-service-server-6479879749-j547m                  1/1     Running     0                3m57s
tmc-local              cluster-service-server-6479879749-tmztw                  1/1     Running     0                3m57s
tmc-local              cluster-sync-egest-5bd9dd7768-ctlds                      1/1     Running     0                3m57s
tmc-local              cluster-sync-egest-5bd9dd7768-jlkmx                      1/1     Running     0                3m57s
tmc-local              cluster-sync-ingest-5bcf6d478-2nvch                      1/1     Running     0                3m57s
tmc-local              cluster-sync-ingest-5bcf6d478-8sz4t                      1/1     Running     0                3m57s
tmc-local              contour-contour-5989d4bc59-cnkgx                         1/1     Running     0                5m59s
tmc-local              contour-contour-certgen-r6s4l                            0/1     Completed   0                5m59s
tmc-local              contour-envoy-5c5xf                                      2/2     Running     0                5m59s
tmc-local              contour-envoy-5jxd6                                      2/2     Running     0                5m59s
tmc-local              contour-envoy-wcz8g                                      2/2     Running     0                5m59s
tmc-local              dataprotection-server-6785bbfb86-p57cd                   1/1     Running     0                3m56s
tmc-local              dataprotection-server-6785bbfb86-s99dx                   1/1     Running     0                3m56s
tmc-local              events-service-consumer-5d9b759fb9-2qcd8                 1/1     Running     0                3m56s
tmc-local              events-service-consumer-5d9b759fb9-dh6hx                 1/1     Running     0                3m57s
tmc-local              events-service-server-598cdf45fc-6vtw4                   1/1     Running     0                3m56s
tmc-local              events-service-server-598cdf45fc-7j852                   1/1     Running     0                3m56s
tmc-local              fanout-service-server-7fcf8444db-g27d7                   1/1     Running     0                3m56s
tmc-local              fanout-service-server-7fcf8444db-k6858                   1/1     Running     0                3m56s
tmc-local              feature-flag-service-server-98b5584c5-v5nsh              1/1     Running     0                3m56s
tmc-local              inspection-server-78bdfdcdf-8splg                        2/2     Running     0                3m55s
tmc-local              inspection-server-78bdfdcdf-jlptc                        2/2     Running     0                3m55s
tmc-local              intent-server-5895db94c9-p7kz9                           1/1     Running     0                3m55s
tmc-local              intent-server-5895db94c9-x78ln                           1/1     Running     0                3m55s
tmc-local              kafka-0                                                  1/1     Running     0                4m44s
tmc-local              kafka-exporter-f5cf87857-gqjwb                           1/1     Running     3 (4m9s ago)     4m44s
tmc-local              kafka-topic-controller-7d7945bd4f-mlhb4                  1/1     Running     0                5m14s
tmc-local              landing-service-server-74475dfb77-xpnkk                  1/1     Running     0                4m1s
tmc-local              minio-b5c9774fd-rvfsd                                    1/1     Running     0                5m29s
tmc-local              minio-provisioning-kxwmw                                 0/1     Completed   0                5m29s
tmc-local              onboarding-service-server-57cd48d498-7m5gc               1/1     Running     0                3m55s
tmc-local              onboarding-service-server-57cd48d498-jrjzw               1/1     Running     0                3m55s
tmc-local              package-deployment-server-6bdd7dfbcc-5r7x2               1/1     Running     0                3m55s
tmc-local              package-deployment-server-6bdd7dfbcc-kmndl               1/1     Running     0                3m55s
tmc-local              pinniped-supervisor-7c8c8bdccc-jwf2w                     1/1     Running     0                5m32s
tmc-local              policy-engine-server-74667d8474-qdfjc                    1/1     Running     0                3m54s
tmc-local              policy-engine-server-74667d8474-rjpmb                    1/1     Running     0                3m54s
tmc-local              policy-insights-server-54fbbf9589-tjvdd                  1/1     Running     0                3m54s
tmc-local              policy-sync-service-server-7fb498dc9f-q9v4w              1/1     Running     0                3m54s
tmc-local              policy-view-service-server-7dcc456757-578d5              1/1     Running     0                3m53s
tmc-local              policy-view-service-server-7dcc456757-nx4d5              1/1     Running     0                3m53s
tmc-local              postgres-endpoint-controller-fb46fffcf-lznpq             1/1     Running     0                4m25s
tmc-local              postgres-postgresql-0                                    2/2     Running     0                5m30s
tmc-local              prometheus-server-tmc-local-monitoring-tmc-local-0       2/2     Running     0                91s
tmc-local              provisioner-service-server-b445dc684-4ktj6               1/1     Running     0                3m53s
tmc-local              provisioner-service-server-b445dc684-bc6f8               1/1     Running     0                3m53s
tmc-local              resource-manager-server-55fd85fd-6x6ft                   1/1     Running     0                3m53s
tmc-local              resource-manager-server-55fd85fd-wr5mr                   1/1     Running     1 (2m15s ago)    3m53s
tmc-local              s3-access-operator-c58fc5c74-jvnq2                       1/1     Running     0                4m27s
tmc-local              schema-service-schema-server-c8c98584d-4sttr             1/1     Running     0                3m53s
tmc-local              telemetry-event-service-consumer-9bf489c5c-mh64f         1/1     Running     0                3m53s
tmc-local              telemetry-event-service-consumer-9bf489c5c-n7qh9         1/1     Running     0                3m53s
tmc-local              tenancy-service-server-6f88bf5b7d-xzqbm                  1/1     Running     0                4m1s
tmc-local              ui-server-54c5986597-6xsqj                               1/1     Running     0                3m52s
tmc-local              ui-server-54c5986597-8c8dx                               1/1     Running     0                3m52s
tmc-local              wcm-server-565b996f56-hdhwb                              1/1     Running     0                3m52s
tmc-local              wcm-server-565b996f56-k4gws                              1/1     Running     0                3m52s
vmware-system-csi      vsphere-csi-controller-68c8c9679-n4rnq                   7/7     Running     61 (28h ago)     2d6h
vmware-system-csi      vsphere-csi-controller-68c8c9679-wjrng                   7/7     Running     44 (28h ago)     2d8h
vmware-system-csi      vsphere-csi-controller-68c8c9679-xwr8b                   7/7     Running     231 (28h ago)    4d10h
vmware-system-csi      vsphere-csi-node-26kjt                                   3/3     Running     12 (3d22h ago)   4d4h
vmware-system-csi      vsphere-csi-node-89l8f                                   3/3     Running     0                2d1h
vmware-system-csi      vsphere-csi-node-8jgdf                                   3/3     Running     0                2d2h
vmware-system-csi      vsphere-csi-node-9nxzh                                   3/3     Running     12 (28h ago)     4d4h
vmware-system-csi      vsphere-csi-node-rdtl6                                   3/3     Running     32 (2d2h ago)    4d3h
vmware-system-csi      vsphere-csi-node-vft5w                                   3/3     Running     0                2d2h

$ kubectl get pod -A | wc -l
     133
```
最初の行はヘッダなので、1パッケージのみが入ったクラスタで132Podが活動しているのは凄いなぁ・・

## TMC-SMへのログイン
それではお待ちかねの、、動作確認！
今回用意した、http://tmc-local.vmwt.gq にアクセスしてみます。
※. ローカルネットワークに展開しているため、皆さんはこのURLにアクセスしても見ることはできませんよ
![スクリーンショット 2023-07-14 19.05.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/47d82d12-c41a-3803-3049-d31f24d08af7.png)

おぉ、こんな感じのログイン画面なのか。「SIGN IN」を押してみると、Oktaの画面に遷移されるので、用意したユーザ/パスワードを入力します。
![スクリーンショット 2023-07-16 15.59.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/72ee5d9f-98a6-64bd-b9f2-fbf1cc70c8d2.png)

サインインを押すと・・・、おぉぉ、ついに初期画面に辿り着いた！感動(T T)
![スクリーンショット 2023-07-16 15.57.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/7b57c340-1361-78b7-e3af-d731ea695de5.png)

いやぁ、なかなかここまで来る大変だった。。お疲れ様でした！

## おまけ：トラブルシューティング

上記までは、最終的にうまくいったケースを紹介しているので、この通りにやればすんなりいくはずですが、ここに来るまでに2つの大きな問題にハマりました。

### 問題 その1
cert-managerのところでも少し触れていますが、well-known CAでは行けなかった問題。
最初はDNS01 ChallengeでClusterIssuerを用意したのですが、その後インストールを進めると、
tmc-local-stackでスタックしましたｗ
```
$ tanzu package installed list -A | grep failed
  tmc-local       tanzu-mission-control                       tmc.tanzu.vmware.com                                1.0.0                          Reconcile failed
  tmc-local       tmc-local-stack                             tmc-local-stack.tmc.tanzu.vmware.com                0.0.17161                      Reconcile failed
```

その時のPod状況: CrashLoopBackOff してはる。。
```
 k get pod -A | grep -v Running | grep -v Completed
NAMESPACE              NAME                                                     READY   STATUS             RESTARTS         AGE
tmc-local              agent-gateway-server-7886cb48ff-6prhr                    0/1     CrashLoopBackOff   52 (2m35s ago)   4h5m
tmc-local              agent-gateway-server-7886cb48ff-9n46z                    0/1     CrashLoopBackOff   51 (106s ago)    4h6m
tmc-local              api-gateway-server-77dd895755-56qsb                      0/1     CrashLoopBackOff   58 (4s ago)      4h37m
tmc-local              api-gateway-server-77dd895755-sknr9                      0/1     CrashLoopBackOff   53 (111s ago)    4h37m
tmc-local              landing-service-server-685dbd6ddb-tt277                  0/1     CrashLoopBackOff   23 (97s ago)     97m
tmc-local              policy-insights-server-7fdf6c58dd-wmp9h                  0/1     CrashLoopBackOff   54 (115s ago)    4h37m
tmc-local              tenancy-service-server-f88f4c447-8ztlk                   0/1     CrashLoopBackOff   57 (113s ago)    4h37m
```

これらのログを見ると、大体こんな感じの`authentication handshake failed` が出ていた
```
$ k logs -n tmc-local agent-gateway-server-6c58845f89-2dmp7
(snip)
time="2023-07-12T09:08:35Z" level=warning msg="[core] [Channel #17 SubChannel #19] grpc: addrConn.createTransport failed to connect to {\n  \"Addr\": \"gts.tmclocal.vmwt.gq:443\",\n  \"ServerName\": \"gts.tmclocal.vmwt.gq:443\",\n  \"Attributes\": null,\n  \"BalancerAttributes\": null,\n  \"Type\": 0,\n  \"Metadata\": null\n}. Err: connection error: desc = \"transport: authentication handshake failed: read tcp 100.96.3.48:38166->172.16.1.100:443: read: connection reset by peer\"" subcomponent=grpc-runtime
{"error":"rpc error: code = Unavailable desc = last connection error: connection error: desc = \"transport: authentication handshake failed: read tcp 100.96.3.48:38166-\u003e172.16.1.100:443: read: connection reset by peer\"","level":"error","msg":"failed to list org information","time":"2023-07-12T09:08:35Z"}
{"error":"rpc error: code = Unavailable desc = last connection error: connection error: desc = \"transport: authentication handshake failed: read tcp 100.96.3.48:38166-\u003e172.16.1.100:443: read: connection reset by peer\"","level":"error","msg":"could not load org cache.","time":"2023-07-12T09:08:35Z"}
{"level":"fatal","msg":"Failed to initialize server with err : rpc error: code = Unavailable desc = last connection error: connection error: desc = \"transport: authentication handshake failed: read tcp 100.96.3.48:38166-\u003e172.16.1.100:443: read: connection reset by peer\"","time":"2023-07-12T09:08:35Z"}
```

その後、自己署名証明書の方式でやったら、うまくいきました

### 問題 その2
こちらが本当に厄介でした。
その後インストールが成功し、ログインを試みると、Okta認証でユーザ/パスワードを入力した後で・・・
![スクリーンショット 2023-07-15 14.44.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18601/b63c2974-f3fe-8e98-2d99-57626c85f745.png)
こんな感じの残念な画面が出て、初期画面に辿り着きませんでした。
Okta周りの設定が怪しいと思ったのですが、いくらパラメータを変えても効果がありません。
識者に相談した結果、以下の状態であることが分かりました。

- 症状 : 不完全な状態で一度インストールされると、`tanzu package installed delete`しても、何らかの間違った設定が残ってしまうことがある。(SecretかPVあたりが怪しいが、詳細には調査していない)
- 原因 : 恐らく問題その１が発生したタイミングで変な設定が残った？
- 対処法 : PVとnamespaceを一度完全に削除してからリトライすることで、全く設定を変えずに再インストールしたら、今度はログインに成功しました。namespaceの削除は盲点でした。

# あとがき
なかなかの大作を書いてしまった。。もしこの記事が役立ったら、コメントいただけると励みになります！