[WIP] elasticsearch を on-premise の kubernetes に operator で入れてみる

# kubernetes 上に elasticsearch を立てる

[helm-charts](https://github.com/elastic/helm-charts) もあるが，将来性を考えると statefulsets とか自分で使いたくないので，operator のほうに寄ってくんだろうな，という予測の下，[cloud-on-k8s](https://github.com/elastic/cloud-on-k8s/) を立ててみる．

## 1. まずは quick start に従って

[公式ドキュメント](https://www.elastic.co/guide/en/cloud-on-k8s/master/index.html)が整備されてるのでこちらに従う．

```
% kubectl apply -f https://download.elastic.co/downloads/eck/0.9.0/all-in-one.yaml
% cat <<EOF | kubectl apply -f -
apiVersion: elasticsearch.k8s.elastic.co/v1alpha1
kind: Elasticsearch
metadata:
  name: quickstart
spec:
  version: 7.2.0
  nodes:
  - nodeCount: 1
    config:
      node.master: true
      node.data: true
      node.ingest: true
EOF
% cat <<EOF | kubectl apply -f -
apiVersion: kibana.k8s.elastic.co/v1alpha1
kind: Kibana
metadata:
  name: quickstart
spec:
  version: 7.2.0
  nodeCount: 1
  elasticsearchRef:
    name: quickstart
EOF
```

そしてこの操作だけでよければ，なぜか[日本語ページ](https://www.elastic.co/jp/elasticsearch-kubernetes)があったりする．for minikube と for GKE しかないが，オンプレのクラスタでも普通に動く．

### 注意事項

default の storageclass が存在しないと，PVC が Pending になって止まるので注意．手元オンプレ環境では，nfs-client-provisioner で nfs から切り出す storageclass を使っている．が，これはこれであとで問題になるので，カスタマイズのところでフォローする．

とりあえず動かしてみたくて，永続化しないのであれば，以下で emptydir にできる．

```
spec:
  nodes:
  - config:
    podTemplate:
      spec:
        volumes:
        - name: elasticsearch-data
          emptyDir: {}
```

nodes: 下に以下のように追加することで storageclass を指定できる．詳細は[このへん](https://www.elastic.co/guide/en/cloud-on-k8s/master/k8s-volume-claim-templates.html)．

```
spec:
  nodes:
  - volumeClaimTemplates:
    - metadata:
        name: elasticsearch-data
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 5Gi
```



いずれも name: は elasticsearch-data 固定なので注意．ここで名前を変えようとするとはまる．

## 2. カスタマイズもろもろ
### namespace は分離したい

このままだと default にぶちまけられるので，namespace を設定する．

CRD は namespace に依存しないので，all-in-one.yaml はそのままでいい．es と kibana の deploy 時に metadata: の下に namespace: elastic とかを入れれば分離できる．kubectl の引数で -n elastic 等として指定してもよい．手元環境では kustomize に任せるつもり．

### マルチノードにしたい

nodeCount: 3 とかにすればマルチノードに．さらに，node.master: false node.data: true 等として master ノードと data ノードを分離することもできる．affinity 制御も可能だが，デフォルトで同じ kubernetes worker に同じ種類の node は上がらないようになっているので普通は困らないだろう．

従来のように master + data + coordinator みたいなのが適切なのかどうかは要検討．ちなみにうちのテスト用 k8s クラスタは 3 worker しかないので，役割分けても同じ物理ノードには載ってしまう．

### tls を off にしたい

なぜか elasticsearch の tls は off にできない(x-pack 売るためじゃないかなーと邪推)が，kibana は off にできる．自動生成された自己証明書でデフォルトは上がってくるが，手持ちのものに差し替えることもできるようだ．リンク先参照．

```
spec:
  http:
    tls:
      selfSignedCertificate:
        disabled: true
```

ref. https://github.com/elastic/cloud-on-k8s/blob/master/docs/accessing-services.asciidoc#disable-tls

### loadbalancer とか ingress とか
手元は ingress w/ traefik なのでこんな感じ．loadbalancer とか nodeport とか適宜．

```
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kibana
  namespace: elastic
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: kibana7.example.jp
    http:
      paths:
      - path: /
        backend:
          serviceName: quickstart-kb-http
          servicePort: 5601
```

### storage

dynamic provisioning だと，delete すると消えてしまうので，Local Volume にして永続化することにした．長くなるので 3. で説明する．

## 3. Storage の永続化とバックアップ

WIP

## 4. リソースとか

WIP

## 5. まとめ

WIP

## 6. 所感

WIP