AWS CDK で OpenSearch Service のエンジンバージョンに v2.15 を簡単に指定可能になりました
こんにちは、製造ビジネステクノロジー部の若槻です。
AWS CDK の最近のリリースである v2.159.0 で、下記のアップデートが追加されていました。
opensearch: support OpenSearch version 2.15 (#31398) (33eea3f)
Amazon OpenSearch Service では 2024/9/10 に OpenSearch バージョン 2.15 のサポートが開始され、パフォーマンス向上や新機能の追加が行われています。
今回のアップデートでは、AWS CDK で OpenSearch のエンジンバージョンに v2.15 を L2 Construct により簡単に指定可能になりました。
試してみた
AWS CDK で作成した OpenSearch Service Domain のエンジンバージョンを v2.13 から v2.15 にアップデートして、OpenSearch の新機能を試してみます。
OpenSearch v2.13 の場合
OpenSearch Domain で v2.13 を指定した場合の CDK コードは下記の通りです。エンジンバージョンは Domain Construct の version
プロパティで指定します。
import * as opensearchservice from 'aws-cdk-lib/aws-opensearchservice';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class CdkSampleStack extends cdk.Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
new opensearchservice.Domain(this, 'OpenSearchDomain', {
version: opensearchservice.EngineVersion.OPENSEARCH_2_13,
});
}
}
上記をデプロイ後、作成された OpenSearch Service Domain をダッシュボードから確認すると、バージョン 2.13 で作成されています。
- Version:
OpenSearch 2.13
- Service software version:
OpenSearch_2_13_R20240520-P5 (latest)
参考までに、この作成された OpenSearch Service ドメインは、複数のノードの集合からなる OpenSearch クラスター、および Application Load Balancer や S3 バケットなどの周辺リソースで構成されています。
amazon-opensearch-service - Amazon OpenSearch Service Intro Workshop [Japanese] より
- Data nodes: 検索対象のデータを保持し、クライアントからの検索リクエストを処理するノードです。
- Master nodes: クラスター全体のモニタリング、管理タスクの実行を担当するノードです。
- Application Load Balancer: ユーザーからのリクエストを Data nodes に振り分けます。
- UltraWarm nodes(Optional): 低頻度で検索される時系列データの保管先として有用なノードです。実体のデータは S3 バケット上に配置されており、UltraWarm nodes がキャッシュノードとして振舞うことでコストとパフォーマンスを両立します。
- Cold storage(Optional): 日常的に検索は行わないが保管が必要なデータの保存先として使用することができます。Cold storage 上のデータはそのままでは検索できませんが、必要時に UltraWarm ノードにデータをアタッチすることで検索が可能となります。アタッチは通常数秒で完了します。
CDK パッケージのアップデート
AWS CDK パッケージを v2.159.0 以上にアップデートします。
npm i aws-cdk-lib@latest aws-cdk@latest
OpenSearch v2.15 にアップデートする
CDK パッケージのアップデート後、OpenSearch Domain のエンジンバージョンで指定可能になった v2.15 に変更します。
import * as opensearchservice from 'aws-cdk-lib/aws-opensearchservice';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class CdkSampleStack extends cdk.Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
new opensearchservice.Domain(this, 'OpenSearchDomain', {
version: opensearchservice.EngineVersion.OPENSEARCH_2_15, // v2.15 に変更
});
}
}
CDK Diff を実行して変更内容を確認します。
$ npx cdk diff
Stack CdkSampleStack
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)
Resources
[~] AWS::OpenSearchService::Domain OpenSearchDomain OpenSearchDomain85D65221
└─ [~] EngineVersion
├─ [-] OpenSearch_2.13
└─ [+] OpenSearch_2.15
✨ Number of stacks with differences: 1
上記変更をデプロイすると、ドメインのアップデートが開始されます。
30 分程度でアップデートが完了し、バージョンが 2.15 になりました。
- Version:
OpenSearch 2.15 (latest)
- Service software version:
OpenSearch_2_15_R20240904-P1 (latest)
ちなみに上記が完了後も CloudFormation 上ではスタックのアップデートは少しの間継続していました。
v2.15 の新機能を試してみる
バージョン 2.15 で追加された新機能であるラジアル探索(Radial search)を試してみます。
ダッシュボードにアクセス可能とする
まず OpenSearch Service Domain のダッシュボードにアクセス可能にするため、Fine-grained access control を設定します。
この時点では {"Message":"User: anonymous is not authorized to perform: es:ESHttpGet because no resource-based policy allows the es:ESHttpGet action"}
となり、アクセスできません。
Fine-grained access control の設定でマスターユーザーを作成します。
指定の IP アドレスからのアクセスのみ許可するアクセスポリシーを設定します。
ちなみに、最初 OpenSearch v2.15 へのアップデート中にこの変更を適用しようとするとエラーとなりました。
A change/update is in progress. Please wait for it to complete before requesting another change.
設定を保存すると適用が開始されましたが、この適用の完了にも 2,30 分掛かりました。
適用の進捗が 85 %まで来ました。
100 %になりました。
ちなみに 85 %時点でダッシュボードにアクセス可能になりました。
先ほど作成したマスターユーザーでログインし、ダッシュボードの初回アクセス時の設定を行います。
Explore on my own を選択します。
Dismiss を選択します。
Private を選択して Confirm をクリックします。
ダッシュボードにアクセスできました。
ラジアル探索(Radial search)を試してみる
新機能である放射状検索(Radial search)を試してみます。
Dev Tools から環境を作成して検索クエリを実行していきます。
類似度計算に L2 距離(ユークリッド距離)を使用する k-NN インデックスを作成します。
PUT knn-index-test
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1,
"index.knn": true
},
"mappings": {
"properties": {
"my_vector": {
"type": "knn_vector",
"dimension": 2,
"similarity": "l2",
"method": {
"name": "hnsw",
"engine": "faiss",
"parameters": {
"ef_construction": 100,
"m": 16,
"ef_search": 100
}
}
}
}
}
}
/* 実行結果 */
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "knn-index-test"
}
2 次元のベクトルと価格が含まれるドキュメントをインデックスに追加します。
PUT _bulk?refresh=true
{"index": {"_index": "knn-index-test", "_id": "1"}}
{"my_vector": [7.0, 8.2], "price": 4.4}
{"index": {"_index": "knn-index-test", "_id": "2"}}
{"my_vector": [7.1, 7.4], "price": 14.2}
{"index": {"_index": "knn-index-test", "_id": "3"}}
{"my_vector": [7.3, 8.3], "price": 19.1}
{"index": {"_index": "knn-index-test", "_id": "4"}}
{"my_vector": [6.5, 8.8], "price": 1.2}
{"index": {"_index": "knn-index-test", "_id": "5"}}
{"my_vector": [5.7, 7.9], "price": 16.5}
/* 実行結果 */
{
"took": 126,
"errors": false,
"items": [
{
"index": {
"_index": "knn-index-test",
"_id": "1",
"_version": 1,
"result": "created",
"forced_refresh": true,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "knn-index-test",
"_id": "2",
"_version": 1,
"result": "created",
"forced_refresh": true,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "knn-index-test",
"_id": "3",
"_version": 1,
"result": "created",
"forced_refresh": true,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "knn-index-test",
"_id": "4",
"_version": 1,
"result": "created",
"forced_refresh": true,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 3,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "knn-index-test",
"_id": "5",
"_version": 1,
"result": "created",
"forced_refresh": true,
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 4,
"_primary_term": 1,
"status": 201
}
}
]
}
ラジアル探索により、ベクトル[7.1, 8.3]に最も近い(類似した)ベクトルを持つドキュメントを検索します。結果では最も類似度の高いドキュメントは、ID "1" であることがわかります。
GET knn-index-test/_search
{
"query": {
"knn": {
"my_vector": {
"vector": [
7.1,
8.3
],
"max_distance": 2
}
}
}
}
/* 実行結果 */
{
"took": 23,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"max_score": 0.98039204,
"hits": [
{
"_index": "knn-index-test",
"_id": "1",
"_score": 0.98039204,
"_source": {
"my_vector": [
7,
8.2
],
"price": 4.4
}
},
{
"_index": "knn-index-test",
"_id": "3",
"_score": 0.9615384,
"_source": {
"my_vector": [
7.3,
8.3
],
"price": 19.1
}
},
{
"_index": "knn-index-test",
"_id": "4",
"_score": 0.62111807,
"_source": {
"my_vector": [
6.5,
8.8
],
"price": 1.2
}
},
{
"_index": "knn-index-test",
"_id": "2",
"_score": 0.5524861,
"_source": {
"my_vector": [
7.1,
7.4
],
"price": 14.2
}
}
]
}
}
OpenSearch v2.15 で追加された新機能であるラジアル探索(Radial search)を行えることが確認できました。
OpenSearch Service ドメインの削除
OpenSearch Service ドメインを削除します。Domain コンストラクトの removalPolicy のデフォルト値は Retain
なので、DESTROY
に変更して削除します。
import * as opensearchservice from 'aws-cdk-lib/aws-opensearchservice';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class CdkSampleStack extends cdk.Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
new opensearchservice.Domain(this, 'OpenSearchDomain', {
version: opensearchservice.EngineVersion.OPENSEARCH_2_15,
removalPolicy: cdk.RemovalPolicy.DESTROY, // 削除ポリシーを DESTROY に設定
});
}
}
おわりに
AWS CDK で OpenSearch Service のエンジンバージョンに v2.15 を簡単に指定可能になったので、アップデートして新機能を試してみました。
今回は新機能としてラジアル探索(Radial search)を試してみましたが、他にも様々な新機能が追加されているので、興味がある方は公式ドキュメントを参照してみてください。
参考
以上