Cluster API OpenStack providerを試した結果のまとめ

<img src="https://raw.githubusercontent.com/kubernetes-sigs/cluster-api/master/logos/kubernetes-cluster-logos_final-02.svg" width=30%>

https://github.com/kubernetes-sigs/cluster-api/blob/master/logos/kubernetes-cluster-logos_final-02.svg

# 目次

* [はじめに](#はじめに)
* [Cluster API 概要](#cluster-api-概要)
* [Cluster API 構成](#cluster-api-構成)
* [作業ログ](#作業ログ)
    * [インストール](#インストール)
    * [Workerノード追加](#workerノード追加)
    * [machineのセルフヒーリング](#machineのセルフヒーリング)
    * [Workload clusterの削除](#workload-clusterの削除)
    * [Workload clusterのUpgrade](#workload-clusterのupgrade)
* [メモ](#メモ)
* [参考文献](#参考文献)

# はじめに

[Mirantis Container Cloud](https://www.mirantis.com/software/docker/docker-enterprise-container-cloud/)でCluster APIが使われていることを知ったので、試してみた。
Cluster APIの簡単な紹介とインストール等を試した結果をまとめました。

# Cluster API 概要

Cluster APIは、k8sのマニフェストを使って宣言的にk8sクラスタのライフサイクル管理（デプロイ、バージョンアップなど）をするためのツールです。
[kubeadm](https://github.com/kubernetes/kubeadm)や[kubespray](https://github.com/kubernetes-sigs/kubespray)などのデプロイツールは、VM、ベアメタルやネットワークなどのインフラをあらかじめ配備する必要がありますが、Cluster APIはインフラのデプロイも実施してくれます。
Cluster APIのサポート対象インフラは、以下URLを参照。
https://cluster-api.sigs.k8s.io/reference/providers.html#infrastructure

# Cluster API 構成

![cluster_api_concepts](https://cluster-api.sigs.k8s.io/images/management-cluster.svg)
https://cluster-api.sigs.k8s.io/user/concepts.html

* Infrastructure provider
    * k8sのデプロイ先の基盤
    * AWSとか、VMwareとか
    * 本記事では、OpenStack
* Management cluster
    * k8sクラスタ（Workload cluster）をライフサイクル管理するためのk8sクラスタ
    * 本記事では、kind上に構築
* Workload cluster
    * Management clusterの管理対象k8sクラスタ

# 作業ログ
## インストール

### 環境情報

* OpenStack
    * Queens
    * 自己署名証明書を使用
* kind
    * v1.19.1
    * ホストOS: Ubuntu 16.04.3 LTS
* Cluster API
    * v0.3.13
    * OpenStack Provider v0.3.3
* プロキシ環境

### 前提条件

* OpenSatckインスタンスから、OpenStackのAPIを発行できること

### インストールの流れ

1. [k8sノード用のQCOW2イメージのビルド](#1-k8sノード用のqcow2イメージのビルド)
2. [Management Clusterとして使用するk8sクラスタの用意](#2-management-clusterとして使用するk8sクラスタの用意)
3. [Management Clusterのインストール](#3-management-clusterのインストール)
4. [Workload Clusterのデプロイ](#4-workload-clusterのデプロイ)

![capi_os.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350260/f2e786a8-f79a-2e7d-11df-205368592810.jpeg)

### インストールのログ

#### 1. k8sノード用のQCOW2イメージのビルド

まずは、パッケージのインストールと[image-builderリポジトリ](https://github.com/kubernetes-sigs/image-builder)をcloneする。

```
~$ sudo apt install qemu-kvm libvirt-bin qemu-utils python3-pip

--- snip ---

~$ sudo usermod -a -G kvm ${USER}
~$ sudo chown root:kvm /dev/kvm
~$ getent group kvm
kvm:x:115:nakkoh
$ curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
OK
$ sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"

--- snip ---

Reading package lists... Done
$ sudo apt-get update && sudo apt-get install packer

--- snip ---

Setting up packer (1.6.6) ...
~$ git clone https://github.com/kubernetes-sigs/image-builder.git
~$ cd image-builder/images/capi/
```

proxy環境のため、[ドキュメント](https://image-builder.sigs.k8s.io/capi/capi.html#setting-up-an-http-proxy)に従って`proxy.json`を作成。

```
~/image-builder/images/capi$ $ PACKER_VAR_FILES=proxy.json make build-qemu-ubuntu-2004

--- snip ---

    qemu: PLAY RECAP *********************************************************************
    qemu: default                    : ok=73   changed=55   unreachable=0    failed=0    skipped=96   rescued=0    ignored=0
    qemu:
==> qemu: Gracefully halting virtual machine...
==> qemu: Converting hard drive...
Build 'qemu' finished after 20 minutes 44 seconds.

==> Wait completed after 20 minutes 44 seconds

==> Builds finished. The artifacts of successful builds are:
--> qemu: VM files in directory: ./output/ubuntu-2004-kube-v1.18.15
$ ll ./output/ubuntu-2004-kube-v1.18.15/ubuntu-2004-kube-v1.18.15 
-rw-r--r-- 1 nakkoh nakkoh 3884253184 Jan 28 08:54 ./output/ubuntu-2004-kube-v1.18.15/ubuntu-2004-kube-v1.18.15
```

作成したQCOW2イメージをGlanceに登録

```
$ openstack image create --disk-format qcow2 --container-format bare \
>   --public --file ./ubuntu-2004-kube-v1.18.15 ubuntu-2004-kube-v1.18.15
+------------------+------------------------------------------------------+
| Field            | Value                                                |
+------------------+------------------------------------------------------+
| checksum         | e1132ef5a0ace08935722342268677cb                     |
| container_format | bare                                                 |
| created_at       | 2021-02-01T05:16:01Z                                 |
| disk_format      | qcow2                                                |
| file             | /v2/images/c9b7e861-3869-4e4d-a4b2-8772e5a3a4cd/file |
| id               | c9b7e861-3869-4e4d-a4b2-8772e5a3a4cd                 |
| min_disk         | 0                                                    |
| min_ram          | 0                                                    |
| name             | ubuntu-2004-kube-v1.18.15                            |
| owner            | 9aa38c14b68342eea4068480374b40f2                     |
| protected        | False                                                |
| schema           | /v2/schemas/image                                    |
| size             | 3884253184                                           |
| status           | active                                               |
| tags             |                                                      |
| updated_at       | 2021-02-01T05:17:11Z                                 |
| virtual_size     | None                                                 |
| visibility       | public                                               |
+------------------+------------------------------------------------------+
```

プロキシ環境であることと、連携対象のOpenStackが自己署名証明書を使用していることから、ビルドしたイメージに以下の変更を実施する必要があった。

* containerdのプロキシ設定
* OpenStackのCA証明書インストール
    * 別の方法がありそうだが、とりあえず暫定対応として実施
    * Openstack APIをコールするコンポーネントは以下の2つ
        * Management Cluster
        * Workload ClusterのControl Plane
    * Management Clusetrはinsecureを指定できる
    * Controle Planeは指定できない（in-treeなCloud Providerを使う場合）
    * 参考
        * https://qiita.com/msi/items/9cb90271836386dafce3#ubuntu-1804
        * https://kubernetes.io/ja/docs/concepts/cluster-administration/cloud-providers/#openstack

#### 2. Management Clusterとして使用するk8sクラスタの用意

bootstrap clusterには、以下のオプションがある。

* 既存のk8sクラスタを使用
* [kind](https://github.com/kubernetes-sigs/kind)を使用

今回は、kindを使用。
https://qiita.com/nakkoh/items/666ec990616e68220f99

bootstrap clusterとして使用するためのクラスタを作成。

```
$ kind create cluster --name cluster-api
Creating cluster "cluster-api" ...
 ✓ Ensuring node image (kindest/node:v1.19.1) 🖼 
 ✓ Preparing nodes 📦  
 ✓ Writing configuration 📜 
 ✓ Starting control-plane 🕹️ 
 ✓ Installing CNI 🔌 
 ✓ Installing StorageClass 💾 
Set kubectl context to "kind-cluster-api"
You can now use your cluster with:

kubectl cluster-info --context kind-cluster-api

Not sure what to do next? 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/
$ kind get clusters
cluster-api
$ k get nodes 
NAME                        STATUS   ROLES    AGE     VERSION
cluster-api-control-plane   Ready    master   8m31s   v1.19.1
```

#### 3. Management Clusterのインストール

##### clusterctlのインストール

```
$ curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v0.3.13/clusterctl-linux-amd64 -o clusterctl
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   648  100   648    0     0   1144      0 --:--:-- --:--:-- --:--:--  1146
100 50.3M  100 50.3M    0     0   458k      0  0:01:52  0:01:52 --:--:--  434k
$ chmod +x ./clusterctl
$ sudo mv ./clusterctl /usr/local/bin/clusterctl
$ clusterctl version
clusterctl version: &version.Info{Major:"0", Minor:"3", GitVersion:"v0.3.13", GitCommit:"fccc84c0070c15ceb89242f3f4b061ad588e27ed", GitTreeState:"clean", BuildDate:"2021-01-22T18:05:45Z", GoVersion:"go1.13.15", Compiler:"gc", Platform:"linux/amd64"}
```

##### Management Clusterの初期化

```
$ clusterctl init --infrastructure openstack
Fetching providers
Installing cert-manager Version="v0.16.1"
Waiting for cert-manager to be available...
Installing Provider="cluster-api" Version="v0.3.13" TargetNamespace="capi-system"
Installing Provider="bootstrap-kubeadm" Version="v0.3.13" TargetNamespace="capi-kubeadm-bootstrap-system"
Installing Provider="control-plane-kubeadm" Version="v0.3.13" TargetNamespace="capi-kubeadm-control-plane-system"
Installing Provider="infrastructure-openstack" Version="v0.3.3" TargetNamespace="capo-system"

Your management cluster has been initialized successfully!

You can now create your first workload cluster by running the following:

  clusterctl config cluster [name] --kubernetes-version [version] | kubectl apply -f -

```

#### 4. Workload Clusterのデプロイ

連携対象OpenStackの`clouds.yaml`の作成。

```yaml

clouds:
  dev:
    insecure: true
    verify: false
    auth:
      username: user01
      user_domain_name: Default
      password: p@$$w0rd
      project_name: cluster-api
      project_domain_name: Default
      auth_url: https://xx.xx.xx.xx:5000/
```

デプロイするためのマニフェストの作成

```
$ wget https://raw.githubusercontent.com/kubernetes-sigs/cluster-api-provider-openstack/master/templates/env.rc -O /tmp/env.rc
$ source /tmp/env.rc ~/clouds.yaml dev
$ export OPENSTACK_CONTROL_PLANE_MACHINE_FLAVOR=m1.medium 
$ export OPENSTACK_NODE_MACHINE_FLAVOR=m1.medium
$ export OPENSTACK_IMAGE_NAME=ubuntu-2004-kube-v1.18.15
$ export OPENSTACK_SSH_KEY_NAME=user01
$ clusterctl config cluster capi-quickstart --infrastructure=openstack:v0.3.3 --kubernetes-version v1.18.5 --control-plane-machine-count=3 --worker-machine-count=3 > capi-quickstart.yaml
Error: value for variables [OPENSTACK_DNS_NAMESERVERS, OPENSTACK_FAILURE_DOMAIN] is not set. Please set the value using os environment variables or the clusterctl config file
$ export OPENSTACK_DNS_NAMESERVERS="8.8.8.8"
$ export OPENSTACK_FAILURE_DOMAIN=nova
$ clusterctl config cluster capi-quickstart --infrastructure=openstack:v0.3.3 --kubernetes-version v1.18.5 --control-plane-machine-count=3 --worker-machine-count=3 > capi-quickstart.yaml
```

* `env.rc`を実行するには[yqコマンド](https://github.com/mikefarah/yq)が必要ですが、インストールするバージョンに注意が必要<br>
今回、最新バージョンのv4.4.1ではエラーが発生し、v3.2.1だとうまく動いた。
* DNSがない環境ですが、`OPENSTACK_DNS_NAMESERVERS`の指定が必須のため、とりあえず適当なDNSを指定（プロキシ環境のため通信できない）

連携対象のOpenStackにはOctaviaがインストールされていないため、`OpenStackCluster`のマニフェストのOctavia関連の変数を変更。

* spec.managedAPIServerLoadBalancer: `true` -> `false`
* spec.useOctavia: `true` -> `false`

マニフェストのapply

```
$ k apply -f capi-quickstart.yaml 
cluster.cluster.x-k8s.io/capi-quickstart created
openstackcluster.infrastructure.cluster.x-k8s.io/capi-quickstart created
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/capi-quickstart-control-plane created
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/capi-quickstart-control-plane created
machinedeployment.cluster.x-k8s.io/capi-quickstart-md-0 created
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/capi-quickstart-md-0 created
kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/capi-quickstart-md-0 created
secret/capi-quickstart-cloud-config created
```

Workload Clusterのデプロイ状況の確認

```
$ kubectl get cluster --all-namespaces
NAMESPACE   NAME              PHASE
default     capi-quickstart   Provisioned
$ kubectl get kubeadmcontrolplane --all-namespaces
NAMESPACE   NAME                            INITIALIZED   API SERVER AVAILABLE   VERSION   REPLICAS   READY   UPDATED   UNAVAILABLE
default     capi-quickstart-control-plane                                        v1.18.15   1                  1         1
```

OpenStackのインスタンスやネットワーク等が作成されていることが確認できた。

```
$ openstack server list --project cluster-api
+--------------------------------------+-------------------------------------+--------+-------------------------------------------------------------------------+---------------------------+-----------+
| ID                                   | Name                                | Status | Networks                                                                | Image                     | Flavor    |
+--------------------------------------+-------------------------------------+--------+-------------------------------------------------------------------------+---------------------------+-----------+
| 1a9d5092-6034-4021-980f-4b338e2e6629 | capi-quickstart-control-plane-nr4ss | ACTIVE | k8s-clusterapi-cluster-default-capi-quickstart=10.6.0.131               | ubuntu-2004-kube-v1.18.15 | m1.medium |
| 5af116e1-b9f7-4151-bbc3-53421cd6a72e | capi-quickstart-control-plane-skmdb | ACTIVE | k8s-clusterapi-cluster-default-capi-quickstart=10.6.0.52, 172.16.70.105 | ubuntu-2004-kube-v1.18.15 | m1.medium |
| 3f95f74c-e0b7-4de4-a6d4-c895546b0762 | capi-quickstart-md-0-jc4db          | ACTIVE | k8s-clusterapi-cluster-default-capi-quickstart=10.6.0.184               | ubuntu-2004-kube-v1.18.15 | m1.medium |
| bb857ae2-5e91-4818-9541-806a3604a1ba | capi-quickstart-md-0-96c8r          | ACTIVE | k8s-clusterapi-cluster-default-capi-quickstart=10.6.0.235               | ubuntu-2004-kube-v1.18.15 | m1.medium |
| d991af25-8f78-4d05-a463-b2302ca741b9 | capi-quickstart-md-0-h7tkg          | ACTIVE | k8s-clusterapi-cluster-default-capi-quickstart=10.6.0.172               | ubuntu-2004-kube-v1.18.15 | m1.medium |
| 3543b624-28da-49ab-a2ab-45dd82bb4a89 | capi-quickstart-control-plane-p8xb6 | ACTIVE | k8s-clusterapi-cluster-default-capi-quickstart=10.6.0.237               | ubuntu-2004-kube-v1.18.15 | m1.medium |
+--------------------------------------+-------------------------------------+--------+-------------------------------------------------------------------------+---------------------------+-----------+
$ openstack network list --project cluster-api
+--------------------------------------+------------------------------------------------+--------------------------------------+
| ID                                   | Name                                           | Subnets                              |
+--------------------------------------+------------------------------------------------+--------------------------------------+
| fe856381-917f-4d4d-936a-ede145c121bf | k8s-clusterapi-cluster-default-capi-quickstart | 5b276bd2-4fc7-4209-8153-e13f0ace4283 |
+--------------------------------------+------------------------------------------------+--------------------------------------+
$ openstack security group list --project cluster-api
+--------------------------------------+-----------------------------------------------------------+---------------------------+----------------------------------+
| ID                                   | Name                                                      | Description               | Project                          |
+--------------------------------------+-----------------------------------------------------------+---------------------------+----------------------------------+
| 8d924e38-e9a9-4d7e-adf7-278b65ea4586 | k8s-cluster-default-capi-quickstart-secgroup-worker       | Cluster API managed group | f05fe56032d6459ba858e504dd875809 |
| eb1a9868-aaf2-46b4-aca2-b3399cbf1674 | default                                                   | Default security group    | f05fe56032d6459ba858e504dd875809 |
| ef4ca42d-26d2-4885-8fc8-332489b3feb8 | k8s-cluster-default-capi-quickstart-secgroup-controlplane | Cluster API managed group | f05fe56032d6459ba858e504dd875809 |
+--------------------------------------+-----------------------------------------------------------+---------------------------+----------------------------------+
```

kubeconfigの生成

```
$ clusterctl get kubeconfig capi-quickstart > capi-quickstart.kubeconfig
apiVersion: v1
clusters:
- cluster:

--- snip ---
```

apiserverのURLを確認すると、controlplaneのFloating IPが設定されていた。

```
$ export KUBECONFIG=~/capi-quickstart.kubeconfig
$ k config current-context 
kind-cluster-api
$ k config use-context 
capi-quickstart-admin@capi-quickstart  kind-cluster-api
$ k config use-context capi-quickstart-admin@capi-quickstart 
Switched to context "capi-quickstart-admin@capi-quickstart".
$ k get po -A
NAMESPACE     NAME                                                          READY   STATUS    RESTARTS   AGE
kube-system   coredns-66bff467f8-697dt                                      0/1     Pending   0          33m
kube-system   coredns-66bff467f8-kvjtw                                      0/1     Pending   0          33m
kube-system   etcd-capi-quickstart-control-plane-nr4ss                      1/1     Running   0          29m
kube-system   etcd-capi-quickstart-control-plane-p8xb6                      1/1     Running   0          33m
kube-system   etcd-capi-quickstart-control-plane-skmdb                      1/1     Running   0          31m
kube-system   kube-apiserver-capi-quickstart-control-plane-nr4ss            1/1     Running   0          29m
kube-system   kube-apiserver-capi-quickstart-control-plane-p8xb6            1/1     Running   0          33m
kube-system   kube-apiserver-capi-quickstart-control-plane-skmdb            1/1     Running   0          31m
kube-system   kube-controller-manager-capi-quickstart-control-plane-nr4ss   1/1     Running   0          29m
kube-system   kube-controller-manager-capi-quickstart-control-plane-p8xb6   1/1     Running   1          33m
kube-system   kube-controller-manager-capi-quickstart-control-plane-skmdb   1/1     Running   0          31m
kube-system   kube-proxy-h6c25                                              1/1     Running   0          31m
kube-system   kube-proxy-nxhnh                                              1/1     Running   0          29m
kube-system   kube-proxy-pvstx                                              1/1     Running   0          31m
kube-system   kube-proxy-q9qbm                                              1/1     Running   0          33m
kube-system   kube-proxy-r56ls                                              1/1     Running   0          31m
kube-system   kube-proxy-stxhl                                              1/1     Running   0          31m
kube-system   kube-scheduler-capi-quickstart-control-plane-nr4ss            1/1     Running   0          29m
kube-system   kube-scheduler-capi-quickstart-control-plane-p8xb6            1/1     Running   1          33m
kube-system   kube-scheduler-capi-quickstart-control-plane-skmdb            1/1     Running   0          31m
```

Calicoのインストール

```
$ k apply -f calico.yaml 
configmap/calico-config created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
daemonset.apps/calico-node created
serviceaccount/calico-node created
deployment.apps/calico-kube-controllers created
serviceaccount/calico-kube-controllers created
$ k get pod -A
NAMESPACE     NAME                                                          READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-855d5b69bc-nhfln                      1/1     Running   0          2m27s
kube-system   calico-node-f4h9t                                             1/1     Running   0          2m28s
kube-system   calico-node-k6j5x                                             1/1     Running   0          2m28s
kube-system   calico-node-khghv                                             1/1     Running   0          2m28s
kube-system   calico-node-rmdzw                                             1/1     Running   0          2m28s
kube-system   calico-node-zbrvj                                             1/1     Running   0          2m27s
kube-system   calico-node-zswm4                                             1/1     Running   0          2m28s
kube-system   coredns-66bff467f8-697dt                                      1/1     Running   0          36m
kube-system   coredns-66bff467f8-kvjtw                                      1/1     Running   0          36m
kube-system   etcd-capi-quickstart-control-plane-nr4ss                      1/1     Running   0          32m
kube-system   etcd-capi-quickstart-control-plane-p8xb6                      1/1     Running   0          36m
kube-system   etcd-capi-quickstart-control-plane-skmdb                      1/1     Running   0          34m
kube-system   kube-apiserver-capi-quickstart-control-plane-nr4ss            1/1     Running   0          32m
kube-system   kube-apiserver-capi-quickstart-control-plane-p8xb6            1/1     Running   0          36m
kube-system   kube-apiserver-capi-quickstart-control-plane-skmdb            1/1     Running   0          34m
kube-system   kube-controller-manager-capi-quickstart-control-plane-nr4ss   1/1     Running   0          32m
kube-system   kube-controller-manager-capi-quickstart-control-plane-p8xb6   1/1     Running   1          36m
kube-system   kube-controller-manager-capi-quickstart-control-plane-skmdb   1/1     Running   0          34m
kube-system   kube-proxy-h6c25                                              1/1     Running   0          33m
kube-system   kube-proxy-nxhnh                                              1/1     Running   0          32m
kube-system   kube-proxy-pvstx                                              1/1     Running   0          33m
kube-system   kube-proxy-q9qbm                                              1/1     Running   0          36m
kube-system   kube-proxy-r56ls                                              1/1     Running   0          34m
kube-system   kube-proxy-stxhl                                              1/1     Running   0          33m
kube-system   kube-scheduler-capi-quickstart-control-plane-nr4ss            1/1     Running   0          32m
kube-system   kube-scheduler-capi-quickstart-control-plane-p8xb6            1/1     Running   1          36m
kube-system   kube-scheduler-capi-quickstart-control-plane-skmdb            1/1     Running   0          34m
$ k get nodes 
NAME                                  STATUS   ROLES    AGE   VERSION
capi-quickstart-control-plane-nr4ss   Ready    master   32m   v1.18.15
capi-quickstart-control-plane-p8xb6   Ready    master   36m   v1.18.15
capi-quickstart-control-plane-skmdb   Ready    master   34m   v1.18.15
capi-quickstart-md-0-96c8r            Ready    <none>   34m   v1.18.15
capi-quickstart-md-0-h7tkg            Ready    <none>   34m   v1.18.15
capi-quickstart-md-0-jc4db            Ready    <none>   34m   v1.18.15
```

Workload Clusterがデプロイされたことが確認できた！

# Workerノード追加

MachineDeploymentのマニフェストの`spec.replicas`の値を`3` -> `4`に変更し、apply

```
$ k get node
NAME                                  STATUS   ROLES    AGE   VERSION
capi-quickstart-control-plane-nr4ss   Ready    master   23h   v1.18.15
capi-quickstart-control-plane-p8xb6   Ready    master   23h   v1.18.15
capi-quickstart-control-plane-skmdb   Ready    master   23h   v1.18.15
capi-quickstart-md-0-96c8r            Ready    <none>   23h   v1.18.15
capi-quickstart-md-0-h7tkg            Ready    <none>   23h   v1.18.15
capi-quickstart-md-0-jc4db            Ready    <none>   23h   v1.18.15
$ k config current-context 
capi-quickstart-admin@capi-quickstart
$ unset KUBECONFIG 
$ k config current-context 
kind-cluster-api
$ k diff -f capi-quickstart.yaml

--- snip ---

   progressDeadlineSeconds: 600
-  replicas: 3
+  replicas: 4
   revisionHistoryLimit: 1
   selector:
     matchLabels:
$ k apply -f capi-quickstart.yaml 
cluster.cluster.x-k8s.io/capi-quickstart unchanged
openstackcluster.infrastructure.cluster.x-k8s.io/capi-quickstart unchanged
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/capi-quickstart-control-plane unchanged
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/capi-quickstart-control-plane unchanged
machinedeployment.cluster.x-k8s.io/capi-quickstart-md-0 configured
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/capi-quickstart-md-0 unchanged
kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/capi-quickstart-md-0 unchanged
secret/capi-quickstart-cloud-config unchanged
$ export KUBECONFIG=~/capi-quickstart.kubeconfig 
$ k config current-context 
capi-quickstart-admin@capi-quickstart
$ k get node
NAME                                  STATUS   ROLES    AGE   VERSION
capi-quickstart-control-plane-nr4ss   Ready    master   23h   v1.18.15
capi-quickstart-control-plane-p8xb6   Ready    master   23h   v1.18.15
capi-quickstart-control-plane-skmdb   Ready    master   23h   v1.18.15
capi-quickstart-md-0-96c8r            Ready    <none>   23h   v1.18.15
capi-quickstart-md-0-b2wpf            Ready    <none>   54s   v1.18.15
capi-quickstart-md-0-h7tkg            Ready    <none>   23h   v1.18.15
capi-quickstart-md-0-jc4db            Ready    <none>   23h   v1.18.15
```

podのreplic数を増やすのと同じ要領で、workerノードを追加できた！

# machineのセルフヒーリング

podと同じようにmachineもセルフヒーリングされるのかを試す。

```
$ k get machine
NAME                                    PROVIDERID                                         PHASE     VERSION
capi-quickstart-control-plane-882wg     openstack://3543b624-28da-49ab-a2ab-45dd82bb4a89   Running   v1.18.15
capi-quickstart-control-plane-9dq4q     openstack://1a9d5092-6034-4021-980f-4b338e2e6629   Running   v1.18.15
capi-quickstart-control-plane-fzm95     openstack://5af116e1-b9f7-4151-bbc3-53421cd6a72e   Running   v1.18.15
capi-quickstart-md-0-666989b788-cm7xj   openstack://8183c932-7e2b-42ba-b321-804759ca79c9   Running   v1.18.15
capi-quickstart-md-0-666989b788-gtqtc   openstack://eafdaf80-bb1c-44ba-93a6-d903a23fe350   Running   v1.18.15
capi-quickstart-md-0-666989b788-j7j45   openstack://3f95f74c-e0b7-4de4-a6d4-c895546b0762   Running   v1.18.15
capi-quickstart-md-0-666989b788-ldct2   openstack://d991af25-8f78-4d05-a463-b2302ca741b9   Running   v1.18.15
$ k delete machine capi-quickstart-md-0-666989b788-ldct2
machine.cluster.x-k8s.io "capi-quickstart-md-0-666989b788-ldct2" deleted
$ k get machine
NAME                                    PROVIDERID                                         PHASE          VERSION
capi-quickstart-control-plane-882wg     openstack://3543b624-28da-49ab-a2ab-45dd82bb4a89   Running        v1.18.15
capi-quickstart-control-plane-9dq4q     openstack://1a9d5092-6034-4021-980f-4b338e2e6629   Running        v1.18.15
capi-quickstart-control-plane-fzm95     openstack://5af116e1-b9f7-4151-bbc3-53421cd6a72e   Running        v1.18.15
capi-quickstart-md-0-666989b788-cm7xj   openstack://8183c932-7e2b-42ba-b321-804759ca79c9   Running        v1.18.15
capi-quickstart-md-0-666989b788-gtqtc   openstack://eafdaf80-bb1c-44ba-93a6-d903a23fe350   Running        v1.18.15
capi-quickstart-md-0-666989b788-j7j45   openstack://3f95f74c-e0b7-4de4-a6d4-c895546b0762   Running        v1.18.15
capi-quickstart-md-0-666989b788-m49k5   openstack://399f6f8a-25f1-4dbf-b14b-65e30d74fc14   Provisioning   v1.18.15
```

machineを削除すると、実体であるOpenStackインスタンスも削除された。
その後、新しいmachineが作成され、OpenStack上でも新しいインスタンスが作成された。
最後に、k8s上でnodeを確認する。

```
$ k get node --kubeconfig ~/capi-quickstart.kubeconfig 
NAME                                  STATUS   ROLES    AGE     VERSION
capi-quickstart-control-plane-nr4ss   Ready    master   5d19h   v1.18.15
capi-quickstart-control-plane-p8xb6   Ready    master   5d19h   v1.18.15
capi-quickstart-control-plane-skmdb   Ready    master   5d19h   v1.18.15
capi-quickstart-md-0-b2wpf            Ready    <none>   4d19h   v1.18.15
capi-quickstart-md-0-jc4db            Ready    <none>   5d19h   v1.18.15
capi-quickstart-md-0-mdv7q            Ready    <none>   6m11s   v1.18.15
capi-quickstart-md-0-ssrsk            Ready    <none>   22m     v1.18.15
```

AGEより、nodeが再追加されていることが確認できた。

# Workload clusterの削除

```
$ k delete cluster capi-quickstart 
cluster.cluster.x-k8s.io "capi-quickstart" deleted
$ k get machine
No resources found in default namespace.
```

OpenStackのリソースも全て削除された。

## Workload clusterのUpgrade

[公式ドキュメント](https://cluster-api.sigs.k8s.io/tasks/upgrading-clusters.html)の手順に沿って実施する。

流れは以下の通り。

1. バージョンアップ先のmachineイメージのビルド
2. 新しいMachinTemplateの作成
2. Management Clusterのバージョンアップ
3. Workload Clusterのバージョンアップ

今回は、Workload Clusterのバージョンを、v1.18.15 -> v1.19.7にバージョンアップする。
インストール済みのManagement Clusterは最新のため、手順2のManagement Clusterのインストールは不要。

まずは、v1.19.7用のmachineイメージをビルドする。

[packerの定義](https://github.com/kubernetes-sigs/image-builder/blob/master/images/capi/packer/config/kubernetes.json)のk8sバージョンを変更する。

```diff
-  "kubernetes_series": "v1.18",
-  "kubernetes_semver": "v1.18.15",
-  "kubernetes_rpm_version": "1.18.15-0",
-  "kubernetes_deb_version": "1.18.15-00",
+  "kubernetes_series": "v1.19",
+  "kubernetes_semver": "v1.19.7",
+  "kubernetes_rpm_version": "1.19.7-0",
+  "kubernetes_deb_version": "1.19.7-00",
```

続いて、新しいOpenStackMachineTemplateを作成する。
既存のマニフェストをコピー、修正して作成する。

```diff
4c4
<   name: capi-quickstart-control-plane
---
>   name: capi-quickstart-v1-19-7
14c14
<       image: ubuntu-2004-kube-v1.18.15
---
>       image: ubuntu-2004-kube-v1.19.7
```

**OpenStackMachineTemplateの名前にドット`.`を使ってはいけない。**
この名前は、OpenStadckインスタンス名のプレフィックスに使用される。
インスタンス名は、ホスト名として使用される。
インスタンス名に、ドット`.`が含まれると、ドットはホスト名に使用できないため、ドットより前の文字列がホスト名に使用される。
（インスタンス名が`capi-v1.19.7`の場合、ホスト名は`capi-v1`となる。）
一方、k8sのノード名にはドットを含んだ名前が指定される。
k8sのノード名とホスト名が異なるとエラーとなり、アップグレードの処理が進まなくなってしまう。

```
$ k apply -f machine-template.yaml 
openstackmachinetemplate.infrastructure.cluster.x-k8s.io/capi-quickstart-v1.19.7 created
$ k get openstackmachinetemplates.infrastructure.cluster.x-k8s.io 
NAME                            AGE
capi-quickstart-control-plane   28m
capi-quickstart-md-0            28m
capi-quickstart-v1-19-7         30s
```

次に、Control planeのMachineTemplateを更新。

```diff
10c10
<     name: capi-quickstart-control-plane
---
>     name: capi-quickstart-v1-19-7
60c60
<   version: v1.18.15
---
>   version: v1.19.7
```

```
$ k apply -f controlplane-v1.19.7.yaml 
kubeadmcontrolplane.controlplane.cluster.x-k8s.io/capi-quickstart-control-plane configured
nakahara@kvm01:~/cluster-api/manifest$ k get machine
NAME                                    PROVIDERID                                         PHASE          VERSION
capi-quickstart-control-plane-4gfgw                                                        Provisioning   v1.19.7
capi-quickstart-control-plane-6lvwt     openstack://47a82286-8ae5-47cf-a192-a3fe82d7f0cd   Running        v1.18.15
capi-quickstart-control-plane-8w4tc     openstack://bc1aaf6f-a4d4-4b1b-abd6-32a4b75f8cfc   Running        v1.18.15
capi-quickstart-control-plane-qmfsf     openstack://2b5583da-ab10-4fe0-b18a-d085d3f1ec9d   Running        v1.18.15
capi-quickstart-md-0-666989b788-ppml8   openstack://589a8dbd-4ec1-4837-ab5a-06155520aae3   Running        v1.18.15
capi-quickstart-md-0-666989b788-spqmc   openstack://bd659750-854c-4151-9881-23687b9c0dc2   Running        v1.18.15
capi-quickstart-md-0-666989b788-t9qmh   openstack://5cd202c9-c741-4aa8-a264-7d7fe82fbf32   Running        v1.18.15
```

新しいバージョンのmachineがプロビジョニングされ始めた。

```
$ k get machine
NAME                                    PROVIDERID                                         PHASE     VERSION
capi-quickstart-control-plane-2qbxh     openstack://b6de7c74-10d5-4c8a-ad0e-6e60f3b49b21   Running   v1.19.7
capi-quickstart-control-plane-4gfgw     openstack://924625d5-368b-4e7d-834f-64329d6f0637   Running   v1.19.7
capi-quickstart-control-plane-jshs2     openstack://0decc13f-b4e6-4ec8-806d-e81f977169a4   Running   v1.19.7
capi-quickstart-md-0-666989b788-ppml8   openstack://589a8dbd-4ec1-4837-ab5a-06155520aae3   Running   v1.18.15
capi-quickstart-md-0-666989b788-spqmc   openstack://bd659750-854c-4151-9881-23687b9c0dc2   Running   v1.18.15
capi-quickstart-md-0-666989b788-t9qmh   openstack://5cd202c9-c741-4aa8-a264-7d7fe82fbf32   Running   v1.18.15
$ k --kubeconfig=../capi-quickstart.kubeconfig get node
NAME                            STATUS   ROLES    AGE     VERSION
capi-quickstart-md-0-5zw99      Ready    <none>   49m     v1.18.15
capi-quickstart-md-0-fh8xt      Ready    <none>   49m     v1.18.15
capi-quickstart-md-0-tkcnd      Ready    <none>   49m     v1.18.15
capi-quickstart-v1-19-7-5kt9m   Ready    master   9m45s   v1.19.7
capi-quickstart-v1-19-7-7sxs6   Ready    master   14m     v1.19.7
capi-quickstart-v1-19-7-vzshb   Ready    master   19m     v1.19.7
```

control planeのアップグレードはうまくいったようである。
つづいて、worker nodeをアップグレードする。

```diff
23,24c23,24
<         name: capi-quickstart-md-0
<       version: v1.18.15
---
>         name: capi-quickstart-v1-19-7
>       version: v1.19.7
```

```
$ k apply -f machinedeployment-v1.19.7.yaml 
machinedeployment.cluster.x-k8s.io/capi-quickstart-md-0 configured
$ k get machine
NAME                                    PROVIDERID                                         PHASE          VERSION
capi-quickstart-control-plane-2qbxh     openstack://b6de7c74-10d5-4c8a-ad0e-6e60f3b49b21   Running        v1.19.7
capi-quickstart-control-plane-4gfgw     openstack://924625d5-368b-4e7d-834f-64329d6f0637   Running        v1.19.7
capi-quickstart-control-plane-jshs2     openstack://0decc13f-b4e6-4ec8-806d-e81f977169a4   Running        v1.19.7
capi-quickstart-md-0-666989b788-ppml8   openstack://589a8dbd-4ec1-4837-ab5a-06155520aae3   Running        v1.18.15
capi-quickstart-md-0-666989b788-spqmc   openstack://bd659750-854c-4151-9881-23687b9c0dc2   Running        v1.18.15
capi-quickstart-md-0-666989b788-t9qmh   openstack://5cd202c9-c741-4aa8-a264-7d7fe82fbf32   Running        v1.18.15
capi-quickstart-md-0-75fd475744-wv5rw   openstack://05e8b161-4c7b-4daf-9fff-25ae02d550a3   Provisioning   v1.19.7
```

しばらく時間を置く。

```
$ k get machine
NAME                                    PROVIDERID                                         PHASE     VERSION
capi-quickstart-control-plane-2qbxh     openstack://b6de7c74-10d5-4c8a-ad0e-6e60f3b49b21   Running   v1.19.7
capi-quickstart-control-plane-4gfgw     openstack://924625d5-368b-4e7d-834f-64329d6f0637   Running   v1.19.7
capi-quickstart-control-plane-jshs2     openstack://0decc13f-b4e6-4ec8-806d-e81f977169a4   Running   v1.19.7
capi-quickstart-md-0-75fd475744-6g9xw   openstack://78f7729e-bba2-4191-94e3-fff7d629e9e2   Running   v1.19.7
capi-quickstart-md-0-75fd475744-jkd8g   openstack://39cc2d06-d4f1-4538-99d4-aa9ad083cfd9   Running   v1.19.7
capi-quickstart-md-0-75fd475744-wv5rw   openstack://05e8b161-4c7b-4daf-9fff-25ae02d550a3   Running   v1.19.7
$ export KUBECONFIG=../capi-quickstart.kubeconfig 
$ k get node
NAME                            STATUS   ROLES    AGE   VERSION
capi-quickstart-v1-19-7-5kt9m   Ready    master   54m   v1.19.7
capi-quickstart-v1-19-7-7sxs6   Ready    master   59m   v1.19.7
capi-quickstart-v1-19-7-7zl7q   Ready    <none>   30m   v1.19.7
capi-quickstart-v1-19-7-slxdl   Ready    <none>   32m   v1.19.7
capi-quickstart-v1-19-7-vzshb   Ready    master   64m   v1.19.7
capi-quickstart-v1-19-7-xq9z4   Ready    <none>   28m   v1.19.7
```

Worker nodeもアップグレードができた！

# メモ

* machineイメージ（QCOW2）には以下が含まれる（[参考](https://cluster-api.sigs.k8s.io/tasks/upgrading-clusters.html#images)）
    * kubeadm
    * kubelet
    * コンテナランタイム
    * コンテナイメージ

# 参考文献

* https://cluster-api.sigs.k8s.io/user/concepts.html
* https://cluster-api.sigs.k8s.io/user/quick-start.html
* https://image-builder.sigs.k8s.io/capi/providers/openstack.html
* https://image-builder.sigs.k8s.io/capi/capi.html#prerequisites
* https://learn.hashicorp.com/tutorials/packer/getting-started-install
* https://qiita.com/msi/items/9cb90271836386dafce3#ubuntu-1804
* https://kubernetes.io/docs/tasks/run-application/run-single-instance-stateful-application/
* https://cluster-api.sigs.k8s.io/tasks/upgrading-clusters.html
* https://cluster-api.sigs.k8s.io/reference/versions.html