CluasterAPI：Management Clusterの構築

執筆日: 2023/04/05

# はじめに

- 構築する環境情報は以下を参照。
  [ClusterAPIによるKubernetesクラスタの操作](https://qiita.com/kikutak/private/b39c271c6eb2c9a3e525)

- 下図の赤枠内を構築する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633524/fe0bac8f-1a7e-9af4-16ff-530a10f83fe2.png)


- 本記事ではVM clusterapiにシングルノードkubernetesクラスタを構築し、その上でClusterAPI Podを動作させるところまで記載する。
- [Cluster API公式ページのQuick Start](https://cluster-api.sigs.k8s.io/user/quick-start.html)を参考に構築する。

# 環境

- Management Clusterをインストールする環境は以下の通り
  | 諸元 | パラメータ |
  |------|------------|
  | cpu | 2コア |
  | メモリ | 4GB |
  | disk | 20GB |
  | OS | Ubuntu 20.04.6 LTS |

# Management Cluster構築

- シングルノードkubernetesを構築します。本記事では公式ドキュメントに従って以下をVM clusterapiにインストールします。
    - kubectl
    - kind
    - docker
    - helm
- 以下の手順は全てclusterapiで行います。

## 必要パッケージインストール

### kubectl インストール

- 参考 https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/
- kubernetesのaptリポジトリをaptのソースリストに追加します。

    ```shell-session
    $ sudo apt-get update
    $ sudo apt-get install -y ca-certificates curl
    $ sudo mkdir -m 0755 -p /etc/apt/keyrings
    $ sudo curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
    $ echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
    ```

- kubectlをインストールします。
    ```shell-session
    $ sudo apt-get update
    $ sudo apt-get install -y kubectl
    $ kubectl version --client
    WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short.  Use --output=yaml|json to get the full version.
    Client Version: version.Info{Major:"1", Minor:"26", GitVersion:"v1.26.3", GitCommit:"9e644106593f3f4aa98f8a84b23db5fa378900bd", GitTreeState:"clean", BuildDate:"2023-03-15T13:40:17Z", GoVersion:"go1.19.7", Compiler:"gc", Platform:"linux/amd64"}
    Kustomize Version: v4.5.7
    ```
  - `WARNING`が出力されますが、コマンドの移行期によるエラーであり気にする必要はありません。いずれ`--short`オプションの出力がデフォルトになります。ちなみに`--short`オプションを指定すると`WARNING`ではないものの`--short`オプションも将来的に削除予定であることを知らせるメッセージが表示されます。(2023/04/06時点)
    ```shell-session
    $ kubectl version --client --short
    Flag --short has been deprecated, and will be removed in the future. The --short output will become the default.
    Client Version: v1.26.3
    Kustomize Version: v4.5.7
    ```

### Docker インストール

- 参考 https://docs.docker.com/engine/install/debian/
- Docker Engineをインストールします。（Docker Desktopではない）
- Dockerのaptリポジトリをaptのソースリストに追加します。
    ```shell-session
    $ sudo apt-get update
    $ sudo apt-get install \
        ca-certificates \
        curl \
        gnupg
    $ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    $ echo \
      "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
      "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
      sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    ```
- Dockerをインストールします。
    ```shell-session
    $ sudo apt-get update
    $ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    $ sudo docker run hello-world
    ```

### Kindインストール

- 参考 https://kind.sigs.k8s.io/docs/user/quick-start/#installation
- kindはバイナリをダウンロードして/usr/local/binに置くだけです。
    ```shell-session
    $ curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.17.0/kind-linux-amd64
    $ chmod +x ./kind
    $ sudo mv ./kind /usr/local/bin/kind
    ```

### Helmインストール

- 参考 https://helm.sh/docs/intro/install/
- helmはバイナリをダウンロード、解凍、インストールしてくれるスクリプトを実行します。
    - /usr/local/binにhelmをインストールしてくれます。
    - インストールが終わったらインストールスクリプトは用済みなので消してしまいます。
    ```shell-session
    $ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
    $ chmod 700 get_helm.sh
    $ ./get_helm.sh
    Downloading https://get.helm.sh/helm-v3.11.2-linux-amd64.tar.gz
    Verifying checksum... Done.
    Preparing to install helm into /usr/local/bin
    helm installed into /usr/local/bin/helm
    $ rm get_helm.sh
    ```

## Management Cluster構築
- 参考 https://cluster-api.sigs.k8s.io/user/quick-start.html
- Management Clusterを構築するため、以下を実施します。
    - kindでシングルノードkubernetesクラスタを構築する。
    - clusterctlをインストールする。
    - ClusterAPIとBYOHをインストールする。

### kindでシングルノードkubernetesクラスタを構築

- ClusterAPIのPodを配置するkubernetesクラスタを構築します。5分くらいでできます。
    ```shell-session
    $ sudo kind create cluster -n management-cluster
    ```
    - `-n` 指定しなくても良いですが、その場合クラスタ名は`kind`になります。

- できたクラスタを確認します。
    - 指定した名前`management-cluster`という名前のクラスタが出来ています。

    ```shell-session
    $ sudo kind get clusters
    management-cluster
    ```

    - kubeconfigは/root/.kube/configにあるのでクラスタ名を確認します。`kind-management-cluster`という名前で作成されています。
    ```shell-session
    $ sudo cat /root/.kube/config
    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority-data: 
        ...
        server: https://127.0.0.1:38347
      name: kind-management-cluster
    contexts:
    - context:
        cluster: kind-management-cluster
        user: kind-management-cluster
      name: kind-management-cluster
    current-context: kind-management-cluster
    kind: Config
    preferences: {}
    users:
    - name: kind-management-cluster
      user:
        client-certificate-data: 
        ...
        client-key-data: 
        ...
    ```
    - クラスタ`kind-management-cluster`が起動していることを確認します。

    ```shell-session
    $ sudo kubectl cluster-info --context kind-management-cluster
    Kubernetes control plane is running at https://127.0.0.1:38347
    CoreDNS is running at https://127.0.0.1:38347/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
    
    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
    ```

    - いちいちsudoするのが面倒くさいのでエイリアスを書いてしまいます。`~/.bash_aliases`に書いておけば.bashrcに読み込み時に参照してくれます。
    ```shell-session 
    $ kubectl get node
    E0329 14:33:07.032459   51327 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
    E0329 14:33:07.033005   51327 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
    E0329 14:33:07.034627   51327 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
    E0329 14:33:07.035707   51327 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
    E0329 14:33:07.037226   51327 memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
    The connection to the server localhost:8080 was refused - did you specify the right host or port?
    $ echo "alias kubectl='sudo kubectl'" >> ~/.bash_aliases
    $ source .bashrc
    $ kubectl get node
    NAME                               STATUS   ROLES           AGE   VERSION
    management-cluster-control-plane   Ready    control-plane   11m   v1.25.3
    ```

### clusterctlをインストール

- clusterctlはManagement ClusterのLifeCycleManagement（LCM）のためのCLIツールです。このコマンドでClusterAPIを構築します。
- clusterctlのインストールはバイナリをダウンロードして`/usr/local/bin`に配置するだけです。
    ```shell-session
    $ curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.3.5/clusterctl-linux-amd64 -o clusterctl
    $ sudo install -o root -g root -m 0755 clusterctl /usr/local/bin/clusterctl
    $ clusterctl version
    clusterctl version: &version.Info{Major:"1", Minor:"3", GitVersion:"v1.3.5", GitCommit:"58770484dee6c99c10e32c06652e9f9643f78e9e", GitTreeState:"clean", BuildDate:"2023-03-02T15:57:13Z", GoVersion:"go1.19.6", Compiler:"gc", Platform:"linux/amd64"}
    ```

### Management Clusterを初期化

- 参考　https://github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/blob/main/docs/getting_started.md
- 作成したクラスタにClusterAPIをインストールします。その際にプロバイダとしてBringYourOwnHost(BYOH)を併せてインストールします。
- BYOHは自身で作成したVM上にWorkload Clusterを構築するために使います。
- `clusterctl init`でシングルノードkubernetesクラスタにMangement Clusterを構築します。
    ```shell-session
    $ sudo clusterctl init --infrastructure=byoh --kubeconfig=/root/.kube/config
    Fetching providers
    Installing cert-manager Version="v1.11.0"
    Waiting for cert-manager to be available...
    Installing Provider="cluster-api" Version="v1.4.0" TargetNamespace="capi-system"
    Installing Provider="bootstrap-kubeadm" Version="v1.4.0" TargetNamespace="capi-kubeadm-bootstrap-system"
    Installing Provider="control-plane-kubeadm" Version="v1.4.0" TargetNamespace="capi-kubeadm-control-plane-system"
    Installing Provider="infrastructure-byoh" Version="v0.3.1" TargetNamespace="byoh-system"
    
    Your management cluster has been initialized successfully!
    
    You can now create your first workload cluster by running the following:
    
      clusterctl generate cluster [name] --kubernetes-version [version] | kubectl apply -f -
    ```
- 以下のコマンドでClusterAPIとBYOHのpodが起動していることを確認できます。
    ```shell-session
    $ kubectl get pod -A | grep -e capi -e byo
    byoh-system                         byoh-controller-manager-7978cfc6cc-wrqz4                         2/2     Running   1 (7h53m ago)   16h
    capi-kubeadm-bootstrap-system       capi-kubeadm-bootstrap-controller-manager-8654485994-cxd85       1/1     Running   0               16h
    capi-kubeadm-control-plane-system   capi-kubeadm-control-plane-controller-manager-5d9d9494d5-mw8q6   1/1     Running   0               16h
    capi-system                         capi-controller-manager-746b4f5db4-79d8f                         1/1     Running   0               16h
    ```
- ここまでの構築状況を図示すると以下のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633524/993c0ab9-5c55-1d07-4045-3b7775d9693e.png)

# まとめ

- 今回はManagement Clusterを構築しました。
- 次回はWorkload Clusterを構築するVMをManagement Clusterに登録し、構築していきます。