Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Lessons from Migrating to OpenSearch: Shard Des...

Avatar for SansanTech SansanTech PRO
December 11, 2025

Lessons from Migrating to OpenSearch: Shard Design, Log Ingestion, and UI Decisions

■ イベント
OpenSearchCon Japan
https://events.linuxfoundation.org/opensearchcon-japan/

■ 発表者
技術本部 Eight Engineering Unit
藤原 和弘

■ Eight 開発エンジニア 採用情報
https://media.sansan-engineering.com/eight-engineer

Avatar for SansanTech

SansanTech PRO

December 11, 2025
Tweet

More Decks by SansanTech

Other Decks in Technology

Transcript

  1. Sansan株式会社 部署 名前 Lessons from Migrating to OpenSearch: Shard Design,

    Log Ingestion, and UI Decisions 2025.12.11 OpenSearchCon Japan 2025 技術本部 Eight Engineering Unit Platform グループ 藤原 和弘
  2. 藤原 和弘 Sansan株式会社 技術本部 Eight Engineering Unit Platformグループ SREチーム 経歴

    - 2024年8⽉、Sansan株式会社にEightのSREとして⼊社 現在は、インフラ領域だけでなく、アプリケーション 領域にもコミットできるように⽇々活動中。 - 前職では新卒から約4年半アマゾンウェブサービス ジャパン合同会社でソリューションアーキテクトとして 働き、社内コミュニティではオブザーバビリティ領域を 専⾨に活動していた。
  3. © Sansan, Inc. - OpenSearch移⾏時の最適な設計 - ノード構成の考え⽅ - シャード設計の実践的アプローチ -

    最適な設計をしないで運⽤するとどうなるか - 安定運⽤のためのチューニング⼿法 - インデックス化負荷の最適化⼿法 - OpenSearch UIの活⽤どころ - 採⽤判断のポイント - 運⽤して分かった良い点・⾟い点 はじめに - ログ基盤でOpenSearch Serviceの 運⽤をしている開発者/SREエンジニア - これからOpenSearch Serviceの 導⼊を検討している⽅ - OpenSearch Dashboardsの活⽤に 課題感がある開発者/SREエンジニア 本セッションで得られる知⾒ 想定聴講者
  4. © Sansan, Inc. 移⾏前のログ分析アーキテクチャ概要 VPC ECS Web/API Fluent Bit Elasticsearch

    Fluentd (Aggregator) Application Load Balancer Amazon Data Firehose Network Load Balancer Workers Fluentd Kibana 略 Amazon Simple Storage Service 調査時や障害時にログ分析 Fargate EC2 Service Task Task Service 10年以上前からログ検索、可視化のためにElasticsearchを活⽤している
  5. © Sansan, Inc. Elasticsearchに流していたログの種類は10種類以上* ログの種類と流⼊量 ※ 各ログ種のログフィールドが異なるため、インデックスは各ログ種ごとに作成している 約 GB/⽇ のログがインデックスされる

    150 アクセスログ アプリケーションログ ⾮同期処理のログ スケジュール実⾏される処理のログ 監査ログ スロークエリログ etc… 流⼊が多いログの おおよそのログ量 ログA:50GB/⽇ ログB:25GB/⽇ ログC:20GB/⽇
  6. © Sansan, Inc. 移⾏背景 運⽤管理コスト - EC2 インスタンス⾃体の セキュリティ対応による 管理コストを軽減したい

    - 当時は2⼈体制だったため、 運⽤管理コストに 割く時間を下げたい セキュリティリスクと 機能追加への追従 - Kibana/Elasticsearchの ソフトウェアバージョンの 追従がされずに塩漬けの ような状態になっていた - SSHができる環境のため、 意図せずOS上の操作や AWSリソースの操作がされて しまうリスクが存在する
  7. © Sansan, Inc. - 移⾏にあたって最低限満たしたい要件 - ログには機密データも含まれるため、Private Subnetに配置すること - サーバーの管理コストを可能な限り下げること

    - ログ保持期間の要件を担保できること - 開発⽣産性、運⽤コストを⼤きく変えないための要件 - 開発者/SREのログ検索・分析体験が損なわれないこと 移⾏要件
  8. © Sansan, Inc. 移⾏後のログ分析アーキテクチャ概要 VPC OpenSearch Service Fluentd (Aggregator) Data

    Firehose NLB OpenSearch UI 略 S3 本⽇触れる部分2 本⽇触れる部分1 ECS Web/API Fluent Bit ALB Workers Fluentd Fargate EC2 Service Task Task Service ECS Service Fargate
  9. © Sansan, Inc. - 移⾏にあたって最低限満たしたい要件 - ログには機密データも含まれるため、Private Subnetに配置すること - サーバーの管理コストを可能な限り下げること

    - ログ保持期間の要件を担保できること - 開発⽣産性、運⽤コストを⼤きく変えないための要件 - 開発者/SREのログ検索・分析体験が損なわれないこと 移⾏要件(再掲) ✅ ✅ ✅ ✅ OpenSearch UIの採⽤ OpenSearch Serviceの採⽤ OpenSearchのISM Policyとエイリアスで実現
  10. © Sansan, Inc. 移⾏の概要 リスクを最⼩化するため、Elasticsearchと並⾏稼働状態で段階的に移⾏ ログ分析の際は、OpenSearch UIに慣れ てもらうために、基本的にOpenSearch UI側を使ってもらうようにした。 緊急時のみKibanaへアクセス

    OpenSearch Fluentd (Aggregator) Data Firehose OpenSearch UI 略 S3 Service Elasticsearch Kibana 送信先にOpenSearchを追加 シングルノード (マスター兼データノード) インデックス① プライマリシャード ×3 ‥‥ シングルノード (マスター兼データノード) インデックス① プライマリシャード① インデックス① レプリカシャード① ‥‥ シングルノードだったため、 プライマリ:レプリカ=1:1で設定 内部向けのログ基盤かつ、 S3にもログを送信していた。 つまり、OpenSearchで 何か起きた際でも ログ損失はないと判断し、 既存踏襲で1台構成に
  11. © Sansan, Inc. 課題①:クラスターがYellowステータスになる https://docs.aws.amazon.com/opensearch- service/latest/developerguide/handling-errors.html#handling-errors-yellow- cluster-status A yellow cluster

    status means the primary shards for all indexes are allocated to nodes in a cluster, but the replica shards for at least one index aren't. Single-node clusters always initialize with a yellow cluster status because there's no other node to which OpenSearch Service can assign a replica. To achieve green cluster status, increase your node count. レプリカシャードをプライマリシャードが置かれているノードとは 別のノードにおけない場合に常にYellowステータスとなる シングルノード構成だったことが原因
  12. © Sansan, Inc. 可⽤性を⾼めつつ、EC2で⾃前で運⽤していたときと ほぼ変わらないコストで対応できた クラスターが不安定になるとアラートに割く時間も増え、運⽤が⼤変になりそう r7g.2xlarge.search * 1台からr7g.medium.search *

    6台にすることでAZを分散させつつ、 クオーラム損失とはならない2台のノード障害までは許容した 対応⽅法 インスタンスタイプ vCPU メモリ (GiB) JVMヒープ (GiB) コスト r7g.2xlarge.search 8 64 32 $0.858/hour r7g.medium.search 1 8 4 $0.107/hour r7g.medium.search * 6 6 48 24 $0.642/hour ノード構成を再考
  13. © Sansan, Inc. 課題②:特定ノードでのCPU負荷が⾼くなる Fluentd側では次のようなエラーが頻発した(⼀部加⼯済み) 特定ノードでCPU使⽤率が100%に張り付く - buffer flush took

    longer time than slow_flush_log_threshold: elapsed_time=22.083716957000433 slow_flush_log_threshold=20.0 - failed to flush the buffer. retry_times=2 next_retry_time=…略…error_class=Fluent::Plugin:: OpenSearchOutput::RecoverableRequestFailure error="could not push logs to OpenSearch cluster - failed to write data into buffer by buffer overflow action=:throw_exception - error_class=Fluent::Plugin::Buffer::BufferOverflowError error="buffer space has too many data
  14. © Sansan, Inc. 課題②:特定ノードでのCPU負荷が⾼くなる 3種類のログの量が多かったが、それぞれのインデックスに対して プライマリ:レプリカを1:1に設定していたため、 ノードを分散させたことで特定のノードにそれらのシャードが偏ってしまっていた。 ④ログが Drop ❌

    ❌ ❌ ⑤ログ⽋損の インシデント発⽣ ①多くの インデックス化 が拒否される ②Fluentdのバッファが 溜まり続ける ③Ephemeral Storage枯渇 放置すると 右記のように インシデントに つながってしまう
  15. © Sansan, Inc. - 3000シャード以上あり、シャード数が過多の状況 - r7g.medium は JVM ヒープが

    4 GiB のため、 ドメイン全体で 600 シャードまでが推奨されている - ログを送信し続けているのでインデックス化負荷が⾼かった (メトリクスとしてもIndexing Rateも⾼かった) - 対策①:シャード数を削減し、シャードをデータノード間で均等に分散させる - シャードあたり30GB ~ 50GB(ログ分析ワークロードの推奨値)に抑えたい - 対策②:レプリカ数をゼロにする - 対策③:refresh_interval を 60 秒以上に増やす インデックス化のパフォーマンスを改善したい これらの対策はhttps://repost.aws/ja/knowledge-center/opensearch-indexing-performanceにも記載されています さらに調査をした結果… ノード間の偏りとシャード数削減 インデックス作成時の負荷を抑えたい
  16. © Sansan, Inc. ⻑期間保存するログかつログ量が少ないものについては、 ⽉ごとにインデックスを作られるように変更した 対策①:シャード数を削減し、シャードをデータノード間で均等に分散させる logstash_format true logstash_dateformat %Y%m%d%H

    logstash_prefix ”logA-${tag[1]}" ログAでのFluentdの設定イメージ logA-huga-2025010100 logA-huga-2025010101 logA-huga-2025010102 … 1⽇で24インデックスが⽣成される つまり、1つのログ種だけで5⽇間で 合計120インデックス⽣成されてしまう logstash_format false include_timestamp true index_name logA-${tag[1]} # エイリアスに送るようにする 例)5⽇間ログを保持する要件がある場合 Before After ログAの1⽇の流⼊量が50GBの場合、 インデックスあたり300GB(50GB * 6ノード)までが推奨値。 ISM Policyを活⽤しつつ5⽇ごとに インデックスを作る⽅針にした。 ログAでのFluentdの設定イメージ ⽣成される インデックス LogA-huga- 000001 LogA-huga- 000002 LogA -huga エイリアス 5⽇で インデックス 切り替え Fluentd 対応⽅法
  17. © Sansan, Inc. プライマリシャード数を6にしてノード分散を実現し、 ロールオーバー戦略を活⽤することで シャード数を削減しながらインデックス化の負荷を抑えた 5⽇間ログを保持する要件がある場合の ISM Policyの設定⽅法 "states":

    [ { "name": "open", "actions": [ { "retry": { "count": 3, "backoff": "exponential", "delay": "1m" }, "rollover": { "min_index_age": "5d", "copy_alias": false } } ], "transitions": [ { "state_name": "delete", "conditions": { "min_index_age": "10d" } } ] }, ~ 略 ~ ] ISM Policyでロールオーバーを実現する例 Fluentdはエイリアスを⾒ているため、ロールオーバーは意識せずにログを送信し続けられる インデックス作成⽇時を条件に、5⽇後にロールオーバーさせ、 10⽇後にインデックスを削除することで要件を満たせる 2025/01/01 ~ 2025/01/05までのログ 2025/01/06 ~ 2025/01/10までのログ LogA-huga- 000001 LogA-huga- 000002 LogA- huga エイリアス ①5⽇で書き込みインデックス切り替え イメージ LogA-huga- 000001 LogA-huga- 000002 ②5⽇で読み込み専⽤になる、10⽇後には削除 されるので2025/01/05のログも5⽇は保持される Fluentd 対応⽅法
  18. © Sansan, Inc. 対応⽅法 PUT /<YOUR INDEX_TEMPLATE>/_settings { "index_patterns": [<YOUR

    INDEX_PATTERNS>], "template": { "settings": { "refresh_interval": "120s", "number_of_shards": 6, "number_of_replicas": 0 } } } *refresh_intervalは即時反映可能なので、 既存の各インデックスに対しても設定した refresh_intervalはインデックスの更新頻度を表しており、更新間隔が ⻑いほどインデックス作成の全体的なパフォーマンスが向上する。 ⼀⽅で、インデックスが更新されてから 新しいデータが検索可能になるまでの時間が⻑くなる。 Dev Toolsでのインデックステンプレート反映例* ▶ S3にもログを送信していたのでOpenSearch上のログ損失は許容した レプリカを設定すると、各レプリカはインデックス作成プロセスを複製する。 つまり、インデックスオペレーションが純増する。 レプリカを無効にすることでインデックス作成プロセスを減らすことにつながるが、 プライマリシャードのデータが失われてしまった場合はデータ損失する。 対策②:レプリカ数をゼロにする 対策③:refresh_intervalを 60 秒以上に増やす (デフォルトは1秒) ▶ ログ分析のユースケースでは120秒は許容として120秒に設定した
  19. © Sansan, Inc. 対応後のノード構成 OpenSearch Fluentd (Aggregator) Data Firehose OpenSearch

    UI 略 S3 Service Elasticsearch Kibana 送信先にOpenSearchを追加 シングルノード (マスター兼データノード) インデックス① プライマリシャード ×3 ‥‥ ノード① (マスター兼データノード) インデックス① プライマリシャード① インデックス② プライマリシャード① ‥‥ ノード② (マスター兼データノード) インデックス② プライマリシャード② インデックス① プライマリシャード② ‥‥ ノード③ (マスター兼データノード) ノード⑤ (マスター兼データノード) ノード④ (マスター兼データノード) ノード⑥ (マスター兼データノード) 緊急時のみ シャードとデータノードが 1:1の関係となり、 負荷が分散される
  20. © Sansan, Inc. 改善後のノードの負荷 ワークロードの特性上、特定の時間帯にIndexing Rateが⾼くなるためその時間帯でCPU負荷も上がるが、 平均で30%、ピーク時で70%ほどのCPU使⽤率に抑えることができた ▶ 1ヶ⽉後にRI購⼊へ Before

    After ベストプラクティスには 基本的に従うべき ただし当てはまるかはケース次第なので まずは実践を 事前のサイジングや インデックス設計も ⼤事だが、運⽤の中でも チューニングを継続する
  21. © Sansan, Inc. 課題③:クラスターがRedステータス時に⼿動で対応が必要となる 通常、ノード障害時には⾃動復旧するが、 レプリカが0だと障害が発⽣したノード上の シャードがロストする。 レプリカは0なのでデータロストと同等であり、 クラスターステータスは⾃動復旧されない。 書き込み先のインデックスのシャードが割り当てされて

    いないためインデックス化が拒否される。 この状態が続くと数時間でもFluentdのバッファが 貯まりFluentd⾃体がログを受けられなくなる。 結果、OpenSearch以外のログ⽋損にもつながるため、 早急な対応が必要。 Fluentdのバッファの容量(%) 約9時間でバッファが溢れてしまう Redステータスになるとどのような影響があるか
  22. © Sansan, Inc. ⼿動での対応⽅法 OpenSearch上でのデータロストは許容していたが、クラスターが⾃動復旧しないことで最終的には全てのログ⽋損に つながるリスクがあるため、その対応コストと早急な対応による精神負荷を考慮できていなかった。 レプリカ0での運⽤は、障害時の対応コストが想定以上に⾼い。▶ レプリカを1にするには更なる負荷軽減が必要 対応⽅法①:インデックスを削除*し、書き込みインデックスを再作成 (対応時間:約30分)

    1時間ごとに⾃動的にスナップショットが取得されるので、 対応⽅法①よりもOpenSearch上でのログ⽋損を抑えられる ü インデックスを⼀時的にClose ü スナップショットからの復元 (ログ量が多いもので1〜2時間くらい復旧に時間を要する) *インデックスを削除すると、そのエイリアスも削除されるので、直後の書き込みリクエストによりエイリアスと同じ名前で新しいインデックスが作成されてしまう。 そのため、各インデックスに対して時間を空けずに作業を実施しなければいけない。 ü 割り当てられていないシャードを持つインデックス削除 ü 書き込みインデックス作成 ü エイリアスの作成と紐付け POST /access-log-recommendation-000010/_close POST /_snapshot/cs-automated/<Snapshot ID>/_restore { "indices": ”logA-huga-000001” } 対応⽅法②:⾃動スナップショットから復元(対応時間:約2〜3時間)
  23. © Sansan, Inc. インデックス負荷を下げるための取り組み② マッピング設定を⾒直す 現在は全てのフィールドがtext + keyword型で⼊っている(デフォルトの挙動)。 ほぼ使われていないので気にしていなかったが、数値も⽂字列として扱われるので PPLでの⼤⼩⽐較などでエラーになる。

    完全⼀致検索で良いフィールドはkeyword、 数値はintegerもしくはfloat、 不規則なフィールド(pathやmessageなど)は text + keyword型にするなど、 最適なマッピング設定を精査中 ~ 略 ~ "country": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "response_time": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, ~ 略 ~ デフォルトのマッピング設定 text型:部分検索(曖昧検索) Keyword型:完全⼀致検索 methodがPOSTのログ pathにmyhomeが 含まれているログ
  24. © Sansan, Inc. インデックス負荷を下げるための取り組み③ セグメントレプリケーションと Remote Backed Storageの机上検討 (OR/OMインスタンス) レプリカを作成した場合でもインデックス化におけるCPU負荷を低減しつつ、

    S3を活⽤した耐久性も備えているため、インデックス化の負荷が⾼いワークロードに最適。 次回のRI購⼊時に合わせて検証なども進めていきたい。 - セグメントレプリケーションと従来のドキュメントレプリケーション - メリット:データは1次コピーにのみインデックス化される - デメリット:書き込んだデータと読み取ったデータの⼀貫性が ⼀定期間は保証されない - Remote Backed Storage - OR/OM系のインスタンスでは、S3にレプリカを配置することで データの冗⻑性を担保している - Redステータス時もS3から⾃動でシャードが復旧される
  25. © Sansan, Inc. 運⽤から得られた学びと教訓 - 既存構成にとらわれずに、ベストプラクティスは基本的に従うべき - ノード分散とシャード均衡 / シャードサイズ

    / ノードあたりのシャード数 - インスタンス選定 - 今回はあまり検討していなかったが、振り返るとOR系のインスタンスも ユースケースに当てはまっていそうだった。 RIは購⼊済みなのでインスタンスタイプ変更検討はもう少し先になる 設計フェーズ 運⽤フェーズ - 継続的なパフォーマンスチューニングの重要性 - レプリカ数やrefresh_intervalの調整。Eightでは、障害時の対応コストを考えると ログ損失を許容したログ基盤でもレプリカを最低1つは持っておきたい - 不要なフィールドはインデックス化しない - 最適なマッピングを設定する - ベストプラクティスが当てはまるかはケース次第なのでまずは実践を
  26. © Sansan, Inc. 当初考えていたアーキテクチャ VPC OpenSearch Service Data Firehose NLB

    Proxy 略 S3 ALB ECS Web/API Fluent Bit ALB Workers Fluentd Fargate EC2 Service Task Task Service Fluentd ECS Service Fargate 調査時や障害時にログ分析 マネージドとはいえ、管理 コンポーネントが増えてしまう
  27. © Sansan, Inc. OpenSearch UIとの出会い IAM認証のみでPrivate Subnet上のOpenSearch に接続可能で検索体験も問題なさそうだった https://aws.amazon.com/jp/blogs/big-data/amazon-opensearch-service-launches-the-next-generation-opensearch-ui/ 画像引⽤:

    2024年11⽉に次世代UIとしてOpenSearch UIがAWSでもサポートされていた 複数のOpenSearchドメインを 1つのUIで検索や分析ができることが 推しポイントに⾒えた しかし、ドキュメントを読んでいくと VPCに関する記述がないこと、 認証はIAM認証が対応していることなどから、 Proxyを⽴てずとも OpenSearch UIで満たせるのでは? 早速検証へ!
  28. © Sansan, Inc. 検索体験 (通常のAWSマネジメントコンソールログインと同様にIAM認証) ▶ OpenSearch UIに⾶ぶ ▶ ワークスペースを選択する

    ▶ Discoverを開く ▶ インデックスパターンを選択 ▶ 好きなクエリ⾔語で検索 基本的にはDiscoverとダッシュボード、モニターが使えればよかったので Observability ワークスペースで構築 最終的にはAnalyticsワークスペースも構築した(理由は後述) ・Observability: ログ・メトリクス・トレース分析に特化 ・Analytics: すべての機能をサポート そのほかにも3つのユースケースが⽤意されている
  29. © Sansan, Inc. - ダッシュボードへのアクセスにProxyを⽤意する必要がない - Kibanaと⼤きくUIが変化していないので学習コストが低い - (AWS特有の話) -

    マネージドなので運⽤⼯数がかからない - IAM統合により認証認可がシンプル - 無料で使⽤可能 良いところ
  30. © Sansan, Inc. - 透過的なアップデートによってUIが変更されることがある - ObservabilityワークスペースはPPLしか使⽤できなくなってしまった - 現時点ではモニターを設定する際にNotificationプラグインがなく、 通知先をUIから設定できない。設定にはProxyが必要になる(本末転倒)

    - OpenSearch UI v2でサポートされそうなのでv2に期待! (https://github.com/opensearch-project/OpenSearch-Dashboards/issues/10524) - ブラウザバックで直前⼊⼒していたクエリに⾶べない - PPL以外ではクエリ履歴が選択できない ⾟いところ
  31. © Sansan, Inc. - 安定運⽤への道のり - ノード構成: 1台 → 6台(AZ分散)に変更しロールオーバー活⽤

    - シャード数: 3000以上 → 300ほどに削減 - ノード分散とレプリカ削減、refresh_interval調整で平均CPU使⽤率30%に改善 - 学びと教訓 - 内部向けログ基盤でもレプリカは必要だが、 インデックス化のパフォーマンスは劣化する - 事前設計だけでなく運⽤中のパフォーマンスチューニングも重要 - ベストプラクティスが当てはまるかはケース次第なのでまずは実践を - OpenSearch UI採⽤でProxyなどの管理コンポーネント削減に成功した まとめ OpenSearch移⾏で得られた知⾒ 今後の取り組み - マッピング設定の最適化 - インデックス化が不要なフィールドの精査 - 次回のRI購⼊に合わせたOR/OM系インスタンスの評価