如何在AWS CDK中创建OpenSearch索引?两种尝试方案均失败
在AWS CDK 2.41.0中创建OpenSearch索引的正确方式
你的两种尝试都存在问题:
- 第一种尝试里的
OpenSearchIndex构造在CDK 2.41.0的aws-opensearchservice模块中根本不存在,官方也没有提供这个L2构造。 - 第二种尝试中
CfnDomain的index属性,是用来配置和Kinesis Firehose集成的索引模板或者索引状态管理(ISM)策略的,不是用来创建常规OpenSearch索引的。
CDK本身没有直接提供创建OpenSearch索引的原生资源,需要通过以下两种方式实现:
方案1:用自定义资源调用OpenSearch API
通过自定义资源触发Lambda函数,调用OpenSearch的创建索引API完成操作:
import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as customResources from 'aws-cdk-lib/custom-resources'; import * as opensearch from 'aws-cdk-lib/aws-opensearchservice'; import * as fs from 'fs'; // 假设已定义好OpenSearch Domain实例 const domain: opensearch.Domain = ...; const indexName = "my-index"; const settingsFilePath = "./settings.json"; const settings = JSON.parse(fs.readFileSync(settingsFilePath, "utf8")); // 创建负责创建索引的Lambda函数 const createIndexLambda = new lambda.Function(this, 'CreateOpenSearchIndexLambda', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', code: lambda.Code.fromInline(` const { Client } = require('@opensearch-project/opensearch'); const { AwsSigv4Signer } = require('@opensearch-project/opensearch/aws'); const { defaultProvider } = require('@aws-sdk/credential-provider-node'); exports.handler = async (event) => { const client = new Client({ ...AwsSigv4Signer({ region: process.env.AWS_REGION, service: 'es', credentials: defaultProvider() }), node: \`https://\${process.env.DOMAIN_ENDPOINT}\` }); try { const exists = await client.indices.exists({ index: process.env.INDEX_NAME }); if (!exists.body) { await client.indices.create({ index: process.env.INDEX_NAME, settings: JSON.parse(process.env.INDEX_SETTINGS) }); console.log(\`索引 \${process.env.INDEX_NAME} 创建成功\`); } else { console.log(\`索引 \${process.env.INDEX_NAME} 已存在\`); } return { Status: 'SUCCESS' }; } catch (error) { console.error('创建索引出错:', error); return { Status: 'FAILED', Error: error.message }; } }; `), environment: { DOMAIN_ENDPOINT: domain.domainEndpoint, INDEX_NAME: indexName, INDEX_SETTINGS: JSON.stringify(settings), AWS_REGION: this.region } }); // 给Lambda授权访问OpenSearch索引 domain.grantIndexWrite(createIndexLambda, indexName); // 创建自定义资源,部署时触发Lambda执行索引创建 new customResources.CustomResource(this, 'CreateOpenSearchIndex', { serviceToken: createIndexLambda.functionArn, properties: { IndexName: indexName } });
方案2:使用CDK Post-Deployment Hook(CDK 2.30.0+支持)
如果你的CDK版本在2.30.0及以上,可以用Post-Deployment Hook来执行索引创建,写法更简洁:
import * as cdk from 'aws-cdk-lib'; import * as opensearch from 'aws-cdk-lib/aws-opensearchservice'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as fs from 'fs'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'OpenSearchIndexStack'); // 创建OpenSearch域名 const domain = new opensearch.Domain(stack, 'MyDomain', { version: opensearch.EngineVersion.OPENSEARCH_2_5, // 域名的其他配置,比如访问策略、实例类型等 }); const indexName = "my-index"; const settingsFilePath = "./settings.json"; const settings = JSON.parse(fs.readFileSync(settingsFilePath, "utf8")); // 创建索引创建函数 const createIndexFn = new lambda.Function(stack, 'CreateIndexFn', { runtime: lambda.Runtime.NODEJS_18_X, handler: 'index.handler', code: lambda.Code.fromInline(` const { Client } = require('@opensearch-project/opensearch'); const { AwsSigv4Signer } = require('@opensearch-project/opensearch/aws'); const { defaultProvider } = require('@aws-sdk/credential-provider-node'); exports.handler = async () => { const client = new Client({ ...AwsSigv4Signer({ region: process.env.AWS_REGION, service: 'es', credentials: defaultProvider() }), node: \`https://\${process.env.DOMAIN_ENDPOINT}\` }); const exists = await client.indices.exists({ index: process.env.INDEX_NAME }); if (!exists.body) { await client.indices.create({ index: process.env.INDEX_NAME, settings: JSON.parse(process.env.INDEX_SETTINGS) }); } }; `), environment: { DOMAIN_ENDPOINT: domain.domainEndpoint, INDEX_NAME: indexName, INDEX_SETTINGS: JSON.stringify(settings), AWS_REGION: stack.region } }); // 授权Lambda访问索引 domain.grantIndexWrite(createIndexFn, indexName); // 添加Post-Deployment Hook,部署完成后执行索引创建 cdk.Aspects.of(stack).add(new cdk.postdeploy.PostDeployHook({ actions: [ new cdk.postdeploy.LambdaInvokeAction({ lambda: createIndexFn }) ] }));
注意事项
- 如果你的OpenSearch域名启用了细粒度访问控制,需要额外配置索引的权限策略,确保Lambda对应的IAM角色能访问目标索引。
- 可以在
client.indices.create的参数中添加mappings字段,用来定义索引的字段映射规则。 - 上述代码中使用了AWS签名认证,确保Lambda能通过IAM权限访问OpenSearch域名,无需硬编码密钥。
内容的提问来源于stack exchange,提问作者Exorcismus
相关产品推荐
相关产品推荐

