Elastic Cloud on Kubernetes(ECK)のESをプロダクションレディにするコツ

Product Team SREのkterui9019です。

Elastic Cloud on Kubernetes(以後ECK)をご存知でしょうか?

Elastic stack(Elastic Search等)を、kubernetes上に展開するためのoperatorなのですが、弊社では今年から段階的にGCEで構築していたESクラスタをECKでリプレイスを進めています。

元々特定のマイクロサービスとのみ通信する小さめのESクラスタが複数個GCE上に存在していたのですが、今年に入ってから円安の影響で無視できないコストとなっていました。 ECKであればkubernetesクラスタ上でElasticStackを展開できるので、高いリソース効率でESを運用することができます。

そこで、しばらくECKを運用していくにつれて本番環境で運用するにあたって考慮すべきポイントが見えてきたので、ECKをプロダクションレディにするコツという形で書いていこうと思います。

ストレージ

ECKでは、ElasticsearchはPersistentVolumeを使用します。 そのため、本番環境で運用する場合にはストレージの拡張性と監視を考えておく必要があります。

まずストレージの拡張性についてですが、kubernetesのPVCを拡張するためには一定の要件があります。

拡張可能なボリューム種類を使っていることと、StorageClassのallowVolumeExpansionフィールドの値がtrueになっている必要があるため、本番運用前にはこれらの要件が満たされているかどうかを確認しておく必要があります。 もし要件が満たせない場合には最初から大きめのディスク容量をrequestしておくであったり、拡張する際には新しいクラスタを横並びに作ってBlue/Green的に容量を増やしたクラスタに切り替えるといった工夫が必要になってくるかと思われます。 なお、GKEのstandard storage classはallowVolumeExpansion=trueがセットしてあったので拡張性に関しては特に気にする必要はなさそうです。

これで拡張性は確保されましたが、肝心のボリュームを拡張するタイミングは手動になります。(私は最初容量もオートスケールしてくれるものだと勘違いしていました😂) つまりボリューム拡張する必要性に気づく必要があるため、監視設定を加える必要があります。 PersistentVolumeの容量に関してはprometheusメトリクスのkubelet_volume_stats_used_bytes, kubelet_volume_stats_available_bytesを参照して取得できるので、以下のような設定をPrometheusに入れることで任意のディスク使用量になったらアラートを上げることができます。

※ECKのES経由で作られるPVCはelasticsearch-data-というプレフィックスがつく仕様のようです。

  groups:
  - name: PVC
    rules:
    - alert: PersistentVolumeCapacity 85%
      expr: |
        kubelet_volume_stats_used_bytes{k8s_cluster=~"<cluster-name>", persistentvolumeclaim=~"elasticsearch-data.*"}
            / kubelet_volume_stats_available_bytes{k8s_cluster=~"<cluster-name>", persistentvolumeclaim=~"elasticsearch-data.*"} > 0.85
      for: 30m
      labels:
        stage: prd
        severity: critical
      annotations:
        text: |
          {{$labels.persistentvolumeclaim}}: {{ $value }}

可観測性

本番運用するにあたってクラスタヘルス等のElasticSearch特有のメトリクスは収集しておきたいと思います。

datadogやkibana上であったり色々とメトリクスを収集して可視化する方法はあると思いますが、今回はPrometheusでメトリクスを収集する方法を紹介します。 事前にelasticsearch exporterプラグインをinitコンテナやDockerfileでインストールしておきます。(下記はDockerfileでインストールするサンプル)

FROM elasticsearch:7.6.0

RUN ./bin/elasticsearch-plugin install --batch https://github.com/vvanholl/elasticsearch-prometheus-exporter/releases/download/7.6.0.0/prometheus-exporter-7.6.0.0.zip

これだけで/_prometheus/metricsを叩くとelasticsearch特有のメトリクスをエクスポートする口が用意できます。 あとは、elasticsearchのpodにptometheus.io/scrape: trueアノテーションを付与するだけでスクレイプすることができます。

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
nodeSets:
    podTemplate:
      metadata:
        annotations:
          prometheus.io/scrape: "true"
          prometheus.io/path: /_prometheus/metrics
          prometheus.io/port: "9200"
          prometheus.io/scheme: http

スナップショット

本番運用ということでスナップショットの取得は考えておきたいポイントかと思います。 スナップショットの取得先にS3やGCSを選択する場合、バージョンによってはプラグインを導入しておく必要があるので、前述のexporterと同様インストールしておきます。(以下はDockerfileでplugin installする例)

FROM elasticsearch:7.6.0

RUN ./bin/elasticsearch-plugin install --batch repository-gcs

認証情報を指定のディレクトリに配備すればリポジトリを使う準備ができたはずなので、kibana等からAPIを叩いてリポジトリの設定をPUTします。

PUT _snapshot/backup_es
{
  "type": "gcs",
  "settings": {
    "bucket": "backup-es,
    "client": "default",
    "base_path": "production",
    "readonly": "true"
  }
}

ここまででスナップショットを取得する準備ができました。 APIを叩いて取得してもいいのですが、v7.5以降はSnapshot Lifecycle Management(SLM)機能が自動で世代管理してくれて便利なので、こちらを使ってスナップショットを取る方法を紹介します。

SLMの設定画面はKibanaのManagement -> Snapshot and Restore -> Policies からアクセスできます。(v7.6.0の場合)

あとはGUIに従ってポチポチ設定するだけで世代数管理されたスナップショットのポリシーを作ることができます。 こちらの機能は非常に簡単なのでスナップショットを定期的に取る場合にはお勧めですが、Elasticsearchのバージョンが足りない場合はsnapshotを取得するAPIを叩くCronjobをkubernetes上にデプロイするなどで対応することができるかと思います。

アップデート

最後にECK Operatorのアップデートについても触れようと思います。

基本的には公式ドキュメントの通りにhelm upgradeやmanifestのapplyをするだけで簡単にアップデートができます。 ただ、一つだけ注意したいのが、バージョンによってはElasticsearch・Kibanaの再起動も伴う可能性があるという点です。

The upgrade process results in an update to all the existing managed resources. This potentially triggers a rolling restart of all Elasticsearch and Kibana pods.

大規模なクラスタや複数台クラスタをホストしている場合、一気にESの再起動が走るとkubernetesクラスタのパフォーマンスを劣化させる原因になりかねません。 こういった場合にはeck.k8s.elastic.co/managed=falseというアノテーションをElasticsearchに付与することで、リソースをOperatorの管理下から外す = 再起動しない状態にすることができます。 これによってオペレータのアップデート前に全てのkind=Elasticsearchに上記アノテーションを付与しておいて、負荷が少ない時間帯に1台ずつアノテーションを外して再起動するといった戦略が取れるようになります。


これらのポイントを抑えておくことで本番環境でも安定してkubernetes上でElasticsearchを運用することができるのではないかと思います。 しばらく使ってみた感じではバグなども見つからず、小さめのクラスタなら本番で使っていけるレベルだと感じているので、複数クラスタの運用コストに困っている方は是非試してみてはいかがでしょうか。

Page top