Index Template V2

Posted by johtani on Thursday, December 17, 2020

目次

Elastic stack (Elasticsearch) Advent Calendar 2020の18日目の記事になります。

本日の勉強会でLTをしましたが、しゃべり足りなかったんで。 Elasticsearch 7.8でこっそりとリリースされたIndex Template V2について調べたのでどんなものかをまとめてみます。 リリースブログには出てきてない(7.8のEsのページのWhat’s newには出てた)ので気づいてない人も多いのではないでしょうか?

Index Templateとは?

まずはIndex Templateがどんなものかを説明しましょう。

Indexの設定やマッピングはデフォルト値以外を設定したい場合に、毎回"mappings"や"settings"の設定を指定してIndexを作成するのは手間がかかります。 そこで便利な機能として提供されているのがIndex Templateです。このIndex TemplateはCluster Stateに保管されます。

Index Templateを利用するときの流れは以下の通りです。

  1. Index Templateの作成
  2. Indexの作成

例えば、3ノード構成のクラスターでインデックスを作成するときに常に"number_of_shards: 3"を設定したいとします。 Index Templateは次のような感じになります。

PUT _template/blog_num_shards
{
  "index_patterns": "blog_*",
  "settings": {
    "index": {
      "number_of_shards": 3
    }
  }
}

または日本語のシンプルな形態素解析のアナライザーの設定を"jp_“という名前でるようできるようにしたい場合には次のような感じになります。

PUT _template/jp_simple_kuromoji
{
  "index_patterns": "jp_",
  "settings": {
    "index": {
      "analysis": {
        "simple_jp": {
          "type": "custom",
          "tokenizer": "kuromoji"
        }
      }
    }
  }
}

インデックステンプレートの登録が終われば、インデックスを作成するタイミングでIndex Templateが適用されます。 例えば、blog_2020というインデックスを作成すると、number_of_shards: 3のインデックスが作成されます(デフォルトは1)。 jp_blog_2020というインデックスを作成すると、simple_jpというAnalyzerが設定されています。 このように、インデックス名を意識するだけで設定が適用されていくのが利点です。

ちなみに、Index TemplateはIndex作成時に適用されるだけなので、Index Templateを変更してもこれまでのインデックスへは影響はありません。

これまでのIndex Templateの問題点

と、Index Templateが便利なのはわかりましたが、ではなぜ今回V2がリリースされたのでしょうか? 先ほどの例を見るとわかりますが、これまでのIndex Templateは部品化が難しいのが問題でした。 Index Templateはそれぞれがインデックスの作成時に適用されます。 が、Index TemplateにIndex Templateを組み込むことはできません。 例えば、先ほどサンプルとして作成したjp_simple_kuromojiのIndex Templateはjp_で始まるインデックスにしか適用できません。

では、blog_で始まるインデックスにもkuromojiのシンプルなアナライザーを使いたくなった場合はどうなるでしょう? 残念ながら、jp_simple_kuromojiと同じ設定をblog_num_shardsのテンプレートに追加するか、jp_simple_kuromojiindex_patternsの部分だけを書き換えた新しいテンプレートを用意するか、jp_simple_kuromojiindex_patternsjp_を追加する方法です。 いずれにしてもIndex Templateの継承(複数のテンプレートを1つのインデックスに紐づける)が必要となります。 この時、複数のIndex Templateが適用されるため、適用する順番が出てきます。 この順番をIndex Templateのorderパラメータで指定できます。

ただ、これも問題のもととなっていました。 複数あるIndex Templateのどれがどの順番で適用されるのか?それはインデックスを作成時にようやくわかります。 使いたい側(インデックス)が、使いたいもの(テンプレート)を指定するのではなく、その逆(使いたいものに使いたい側の情報を設定しなくてはならない(index_patternsorder))になっているのでわかりにくくなっていました。

ということで解決策としてリリースされたのがIndex Template V2です(ちなみに名前にV2とは言ってるわけではなく、現在のIndex Templateの機能がlegacy index templateという名前になり、Deprecatedになっています(まだログには出ない))。

Index Template V2

7.8のWhat’s newドキュメントではComposable Index Templateと紹介されています。 大きく3つのエンドポイントが提供されます。

  • Component Template 用API
    • テンプレートのコンポーネントという単位で管理するためのAPI。
    • 登録更新、削除、取得が可能
  • Index Template 用API
    • Index Templateを管理するためのAPI
    • 登録更新、削除、取得が可能
  • Simulate index template API(Experimental)
    • Index Template

