エンジニアの竹田です。
BUYMAの検索システムやMLOps基盤の開発・運用を担当しております。
今回はSolr Operatorによる検索システム構築を行いましたので、その実施内容と得られた知見についてご紹介したいと思います。
はじめに
昨期から今期にかけて、オンプレミスのシステムからの脱却、およびマイクロサービス化を目指し、商品検索システムのリプレイスを進めていました。
エニグモでは機能毎にApache Solrを用いた複数の検索システムを保持しており、クラウド移行に伴い、構築面や運用面の負担は大幅に軽減できております。
なお、リプレイスを行った商品検索システムの構成も下記の記事と大きくは変わっていません。 tech.enigmo.co.jp
今回フォーカスする検索システムの課題
検索システムの運用には、開発案件や障害対応、システムのバージョンアップやシステム増強作業などがあります。
中でも開発案件は、本番と同等のデータを利用したシステムにて検索の並び順や検索ヒット内容の検証が必要となる場合があります。
今まではオンプレミス環境にそのシステムを構築していましたが、今回の商品検索のクラウド移行に合わせ、同環境をクラウド上に構築することになりました。
システムのライフサイクルが短いため、より簡素に構築・廃棄を行えるようにしたいという課題があり、そこで案として出たのがSolr Operatorの利用です。
結果次第ではサービス運用でも利用できる可能性も考慮してSolr Operatorを利用した構築の検証を行いました。
なお、本記事ではある程度KubernetesやApache Solrのことをご存知の方を対象としている点をご容赦ください。
Solr Operatorについて
Welcome - Apache Solr Operator
Solr OperatorはKubernetesのCRD(Custom Resource Definition)として提供されているもので、SolrCloudやZookeeperClusterといったkindによりSolrシステムを一元管理するイメージという理解で良いかと思います。
2023/04/24にv0.7.0がリリースされています。
Solr Operatorの概要や簡素な構築方法については、Google CloudのShimojo様が非常に分かりやすいブログ記事を公開されていますので是非ご参考にしてみてください。
Solr Operator を利用して SolrCloud クラスタを GKE Autopilot に構築する (前編) zenn.dev
Solr Operator を利用して SolrCloud クラスタを GKE Autopilot に構築する (後編) zenn.dev
構築時の簡単な構成は、以下のようになっています。
Zookeeper Operatorについては特に触る必要がなかったため、本記事では触れていません。
Solr Operator CRDの各リソース項目について
Solr OperatorはCustom Resource Definition(CRD)として提供されており、項目に合わせて定義を埋めていく形になります。
構成管理を考えた場合、helm install
でSolrCloudクラスタを構築する際に適宜パラメータとして指定するよりも、Kubernetesマニフェストとして管理するのが望ましいと思われます。
※helm install
ではなく、マニフェストを作成してkubectl apply -f <作成したマニフェストのyamlファイル>
で構築する方式
以下に、kind: SolrCloud
において利用頻度が高いと見込まれるパラメータを列挙してみました。
spec配下の設定項目 | 内容 | 備考 |
---|---|---|
solrImage | 利用するsolrのコンテナイメージを指定 | 独自ビルドしたイメージも指定可能 |
solrOpts | solr起動時のパラメータを指定 | |
solrJavaMem | javaのヒープサイズを指定 | |
solrAddressability | solrの解放ポートや外部接続定義を指定 | |
solrGCTune | GarbageColleciton用のチューニングパラメータを指定 | |
customSolrKubeOptions | solrのカスタム項目を指定 | (※1) |
updateStrategy | solrの更新方式をを指定 | 未指定時のデフォルトがrollingUpdateのため注意 |
dataStorage | solrのデータ格納先ストレージ | persistentにして永続ディスクを利用 |
replicas | solr podのレプリカ数 |
(※1) 以下、customSolrKubeOptions配下の項目
spec.customSolrKubeOptions配下の設定項目 | 内容 | 備考 |
---|---|---|
ingressOptions | 外部にingressを利用している場合に利用 | annotationsでBackendConfigを指定するなどで利用 |
configMapOptions | providedConfigMapにカスタムConfigMapを指定 | solr.xml やlog4j2.xml を定義できる |
podOptions | solr podに対するオプション項目 | (※2) |
(※2) 以下、podOptions配下の項目
spec.customSolrKubeOptions.podOptions配下の設定項目 | 内容 | 備考 |
---|---|---|
resources | CPUやメモリのlimits/requestsを設定 | |
livenessProbe | Solrが動作しているかどうか | 指定しないとhealthcheckが通らず、podが起動しない |
readinessProbe | Solrがトラフィックを受けられるかどうか | 指定しないとhealthcheckが通らず、podが起動しない |
initContainers | Solr PodのinitContainersを定義できる | |
sidecarContainers | Solr Podに設置するサイドカーコンテナを定義できる |
あくまでサンプルですが、以下のようなマニフェストになるかと思います。
apiVersion: solr.apache.org/v1beta1 kind: SolrCloud metadata: name: example namespace: solr spec: replicas: 3 solrImage: tag: 9.2.1 pullPolicy: IfNotPresent solrGCTune: -XX:NewRatio=3 -XX:SurvivorRatio=4 solrJavaMem: -Xms2048M -Xmx2048M solrAddressability: commonServicePort: 8983 updateStrategy: method: StatefulSet dataStorage: persistent: pvcTemplate: spec: resources: requests: storage: 100Gi reclaimPolicy: Retain customSolrKubeOptions: configMapOptions: providedConfigMap: solr-config-map # configMapは先に作成・適用しておく必要がある ingressOptions: annotations: cloud.google.com/backend-config: '{"ports": {"8983":"solrcloud-backend-config"}}' cloud.google.com/neg: '{"ingress": true}' podOptions: resources: limits: cpu: 2 memory: 6Gi requests: cpu: 2 memory: 6Gi livenessProbe: initialDelaySeconds: 30 periodSeconds: 10 httpGet: scheme: HTTP path: /solr/admin/info/health port: 8983 readinessProbe: initialDelaySeconds: 15 periodSeconds: 5 httpGet: scheme: HTTP path: /solr/admin/info/health port: 8983
補足となりますが、Solrが起動しない場合は、概ね以下の方法で原因を特定できます。
- Solr Podを
kubectl describe
で確認
kubectl describe pod example-solrcloud-0 -n solr
- solr-operator Podを
kubectl logs
で確認
kubectl logs solr-operator-xxxxxxxxxx-xxxx -n solr
マニフェスト適用後は、solrスキーマ定義やsolrconfig.xmlの配置、コレクションの作成と進めて検索できる状態にします。
こちらの作業についての手順は割愛します。
Solr起動後の管理画面等への接続については、上記で図示した通りingress
経由としました。
実際に構築してみた所感
まだ検証段階ではありますが、以下の恩恵を得られるものと思います。
- Zookeeperを特に意識しなくて良い
- ディレクトリ構成も基本的には意識しなくて良い
- SolrCloudを構築する上でのSolrの学習コストが下がる
- マニフェストさえ用意しておけばSolrCloudシステムの作成、削除がkubectlコマンド一発で完遂する
- CRDの項目が充実しており、かなり細かい点まで定義可能
苦労した点としては以下になります。
- マニファストの設定誤りや漏れがあると結構ハマる
- 特にヘルスチェック、リソース定義周りの定義誤りは何が問題なのか分かり辛い
- CRDはかなり長大なマニフェストのため読み解くのが大変
- 日本語での参考文献がほとんどない
運用利用に当たっては以下の項目を意識・検討する必要があることも分かりました。
- Solr Operatorで構築できるのはSolrのインフラ面のみ
- Solrのスキーマ定義や構成ファイルの配置は
configsets API
やzkCliコマンド
を利用する必要がある
- Solrのスキーマ定義や構成ファイルの配置は
- アクセス周りのセキュリティを気にしておく必要がある
- 監視関連の定義は別途検討の必要がある
- エニグモでは検索システムの監視にDatadogを利用しているため、対応方法を調査・検討する必要あり
- Solr Prometheus Exporterを利用する方法もある
- 用途の異なる検索システムを1つのSolrCloud kindに集約しない方が良いかもしれない
- Solr Podの名称がprefix固定の連番suffix(例:
xxx-solrcloud-1
、xxx-solrcloud-2
)での管理となるため、Pod名称から用途が判別し辛い
- Solr Podの名称がprefix固定の連番suffix(例:
- 実サービスでの利用はAutopilotクラスタよりStandardクラスタの方が良いかもしれない
- オートスケールに時間を要するため、ある程度リソースが確保された状態でないと運用は難しそう
- Solr Operator自体のバージョンアップへの追従
また、合わせてSolr構成も見直した方が良いと感じました。
- NRTや全TLOGのレプリカタイプでコレクションを作成した方が良い
- 1podがダウンしても更新や検索に影響のないシステム構成にする必要あり
- 必然的にDataImportHandlerのようにデータをpullする方式の採用は難しくなる
検証用途には手順を圧縮できるため便利に感じる一方、サービス運用には検討すべきことが多いという印象でした。
業務等でSolr Operatorの利用を検討されているようでしたら、本記事が一助になれば幸いです。
最後に
弊社では、本記事に記載したような新しい取り組みや、より良いシステムを作りを一緒に進めていくためのメンバーを随時募集しています!
株式会社エニグモ すべての求人一覧