Amazon OpenSearch Serverless is a serverless deployment option for Amazon OpenSearch Service that makes it straightforward to run search and analytics workloads without managing infrastructure. Customers using OpenSearch Serverless often need to copy documents between two indexes within the same collection or across different collections. This primarily arises from two scenarios:
Amazon OpenSearch Ingestion had recently introduced a feature supporting OpenSearch as a source. OpenSearch Ingestion, a fully managed, serverless data collector, facilitates real-time ingestion of log, metric, and trace data into OpenSearch Service domains and OpenSearch Serverless collections. We can leverage this feature to address these two scenarios, by reading the data from an OpenSearch Serverless Collection. This capability allows you to effortlessly copy data between indexes, making data management tasks more streamlined and eliminating the need for custom code.
In this post, we outline the steps to copy data between two indexes in the same OpenSearch Serverless collection using the new OpenSearch source feature of OpenSearch Ingestion. This is particularly useful for reindexing operations where you want to change your data schema. OpenSearch Serverless and OpenSearch Ingestion are both serverless services that enable you to seamlessly handle your data workflows, providing optimal performance and scalability.
Solution overview The following diagram shows the flow of copying documents from the source index to the destination index using an OpenSearch Ingestion pipeline.
Implementing the solution consists of the following steps:
Prerequisites To get started, you must have an active OpenSearch Serverless collection with an index that you want to reindex (copy). Refer to Creating collections to learn more about creating a collection.
When the collection is ready, note the following details:
You use these details in the ingestion pipeline configuration.
Create an IAM role to use as a pipeline role An OpenSearch Ingestion pipeline needs certain permissions to pull data from the source and write to its sink. For this walkthrough, both the source and sink are the same, but if the source and sink collections are different, modify the policy accordingly.
Complete the following steps:
opensearch-ingestion-pipeline-policy) that provides permission to read and send data to the OpenSearch Serverless collection. The following is a sample policy with least privileges (modify {account-id}, {region}, {collection-id} and {collection-name} accordingly):{ "Version": "2012-10-17", "Statement": [{ "Action": [ "aoss:BatchGetCollection", "aoss:APIAccessAll" ], "Effect": "Allow", "Resource": "arn:aws:aoss:{region}:{account-id}:collection/{collection-id}" }, { "Action": [ "aoss:CreateSecurityPolicy", "aoss:GetSecurityPolicy", "aoss:UpdateSecurityPolicy" ], "Effect": "Allow", "Resource": "*", "Condition": { "StringEquals": { "aoss:collection": "{collection-name}" } } } ]}opensearch-ingestion-pipeline-role) that the OpenSearch Ingestion pipeline will assume. While creating the role, use the policy you created (opensearch-ingestion-pipeline-policy). The role should have the following trust relationship (modify {account-id} and {region} accordingly):{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Service": "osis-pipelines.amazonaws.com" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "aws:SourceAccount": "{account-id}" }, "ArnLike": { "aws:SourceArn": "arn:aws:osis:{region}:{account-id}:pipeline/*" } } }]}arn:aws:iam::111122223333:role/opensearch-ingestion-pipeline-role).Update the data access policy attached to the OpenSearch Serverless collection After you create the IAM role, you need to update the data access policy attached to the OpenSearch Serverless collection. Data access policies control access to the OpenSearch operations that OpenSearch Serverless supports, such as PUT <index> or GET _cat/indices. To perform the update, complete the following steps:
{account-id} and {collection-name} accordingly):{ "Rules": [{ "Resource": [ "index/{collection-name}/*" ], "Permission": [ "aoss:CreateIndex", "aoss:UpdateIndex", "aoss:DescribeIndex", "aoss:ReadDocument", "aoss:WriteDocument" ], "ResourceType": "index" }], "Principal": [ "arn:aws:iam::{account-id}:role/opensearch-ingestion-pipeline-role" ], "Description": "Provide access to OpenSearch Ingestion Pipeline Role"}You can also use the Visual Editor method to choose Add another rule and add the preceding permissions for arn:aws:iam::{account-id}:role/opensearch-ingestion-pipeline-role.
Now you have successfully allowed the OpenSearch Ingestion role to perform OpenSearch operations against the OpenSearch Serverless collection.
Create and configure the OpenSearch Ingestion pipeline to copy the data from one index to another Complete the following steps:
OpenSearchDataMigrationPipeline.sample-ingestion-pipeline).Update the following information for the source:
hosts and specify the endpoint of the existing OpenSearch Serverless collection that was copied as part of prerequisites.include and index_name_regex, and specify the name of the index that will act as the source (in this demo, we’re using logs-2024.03.01).region under aws and specify the AWS Region where your OpenSearch Serverless collection is (for example, us-east-1).sts_role_arn under aws and specify the role that has permission to read data from the OpenSearch Serverless collection (for example, arn:aws:iam::111122223333:role/opensearch-ingestion-pipeline-role). This is the same role that was added in the data access policy of the collection.serverless flag to true.serverless_options and network_policy_name and specify the name of the network policy used for the collection.scheduling, interval, index_read_count, and start_time and modify these parameters accordingly.Time series or Vector search type, you can keep the scheduling, interval, index_read_count, and start_time parameters commented.Update the following information for the sink:
hosts and specify the endpoint of the existing OpenSearch Serverless collection.sts_role_arn under aws and specify the role that has permission to write data into the OpenSearch Serverless collection (for example, arn:aws:iam::111122223333:role/opensearch-ingestion-pipeline-role). This is the same role that was added in the data access policy of the collection.serverless flag to true.serverless_options and network_policy_name and specify the name of the network policy used for the collection.index and provide the index name to which you want to transfer the documents (for example, new-logs-2024.03.01).document_id, you can get the ID from the document metadata in the source and use the same in the target.Search type of collection. If your collection is of the Time Series or Vector Search type, you should comment out the document_id line.bucket, region and sts_role_arn keys within the dlq section can be modified to capture any failed requests in an S3 bucket.opensearch-ingestion-pipeline-role needs to be given, if configuring DLQ. Please refer Writing to a dead-letter queue, for the changes required.dlq block.Now click on Validate pipeline to validate the pipeline configuration.
It will take a couple of minutes to create the ingestion pipeline. After the pipeline is created, you will see the documents in the destination index, specified in the sink (for example, new-logs-2024.03.01). After all the documents are copied, you can validate the number of documents by using the count API.
When the process is complete, you have the option to stop or delete the pipeline. If you choose to keep the pipeline running, it will continue to copy new documents from the source index according to the defined schedule, if specified.
In this walkthrough, the endpoint defined in the hosts parameter under source and sink of the pipeline configuration belonged to the same collection which was of the Search type. If the collections are different, you need to modify the permissions for the IAM role (opensearch-ingestion-pipeline-role) to allow access to both collections. Additionally, make sure you update the data access policy for both the collections to grant access to the OpenSearch Ingestion pipeline.
Create an index template using the OpenSearch Ingestion pipeline to define mapping In OpenSearch, you can define how documents and their fields are stored and indexed by creating a mapping. The mapping specifies the list of fields for a document. Every field in the document has a field type, which defines the type of data the field contains. OpenSearch Service dynamically maps data types in each incoming document if an explicit mapping is not defined. However, you can use the template_type parameter with the index-template value and template_content with JSON of the content of the index-template in the pipeline configuration to define explicit mapping rules. You also need to define the index_type parameter with the value as custom.
The following code shows an example of the sink portion of the pipeline and the usage of index_type, template_type, and template_content:
sink: - opensearch: # Provide an AWS OpenSearch Service domain endpoint hosts: [ "<<OpenSearch-Serverless-Collection-Endpoint>>" ] aws: # Provide a Role ARN with access to the domain. This role should have a trust relationship with osis-pipelines.amazonaws.com sts_role_arn: "arn:aws:iam::111122223333:role/opensearch-ingestion-pipeline-role" # Provide the region of the domain. region: "us-east-1" # Enable the 'serverless' flag if the sink is an Amazon OpenSearch Serverless collection serverless: true # serverless_options: # Specify a name here to create or update network policy for the serverless collection # network_policy_name: "network-policy-name" # This will make it so each document in the source cluster will be written to the same index in the destination cluster index: "new-logs-2024.03.01" index_type: custom template_type: index-template template_content: > { "template" : { "mappings" : { "properties" : { "Data" : { "type" : "text" }, "EncodedColors" : { "type" : "binary" }, "Type" : { "type" : "keyword" }, "LargeDouble" : { "type" : "double" } } } } } # This will make it so each document in the source cluster will be written with the same document_id in the destination cluster document_id: "${getMetadata(\"opensearch-document_id\")}" # Enable the 'distribution_version' setting if the AWS OpenSearch Service domain is of version Elasticsearch 6.x # distribution_version: "es6" # Enable and switch the 'enable_request_compression' flag if the default compression setting is changed in the domain. See https://docs.aws.amazon.com/opensearch-service/latest/developerguide/gzip.html # enable_request_compression: true/false # Enable the S3 DLQ to capture any failed requests in an S3 bucket # dlq: # s3: # Provide an S3 bucket # bucket: "<<your-dlq-bucket-name>>" # Provide a key path prefix for the failed requests # key_path_prefix: "<<logs/dlq>>" # Provide the region of the bucket. # region: "<<us-east-1>>" # Provide a Role ARN with access to the bucket. This role should have a trust relationship with osis-pipelines.amazonaws.com # sts_role_arn: "<<arn:aws:iam::111122223333:role/opensearch-ingestion-pipeline-role>>"
Or you can create the index first, with the mapping in the collection before you start the pipeline.
If you want to create a template using an OpenSearch Ingestion pipeline, you need to provide aoss:UpdateCollectionItems and aoss:DescribeCollectionItems permission for the collection in the data access policy for the pipeline role (opensearch-ingestion-pipeline-role). The updated JSON block for the rule would look like the following:
{ "Rules": [ { "Resource": [ "collection/{collection-name}" ], "Permission": [ "aoss:UpdateCollectionItems", "aoss:DescribeCollectionItems" ], "ResourceType": "collection" }, { "Resource": [ "index/{collection-name}/*" ], "Permission": [ "aoss:CreateIndex", "aoss:UpdateIndex", "aoss:DescribeIndex", "aoss:ReadDocument", "aoss:WriteDocument" ], "ResourceType": "index" } ], "Principal": [ "arn:aws:iam::{account-id}:role/opensearch-ingestion-pipeline-role" ], "Description": "Provide access to OpenSearch Ingestion Pipeline Role" }
Conclusion In this post, we showed how to use an OpenSearch Ingestion pipeline to copy data from one index to another in an OpenSearch Serverless collection. OpenSearch Ingestion also allows you to perform transformation of data using various processors. AWS offers various resources for you to quickly start building pipelines using OpenSearch Ingestion. You can use various built-in pipeline integrations to quickly ingest data from Amazon DynamoDB, Amazon Managed Streaming for Apache Kafka (Amazon MSK), Amazon Security Lake, Fluent Bit, and many more. You can use the following OpenSearch Ingestion blueprints to build data pipelines with minimal configuration changes.
About the Authors Utkarsh Agarwal is a Cloud Support Engineer in the Support Engineering team at Amazon Web Services. He specializes in Amazon OpenSearch Service. He provides guidance and technical assistance to customers thus enabling them to build scalable, highly available, and secure solutions in the AWS Cloud. In his free time, he enjoys watching movies, TV series, and of course, cricket. Lately, he has also been attempting to master the art of cooking in his free time – the taste buds are excited, but the kitchen might disagree.
Prashant Agrawal is a Sr. Search Specialist Solutions Architect with Amazon OpenSearch Service. He works closely with customers to help them migrate their workloads to the cloud and helps existing customers fine-tune their clusters to achieve better performance and save on cost. Before joining AWS, he helped various customers use OpenSearch and Elasticsearch for their search and log analytics use cases. When not working, you can find him traveling and exploring new places. In short, he likes doing Eat → Travel → Repeat.