👻
Opensearchでnetwork policyをprivateに限定するとterraformでindexが作成できない
OpenSearch Serverless をTerraformでマネージしたい。
Collection、ネットワークポリシー、データポリシーなど基本的な要素はTerraformのawsのプロパイダに含まれるが、awsプロバイダではindexが作成できない。
そこでOpenSearchプロバイダを入れて、以下のようにopensearch_indexリソースを使ってindexを定義することになる。
# Configure the OpenSearch provider
provider "opensearch" {
url = "http://127.0.0.1:9200"
}
resource "opensearch_index" "test-simple-index" {
name = "terraform-test"
number_of_shards = "1"
number_of_replicas = "1"
mappings = <<EOF
{
"properties": {
"name": {
"type": "text"
}
}
}
EOF
}
resource "opensearch_index" "index" {
name = "sample"
aliases = jsonencode(
{
"log": {
"is_write_index": true
}
}
)
number_of_replicas = "1"
number_of_shards = "1"
mappings = jsonencode({
"properties": {
"age": {
"type": "integer"
}
}
})
}
引用:
https://registry.terraform.io/providers/opensearch-project/opensearch/latest/docs/resources/index
これはnetwork policyがPublicの場合はうまくいくが、privateにするとエラーになる。
(※Googleで検索すると、network policyをPublicにした例ばかり出るので注意が必要)
Network PolicyをPrivateにする場合、接続元を許可したVPCE経由でないとIndexの作成ができないので、Indexを作成するためのLambdaを用意してInvokeする設計にする。
↓のLambdaをVPCEを接続したSubnetに配置
Lambda関数
import boto3
from opensearchpy import OpenSearch, RequestsHttpConnection, AWSV4SignerAuth
def lambda_handler(event, context):
auth = AWSV4SignerAuth(credentials, region_name, 'aoss')
client = OpenSearch(
hosts=[{'host': endpoint, 'port': 443}],
http_auth=auth,
use_ssl=True,
verify_certs=False,
connection_class=RequestsHttpConnection,
timeout=10,
max_retries=3,
retry_on_timeout=True
)
index_body = {
"mappings": {
"properties": {
"vector": {
"type": "knn_vector",
"dimension": 1024
},
"text": {
"type": "text"
},
"metadata": {
"type": "text"
}
}
}
}
response = client.indices.create(
index='test_index',
body=index_body
)
Terraform
data "archive_file" "lambda_function" {
type = "zip"
source_dir = var.lambda_source_dir
output_path = "${var.lambda_source_dir}/../build/lambda_function.zip"
}
resource "aws_lambda_function" "lambda" {
filename = data.archive_file.lambda_function.output_path
source_code_hash = data.archive_file.lambda_function.output_base64sha256
function_name = "index_creater"
role = var.lambda_role_arn
handler = "main.lambda_handler"
runtime = "pyhon3.11"
timeout = 300
memory_size = 512
dynamic "vpc_config" {
for_each = length(var.vpc_subnet_ids) > 0 ? [1] : []
content {
subnet_ids = var.vpc_subnet_ids
security_group_ids = var.lambda_security_group_id
}
}
tags = var.tags
}
Lambdaの実行自体は手動コマンドで実行してもいいし、null_resourceでコレクションの作成にフックしてaws cliを実行してもいい。
Discussion