Legacy Index Templateとの大きな違いは、

  • テンプレートをコンポーネントにできる
  • 1つのインデックスに適用されれるテンプレートは1つだけ

という点です。これまでとは挙動が異なるので注意が必要です。

新しいIndex Templateを利用する際の流れは次のようになります。

  1. Component Templateの作成
  2. Index Templateの作成
  3. 作成したIndex Templateの挙動を確認
  4. 実際にIndex名を指定してIndex Templateの挙動を確認

という形です。では、それぞれの機能を見ていきましょう。

Coponent Template API

テンプレートコンポーネントを管理するためのAPIです。 具体的なAPIごとに説明していきます。

PUT _component_template

コンポーネントを登録、変更するためのAPIです。公式ドキュメントはこちらです。 先ほどのkuromojiのAnalzyerをコンポーネントとして登録してみましょう。

PUT _component_template/jp_simple_kuromoji
{
  "template": {
    "settings": {
        "index": {
        "analysis": {
          "analyzer": {
            "simple_jp": {
            "type": "custom",
            "tokenizer": "kuromoji_tokenizer"
            }
          }
        }
      }
    }
  },
  "version": 1,
  "_meta": {
    "description": "simpleなKuromoji analyzer"
  }
}

先ほどと特に違いはありません。templateという階層が1段増え、index_patternsがなくなりました。 template部分はIndexに設定するsettingsmappingsaliasesが指定可能です。 ちなみに、“template"の中身をそのままIndex作成時に使用した場合にエラーにならない設定である必要があります。 ここは注意が必要です。例えば、component Aでkuromojiのアナライザーの設定をし、component Bでそのアナライザーを使用するフィールドのmappingだけを記述した場合、component Bでエラーが発生します。上記のようなシチュエーションでは、Index Templateで利用するフィールドを定義し、component Aを利用する宣言をすれば問題ありません。

そのほかに使えるパラメータで便利なものを紹介しておきます。

  • クエリパラメータ

    • create: URLに指定するパラメータ。trueを指定することで、既に存在する場合にエラーを返してくれる。更新も同じAPIなので間違わないようにするために利用すると便利。デフォルトはfalse
  • リクエストボディ

    • _meta: テンプレートにメタ情報を付与できる。_metaの中は自由に記述可能。コメントなどを書いておくとあとでわかりやすい

GET _component_template

コンポーネントを取得するためのAPIです。公式ドキュメントはこちらです。 一覧での取得とリストでの取得が可能です。

一覧取得サンプル

