💭

TerraformによるAlgoliaの構成管理

2021/12/31に公開

Algolia Advent Calendar 202131 21日目の記事です。(だいぶ遅れてしまい恐縮です🙇‍♂️)

メルカリUSの検索チームでバックエンドエンジニアをしている、k-yomoです。

この記事では、今年開発したAlgoliaのTerraform Providerについて紹介したいと思います。
https://registry.terraform.io/providers/k-yomo/algolia/latest/docs

また、上記のTerraform ProviderはOSSとしてGithubに公開されています。
https://github.com/k-yomo/terraform-provider-algolia

開発背景

メルカリUSでは検索機能に全文検索SaaSであるAlgoliaを利用しています。メルカリUSのAlgolia活用事例については、AlgoliaのWebサイトでもご紹介頂いているので、ご覧頂けると幸いです。
https://resources.algolia.com/marketplaces/mercari

そして、社内ではJavascript、Ruby、シェルスクリプトの3つをリソース毎に使い分けた独自のCLIを用いてAlgoliaの各種設定のIaCを実現しています。しかし、メンテナンスのコストや、運用の煩雑さがあったため、Terraformで管理したら楽になるのでは?と考えました。

既存のTerraform Providerもいくつかあったのですが、メンテナンスがされていなさそうだったり、IndexやAPIキー等の一部のリソースしかサポートされていない等があり、また自身としてもTerraform Providerを一度作ってみたい気持ちがあったことから、1からTerraform Providerを自作するに至りました。

現在時点でまだ社のツールは置き換えられていませんが、IndexやRule、Synonymなど主要なリソースをカバーしており、下記のコメントを下さった方がフランスの企業で使用している?ようなのと、Algoliaの社内でも使って下さったとのことで大変嬉しい限りです。

https://github.com/k-yomo/terraform-provider-algolia/issues/40#issuecomment-939879868


k-yomoさんのTerraform Provider Algoliaを試してみる

Terraformで構成管理することのメリット

Algoliaに限った話ではないですが、ここで簡単にTerraformないしはIaCでインフラの構成管理をするメリットについて簡単に紹介したいと思います。

インフラ構成をgit管理できる

個人的にTerraformを使うことの最大のメリットの1つがgit管理に付随する下記のような恩恵が得られることだと考えます。

マニュアル運用のミスをなくす

コンソールからの設定では「間違ったアプリケーションに変更を適用してしまっていた」、「設定項目を誤って適用してしまっていた」など、細心の注意を払ってしまっていても人為的な操作にはミスがつきものです。

Terraformを使った構成管理では、レビューで確認した差分が反映されるため、設定ミスや想定していない変更を少なくすることが出来ます。
※API、Providerなどのバグもあるため、意図しない変更が起きる可能性はあります

開発環境と本番環境の設定のズレを最小限にする

下記の記事で詳しく説明されているようなsymlinkを使ったディレクトリ構成やTerraform Workspaceなどを利用することで、開発環境と本番環境で構成の差分を最小限に保つことが出来ます。
https://www.m3tech.blog/entry/2020/07/27/150000

symlinkを使ってAlgoliaの設定をTerraformで管理するexampleのリポジトリを以前に作ったため、興味がある方は参照頂けると幸いです。
https://github.com/k-yomo/algolia-terraform-example

また、indexの規模によっては、複数のAlgoliaクラスターを運用しているケースもあるかと思います。Terraformを利用すれば、複数のクラスター上に適用したい同一の設定も一括で管理することが可能です。(実装例を追って使い方に追記したいと思います🙏)

使い方

Algolia Providerを使ったTerraform初期設定からindexの作成までは、Algoliaのソリューションエンジニアである、shinodoggさんに詳しく解説頂いているので、ご覧頂けますと幸いです。
https://shinodogg.com/2021/11/04/terraform-provider-algolia/

レプリカindexの設定

Algoliaを利用する際にはいくつかのソートに対応するためにレプリカindexを使用するケースがよくあることかと思います。しかし、Terraformを使用する場合、プライマリーindexの設定更新をレプリカにも反映するForward to replicasは使用できません。

そこで、Terraformを使用する際は以下のような形でランキングや特定の項目のみ、index毎の設定に書き換えることが出来ます。また、他の利用ユーザーの事例ではmoduleを作ってまとめている、という方もいました。

