Azure Kubernetes Service(AKS)上のk8sクラスタにhelmを使ってkafkaをdeployする

Azure Kubernetes Service(以降：AKS)でhelmを使って見たメモです。
helmやkubernetes(以降：k8s)のことも触れます。

# helmとは？

https://helm.sh/

k8s上にdeployされるsoftwareをパッケージ管理するための製品です。
yumやaptのk8s版とよく言われます。
自分は少し違う印象をもっていますが、それが分かりやすいのでこの時点ではそんな感じでOK。
上記件は後ほど少し触れます。

# AKSでhelmを使ってdeploy!

https://docs.microsoft.com/ja-jp/azure/aks/kubernetes-helm
上記にドキュメントがまとまっていますので、実際試す場合は上記に沿ってやっていくとよいでしょう。
ちなみにAKS固有なポイントは特にありません。オンプレk8sでもほぼ同じ流れでできます。

以降上記docに無い部分を補足しつつ、メッセージング基盤である[kafka](https://kafka.apache.org/)をhelmでdeployしてみようと思います。

# helm環境の準備

AKSの場合はcloud shellを利用すればhelm clientは既に導入されていますが、(Azureに用意されていない)CI/CDと組み合わせたい場合用に[azure cliのdocker image](https://hub.docker.com/r/microsoft/azure-cli/)を利用するとよいと思います。
このイメージにhelmが入っていればいいのですが、たぶん入っていないので[ここ](https://hub.docker.com/r/lachlanevenson/k8s-helm/)のdocker fileを参考に、azure cli + helmが入ったイメージを作っておくのもよいと思います。
(helmの導入はバイナリファイルのダウンロードのみ）

gcloudSDK + helmを実行するimageを使ってCI/CDでまわしていますが、azure cli + helmは未確認なので紹介程度とさせてもらいます。
以降本項ではcloud shellを用いて以降実施した内容を記載していきます。

# helmのバージョン確認

## tiller install前

```bash
admin@Azure:~$ helm version
Client: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"}
Error: could not find tiller
admin@Azure:~$
```
tiller install前は当然ながらversion情報は何も表示されません。
`could not find tiller`と表示されます。

## tiller install後
```bash
admin@Azure:~$ helm version
Client: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"}
```
tiller install後はversionを確認するとServer側もバージョンが表示されます。

```bash
admin@Azure:~$ kubectl get pod -n kube-system | grep tiller
tiller-deploy-XXXXXXXXXX-XXXXX                                    1/1       Running   0          3m
admin@Azure:~$
```
tillerのpodもちゃんと起動していますので、これで利用準備OKです。

# helm repositoryの追加

デフォルトでは、localとstableのみですが、kafkaは18.09.23時点でincubatorなのでincubator repositoryを追加します。

```bash
admin@Azure:~$ helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/
"incubator" has been added to your repositories
admin@Azure:~$ helm repo list
NAME            URL
stable          https://kubernetes-charts.storage.googleapis.com
local           http://127.0.0.1:8879/charts
incubator       https://kubernetes-charts-incubator.storage.googleapis.com/
```

# helmを使ったkafka deploy

kafkaのhelm chartは[こちら](https://github.com/helm/charts/tree/master/incubator/kafka)になります。
helmを用いると必要な製品がササっとdeployされます。
ただ、実際の利用を考えると用途に応じて調整したいパラメータがあると思います。
それらはhelmの思想としては、values.yamlというファイルにて設定できるようになっていますので、利用者はそのパラメータを変更し、実際に製品をdeployします。

少しパラメータの中を見てみましょう。

## values.yamlの中身
### ポッド数

```yaml
## The StatefulSet installs 3 pods by default
replicas: 3
```
いくつkafkaを作成するかの設定です。デフォルトでは3つのkafka用podが作られます。

### 
### イメージプルポリシー
```yaml
## Specify a imagePullPolicy
## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images
imagePullPolicy: "IfNotPresent"
```
コンテナイメージをプルする際の設定です。
"IfNotPresent"はキャッシュされたイメージを使うための設定です。
ただし、コンテナのタグが"latest"の場合はこの値は無視されて常にimageをpullしにいきます。

### CPU/MEMの割り当て設定
```yaml
## Configure resource requests and limits
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
resources: {}
  # limits:
  #   cpu: 200m
  #   memory: 1536Mi
  # requests:
  #   cpu: 100m
  #   memory: 1024Mi
kafkaHeapOptions: "-Xmx1G -Xms1G"
```
#### resources
CPU、メモリの割り当て設定です。
200mは0.2core(0.2vCPU)です。1000mは1core。"1"と記載しても同じ意味です。
requestsは初期割り当て、limitは最大割り当てです。
defaultではコメントアウトされていますが、本番利用時は必ず指定するようにしましょう。
これはk8sのリソース管理機能です。

#### kafkaHeapOptions
kafkaはJavaアプリなのでJVMのオプションになります。
kafkaプロセスを起動する際のオプションになります。
これはk8sのリソース管理機能ではないです。

なので、values.yamlにはk8sのものとkafkaの設定情報両方が入っています。
当然ながらk8sおよびkafkaの知識が必要です。

### podの配置ルール
```yaml
affinity: {}
## Alternatively, this typical example defines:
## antiAffinity (to keep Kafka pods on separate pods)
## and affinity (to encourage Kafka pods to be collocated with Zookeeper pods)
# affinity:
#   podAntiAffinity:
#     requiredDuringSchedulingIgnoredDuringExecution:
#     - labelSelector:
#         matchExpressions:
#         - key: app
#           operator: In
#           values:
#           - kafka
#       topologyKey: "kubernetes.io/hostname"
#   podAffinity:
#     preferredDringSchedulingIgnoredDuringExecution:
#      - weight: 50
#        podAffinityTerm:
#          labelSelector:
#            matchExpressions:
#            - key: app
#              operator: In
#              values:
#                - zookeeper
#          topologyKey: "kubernetes.io/hostname"
```

podをどのように配置するかのアフィニティ設定です。
- 既にkafka podが存在しているnodeには別のkafkaのpodを起動させない(同じnode上にkafkaを乗せない、冗長性のための設定)
- kafka podが起動しているnodeと同じnodeにzookeeperをなるべく(あくまでなるべくです）のせる。

コメントアウトされている部分の意味は上記となります。

### JMX exporter取得設定
```yaml
## Prometheus Exporters / Metrics
##
prometheus:
  ## Prometheus JMX Exporter: exposes the majority of Kafkas metrics
  jmx:
    enabled: false
```
[prometheus](https://prometheus.io/)のメトリクス情報を収集するかの設定
こちらをenabledをtrueにするとjmxで採取した情報をprometheusで見るためのexporterを作ります。

### kafka exporter取得設定
```yaml
  ## Prometheus Kafka Exporter: exposes complimentary metrics to JMX Exporter
  kafka:
    enabled: false
```
kafka用のprometheusメトリクス情報を取得するかの設定。
broker数などのkafkaのメトリクス情報を採取します。
kafkaと同じpodに配備される別コンテナとして生成します。

### exporterのprometheus連携設定
```yaml
operator:
  ## Are you using Prometheus Operator?
  enabled: false

  serviceMonitor:
    # Namespace Prometheus is installed in
    namespace: monitoring

    ## Defaults to whats used if you follow CoreOS [Prometheus Install Instructions](https://github.com/coreos/prometheus-operator/tree/master/helm#tldr)
    ## [Prometheus Selector Label](https://github.com/coreos/prometheus-operator/blob/master/helm/prometheus/templates/prometheus.yaml#L65)
    ## [Kube Prometheus Selector Label](https://github.com/coreos/prometheus-operator/blob/master/helm/kube-prometheus/values.yaml#L298)
    selector:
      prometheus: kube-prometheus
```
coreOSが提供しているPrometheus Operatorと連携し、上記で設定したexporterの情報をprometheusから見れるような連携設定を入れます。

### ちょっと思い出そう

このページの冒頭で「helmは、yumやaptのk8s版とよく言われます。」と言いましたが、上記で説明したように
- ポッドにどれだけのリソースを割り当てるか
- ポッドをどのように起動させるか
- メトリクス情報を収集するか
- 収集したメトリクス情報を連携させるか
といった設定が行われます。

なので、自分の理解としては
**「helmは製品インストール＋パラメータ設定＋必要な製品との連携」まで見据えた、利用できる状態で製品を設定するためのもの」**
と理解しています。
ちなみにvalues.yamlに定義した内容に沿ってどのように処理が行われるかはtemlatesフォルダ内のyamlファイルに記載されています。(helmの動きとしてはtemplatesフォルダ内のyamlファイルが一式呼ばれます)
なので、すべてのhelm chartが上記のようにいろいろな設定をしてくれるわけではないということは理解しておく必要があります。
逆をいえば、こういったhelm chartを使う場合はどのような設定が行われるか、templatesフォルダ内のyamlを理解できる必要があります。


*Happy Helming!*


## kafkaのdeploy

言いたいことは終わったのであとはサラっと。

```bash
admin@Azure:~$ helm install -n happykafka incubator/kafka --set replicas=1,prometheus.jmx.enabled=true,prometheus.kafka.enabled=true --namespace kafka
NAME:   happykafka
LAST DEPLOYED: Fri Sep 21 16:21:20 2018
NAMESPACE: kafka
STATUS: DEPLOYED
(以下略)

```

install時は --set オプションで値を指定することが可能です。
replicas=1にしましたので、先ほどvalues.yamlにはreplicasは3になっていましたが、1でdeployされます。
また、これからのパラメータは`-f <yaml file>`でファイル形式で指定することも可能です。

## リリース情報の確認
```bash
admin@Azure:~$ helm list
NAME                    REVISION        UPDATED                         STATUS          CHART                           APP VERSION     NAMESPACE
happykafka              1               Fri Sep 21 16:21:20 2018        DEPLOYED        kafka-0.10.0                    4.1.2           kafka
```
リリース管理されます。バックアウトやバージョンアップをしていくことが可能です。
ちなみに、`helm delete --purge happykafka`でkafka関連のリソースは完全消去されます。

## kafka pod起動確認
```
admin@Azure:~$ kubectl get pod -n kafka
NAME                                   READY     STATUS    RESTARTS   AGE
happykafka-0                           2/2       Running   0          3m
happykafka-exporter-7666fc6c59-jsd8c   1/1       Running   1          3m
happykafka-zookeeper-0                 1/1       Running   0          3m
happykafka-zookeeper-1                 1/1       Running   0          2m
happykafka-zookeeper-2                 1/1       Running   0          1m
```
kakfaのpodは1つしか起動していないことが分かります。
また、kafkaのメトリクス情報を取得するexporterが起動していることが分かります。

kafkaのhelm chartをよく覗いていけば分かるのですが、happykafka-zookeeper-x はzookeeperです。
kafkaのクラスタリングを管理する製品です。

では皆様良きHelm Lifeを！