HelmでMongoDBをInstallしてみる

# 概要
これまでKubernetes(以下k8s)に触ってきて、ある程度理解が深まってきたなと実感していたのですが、Helmに関してはよく分かっていない状態でした。  
キャッチアップする必要があると思い、初歩的な内容から勉強しました。  
用語の整理から初めて、Helmのインストール、MongoDBを起動させるところまでを記載します。

# 環境
OS：WSL2 Ubuntu 22.04  
k8s server：1.27.2

# 用語
Helmに関する用語をまずは整理しました。  
  

|  用語  |  意味  |
| ---- | ---- |
|  Helm  |  k8s用のパッケージマネージャーとよく説明される。つまり、アプリケーションの動作に必要なk8sリソースの一式(Pod,Service,Secretなど)を簡単にデプロイできて更にアップグレードやロールバックも出来るツール。簡単にというのは、通常であれば個々に用意したマニフェストをデプロイする必要があり手間がかかるが、Helmを利用するとそれらをまとめることが出来る、ということ。  |
|  Chart  |  k8sリソースをデプロイするためのテンプレートファイルや設定ファイルなどをまとめたファイル群。  |
|  Repository  |  Chartの保存場所。Docker imageのRepositoryとは別物であるので注意。公式の Public Repositoryとして、安定版のstableと非安定版のincubatorがある。基本的にはstableを使えば良い。  |
|  Install  |  Chartを使ってアプリケーションをデプロイすること。  |
|  Release  |  Installされたアプリケーションの実体。ChartがクラスだとしたらReleaseはChartから生成されたインスタンスに相当する。  |

