Create a sink connector from Apache Kafka® to OpenSearch®
The OpenSearch sink connector writes data from Aiven for Apache Kafka® to OpenSearch®.
Prerequisites
To set up an OpenSearch sink connector, you need an Aiven for Apache Kafka service with Kafka Connect enabled or a dedicated Aiven for Apache Kafka Connect cluster.
Collect the following information about the target OpenSearch service:
OS_CONNECTION_URL: The OpenSearch connection URL, in the form ofhttps://HOST:PORTOS_USERNAME: The OpenSearch username to connectOS_PASSWORD: The password for the username selectedTOPIC_LIST: The comma-separated list of topics to sink
If the source data is in Avro format, also collect the following information:
SCHEMA_REGISTRY_HOST: Host from the Schema Registry tab. This is the same hostname as the Kafka service.SCHEMA_REGISTRY_PORT: Port from the Schema Registry tab.SCHEMA_REGISTRY_USER: User from the Schema Registry tab.SCHEMA_REGISTRY_PASSWORD: Password from the Schema Registry tab.
For Aiven for OpenSearch® and Aiven for Apache Kafka®, find these values
on the service Overview page in the Aiven
Console. On Aiven for Apache Kafka®, Schema
Registry connection details are in the Schema Registry tab. You can
also run avn service get with the
Aiven CLI.
As of version 3.0, Aiven for Apache Kafka no longer supports Confluent Schema Registry. For more information, see Karapace.
Setup an OpenSearch sink connector with Aiven Console
The following example demonstrates how to setup a OpenSearch sink connector for Apache Kafka using the Aiven Console.
Define a Kafka Connect configuration file
Define the connector configuration in a file named opensearch_sink.json
with the following content:
{
"name":"CONNECTOR_NAME",
"connector.class": "io.aiven.kafka.connect.opensearch.OpensearchSinkConnector",
"topics": "TOPIC_LIST",
"connection.url": "OS_CONNECTION_URL",
"connection.username": "OS_USERNAME",
"connection.password": "OS_PASSWORD",
"type.name": "TYPE_NAME",
"tasks.max":"1",
"key.ignore": "true",
"key.converter": "io.confluent.connect.avro.AvroConverter",
"key.converter.schema.registry.url": "https://SCHEMA_REGISTRY_HOST:SCHEMA_REGISTRY_PORT",
"key.converter.basic.auth.credentials.source": "USER_INFO",
"key.converter.schema.registry.basic.auth.user.info": "SCHEMA_REGISTRY_USER:SCHEMA_REGISTRY_PASSWORD",
"value.converter": "io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url": "https://SCHEMA_REGISTRY_HOST:SCHEMA_REGISTRY_PORT",
"value.converter.basic.auth.credentials.source": "USER_INFO",
"value.converter.schema.registry.basic.auth.user.info": "SCHEMA_REGISTRY_USER:SCHEMA_REGISTRY_PASSWORD"
}
The configuration file contains the following entries:
name: Name of the connector.connection.url,connection.username,connection.password: OpenSearch connection values from the prerequisites.type.name: OpenSearch type name the connector uses when indexing.key.ignore: Iftrue, the connector ignores the message key and sets the document ID totopic+partition+offset. Otherwise it uses the message key.tasks.max: Maximum number of tasks to run in parallel. The default is1.key.converterandvalue.converter: Define the message data format in the Apache Kafka topic. For Avro, useio.confluent.connect.avro.AvroConverter.existing.resource.typeandtopic.to.existing.resource.mapping: Optional properties that send records to an existing OpenSearch resource, such as an index alias, instead of an index named after the topic. Add them before you create the connector. For details, see Write to an existing OpenSearch resource.
Include the key.converter and value.converter sections only when
the source data is in Avro format. If you omit them, Kafka Connect
reads the messages as binary. For Avro, the converter retrieves the
schema from Karapace.
When the source data is Avro, set the following parameters:
value.converter.schema.registry.url: Schema Registry URL in the formhttps://SCHEMA_REGISTRY_HOST:SCHEMA_REGISTRY_PORT. Use the values from the prerequisites.value.converter.basic.auth.credentials.source: Set toUSER_INFOto log in with a username and password.value.converter.schema.registry.basic.auth.user.info: Schema Registry credentials in the formSCHEMA_REGISTRY_USER:SCHEMA_REGISTRY_PASSWORD. Use the values from the prerequisites.
For the full set of connector parameters, see the OpenSearch sink connector configuration options.
Create a Kafka Connect connector with the Aiven Console
To create a Kafka Connect connector:
-
Log in to the Aiven Console and select the Aiven for Apache Kafka® or Aiven for Apache Kafka Connect® service where the connector needs to be defined.
-
Click Manage stream > Connectors from the left sidebar.
-
Select Create New Connector, it is enabled only for services with Kafka Connect enabled.
-
Select OpenSearch sink.
-
In the Common tab, locate the Connector configuration text box and click on Edit.
-
Paste the connector configuration (stored in the
opensearch_sink.jsonfile) in the form. -
Click Apply.
noteThe Aiven Console parses the configuration file and fills the relevant UI fields. You can review the UI fields across the various tab and change them if necessary. The changes will be reflected in JSON format in the Connector configuration text box.
-
After all the settings are correctly configured, click Create connector.
-
Verify the connector status under Manage stream > Connectors.
-
Verify that the data is available in the target OpenSearch resource. By default, the connector writes to an index based on the Apache Kafka topic name. In your Aiven for OpenSearch service, select Indexes to view the index. If the configuration maps the topic to an existing resource, verify that resource instead. See Write to an existing OpenSearch resource.
You can also create connectors using the Aiven CLI command.
Write to an existing OpenSearch resource
From connector version 3.2.0, you can write to an existing OpenSearch resource. The connector does not create an index from the Kafka topic name.
Writing to an existing resource is useful when you manage index rotation with a write alias. You rotate daily or weekly indices behind a stable alias.
Create the target resource in OpenSearch before you start the connector. Then set the following properties in the connector configuration:
existing.resource.type: The type of existing OpenSearch resource. To write to an index alias, set this toindex_alias.topic.to.existing.resource.mapping: Maps Kafka topics to existing OpenSearch resources. Use the formattopic_name:resource_name. Separate multiple mappings with commas.
{
"connection.url": "OS_CONNECTION_URL",
"connection.username": "OS_USERNAME",
"connection.password": "OS_PASSWORD",
"existing.resource.type": "index_alias",
"topic.to.existing.resource.mapping": "orders:orders_write_alias",
"key.ignore": "true",
"schema.ignore": "true"
}
This example maps the orders topic to the orders_write_alias alias.
For other existing.resource.type values, see the connector
configuration
options.
Create daily OpenSearch indices
To write through a stable write alias, use an existing resource mapping.
To include the message date in the index name, use the TimestampRouter
transformation and create the indices first.
To store the Apache Kafka messages in a daily OpenSearch index, add the
following TimestampRouter transformation to the connector properties
file. The transformation defines the index name as the topic name
followed by the message date.
"transforms": "TimestampRouter",
"transforms.TimestampRouter.topic.format": "${topic}-${timestamp}",
"transforms.TimestampRouter.timestamp.format": "yyyy-MM-dd",
"transforms.TimestampRouter.type": "org.apache.kafka.connect.transforms.TimestampRouter"
The current version of the OpenSearch sink connector is not able to automatically create daily indices in OpenSearch. Therefore create the indices with the correct name before starting the sink connector. You can create OpenSearch indices in many ways including CURL commands.
Create a sink connector for JSON with a schema
If you have a topic named iot_measurements that contains the following
JSON, including an embedded schema:
{
"schema": {
"type":"struct",
"fields":[{
"type":"int64",
"optional": false,
"field": "iot_id"
},{
"type":"string",
"optional": false,
"field": "metric"
},{
"type":"int32",
"optional": false,
"field": "measurement"
}]
},
"payload":{ "iot_id":1, "metric":"Temperature", "measurement":14}
}
{
"schema": {
"type":"struct",
"fields":[{
"type":"int64",
"optional": false,
"field": "iot_id"
},{
"type":"string",
"optional": false,
"field": "metric"
},{
"type":"int32",
"optional": false,
"field": "measurement"
}]
},
"payload":{"iot_id":2, "metric":"Humidity", "measurement":60}}
}
Each message includes the JSON schema, which increases payload size. For a smaller payload, use Avro with Karapace.
You can sink the iot_measurements topic to OpenSearch with the
following connector configuration, after replacing OS_CONNECTION_URL,
OS_USERNAME, and OS_PASSWORD:
{
"name":"sink_iot_json_schema",
"connector.class": "io.aiven.kafka.connect.opensearch.OpensearchSinkConnector",
"topics": "iot_measurements",
"connection.url": "OS_CONNECTION_URL",
"connection.username": "OS_USERNAME",
"connection.password": "OS_PASSWORD",
"type.name": "iot_measurements",
"tasks.max":"1",
"key.ignore": "true",
"value.converter": "org.apache.kafka.connect.json.JsonConverter"
}
The configuration file contains the following entries:
topics: Set toiot_measurements.value.converter: JSON converter. The sample messages include an embedded schema, so leave schema support enabled.key.ignore: Iftrue, the connector ignores the empty message key and sets the document ID totopic+partition+offset.
Create a sink connector for schemaless JSON
If you have a topic named students that contains the following
schemaless JSON:
Key: 1 Value: {"student_id":1, "student_name":"Carla"}
Key: 2 Value: {"student_id":2, "student_name":"Ugo"}
Key: 3 Value: {"student_id":3, "student_name":"Mary"}
You can sink the students topic to OpenSearch with the following
connector configuration, after replacing OS_CONNECTION_URL,
OS_USERNAME, and OS_PASSWORD:
{
"name":"sink_students_json",
"connector.class": "io.aiven.kafka.connect.opensearch.OpensearchSinkConnector",
"topics": "students",
"connection.url": "OS_CONNECTION_URL",
"connection.username": "OS_USERNAME",
"connection.password": "OS_PASSWORD",
"type.name": "students",
"tasks.max":"1",
"key.converter": "org.apache.kafka.connect.storage.StringConverter",
"value.converter": "org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable": "false",
"schema.ignore": "true"
}
The configuration file contains the following entries:
topics: Set tostudents.key.converter: String converter for the message key.value.converter: JSON converter for the message value.value.converter.schemas.enable: Set tofalsewhen the value has no schema so the connector does not read a schema.schema.ignore: Set totrueso the connector does not infer a schema before it writes to OpenSearch.
The connector sets the OpenSearch document ID to the message key.