helmの過去、現在、未来

## はじめに
Kubernetesの`helm`ご存知でしょうか?
`helm`は、`apt`や`yum`の様なKubernetes版パッケージマネージャです。

今年の6月ごろに[k8s meetup Tokyo #2](https://k8sjp.connpass.com/event/33508/)でhelmの話をした時はまだ使える状態ではなく
`helm`の元となっているDeisの`helm-classic`をオススメしていました。[[参照](https://speakerdeck.com/ladicle/kubernetes-helm-and-helmc?slide=1)]

現在の`helm`バージョンは2.1.3、十分に使るようになってます。
`helm-classic`には`PetSet`や`ScheduledJob`など新機能に対応し無いので`hlem`への移行をオススメします。

## 用語

読み進めていくにあたり最低限必要な用語の定義です。

|Name|Description|
|----|-----------|
|Package|`Jenkins`, `Spark`などの`helm`を使ってk8s上にインストールアプリケーション|
|Chart|パッケージを構築するために必要にな`Service`/`Deployment`/`ConfigMap`などのYAML(JSON)のファイル群|
|Release|k8s上にインストールされたパッケージ|

## 使いかた

### helmをインストールする

インストール方法はGithubの[release](https://github.com/kubernetes/helm/releases)ページからディストリビューションにあったバイナリを落としてきてよしなに配置するだけ。
ただし、初回のみ初期設定コマンドの実行が必要になります。

```bash
helm init
```
を実行すると`$HOME/.helm`ディレクトリの中に設定ファイルが配置され
`tailer`がk8s上にコンテナとして起動します。(こちらの詳細は次章)

> **注意**
> kubectlが`helm init`を実行する環境に設定されていること
> k8sはバージョン1.4以降であること

### レポジトリを確認する

パッケージの追加の前に一旦レポジトリの確認とアップデートをしておきます。
デフォルトはGCPを向いてますが、この中身は[charts](https://github.com/kubernetes/charts)で管理されています。

```bash
# レポジトリの一覧表示
$ helm repo list
NAME    URL
stable  https://kubernetes-charts.storage.googleapis.com/
local   http://127.0.0.1:8879/charts

# レポジトリのアップデート
$ 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!⎈
```

レポジトリ一覧の中に`local`が含まれていますが、単純に該当アドレスにアクセスしても繋がりません。
これを動かすためには`serve`コマンドを実行する必要があります。
`serve`を実行すると`$HELM_HOME/repository/local`内の`charts`が呼び出せるようになります。

```bash
# デフォルトでは起動していない
$ curl http://127.0.0.1:8879/charts
curl: (7) Failed to connect to 127.0.0.1 port 8879: Connection refused

# ローカルのchartsサーバを起動する
$ helm serve
Regenerating index. This may take a moment.
Now serving you on 127.0.0.1:8879

# 別のプロンプト上で実行
$ curl localhost:8879
<html>
<head>
        <title>Helm Repository</title>
</head>
<h1>Helm Charts Repository</h1>
<ul>

</ul>
<body>
<p>Last Generated: 2016-12-25 17:40:23.95566401 &#43;0900 JST</p>
</body>
</html>
```

### k8sにパッケージをインストールする

試しにgrafanaをk8sにインストールしてみます。
名前がわからないのでとりあえず`search`コマンドを実行。

```bash
# searchになにも引数を渡さないと全パッケージが表示されます
$ helm search grafana
NAME            VERSION DESCRIPTION
stable/grafana  0.2.0   A Helm chart for Kubernetes
```

`stabl/grafana`というのが見つかりました。
この`stable`という部分は、レポジトリ名と一致しています。
よって、前章で出てきた`stable`レポジトリの中に存在していることが分かります。
では、これを`install`コマンドでk8s上に立ち上げてみます。

```bash
# grafanaをインストールする
$ helm install stable/grafana

NAME:   auxilliary-leopard
LAST DEPLOYED: Sun Dec 25 17:57:19 2016
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Service
NAME                         CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
auxilliary-leopard-grafana   10.108.32.18   <none>        80/TCP    1s

==> extensions/Deployment
NAME                         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
auxilliary-leopard-grafana   1         1         1            0           1s

==> v1/PersistentVolumeClaim
NAME                         STATUS    VOLUME    CAPACITY   ACCESSMODES   AGE
auxilliary-leopard-grafana   Pending                                      1s

==> v1/Secret
NAME                         TYPE      DATA      AGE
auxilliary-leopard-grafana   Opaque    2         1s

==> v1/ConfigMap
NAME                                DATA      AGE
auxilliary-leopard-grafana-config   1         1s
auxilliary-leopard-grafana-dashs   0         1s


NOTES:
1. Get your 'admin' user password by running:

   printf $(printf '\%o' `kubectl get secret --namespace default auxilliary-leopard-grafana -o jsonpath="{.data.grafana-admin-password[*]}"`);echo

2. The Grafana server can be accessed via port 80 on the following DNS name from within your cluster:

   auxilliary-leopard-grafana.default.svc.cluster.local

   Get the Grafana URL to visit by running these commands in the same shell:

     export POD_NAME=$(kubectl get pods --namespace default -l "app=auxilliary-leopard-grafana,component=grafana" -o jsonpath="{.items[0].metadata.name}")
     kubectl --namespace default port-forward $POD_NAME 3000

3. Login with the password from step 1 and the username: admin

# k8s上で立ち上がっていることを確認する
$ kubectl get po
NAME                                          READY     STATUS    RESTARTS   AGE
auxilliary-leopard-grafana-2846005379-p35ss   0/1       Running   0          2m

# helmでリリースしたものを一覧表示する
$ helm list
NAME                    REVISION        UPDATED                         STATUS          CHART
auxilliary-leopard      1               Sun Dec 25 17:57:19 2016        DEPLOYED        grafana-0.2.0

# ステータスを表示する
$ helm status auxilliary-leopard
LAST DEPLOYED: Sun Dec 25 17:57:19 2016
NAMESPACE: default
~~ 省略 ~~
```

インストールを実行すると、
grafanaでは、`Service`/`Deployment`/`PersistentVolumeClaim`/`Secret`/`ConfigMap`の5つが追加されました。
これは、標準出力に吐き出されるリソースの一覧からわかります。
また、`list`コマンドでリリースしたパッケージを一覧や、statusで単体の状態を見ることができます。

## helmのアーキテクチャ

### 思想とライフサイクル

`helm`は[12FactorApp](http://12factor.net/)に則っていて、Chart(Template + Config)をRelaseとして管理されています。
Releaseは`upgrade`コマンドで修正内容の適用、問題があれば`rollback`コマンドで元に戻すこともできます。
Releaseのリビジョン遷移は`history`コマンドで確認することができます。

```bash
$ helm history angry-bird
REVISION   UPDATED                      STATUS           CHART
1           Mon Oct 3 10:15:13 2016     SUPERSEDED      alpine-0.1.0
2           Mon Oct 3 10:15:13 2016     SUPERSEDED      alpine-0.1.0
3           Mon Oct 3 10:15:13 2016     DEPLOYED        alpine-0.1.0
```

### 構成と通信方法

主な構成要素は`helm`, `Repository`, `tiller`の3つです。
`helm`は`Chart`の、`tiller`は`Release`の管理を行っていて、ざっくり機能を挙げるとこんな感じ。

#### Helm
* ローカルの`chart`開発
* レポジトリの管理
* `Tiller`サーバとの通信
    * インストールする`chart`の送信
    * `Release`情報の取得
    * `Release`に対するアップグレードやアンインストールの要求

#### Tiller
* Helmクライアントからのリクエスト受付
* `chart`と`configuration`を組み合わせた`release`のビルド
* `chart`をk8sへインストールし、`release`をトラックする
* k8sへ`chart`のアップグレードとアンインストールをする

![image](https://qiita-image-store.s3.amazonaws.com/0/26683/c0eaeebb-abe9-8b12-c27d-4b07845f548a.png)

`helm`と`tiller`間の通信はgRPCが使用されていて、`tiller`がgRPCサーバの役目をもっています。
`k8s`と`tailler`間は単純にK8sのクライアントライブラリを叩いているのでREST+JSONで通信されています。
また、`tiller`の情報はk8sのConfigMapに保存されているので、DBは保持していません。


> 力尽きたのでここら辺で止めておきます。
> Chartsの作り方やhelmcからの移行はまたどこかで...

## 今後どうなるのか?

ロードマップはGithubのWikiで公開されてます。
https://github.com/kubernetes/helm/wiki/Roadmap
大きな変更としては、Manページを作れるようにする`doc`コマンドやレポジトリへの認証機能の追加です。

## おわりに

helmは開発も活発なので今後もどんどん便利になっていきそうです。
⎈ Happy Helming!⎈