ArgoCD + Cluster API で EKSクラスタをGitOpsする

EKSクラスタの構築にeksctlを使ってる方も多いと思うんですが、宣言的に管理したいって思うようになりませんか？
となると、Terraformか・・・ってなるんですけど、個別に作らないといけないものも多くなるし、ちょっとめんどくさそう。

Kubernetesなので、アプリケーションをGitOpsで運用しているっていう方もからすると、せっかくArgoCDでGitOpsやってるんだから、クラスタの構築もこのフローでできないものか・・・
と思うことはないですか？

それ、Cluster APIを使えばできます！

## Cluster API

https://cluster-api.sigs.k8s.io/
> Cluster API is a Kubernetes sub-project focused on providing declarative APIs and tooling to simplify provisioning, upgrading, and operating multiple Kubernetes clusters.

Kubernetesクラスタの運用を宣言的APIでできるよってことです。
2021/4/6現在、Experimentalですが、EKSもサポートされています。
https://github.com/kubernetes-sigs/cluster-api-provider-aws/blob/master/docs/book/src/topics/eks/index.md

クラスタ構築に関する内容をKubernetesのManifestに定義できるので、これをArgoCDで管理すると、クラスタ運用をGitOpsで宣言的に管理できるってわけです。


## やりかた

### 事前準備
- デプロイする用のクラスタをつくる
    - EKSでも、ローカルでkind、minikubeとかでも
- ArgoCDをインストールする
- Cluster API EKS support の初期設定
  - https://www.weave.works/blog/introducing-eks-support-in-cluster-api `Walkthrough of creating your first EKS cluster` のところ

このへんは割愛します。

### Cluster APIのリソースを作成
current-contextが作成したクラスタになっている状態で、下記を実行します。

```bash
export EXP_EKS=true
export EXP_MACHINE_POOL=true
export EXP_CLUSTER_RESOURCE_SET=true
clusterctl init --infrastructure=aws --control-plane=aws-eks --bootstrap=aws-eks
```
必要なリソースが作成されます。

```
$ kubectl get deployments.apps -A
NAMESPACE                       NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
capa-eks-bootstrap-system       capa-eks-bootstrap-controller-manager       1/1     1            1           1m
capa-eks-control-plane-system   capa-eks-control-plane-controller-manager   1/1     1            1           1m
capa-system                     capa-controller-manager                     1/1     1            1           1m
capi-system                     capi-controller-manager                     1/1     1            1           1m
capi-webhook-system             capa-controller-manager                     1/1     1            1           1m
capi-webhook-system             capa-eks-control-plane-controller-manager   1/1     1            1           1m
capi-webhook-system             capi-controller-manager                     1/1     1            1           1m
cert-manager                    cert-manager                                1/1     1            1           1m
cert-manager                    cert-manager-cainjector                     1/1     1            1           1m
cert-manager                    cert-manager-webhook                        1/1     1            1           1m
```

### クラスタの作成
下記のようなManifestを作成し、Githubリポジトリに置きます。

```yaml:cluster.yaml
apiVersion: cluster.x-k8s.io/v1alpha3
kind: Cluster
metadata:
  name: mycluster
  namespace: default
  annotations:
    link.argocd.argoproj.io/external-link: https://ap-northeast-1.console.aws.amazon.com/eks/home?region=ap-northeast-1#/clusters/mycluster
spec:
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1alpha3
    kind: AWSManagedControlPlane
    name: mycluster-control-plane
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
    kind: AWSManagedCluster
    name: mycluster
    
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
kind: AWSManagedCluster
metadata:
  name: mycluster
  namespace: default

---
apiVersion: controlplane.cluster.x-k8s.io/v1alpha3
kind: AWSManagedControlPlane
metadata:
  name: mycluster-control-plane
  namespace: default
spec:
  eksClusterName: mycluster
  region: ap-northeast-1
  version: v1.19
  associateOIDCProvider: true
```
このManifestではネットワーク設定がないので、VPCも新規に作成されます。
既存VPCに構築する場合は、`AWSManagedControlPlane` の `spec.networkSpec`に設定できます。
その他、設定の詳細は[このへん](https://pkg.go.dev/sigs.k8s.io/cluster-api-provider-aws/controlplane/eks/api/v1alpha3#AWSManagedControlPlaneSpec)から探っていく感じです。

ArgoCDでアプリケーションを作成し、Syncします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/2bb90a19-ae5c-36e0-5cdd-c663e255a35a.png)



`link.argocd.argoproj.io/external-link` にマネージメントコンソールのURLを入れとくと↓のように直接設定画面開けるので便利ですね。

`kubeconfig`もSecretとして作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/557bbcc2-f45c-afe1-6caa-e8137dc8a73b.png)

マネージドコンソールで見るとクラスタができています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/19891d35-f3cd-d453-7630-f3ce20703d07.png)


### マネージドノードグループを追加

マネージドノードグループをつくります。
こんなManifestをリポジトリに置きます。


```yaml:mng0.yaml
---
apiVersion: exp.cluster.x-k8s.io/v1alpha3
kind: MachinePool
metadata:
  name: mng-0
  namespace: default
spec:
  clusterName: mycluster
  replicas: 2
  template:
    metadata:
    spec:
      bootstrap:
        configRef:
          apiVersion: bootstrap.cluster.x-k8s.io/v1alpha3
          kind: EKSConfigTemplate
          name: mycluster-template
      clusterName: mycluster
      infrastructureRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
        kind: AWSManagedMachinePool
        name: mng-0
      version: v1.19.0
---
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
kind: AWSManagedMachinePool
metadata:
  name: mng-0
  namespace: default
spec:
  eksNodegroupName: mng-0
  additionalTags:
    env: test
  roleName: nodes.cluster-api-provider-aws.sigs.k8s.io
  diskSize: 50
  instanceType: t2.medium
  scaling:
    minSize: 1
    maxSize: 3

---
apiVersion: bootstrap.cluster.x-k8s.io/v1alpha3
kind: EKSConfigTemplate
metadata:
  name: mycluster-template
  namespace: default
spec:
  template: {}
```

ArgoCDでSyncします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/8679148d-5bb4-c05e-1daa-0c6235373e4e.png)

ノードグループが作成されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/15eda17d-5c7f-7282-24b6-84e8d47624e3.png)


### クラスタの削除
ArgoCDでアプリケーションを削除すればクラスタも削除されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/cfc3975e-159e-f6d4-8890-5587de1aa8b2.png)


## 参照
https://cluster-api.sigs.k8s.io/introduction.html
https://cluster-api-aws.sigs.k8s.io/introduction.html
https://cluster-api-aws.sigs.k8s.io/topics/eks/index.html
https://www.weave.works/blog/introducing-eks-support-in-cluster-api
https://pkg.go.dev/sigs.k8s.io/cluster-api
https://pkg.go.dev/sigs.k8s.io/cluster-api-provider-aws