Helmの使い方を3分で理解する

Kubernetesクラスタに Helmを使ったセットアップが増えているように思います。そこで、Helmコマンドの基本的な使い方を整理しました。


## Helmの3大コンセプト

Helmは、以下の3点を押さえておくと、理解しやすくなります。

#### (1) チャートは、ヘルムのパッケージである。
チャートには、ツール、アプリケーション そして サービスなどをKubernetes クラスタで実行に必要なすべてのリソース定義が入っている。類似の概念として、RedHat系Linuxのyumコマンド、Debian系Linuxのaptコマンドなどがある。

#### (2) リポジトリは、チャートを集め共有するための場所である。
類似の概念では、Perl言語のCPANリポジトリ、Fedora Package Database などがあるが、Kubernetes 用である。

#### (3) リリースは、Kubernetes上で実行されているチャートのインスタンスである。
一つのKubernetesクラスタに、一つのチャートを複数回インストールして実行できる。インストールする度に、新しいリリースが作成される。




## Helmを使ったインストール

Helmのパッケージであるチャートを検索する。

~~~
$ helm search stable/mysql
NAME           HART VERSION  APP VERSION  DESCRIPTION                                                 
stable/mysql   0.15.0        5.7.14       Fast, reliable, scalable, and easy to use open-source rel...
~~~

同一のKubernetesクラスタに、二つのMySQLインスタンス（リリース）を起動してみる。

~~~
$ helm install -n mysql-1 stable/mysql
$ helm install -n mysql-2 stable/mysql
~~~

Helmでインスタンス化したパッケージであるリリースをリストした。

~~~
$ helm list
NAME   	REVISION  UPDATED                   STATUS    CHART         APP VERSION	NAMESPACE
mysql-1	1         Tue Feb 26 16:34:14 2019  DEPLOYED  mysql-0.15.0  5.7.14     	default  
mysql-2	1         Tue Feb 26 16:34:22 2019  DEPLOYED  mysql-0.15.0  5.7.14     	default  
~~~

これらのMySQLは、Deploymentコントローラ下で実行され、サービスでクラスタ内に公開されている。 

~~~
$ kubectl get deploy
NAME             DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
mysql-1          1         1         1            1           6m4s
mysql-2          1         1         1            1           5m56s

$ kubectl get svc
NAME          TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
mysql-1       ClusterIP      172.21.92.138   <none>           3306/TCP       7m10s
mysql-2       ClusterIP      172.21.37.11    <none>           3306/TCP       9m12s
~~~

MySQLに必要な永続ストレージも、上記のコマンドだけでデプロイされ、ポッドにマウントされている。`helm install チャート名` で必要なリソースも確保されるので便利です。  決まりパターンを実行するのであれば、helmを使わない手は無いように思える。

~~~
$ kubectl get pvc
NAME      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
mysql-1   Bound    pvc-ea7a9751-3998-11e9-b1f5-f2b8cea2bb42   20Gi       RWO            ibmc-file-bronze   6m14s
mysql-2   Bound    pvc-ef314910-3998-11e9-b1f5-f2b8cea2bb42   20Gi       RWO            ibmc-file-bronze   6m6s
~~~

## インストールの削除

Helmでインストールしたリストを表示、名前を指定して削除を実行する。

~~~
$ helm list
NAME   	REVISION	UPDATED                 	STATUS  	CHART       	APP VERSION	NAMESPACE
mysql-1	1       	Tue Feb 26 16:34:14 2019	DEPLOYED	mysql-0.15.0	5.7.14     	default  
mysql-2	1       	Tue Feb 26 16:34:22 2019	DEPLOYED	mysql-0.15.0	5.7.14     	default  

$ helm delete mysql-1
release "mysql-1" deleted
~~~


## 事前にカスタマイズする方法

基本的な流れは、Helmチャートでカスタマイズできる項目をYAMLファイルに書き出して、編集後に適用する。`helm inspect values チャート名` とすることで、変更可能なパラメータのYAMLファイルを出力するので、編集して、-f オプションで読み込ませてインストールする。

~~~
$ helm inspect values stable/mysql > config.yml
$ vi config.yml
$ helm install -n mysql-3 -f config.yml stable/mysql
~~~

コマンドラインで、変数名を指定して値をセットする方法もあるが、変更の記録とする上で、YAMLに書き出すと良いと思う。


## Helmで起動したリリースの利用方法

`helm search` でチャートを探すか、Helm チャートのGitHub https://github.com/helm/charts/ から探したチャートの利用方法は、`helm inspect チャート名` で表示されるものか、GitHubのReadme.md を参照する。また、インストールすると、必要な情報はターミナルに表示されるのでメモしておく。

`helm inspect` で表示される例

~~~
$ helm inspect stable/mysql
appVersion: 5.7.14
description: Fast, reliable, scalable, and easy to use open-source relational database
  system.
＜以下省略＞
~~~

`helm install` 実行時に表示される例 

~~~
$ helm install -n mysql-1 stable/mysql
NAME:   mysql-1
LAST DEPLOYED: Tue Feb 26 16:34:14 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Pod(related)
NAME                      READY  STATUS   RESTARTS  AGE
mysql-1-7fb5fc47c5-5z7d7  0/1    Pending  0         0s

==> v1/Secret
NAME     TYPE    DATA  AGE
mysql-1  Opaque  2     0s

==> v1/ConfigMap
NAME          DATA  AGE
mysql-1-test  1     0s

==> v1/PersistentVolumeClaim
NAME     STATUS   VOLUME            CAPACITY  ACCESS MODES  STORAGECLASS  AGE
mysql-1  Pending  ibmc-file-bronze  0s

