【GitOps】ArgoCDとK8s Cluster APIでKubernetesクラスタをGitOpsする（ClusterOps）

## はじめに 
- `Cluster API`などのK8sクラスタ管理ツールと`GitOps`を組み合わせることを`ClusterOps`と呼んでいる記事がある。本記事でも`ClusterOps`と呼び、実機で検証してみることとする。

## 環境
- AWS EC2
  - Docker 20.10.13
  - Ubuntu 20.04.3
  - kind v0.12.0
  - (こちらの事前インストールは特に必要なし)clusterctl 1.1.3
  - （必要に応じて）Nginx 1.18.0
  - （必要に応じて）Helm v3.8.1

## 前提
- 上記の環境が用意できていること。（バージョンに関しては各自で適当なものを選択する。）

## 管理クラスタの作成

- 管理クラスタの設定ファイルを作成する

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

- 上記の設定ファイルをもとに、管理クラスタを作成する

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


## clusterctlのインストール

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


## ArgoCDのインストール

[ArgoCDドキュメント](https://argo-cd.readthedocs.io/en/stable/getting_started/)に従い、ArgoCDをインストールする。

<details><summary>（参考） Argo CDインストール手順</summary><div>

- Argo CDのインストール

```bash
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
```　

- Argo CDのCLIのインストール

```bash
sudo curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo chmod +x /usr/local/bin/argocd
```

- Argo CDのUIに外部からアクセスする。<EC2のプライベートIPを設定することに注意>

```bash
kubectl port-forward svc/argocd-server -n argocd 8080:443 --address=<EC2のプライベートIPアドレス>
```

- Nginxをインストールして、外部（リモート）からArgo CDのWeb UIにアクセスできるようにする。

```bash
sudo apt update
sudo apt install nginx
```

- `/etc/nginx/nginx.conf` に下記の内容を記載する。`listen`にはリモートサーバのIPアドレスを、`proxy_pass`にはKindのコンテナのIPアドレスを記載する

```bash:nginx.conf
stream {
  server {
      listen 172.31.24.235;
      #TCP traffic will be forwarded to the specified server
      proxy_pass 192.168.49.2;
  }
}
```

</div></details>

## Helmのインストール

<details><summary>（参考） Helmインストール手順</summary><div>

- https://helm.sh/ja/docs/intro/install/ を参考にHelmをインストールする。

```bash
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
```
</div></details>

## 管理クラスタの初期化

- Docker環境でCluster APIを利用できるように、初期化でDockerのオプションを指定する

```bash
clusterctl init --infrastructure docker
```

- 下記のようなログが末尾に出力される

```bash
clusterctl generate cluster [name] --kubernetes-version [version] | kubectl apply -f -
```

## ワークロードクラスタの作成

- 上記のログを参考にして、ワークロードクラスタを作成する。

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

kubectl apply -f capi-quickstart.yaml
```

- この時点で二つの`kind`クラスタを確認できる

```bash
$ kind get clusters
capi-quickstart
kind
```

- Cluster APIの動作確認ができたので、ワークロードクラスタを削除する

```bash
kubectl delete cluster capi-quickstart
```

## ClusterOpsを実装する

- 先ほどまでで、`ArgoCD`と`Cluster API`の動作が確認できたので、次に`ClusterOps`を実装する。

- ArgoCDの設定ファイルを作成する

```argocd-application-capi.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: cluster-api
  namespace: argocd
spec:
  destination:
    namespace: 'default'
    server: https://kubernetes.default.svc
  project: default
  source:
    helm:
      valueFiles:
      - values.yaml
    path: charts/capi-docker
    repoURL: https://github.com/rinakamura/clusterops_demo
    targetRevision: HEAD
  syncPolicy: {}
```

- 上記の設定ファイルをapplyする。
```bash
kubectl apply -f argocd-application-capi.yaml
```

- Argo のUIが変化して、先程のアプリケーションが表示される

![argocd_project.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475824/ebbce3ba-5aa8-411d-b933-9fce1c0a8f16.png)

- GitHubと同期する。GitHubにはHelmの設定ファイルを配置する。
    - （配置例）https://github.com/rinakamura/clusterops_demo

- この状態でArgo UIからSync APPSボタンを押すと、クラスタが作成される。
![argo_cd_sync.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475824/e58fdee3-01db-8560-3409-23f9bc24287d.png)

- CLI上でもクラスタが作成されていることが確認できる。

```bash
$ kind get clusters
capi-quickstart
kind
```

## ワークロードクラスタの`kubeconfig`を取得し、`Pod`が動作しているか確認する。

- `kubeconfig`を取得する

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

- `Pod`が動作しているか確認。

```bash
$ kubectl --kubeconfig capi-quickstart.kubeconfig get po -A
```

<details><summary>（参考）出力</summary><div>

```bash
kube-system   etcd-capi-quickstart-control-plane-7vqrr                      1/1     Running   0             16m
kube-system   etcd-capi-quickstart-control-plane-tc4tw                      1/1     Running   0             17m
kube-system   kube-apiserver-capi-quickstart-control-plane-7vqrr            1/1     Running   1 (16m ago)   16m
kube-system   kube-apiserver-capi-quickstart-control-plane-tc4tw            1/1     Running   0             17m
kube-system   kube-controller-manager-capi-quickstart-control-plane-7vqrr   1/1     Running   0             14m
kube-system   kube-controller-manager-capi-quickstart-control-plane-tc4tw   1/1     Running   0             17m
kube-system   kube-proxy-47dt4                                              1/1     Running   0             17m
kube-system   kube-proxy-5j6f4                                              1/1     Running   0             16m
kube-system   kube-proxy-bn26b                                              1/1     Running   0             16m
kube-system   kube-proxy-sczlt                                              1/1     Running   0             16m
kube-system   kube-proxy-z5rfv                                              1/1     Running   0             16m
kube-system   kube-scheduler-capi-quickstart-control-plane-7vqrr            1/1     Running   0             16m
kube-system   kube-scheduler-capi-quickstart-control-plane-tc4tw            1/1     Running   0             17m
```

</div></details>

正常に動作しているようだ。


## 最後に

本記事では`Cluster API`と`Argo CD`を用いて、K8sクラスタをGitOps的に管理する手法を実践しました。何かコメント等あればコメント欄にご記入ください。