fluxのget startedをやった

# はじめに
業務でfluxを使うので、改めてget startedを一通り舐めてみました。その時のメモをまとめ直して、備忘録的に投稿しておきます。

# fluxのコアコンセプト
fluxを使う上で、fluxのコアコンセプトを把握しておく必要があリます。fluxを使うにあたって概念を理解しておく必要があるし、単語が頻繁にドキュメントに登場するので、内容を理解していなければならなりません。
**gitops**
Githubなどのバージョンコントロールシステム上に、自分たちのサービスやシステムのあるべき姿を宣言的に記載した設定ファイルを配置し、その変更を追跡して自動適用する仕組み。
**Sources**
システムの設定ファイルを保存する場所のこと。Gitリポジトリ、Helmリポジトリのほか、Bucketと呼ばれるアーティファクトなどのアセットを保管しておくストレージを選択できる。
**Reconciliation**
システムやサービスの現在の状態を、設定ファイルに記載されたあるべき姿に合わせていく動作のこと。Fluxが自動でやってくれる。
**Kustomization**
Fluxをインストールすると追加されるカスタムリソースで、どのSourceの、どのパスにある内容でReconciliationするかを記述する。
**Bootstrap**
Fluxのコンポーネントや各種カスタムリソースをインストールするプロセスをBootstrapと呼ぶ。

# Get Started
Get Startedを実行する前に、あらかじめ以下のリソースを用意しておく必要があります。

* Repo権限を持ったGithubのPAT(Personal Access Token)
* Kubernetes cluster

Repo権限を持ったPATは、Githubの右上のユーザーアイコン>Settings>Developer Settings>Personal Access Token>Generate New Tokenから作成できます。作成後にPATのシークレットが表示されるので、以下の環境変数に保存します(後で使うのでユーザ名の環境変数も用意します)。

```
export GITHUB_TOKEN=<your-token>
export GITHUB_USER=<your-username>
```

Kubernets Clusterは何を使っても良いですが、今回はminikubeを使用しました。minikubeとkubernetesのバージョンは以下の通りです。

```
$ minikube version
minikube version: v1.24.0
commit: 76b94fb3c4e8ac5062daf70d60cf03ddcc0a741b
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.1", GitCommit:"86ec240af8cbd1b60bcc4c03c20da9b98005b92e", GitTreeState:"clean", BuildDate:"2021-12-16T11:33:37Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.3", GitCommit:"c92036820499fedefec0f847e2054d824aea6cd1", GitTreeState:"clean", BuildDate:"2021-10-27T18:35:25Z", GoVersion:"go1.16.9", Compiler:"gc", Platform:"linux/amd64"}
$
```

これで必要なリソースが用意できたので、Get Startedを一通り進めていきます。

## 1. flux cliのインストール
fluxは操作にコマンドラインツールを使用します。今回はMacで操作したのでHomebrewでインストールしますが、インストール用のshell scriptが用意されているのでそちらからインストールすることもできます。

```
brew install fluxcd/tap/flux
```

## 2. Kubernetesクラスタの要件チェック
fluxを実行するための要件をクラスタが満たすかチェックします。出力を見る限りクラスタのバージョンしか見ていない？

```
$ flux check --pre
► checking prerequisites
✔ Kubernetes 1.22.3 >=1.19.0-0
✔ prerequisites checks passed
$
```

## 3. flux コンポーネントのデプロイ
`flux bootstrap`コマンドを使用して行います。githubをsourceにする場合、サブコマンドまで含めると`flux bootstrap github`になります。

```
flux bootstrap github \
  --owner=$GITHUB_USER \
  --repository=fleet-infra \
  --branch=main \
  --path=./clusters/my-cluster \
  --personal
```

この時、環境変数`GITHUB_TOKEN`からPATのシークレットを取得しているので、あらかじめ定義しておく必要があります。もしこの環境変数がない場合、`flux`コマンドから対話的に質問されます。

:::note info
flux bootstrapコマンドをfluxインストール済みのクラスタに実行した場合、必要があればコンポーネントのアップデートが行われます。bootstrapコマンドは冪等であり、複数回実行しても安全なことがドキュメントに明記されています。
:::

:::note warn
この操作によりgithub上にfleet-infraという名前のリポジトリが作成され、Deploy Keyが登録されます。このDeploy Keyは予め作成したPATに紐づいているため、PATが期限切れや削除などで無功になると、全てのDeploy Keyが無功になり、fluxがReconciliationできなくなります。
:::

## 4. fleet-infra リポジトリをクローンする
fleet-infraリポジトリを手元にクローンします。先程のbootstrap操作で、クラスタのfluxはfleet-infraリポジトリの/clusters/my-clusterディレクトリをsourceとしてreconciliationするようになっているので、このディレクトリに設定ファイルを追加していきます。

```
git clone https://github.com/$GITHUB_USER/fleet-infra
cd fleet-infra
```

## 5. podinfo repositoryをfluxに追加
サンプルアプリケーションとして、podinfoを使用します。このアプリケーションはgithub上で公開されているので、まずはそのリポジトリをsourceとして追加します。

```
flux create source git podinfo \
  --url=https://github.com/stefanprodan/podinfo \
  --branch=master \
  --interval=30s \
  --export > ./clusters/my-cluster/podinfo-source.yaml
```