==> v1/Service
NAME     TYPE       CLUSTER-IP     EXTERNAL-IP  PORT(S)   AGE
mysql-1  ClusterIP  172.21.92.138  <none>       3306/TCP  0s

==> v1beta1/Deployment
NAME     DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
mysql-1  1        1        1           0          0s


NOTES:
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
mysql-1.default.svc.cluster.local

To get your root password run:

    MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default mysql-1 -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)

To connect to your database:

1. Run an Ubuntu pod that you can use as a client:

    kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il

2. Install the mysql client:

    $ apt-get update && apt-get install mysql-client -y

3. Connect using the mysql cli, then provide your password:
    $ mysql -h mysql-1 -p

To connect to your database directly from outside the K8s cluster:
    MYSQL_HOST=127.0.0.1
    MYSQL_PORT=3306

    # Execute the following command to route the connection:
    kubectl port-forward svc/mysql-1 3306

    mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}
~~~


## Helmコマンドのインストール

Helmは、管理用パソコンにコマンドをインストールして、Kubernetes クラスタに `tiller` をインストールする。 

インストールする前に、kubectl でクラスタにアクセスできることを確認しておきます。

~~~
$ kubectl get node
NAME           STATUS   ROLES    AGE   VERSION
10.193.10.44   Ready    <none>   11d   v1.12.5+IKS
10.193.10.7    Ready    <none>   11d   v1.12.5+IKS
10.193.10.8    Ready    <none>   11d   v1.12.5+IKS
~~~

helmクライアントをインストールする。インストールする方法は、いくつかあります。 IBM Cloud CLI のインストーラを利用すると、kubectlコマンドと一緒にインストールされます。

* INSTALLING THE HELM CLIENT https://helm.sh/docs/using_helm/#installing-the-helm-client
* Getting started with the IBM Cloud CLI https://console.bluemix.net/docs/cli/index.html#overview

インストールして、helmコマンドを実行しみると、Clientのバージョンは表示されますが、サーバー側は、tillerが見つからないというエラーが発生します。

~~~
$ helm version
Client: &version.Version{SemVer:"v2.12.3", GitCommit:"eecf22f77df5f65c823aacd2dbd30ae6c65f186e", GitTreeState:"clean"}
Error: could not find tiller
~~~

Kubernetesクラスタに、tiller をインストールすることで、Helm のインストールが完了します。クラウドプロバイダーによってYAMLが少し異なるようなので、各社クラウドプロバイダーのガイドに従って、インストールします。　次は IBM の IKS の例です。

~~~
$ kubectl apply -f https://raw.githubusercontent.com/IBM-Cloud/kube-samples/master/rbac/serviceaccount-tiller.yaml
serviceaccount/tiller created
clusterrolebinding.rbac.authorization.k8s.io/tiller created
~~~

それぞれのクラウド・プロバイダーのガイドに従って、初期化します。

~~~
$ helm init --service-account tiller
$HELM_HOME has been configured at /Users/maho/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!
~~~

tillerが動作していることを確認します。

~~~
$ kubectl get serviceaccount -n kube-system | grep tiller
tiller                               1         24s
~~~

これで、Kubernetesクラスタのtiller とも繋がり、`helm version`が動作するようになりました。

~~~
$ helm version
Client: &version.Version{SemVer:"v2.12.3", GitCommit:"eecf22f77df5f65c823aacd2dbd30ae6c65f186e", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.12.3", GitCommit:"eecf22f77df5f65c823aacd2dbd30ae6c65f186e", GitTreeState:"clean"}
~~~



## Helm リポジトリの追加

クラウドベンダーが独自に提供する Helm チャートのリポジトリを追加するには、`helm repo add` コマンドを利用します。IBMクラウドのドキュメントに従って、以下の二つを追加しました。

~~~
$  helm repo add ibm https://registry.bluemix.net/helm/ibm
"ibm" has been added to your repositories
$  helm repo add ibm-charts https://registry.bluemix.net/helm/ibm-charts
"ibm-charts" has been added to your repositories
$ helm repo add ibm-stable https://raw.githubusercontent.com/IBM/charts/master/repo/stable
"ibm-stable" has been added to your repositories
$ helm repo add ibm-community https://raw.githubusercontent.com/IBM/charts/master/repo/community
"ibm-community" has been added to your repositories
~~~

updateを実行して、リストを最新化しておきます。

~~~
$  helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "ibm" chart repository
...Successfully got an update from the "ibm-charts" chart repository
...Successfully got an update from the "stable" chart repository
...Successfully got an update from the "kubernetes" chart repository
Update Complete. ⎈ Happy Helming!⎈ 
~~~

現在のリポジトリのリストを表示するには、`helm repo list` を実行します。

~~~
$ helm repo list
NAME      	URL                                             
stable    	https://kubernetes-charts.storage.googleapis.com
local     	http://127.0.0.1:8879/charts                    
ibm       	https://registry.bluemix.net/helm/ibm           
ibm-charts	https://registry.bluemix.net/helm/ibm-charts    
kubernetes	https://kubernetes-charts.storage.googleapis.com
~~~

リポジトリに登録されたチャートをリストするには、`helm search`を実行します。

~~~
$ helm search 
NAME                                          	CHART VERSION	APP VERSION                             	DESCRIPTION                                                 
ibm-charts/ibm-ace-dashboard-dev              	1.1.0        	                                        	App Connect Enterprise Dashboard                            
ibm-charts/ibm-ace-server-dev                 	1.1.0        	                                        	This helm chart is used by the IBM App 
＜以下省略＞
~~~


## 参考資料


* [Setting up Helm in IBM Cloud Kubernetes Service](https://console.bluemix.net/docs/containers/cs_integrations.html#helm)
* [Installing Helm](https://helm.sh/docs/using_helm/#installing-helm)