You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 20:48:11