GET /_component_template
GET /_component_template/*

これ以外に、IDを指定して取得することも可能です。

GET _component_template/jp_simple_kuromoji

*を利用して複数取得も可能です。

GET _component_template/jp*
GET _component_template/j*_*

DELETE _component_template

コンポーネントを削除するためのAPIです。公式ドキュメントはこちらです。 IDを指定してコンポーネントを削除できます。

DELETE /_component_template/jp_simple_kuromoji

ID指定以外に*を利用することも可能ですが気を付けて使用しましょう。

DELETE /_component_template/jp_*
DELETE /_component_template/*

ちなみにIndex Templateで利用されているコンポーネントを削除しようとした場合はエラー(ステータスコード400)が返ってきます。 *などを使用して削除しようとした場合は、ひとつでも利用されているものが含まれている場合は削除は実行されずにエラーだけが返ってくるようになっています。

Index Template API

Index Templateを管理するためのAPIです。 Component Template APIで定義したコンポーネントを利用してテンプレートを作成できます。コンポーネントを利用しないで単体で完結したテンプレートも作成可能です。 具体的なAPIごとに説明していきます。

PUT _index_template

Index Templateを登録・更新するためのAPIです。公式ドキュメントはこちらです。

これまでのLegacy Index TemplateのAPIのエンドポイント(_template)ではなく、(_index_template)というエンドポイントになっていることにまず注意してください。 先ほど作成したjp_simple_kuromojiコンポーネントと、追加で作成した3_shardsというコンポーネントを利用して blog_で始まるインデックスに適用できるIndex Templateを作成してみましょう。

PUT _index_template/blog_template
{
  "index_patterns": ["blog_*"],
  "template": {  
    "mappings": {
      "properties": {
        "hoge": {
          "type": "text",
          "analyzer": "simple_jp"
        }
      }
    }
  },
  "priority": 100,
  "composed_of": ["jp_simple_kuromoji", "3_shards"]
}

composed_ofというパラメータに利用したいコンポーネントを配列で記述していきます。 Index Templateが適用される時に、ここに記述されている順番でコンポーネントが適用されていきます。 ですので、最後に書いてあるテンプレートが一番強いことになります。 これは例えば、同じ設定値number_of_shardsを2つのコンポーネントが設定している場合に、最後に設定した値がインデックスに採用されるという意味です (公式ドキュメントにサンプルが掲載されています)。 なお、存在しないコンポーネントをcomposed_ofに指定した場合は400エラーが返ってきます。同じコンポーネントを複数重複して指定した場合は特にエラーにはなりませんでした。 composed_ofを指定しなければ、単体で完結したテンプレートを定義可能です。

次に重要な設定はpriorityです。これまでのテンプレート機能と異なる点で説明しましたが、

1つのインデックスに適用されれるテンプレートは1つだけ となっています。 この1つを決めるための値がpriorityになります。 インデックス名によってはindex_patternの定義によって、複数のIndex Templateにマッチします。例えばblog_**_2020のIndex Templateがあった場合にblog_2020というインデックスを作った場合です。 この時、Elasticsearchはpriorityの大きい値を持ったIndex Templateだけを適用します。 blog_*のIndex Templateのproperty10*_2020のIndex Templateのproperty100だった場合、*_2020のテンプレートが適用されます。Legacy Index Templateではorderという似たパラメータがありましたが、こちらは適用する順序を決定するためのものでした。挙動が違うので注意しましょう。

ちなみに、blog_**_2020propertyがどちらも10というIndex TemplateをPUTしようとした場合、2番目にIndex TemplateをPUTするタイミングでエラーが返ってきます。

そのほかに使えるパラメータで便利なものはPUT _component_templateと同様にcreate_metaです。

GET _index_template

Index Templateを取得するためのAPIです。公式ドキュメントはこちらです。 一覧での取得とリストでの取得が可能です。

一覧取得サンプル

GET /_index_template
GET /_index_template/*

これ以外に、IDを指定して取得することも可能です。

GET _index_template/blog_template

*を利用して複数取得も可能です。

GET _index_template/blog_*
GET _index_template/b*_*

DELETE _index_template

Index Templateを削除するためのAPIです。公式ドキュメントはこちらです。

IDを指定してコンポーネントを削除できます。

DELETE /_component_template/jp_simple_kuromoji

ID指定以外に*を利用することも可能ですが気を付けて使用しましょう。

DELETE /_component_template/jp_*
DELETE /_component_template/*

最後のサンプルを実行すると、Elasticのツールなどが登録したIndex Template以外はすべて削除されてしまうので本当に気を付けましょう。

Simulalte API

さて、コンポーネントとテンプレートを作成したので確認をしましょう。 Legacy Index Templateでは確認するためには実際にインデックスを作成するしかありませんでしたが、V2ではSimulate APIが用意されています。 このSimulate APIには2つのAPIがあります。

  • POST /_index_template/_simulate/<テンプレート名>
  • POST /_index_template/_simulate_index/<インデックス名>

Index Templateの確認のためのAPIとインデックス名を指定したときに出来上がるIndexの設定を確認するためのAPIです。 Indexを実際に作成しなくても確認できるのは便利ですね。

例えば先ほど作成したblog_templateを試してみましょう。

_index_template/_simulate API

POST _index_template/_simulate/blog_template

レスポンスはこんな感じです。

{
  "template" : {
    "settings" : {
      "index" : {
        "analysis" : {
          "analyzer" : {
            "simple_jp" : {
              "filter" : [
                "kuromoji_readingform"
              ],
              "type" : "custom",
              "tokenizer" : "kuromoji_tokenizer"
            }
          }
        },
        "number_of_shards" : "3"
      }
    },
    "mappings" : {
      "properties" : {
        "hoge" : {
          "type" : "text",
          "analyzer" : "simple_jp"
        }
      }
    },
    "aliases" : { }
  },
  "overlapping" : [
    {
      "name" : "blog_template2",
      "index_patterns" : [
        "blog_*"
      ]
    }
  ]
}

templateにコンポーネントがマージされた結果が出力されます。 overlappingindex_patternsがかぶる可能性があるIndex Templateの情報が出力されます。 サンプル用にblog_template2という、同じindex_patternspriorityが低いものを登録してあるためです。 index_patternsが完全に同じではなくとも、重複する可能性があるものはここに出力されます。 例えば、index_patternsb*という別のIndex Templateを作成してからSimulate APIを実行すると、overlappingにそのIndex Templateも出力されます。

Simulate Index Template APIのもう一つの機能は登録前のIndex Templateの確認です。 リクエストのURLのテンプレート名をなくし、PUT _index_templateと同じJSONをリクエストボディとして送信した場合、コンポーネントをマージしたテンプレートがどんなものかを確認できます。

POST _index_template/_simulate
{
  "index_patterns": ["blog_*"],
  "template": {
    "mappings": {
      "properties": {
        "hoge": {
          "type": "text",
          "analyzer": "simple_jp"
        }
      }
    }
  },
  "priority": 10,
  "composed_of": ["jp_simple_kuromoji"]
}

このリクエストを送信すると、コンポーネントがマージされた結果が返ってきます。index_patternsがかぶるものがある場合はoverlappingも一緒に返却されます。

_index_template/_simulate_index API

今度はインデックス名を指定するSimulate APIを試してみましょう。

POST _index_template/_simulate_index/blog_2021

これだけです。

{
  "template" : {
    "settings" : {
      "index" : {
        "analysis" : {
          "analyzer" : {
            "simple_jp" : {
              "filter" : [
                "kuromoji_readingform"
              ],
              "type" : "custom",
              "tokenizer" : "kuromoji_tokenizer"
            }
          }
        },
        "number_of_shards" : "3"
      }
    },
    "mappings" : {
      "properties" : {
        "hoge" : {
          "type" : "text",
          "analyzer" : "simple_jp"
        }
      }
    },
    "aliases" : { }
  },
  "overlapping" : [
    {
      "name" : "fuga",
      "index_patterns" : [
        "b*"
      ]
    },
    {
      "name" : "2021",
      "index_patterns" : [
        "*_2021"
      ]
    }
  ]
}

例で作成したblog_templateが適用されていますが、それ以外にindex_patternsに合致したがpriorityが低くて適用されなかったものがoverlappingに出力されています。 実際に適用されたテンプレートの名前も別途出力してくれるとわかりやすいかもしれないですね。 (*_2021というインデックスパターンのテンプレートを試しに作ってみたのですが、これはバグがありそうです。2021に合致するインデックス名をSimulateしたらoverlappingに合致しないものがたくさん出てきました。バグ報告しとくか)。

Kibana対応

ここまで、Index Template V2のAPIの説明でしたが、Kibanaでの対応についても調べてみました。

Index Management(Stack Management機能。Elasticライセンスが必要だが無償の機能)

7.9からKibanaのIndex管理画面でComposable Templateが利用できるようになっています(GitHub Issue)。 画面のスクショを一通り貼っておきます。残念ながら、それぞれのJSONの編集部分では補完などはサポートされていないようでした。 頑張って自分でsettingsやmappingsのJSONを記述していく感じになります。JSONとして正しいかどうかはチェックしてくれます。 Index Templateのウィザードでは、ボタンでコンポーネントを追加したり削除したり、順序を入れ替えたりといった作業が可能になっています。 また、プレビュー表示が可能なので、composed_ofで選択したものが今どのように適用されているか?といったのも確認できるようになっていました。 結構便利に管理できそうです。ちなみにスクショは7.10の画面になります。

  • Component Template周り
    • 一覧表示とウィザード

  • Index Template周り
    • 一覧表示とウィザード

Console(Dev Tools。OSSで利用可能)

リクエストを実行は可能ですが、自動補完機能は一部のみ対応しているようです(GitHub Issue)。

対応済みの機能

  • DELETE _component_template (ただし、ここまで。存在するコンポーネント名は補完されない)

上記以外はまだ未対応のようです。 プルリクエストチャンスかも?

参考

まとめ

ちょっと長くなってしまいましたが、新しいIndex Templateについての紹介でした。 これまでと違い、複数のテンプレートが適用されない点があるのでそこは注意が必要そうです。 コンポーネントをうまく使えば、管理が簡易化はされそうですね。


comments powered by Disqus