Cluster API の Docker Provider を利用する

# 目的

Cluster API は、複数の Kubernetes クラスターのプロビジョニング、アップグレード、運用を簡素化するための宣言型 API とツールの提供に重点を置いた Kubernetes サブプロジェクトである。
詳しい Cluster API の概要は公式ドキュメントや下記の記事を参照するとよい。

- [Kubernetes Cluster API](https://cluster-api.sigs.k8s.io/introduction.html)
- [ClusterAPIによるKubernetesクラスタの操作](https://qiita.com/kikutak/items/b39c271c6eb2c9a3e525)

Cluster API はプラットフォーム毎に用意された Provider という機構を使うことでプラットフォームの差分を吸収し、Kubernetes クラスタを構築できる。
ここでは Provider の 1 つとして Docker を利用する。
Docker Provider は運用環境での使用を目的として設計されておらず、開発環境のみを対象としている。
しかし、使用可能な Provider の中では比較的事前準備が少なく動作する。
そのため、Cluster API を初めて触る人にとって最も取り組みやすい Provider の 1 つであると考えている。

今回は 1 つのマシン上に必要なソフトウェアをすべてインストールし、Cluster API の Docker Provider を動作させる。
インストール手順は下記を参考にする。

- [The Cluster API Book Quick Start](https://cluster-api.sigs.k8s.io/user/quick-start.html#quick-start)

# 構成

下記のマシンを 1 台準備する。

- Disk: 50GB
- Cores: 2 core
- Memory: 4GB
- OS: Ubuntu 20.04

# 手順

## Docker

Docker をインストールする。

```
sudo apt install docker.io -y
```

一般ユーザが Docker を操作できるようにするため、一般ユーザを docker グループに追加し、再度ログインする。

```
sudo usermod -a -G docker <username>
exit
```

## kubectl

kubectl をインストールする。

```
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
sudo apt install -y kubectl
```

## kind

kind をインストールする。
インストールした kind は Management Cluster として利用する。

```
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.19.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
```

Docker Provider がホスト上の Docker にアクセスできるようにするための種類の構成ファイルを作成する。

```
cat << _EOF_ > kind-cluster-with-extramounts.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraMounts:
    - hostPath: /var/run/docker.sock
      containerPath: /var/run/docker.sock
_EOF_
```

Kubernetes Cluster を作成する。

```
kind create cluster --config kind-cluster-with-extramounts.yaml
```

作成された Kubernetes Cluster の動作を確認する。

```
$ kubectl get pod -A
NAMESPACE            NAME                                         READY   STATUS    RESTARTS   AGE
kube-system          coredns-5d78c9869d-rkcwg                     1/1     Running   0          8s
kube-system          coredns-5d78c9869d-z6zj2                     1/1     Running   0          8s
kube-system          etcd-kind-control-plane                      1/1     Running   0          20s
kube-system          kindnet-ggj6z                                1/1     Running   0          8s
kube-system          kube-apiserver-kind-control-plane            1/1     Running   0          20s
kube-system          kube-controller-manager-kind-control-plane   1/1     Running   0          20s
kube-system          kube-proxy-cdf4z                             1/1     Running   0          8s
kube-system          kube-scheduler-kind-control-plane            1/1     Running   0          22s
local-path-storage   local-path-provisioner-6bc4bddd6b-fklmj      1/1     Running   0          8s
```

## clusterctl

clusterctl をインストールする。
clusterctl は Management Cluster のライフサイクルを処理できる。

```
curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.4.2/clusterctl-linux-amd64 -o clusterctl
chmod +x ./clusterctl
sudo mv ./clusterctl /usr/local/bin/clusterctl
```

## Management Cluster

### 初期化

Feature Gates (アルファステータスの機能) を有効化する。

```
export CLUSTER_TOPOLOGY=true
```

Management Cluster を初期化する。

```
$  clusterctl init --infrastructure docker
Fetching providers
Installing cert-manager Version="v1.11.1"
Waiting for cert-manager to be available...
Installing Provider="cluster-api" Version="v1.4.2" TargetNamespace="capi-system"
Installing Provider="bootstrap-kubeadm" Version="v1.4.2" TargetNamespace="capi-kubeadm-bootstrap-system"
Installing Provider="control-plane-kubeadm" Version="v1.4.2" TargetNamespace="capi-kubeadm-control-plane-system"
Installing Provider="infrastructure-docker" Version="v1.4.2" TargetNamespace="capd-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 -
```

### 環境変数の設定

通常の動作を試すのみであれば、特に設定する必要はないが、自身の環境に応じて変更する。

Docker Provider では、特別なネットワーク設定が必要な場合に次の環境変数を設定できる。

```
# The list of service CIDR, default ["10.128.0.0/12"]
export SERVICE_CIDR=["10.96.0.0/12"]

# The list of pod CIDR, default ["192.168.0.0/16"]
export POD_CIDR=["192.168.0.0/16"]

# The service domain, default "cluster.local"
export SERVICE_DOMAIN="k8s.test"
```

デフォルトで有効になっている Pod Security Standard を無効にすることも可能だが、推奨されない。

```
export ENABLE_POD_SECURITY_STANDARD="false"
```

### Workload Cluster 作成用のマニフェストファイル作成

Workload Cluster を作成するためのマニフェストファイルを作成する。
今回は capi-quickstart という名前の Workload Cluster を作成する。

- flavor
インフラストラクチャプロバイダー毎に準備されている Workload Cluster のテンプレート
Docker Provider の場合は運用環境での使用を目的として設計されておらず、開発環境のみを対象としているため、`development` とする
- kubernetes-version
Workload Cluster の Kubernetes Version を指定する
- control-plane-machine-count
Workload Cluster の Control Plane の台数を指定する
- worker-machine-count
Workload Cluster の Worker Node の台数を指定する

```
clusterctl generate cluster capi-quickstart \
  --flavor development \
  --kubernetes-version v1.27.0 \
  --control-plane-machine-count=1 \
  --worker-machine-count=1 \
  > capi-quickstart.yaml
```

### Workload Cluster 作成

Workload Cluster を作成する。
上記で作成されたマニフェストをアプライすることで Control Plane と Worker Node が各 1 台ずつ作成される。

```
$ kubectl apply -f capi-quickstart.yaml
clusterclass.cluster.x-k8s.io/quick-start created
dockerclustertemplate.infrastructure.cluster.x-k8s.io/quick-start-cluster created
kubeadmcontrolplanetemplate.controlplane.cluster.x-k8s.io/quick-start-control-plane created
dockermachinetemplate.infrastructure.cluster.x-k8s.io/quick-start-control-plane created
dockermachinetemplate.infrastructure.cluster.x-k8s.io/quick-start-default-worker-machinetemplate created
kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/quick-start-default-worker-bootstraptemplate created
cluster.cluster.x-k8s.io/capi-quickstart created
```

作成状況は下記で確認できる。
MachineDeployment/xxxx の READY 以外が True となっていれば問題ない。
MachineDeployment/xxxx は Calico 等の CNI をインストールすることで True となる。
CNI をインストールすることで Pod ネットワークを構成でき、Workload Cluster 上で Pod を動作させることができるようになる。
そのため、必要があれば CNI をインストールするとよい。

```
$ clusterctl describe cluster capi-quickstart
NAME                                                             READY  SEVERITY  REASON                       SINCE  MESSAGE

Cluster/capi-quickstart                                          True                                          56s

├─ClusterInfrastructure - DockerCluster/capi-quickstart-cv78j    True                                          106s

├─ControlPlane - KubeadmControlPlane/capi-quickstart-9zkz5       True                                          56s

│ └─Machine/capi-quickstart-9zkz5-qbgg5                          True                                          58s

└─Workers

  └─MachineDeployment/capi-quickstart-md-0-hgxb8                 False  Warning   WaitingForAvailableMachines  106s   Minimum availability requires 1 replicas, current 0 available
    └─Machine/capi-quickstart-md-0-hgxb8-6968755649xk6k6n-6pv5j  True                                          31s

```

Workload Cluster の kubeconfig を取得する。

```
clusterctl get kubeconfig capi-quickstart > capi-quickstart.kubeconfig
```

取得した kubeconfig を利用し、Workload Cluster のノードを確認する。

```
$ kubectl --kubeconfig=./capi-quickstart.kubeconfig get nodes -o wide
NAME                                                STATUS     ROLES           AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
capi-quickstart-9zkz5-qbgg5                         NotReady   control-plane   2m36s   v1.27.0   172.18.0.4    <none>        Ubuntu 22.04.2 LTS   5.4.0-149-generic   containerd://1.6.19-46-g941215f49
capi-quickstart-md-0-hgxb8-6968755649xk6k6n-6pv5j   NotReady   <none>          2m8s    v1.27.0   172.18.0.5    <none>        Ubuntu 22.04.2 LTS   5.4.0-149-generic   containerd://1.6.19-46-g941215f49
```

また、Docker 側でもプロセスを確認できる。

```
$ docker ps -a
CONTAINER ID   IMAGE                               COMMAND                  CREATED         STATUS         PORTS                                  NAMES
ba8d301e01ea   kindest/node:v1.27.0                "/usr/local/bin/entr…"   2 minutes ago   Up 2 minutes                                          capi-quickstart-md-0-hgxb8-6968755649xk6k6n-6pv5j
7e2eb311eb8c   kindest/node:v1.27.0                "/usr/local/bin/entr…"   3 minutes ago   Up 3 minutes   34191/tcp, 127.0.0.1:34191->6443/tcp   capi-quickstart-9zkz5-qbgg5
8b5968483e0f   kindest/haproxy:v20230330-2f738c2   "haproxy -sf 7 -W -d…"   3 minutes ago   Up 3 minutes   43505/tcp, 0.0.0.0:43505->6443/tcp     capi-quickstart-lb
6c9350879f83   kindest/node:v1.27.1                "/usr/local/bin/entr…"   9 minutes ago   Up 9 minutes   127.0.0.1:45555->6443/tcp              kind-control-plane
```

# まとめ

今回は Docker Provider を用いて Cluster API の動作を確認した。
Docker Provider を使用することでマシン等の構成コストが低い Cluster API を試すことができる。
Docker で Kubernets Cluster を作成する手段として本文中にも利用した kind もある。
Cluster API は Kubernetes Cluster を Kubernetes のリソースとして管理する。
そのため、Kubernetes Cluster に対してもオーケストレーションを実行できる。

しかし、本文中にも記載している通り Docker Provider は開発環境用に設計されており、運用環境での使用は非推奨である。
ただ、Cluster API の一連の動作を試す・Cluster API の構成要素を実機を動作させつつ試す点においては十分かつ簡単に実施できる。
そのため、Cluster API の入門として Docker Provider を試し、他 Provider の使用を試すとよいと考えている。

そこで、次の記事では実際に OpenStack Provider で Workload Cluster を動作させることを試し、そのための手順をまとめる。