# Helm インストール
私の環境にはまだHelmが入っていなかったため、インストールから実施します。  
[こちら](https://helm.sh/ja/docs/intro/install/)	に記載のとおり方法はいくつかありますが、今回はバイナリファイルを展開する形でインストールします。

次のURLからバイナリファイルをダウンロードし、マシンに格納します。
https://github.com/helm/helm/releases

マシンへの格納後、ファイルを解凍します。
```
$ tar -zxvf helm-v3.13.1-linux-amd64.tar.gz
linux-amd64/
linux-amd64/LICENSE
linux-amd64/helm
linux-amd64/README.md
```

helmバイナリを/usr/local/binに移動します。
```
$ sudo mv linux-amd64/helm /usr/local/bin/helm
$ which helm
/usr/local/bin/helm
```

helmがインストールされていることを確認します。
```
$ helm version
WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /home/hoge/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /home/hoge/.kube/config
version.BuildInfo{Version:"v3.13.1", GitCommit:"3547a4b5bf5edb5478ce352e18858d8a552a4110", GitTreeState:"clean", GoVersion:"go1.20.8"}
```

私の環境ではWARNINGメッセージが表示されました。  
これは~/.kube/configに対して、所有グループ/その他からのread権限がついているため表示されます。  
パーミッションを600に変更してください。

# Helmを使ってMongoDBをInstallする
アプリケーションをInstallするには、次の2つの方法があります。
1. stable Repositoryなどで公開されているChartを直接利用する。
2. ローカルマシンにChartを用意し、そこからInstallする。  

Chartのカスタマイズをする場合には2の方法が有効ですが、今回はそこまでは実施しません。  
1の方法で実施していきます。  

## ローカルマシンにRepositoryを登録
`helm repo add ＜Repository名＞ <URL＞`を実行し、Chartを提供しているRepositoryをローカルマシン上に登録する必要があります。  
今回はstable Repositoryを利用しようと思うので、こちらをaddします。

```
$ helm repo add stable https://charts.helm.sh/stable
stable has been added to your repositories
```

ここで登録したRepositoryの情報は、~/.config/helm/repositories.yamlに記載されています。

また、`helm search repo <chart名>`を実行することで、登録したRepositoryにて提供されているChartを検索できます。MongoDBのChartを検索してみます。

```
$ helm search repo mongodb
NAME                                    CHART VERSION   APP VERSION     DESCRIPTION
stable/mongodb                          7.8.10          4.2.4           DEPRECATED NoSQL document-oriented database tha...
stable/mongodb-replicaset               3.17.2          3.6             DEPRECATED - NoSQL document-oriented database t...
stable/prometheus-mongodb-exporter      2.8.1           v0.10.0         DEPRECATED A Prometheus exporter for MongoDB me...
stable/unifi                            0.10.2          5.12.35         DEPRECATED - Ubiquiti Network's Unifi Controller
```
Chartは`<Repository名>/<Chart名>`という形で表示されます。
一番上のstable/mongodbというChartを利用したいと思います。
なお、コマンド実行結果で表示されているCHART VERSIONは文字通りChartのバージョンのことを指しており、  
APP VERSIONはアプリケーションのバージョンなのでMongoDBのバージョンを指しています。  


## Repositoryをアップデートする
ローカルマシンに登録したRepositoryの情報は時間が経つにつれて情報が古くなるので、Installする前にRepositoryをアップデートしておきます。

```
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈Happy Helming!⎈
```

## Installされるk8sリソースを確認する
Installによって、実際にどのようなパラメータでどのようなk8sリソースが作成されるのかを事前に確認したい場合は、`helm template <release名> <リポジトリ名>/<Chart名>` を実行することでyamlを確認することができます。

```
$ helm template mongodb-release stable/mongodb
WARNING: This chart is deprecated
---
# Source: mongodb/templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mongodb-release
  labels:
    app: mongodb
    chart: mongodb-7.8.10
    release: "mongodb-release"
    heritage: "Helm"
type: Opaque
data:
  mongodb-root-password: "dkxpMDJxeTVLWQ=="
---
# Source: mongodb/templates/pvc-standalone.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  labels:
    app: mongodb
    chart: mongodb-7.8.10
    heritage: Helm
    release: mongodb-release
  name: mongodb-release
spec:
  accessModes:
    - "ReadWriteOnce"
  resources:
    requests:
      storage: "8Gi"
---
# Source: mongodb/templates/svc-standalone.yaml
apiVersion: v1
kind: Service
metadata:
  name: mongodb-release
  labels:
    app: mongodb
    chart: mongodb-7.8.10
    release: "mongodb-release"
    heritage: "Helm"
spec:
  type: ClusterIP
  ports:
  - name: mongodb
    port: 27017
    targetPort: mongodb
  selector:
    app: mongodb
    release: "mongodb-release"
---
# Source: mongodb/templates/deployment-standalone.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongodb-release
  labels:
    app: mongodb
    chart: mongodb-7.8.10
    release: "mongodb-release"
    heritage: "Helm"
spec:
  strategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: mongodb
      release: "mongodb-release"
  template:
    metadata:
      labels:
        app: mongodb
        release: "mongodb-release"
        chart: mongodb-7.8.10
    spec:
      securityContext:
        fsGroup: 1001
      initContainers:
      containers:
      - name: mongodb-release
        image: docker.io/bitnami/mongodb:4.2.4-debian-10-r0
        imagePullPolicy: "IfNotPresent"
        securityContext:
          runAsNonRoot: true
          runAsUser: 1001
        env:
        - name: MONGODB_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mongodb-release
              key: mongodb-root-password
        - name: MONGODB_SYSTEM_LOG_VERBOSITY
          value: "0"
        - name: MONGODB_DISABLE_SYSTEM_LOG
          value: "no"
        - name: MONGODB_ENABLE_IPV6
          value: "no"
        - name: MONGODB_ENABLE_DIRECTORY_PER_DB
          value: "no"
        ports:
        - name: mongodb
          containerPort: 27017
        livenessProbe:
          exec:
            command:
            - mongo
            - --eval
            - "db.adminCommand('ping')"
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 6
        readinessProbe:
          exec:
            command:
            - mongo
            - --eval
            - "db.adminCommand('ping')"
          initialDelaySeconds: 5
          periodSeconds: 10
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 6
        volumeMounts:
        - name: data
          mountPath: /bitnami/mongodb
          subPath:
        resources:
          {}
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: mongodb-release
```

secret,pvc,service,deploymentが作成されることや、それらのパラメータがどうなっているのかを確認できました。

## MongoDBをInstallする
ここまで実施したら、MongoDBをInstallしてみます。
`helm install <release名> <リポジトリ名>/<Chart名>`で Installできます。  

```
$ helm install mongodb-release stable/mongodb
WARNING: This chart is deprecated
NAME: mongodb-release
LAST DEPLOYED: Tue Nov 21 16:24:00 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
This Helm chart is deprecated

Given the `stable` deprecation timeline (https://github.com/helm/charts#deprecation-timeline), the Bitnami maintained Helm chart is now located at bitnami/charts (https://github.com/bitnami/charts/).

----以下省略----
```

Installができたら、Releaseが作成されたはずなので `helm list` で確認してみます。
mongodb-releaseが作成したReleaseになります。
```
$ helm list
NAME            NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
mongodb-release default         1               2023-11-21 16:24:00.056757693 +0900 JST deployed        mongodb-7.8.10  4.2.4
```

PodやServiceなどのk8sリソースも作成されているかどうか確認してみます。
```
$ kubectl get pod
NAME                                  READY   STATUS    RESTARTS       AGE
mongodb-release-6b4b7b9c8-tcf2p       1/1     Running   0              54s

$ kubectl get svc
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE				
mongodb-release     ClusterIP   10.43.201.156   <none>        27017/TCP   77s

$ kubectl get pvc
NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mongodb-release                    Bound    pvc-6e116588-0f0b-4851-83ee-44408a59e3dc   8Gi        RWO            local-path     61s

$ kubectl get secret
NAME                                    TYPE                             DATA   AGE
mongodb-release                         Opaque                           1      6m56s
sh.helm.release.v1.mongodb-release.v1   helm.sh/release.v1               1      6m56s
```

# MongoDBをUninstallする
検証用途で作成したため、最後に`helm uninstall <release名>` でUninstallしておきます。

```
$ helm uninstall mongodb-release
release "mongodb-release" uninstalled
```

`helm list`でReleaseが削除されていることが確認できます。

```
$ helm list
NAME    NAMESPACE       REVISION        UPDATED STATUS  CHART   APP VERSION
```

# 所感
Chartの構造を理解することや設定ファイルのカスタマイズを次回試したいと思います。

# 参考
次のページを参考にさせていただきました。  
https://helm.sh/ja/docs/intro/  
https://knowledge.sakura.ad.jp/23603/  
https://qiita.com/thinksphere/items/5f3e918015cf4e63a0bc