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


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

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

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

Cluster API

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で宣言的に管理できるってわけです。

やりかた

事前準備

このへんは割愛します。

Cluster APIのリソースを作成

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

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リポジトリに置きます。

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に構築する場合は、AWSManagedControlPlanespec.networkSpecに設定できます。
その他、設定の詳細はこのへんから探っていく感じです。

ArgoCDでアプリケーションを作成し、Syncします。

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

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

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

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

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

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します。

ノードグループが作成されています。

クラスタの削除

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

参照

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