上記のコマンドを実行すると、./clusters/my-cluster/podinfo-source.yamlに`kind: GitRepository`リソースのマニフェストが作成されます。このリソースはpodinfoアプリケーションのリポジトリのURLと対象となるブランチを示しています。
このマニフェスト自体の適用もfluxを利用して行います。これにより、今後podinfoのリポジトリが変更になってもマニフェストを変更することによって自動で変更が適用され、設定を記述的に行うことができます。
作成したマニフェストをリモートリポジトリにpushします。

```
git add -A && git commit -m "Add podinfo GitRepository"
git push
```

これにより、`podinfo`という`gitrepository`リソースがクラスタに作成されます。

```
$ kubectl get gitrepository -n flux-system
NAME          URL                                        READY   STATUS                                                              AGE
flux-system   ssh://git@github.com/uS-aito/fleet-infra   True    Fetched revision: main/0daf1b33f931f59452c3a5a0fd3248f5100a98d8     45h
podinfo       https://github.com/stefanprodan/podinfo    True    Fetched revision: master/132f4e719209eb10b9485302f8593fc0e680f4fc   2m9s
$
```

## 6. podinfo applicationのデプロイ
`Kustomization`リソースを作成します。このリソースの中で、ソースはどこかや、何分おきにそのソースを確認するか、そのソースリポジトリの中のどのディレクトリの内容を適用するか、を設定しています。

```
flux create kustomization podinfo \
  --target-namespace=default \
  --source=podinfo \
  --path="./kustomize" \
  --prune=true \
  --interval=5m \
  --export > ./clusters/my-cluster/podinfo-kustomization.yaml
```

:::note info
fluxを使用していると、二種類のkind: Kustomizationのリソースを操作することになるので、注意が必要です。
kustomization.kustomize.toolkit.fluxcd.ioはfluxのカスタムリソースで、reconciliationのソースや動作の内容を記述しています。kustomization.kustomize.config.k8s.ioはkubernetesのKubernetes Resource Model (KRM) objectを記述するためのリソースで、適用するマニフェストの一覧やパッチなどを記述することができます。
fluxでは、kustomization.kustomize.config.k8s.ioの.spec.resourcesにアプリケーションで使用するマニフェストの一覧を記述しておき、kustomization.kustomize.toolkit.fluxcd.ioで前述のkustomizationファイルを指定する利用方が多くなります。podinfoでは、リポジトリのkustomizeディレクトリにkustomizationファイルが保存されているため、そのディレクトリをpathで指定しています。
:::

作成した内容をpushします。fluxが変更を検出し、reconciliationします。

```
git add -A && git commit -m "Add podinfo Kustomization"
git push
```

```
$ flux get kustomizations
flux-system     True    Applied revision: main/77d6c9cff44fff6220bd8de07cee745c1d96545e main/77d6c9cff44fff6220bd8de07cee745c1d96545e   False
podinfo True    Applied revision: master/132f4e719209eb10b9485302f8593fc0e680f4fc       master/132f4e719209eb10b9485302f8593fc0e680f4fc False
$
```

## 7. podinfoのカスタマイズ
podinfoは他人のリポジトリなので、その内容を任意に書き換えることはできません。このため、内容をカスタマイズするために、[in-line patches](https://fluxcd.io/docs/components/kustomize/kustomization/#override-kustomize-config)という仕組みが用意されています。kustomizationリソースの`.spec`に以下の項目を追加すると、podinfoのマニフェストを書き換えることができます。

```
  patches:
    - patch: |-
        apiVersion: autoscaling/v2beta2
        kind: HorizontalPodAutoscaler
        metadata:
          name: podinfo
        spec:
          minReplicas: 3             
      target:
        name: podinfo
        kind: HorizontalPodAutoscaler
```

# リソースのクリーンアップ
本章は大元のget startedには含まれていませんが、クリーンアップを行わないとget startedで作成したリソースやgithubのfleet-infraリポジトリが残ったままになるため、それらの削除を行います。
## podinfo リソースの削除
podinfoの`gitrepository`や`kustomization`を削除します。
1. podinfo-kustomization.yamlとpodinfo-source.yamlの内容を全てコメントアウトしてpushする。
2. fluxをアンインストールする。以下のコマンドでfluxのCRD及びコンポーネントを全て削除する。

```
flux uninstall --namespace=flux-system
``` 

3. podinfo及びfluxが削除されたことを確認する。podinfoのdeployment及びserviceが削除されたことを確認する。

```
$ kubectl -n default get deployments,services
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   46h
$
```

fluxのnamespaceが削除されたことを確認する。

```
$ kubectl get ns
NAME              STATUS   AGE
default           Active   46h
kube-node-lease   Active   46h
kube-public       Active   46h
kube-system       Active   46h
$
```
## fleet-infra リポジトリの削除
fleet-infraリポジトリ > settings > Danger ZoneのDelete this repositoryをクリックします。リポジトリ名を入力し、削除ボタンをクリックします。

以上でリソースのクリーンアップは完了です。

# まとめ
fluxのget startedを一通り実行することで、fluxを使用したGitOpsの流れを確認することができました。
`kustomization.kustomize.config.k8s.io`に適用するマニフェストの一覧を作成し、このマニフェストがあるリポジトリを示す`gitresource`リソースと`kustomization.kustomize.toolkit.fluxcd.io`リソースを作成することで、reconciliationが実行されます。