locals {
  products_v1_primary_index_name = "products-v1"
  products_v1_indices = {
    "products-v1" : {
      ranking = [
        "typo",
        "geo",
        "words",
        "filters",
        "proximity",
        "attribute",
        "exact",
        "custom",
      ]
    },
    "products-v1.sort_by_price_asc" : {
      ranking = ["asc(price)"]
    }
    "products-v1.sort_by_price_desc" : {
      ranking = ["desc(price)"]
    }
  }
}

resource "algolia_index" "products_v1" {
  for_each = local.products_v1_indices
  name = each.key
  primary_index_name = each.key == local.products_v1_primary_index_name ? null : local.products_v1_primary_index_name

  ranking_config {
    ranking = each.value.ranking
  }

  attributes_config {
    searchable_attributes = [
      "name",
      "category_names",
      "brand_name",
      "colors",
      "unordered(description)",
    ]
    attributes_for_faceting = [
      "category_id",
      "brand_id",
      "colors"
    ]
    unretrievable_attributes = []
    attributes_to_retrieve = [
      "name",
      "main_image_url",
      "category_id",
      "category_names",
      "brand_id",
      "brand_name",
      "colors",
      "description",
      "price",
      "created_at",
      "updated_at",
    ]
  }

  performance_config {
    numeric_attributes_for_filtering = [
      "price",
    ]
  }

  languages_config {
    index_languages = ["ja"]
    query_languages = ["ja"]
    attributes_to_transliterate = ["*"]
  }
}

利用時の注意点

algolia_synonymsは排他的

Terraform Providerを利用して、下記のようにsynonymを定義することができます。
このalgolia_synonymsは実装の制約からReplaceAllSynonyms APIを使用しており、既存の設定を上書きする仕様となっています。(GCPのgoogle_project_iam_policyと同じ挙動です。)

resource "algolia_synonyms" "example" {
  index_name = algolia_index.example.name

  synonyms {
    object_id = "test_1"
    type      = "synonym"
    synonyms  = ["smartphone", "mobile phone", "cell phone"]
  }
  synonyms {
    object_id = "test_2"
    type      = "oneWaySynonym"
    input     = "smartphone"
    synonyms  = ["iPhone", "Pixel"]
  }
}

https://www.algolia.com/doc/api-reference/api-methods/replace-all-synonyms/

Algolia Provider使用の際は上記の上書きされてしまう点に注意してご利用頂けると幸いです。

indexの削除

v0.2.6からindexにdeletion_protectionというフィールドを追加しました。deletion_protectionは意図しないdestroyを防ぐ目的でdefaultでtrueになっています。
indexを削除する際は、下記のようにdeletion_protectionを明示的にfalseにする必要があります。

resource "algolia_index" "example" {
  name                = "example"
  deletion_protection = false
}

Timeout問題

https://github.com/k-yomo/terraform-provider-algolia/issues/49

indexの設定の更新は場合によって長時間かかる場合があります。v0.2.5以前のバージョンでは、Timeoutが1時間に設定されているため、1時間を超えた場合にタイムアウトが起きてしまいます。

設定自体は非同期にてAlgoliaのindexに反映され、反映後に再度terraform refreshを行えば、最新の設定がterraformのstateにも同期されるので、timeoutが起きても大きな問題はありません。

v0.2.6からindexのcreateupdateについてはTimeoutを無期限にしており、また非同期による適用など現在修正対応を考えています。

Algolia Providerの利用時の注意点についてご紹介しました。上記に限らず、もしAlgolia Providerを使用する中で欲しい機能であったり、問題が生じた場合は小さなことでもIssueから報告いただけると幸いです。

まとめ

今回は、Terraform Provider Algoliaの開発背景からTerraformを用いたAlgoliaの構成管理・利用時の注意点までご紹介しました。Providerの使い方についてはもう少し事例を追記できればと思いますが、Algoliaを利用している方やAlgoliaの導入を考えている方の参考になりましたら幸いです。

また、まだ弊社では実運用には至っていません。2022年は未実装のリソースを追加 & テストを拡充し、検証が出来れば社のAlgoliaの構成管理もTerraformに移行したいと考えています!その際はまた社のブログから報告できればと思います。

それでは、皆さん良いお年を!!

Discussion