The modern cloud infrastructure landscape is defined by the velocity and volume of data generation. Enterprises and startups alike generate massive streams of real-time data from user interactions, IoT sensors, application logs, and financial transactions. Managing this data flow with reliability, scalability, and minimal operational overhead is a primary challenge for DevOps engineers and cloud architects. Amazon Kinesis Firehose has emerged as a critical component in the AWS ecosystem for addressing this challenge. It is a fully managed, elastic service designed to easily capture, transform, and load streaming data for analytics and machine learning. Unlike other streaming services that require complex consumer logic, Firehose simplifies the process by buffering incoming data, aggregating it into batches, and delivering it to destinations such as Amazon S3, Amazon Redshift, Amazon OpenSearch Service, and Amazon Data Firehose with just a few clicks or lines of code.
In the context of Infrastructure as Code (IaC), Terraform provides the aws_kinesis_firehose_delivery_stream resource, which allows engineers to declaratively manage these delivery streams. This resource abstracts the complexity of configuring IAM roles, S3 buckets, Redshift clusters, and OpenSearch domains into a single, manageable block. By leveraging Terraform, organizations can standardize their data pipelines across multiple environments, ensuring consistency, repeatability, and auditability. This article provides a comprehensive technical analysis of the aws_kinesis_firehose_delivery_stream resource, covering its architecture, configuration options, destination types, and best practices for module design.
Resource Overview and Core Architecture
The aws_kinesis_firehose_delivery_stream resource manages the lifecycle of a Kinesis Firehose delivery stream. A delivery stream is the fundamental unit of Kinesis Firehose, acting as a managed service that can handle the ingestion of streaming data and the delivery of that data to one or more destinations. The resource requires at least two arguments: a unique name for the stream and a destination specifying where the data will be sent. The destination argument is a string that must correspond to one of the supported destination types, such as extended_s3, s3, redshift, elasticsearch, or opensearch.
A minimal configuration to initialize a Kinesis Firehose delivery stream using Terraform is straightforward. The following example demonstrates the bare minimum required to create a functional stream resource. While this configuration allows the stream to exist, it does not define the specific destination configuration, which is a mandatory aspect of a functional pipeline.
hcl
resource "aws_kinesis_firehose_delivery_stream" "example" {
# Required arguments
name = "my-kinesis-firehose-delivery-stream"
}
In production environments, the configuration is significantly more complex due to the necessity of defining the destination, IAM roles, and processing configurations. The resource interacts with several other AWS services to function correctly. For instance, when delivering to S3, it requires an S3 bucket and an IAM role that grants Kinesis Firehose permission to write to that bucket. When delivering to Redshift, it requires a Redshift cluster, a database user, and an S3 bucket for staging. The Terraform provider handles the dependencies between these resources, ensuring that the IAM roles are created before the Firehose stream attempts to assume them.
Destination Configuration: Extended S3
The extended_s3 destination is the most commonly used configuration for Kinesis Firehose, particularly for log aggregation and data lake ingestion. This destination type allows for more granular control over how data is written to S3 compared to the standard s3 destination. Key features of the extended_s3_configuration block include the ability to specify buffer size, buffer interval, and compression format. Additionally, it supports the use of AWS Lambda functions to transform or filter data before it is delivered to S3.
The following Terraform configuration illustrates an extended_s3 delivery stream. It defines a S3 bucket and an IAM role specifically for Kinesis Firehose. The configuration includes a processing_configuration block that enables a Lambda function to process the data. This is useful for scenarios where raw logs need to be parsed or normalized before being stored in the data lake.
```hcl
resource "awskinesisfirehosedeliverystream" "extendeds3stream" {
name = "terraform-kinesis-firehose-extended-s3-test-stream"
destination = "extended_s3"
extendeds3configuration {
rolearn = "${awsiamrole.firehoserole.arn}"
bucketarn = "${awss3_bucket.bucket.arn}"
processing_configuration = [
{
enabled = "true"
processors = [
{
type = "Lambda"
parameters = [
{
parameter_name = "LambdaArn"
parameter_value = "${aws_lambda_function.lambda_processor.arn}:$LATEST"
}
]
}
]
}
]
}
}
resource "awss3bucket" "bucket" {
bucket = "tf-test-bucket"
acl = "private"
}
resource "awsiamrole" "firehoserole" {
name = "firehosetest_role"
assumerolepolicy = <
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "firehose.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
```
In this example, the processing_configuration block is crucial. It references a Lambda function ARN, indicating that data passing through the stream will be processed by the Lambda function before delivery. The enabled attribute is set to "true" to activate this feature. The S3 bucket is configured with a private ACL to ensure data security, and the IAM role is configured to allow the firehose.amazonaws.com service to assume the role, granting it the necessary permissions to write to the bucket.
Destination Configuration: Amazon Redshift
For organizations that require immediate analytics on streaming data, Kinesis Firehose can deliver data directly to Amazon Redshift. This eliminates the need for intermediate ETL processes, allowing data to be available in the data warehouse within seconds of ingestion. The redshift destination configuration requires more parameters than the S3 destination, including details about the Redshift cluster, database table, and S3 staging bucket.
The redshift_configuration block includes parameters such as cluster_jdbcurl, username, password, data_table_name, and data_table_columns. Additionally, it supports S3 backup configuration, which stores a copy of the data in S3 in case of delivery failures or for auditing purposes.
```hcl
resource "awskinesisfirehosedeliverystream" "test_stream" {
name = "terraform-kinesis-firehose-test-stream"
destination = "redshift"
s3configuration {
rolearn = "${awsiamrole.firehoserole.arn}"
bucketarn = "${awss3bucket.bucket.arn}"
buffersize = 10
bufferinterval = 400
compression_format = "GZIP"
}
redshiftconfiguration {
rolearn = "${awsiamrole.firehoserole.arn}"
clusterjdbcurl = "jdbc:redshift://${awsredshiftcluster.testcluster.endpoint}/${awsredshiftcluster.testcluster.databasename}"
username = "testuser"
password = "T3stPass"
datatablename = "test-table"
copyoptions = "delimiter '|'"
datatablecolumns = "test-col"
s3backupmode = "Enabled"
s3_backup_configuration {
role_arn = "${aws_iam_role.firehose_role.arn}"
bucket_arn = "${aws_s3_bucket.bucket.arn}"
buffer_size = 15
buffer_interval = 300
compression_format = "GZIP"
}
}
}
```
In this configuration, the buffer_size is set to 10 MB, and the buffer_interval is 400 seconds. This means Firehose will deliver data to Redshift every 10 MB or every 400 seconds, whichever comes first. The compression_format is set to GZIP to reduce the amount of data transferred. The copy_options parameter specifies the delimiter for the data table, which is essential for ensuring that the data is correctly parsed into the Redshift table.
Destination Configuration: Amazon OpenSearch Service
Kinesis Firehose also supports delivery to Amazon OpenSearch Service (formerly Elasticsearch). This is particularly useful for real-time monitoring and log analysis. The elasticsearch destination configuration (now typically referred to in the context of OpenSearch) requires the domain ARN and the index and type names.
```hcl
resource "awselasticsearchdomain" "testcluster" {
domainname = "firehose-es-test"
}
resource "awskinesisfirehosedeliverystream" "test_stream" {
name = "terraform-kinesis-firehose-test-stream"
destination = "elasticsearch"
s3configuration {
rolearn = "${awsiamrole.firehoserole.arn}"
bucketarn = "${awss3bucket.bucket.arn}"
buffersize = 10
bufferinterval = 400
compression_format = "GZIP"
}
elasticsearchconfiguration {
domainarn = "${awselasticsearchdomain.testcluster.arn}"
rolearn = "${awsiamrole.firehoserole.arn}"
indexname = "test"
type_name = "test"
}
}
```
The configuration includes a processing_configuration block, similar to the S3 example, allowing for data transformation before delivery to OpenSearch. This is particularly useful for enriching logs with metadata or filtering out irrelevant data before it is indexed.
Module Design and Reusability
Creating a reusable Terraform module for AWS streaming and messaging is a best practice for standardizing infrastructure across projects. A well-designed module can encapsulate the complexity of creating Kinesis Data Streams, Kinesis Firehose Delivery Streams, and SQS Queues, providing a simplified interface for consumers.
The following module structure demonstrates how to create a reusable Terraform module for a streaming stack. The module accepts inputs such as project_name, environment, and kinesis_shard_count, and outputs the ARNs of the created resources.
hcl
module "streaming_stack" {
source = "./modules/streaming"
project_name = "orders"
environment = "prod"
kinesis_shard_count = 1
firehose_destination_s3_bucket_arn = aws_s3_bucket.logs.arn
sqs_fifo = false
sqs_visibility_timeout = 30
}
The module defines the following resources:
- An AWS Kinesis Data Stream for ingesting records.
- An AWS Kinesis Firehose Delivery Stream that delivers data to S3.
- An AWS SQS Queue that can receive messages or be wired into downstream consumers.
The outputs.tf file of the module exports the ARNs of the created resources, allowing downstream resources to reference them.
```hcl
output "streamarn" {
value = awskinesis_stream.provisioned.arn
}
output "streamname" {
value = awskinesis_stream.provisioned.name
}
output "firehosearn" {
value = awskinesisfirehosedeliverystream.tos3.arn
}
```
This modular approach ensures that the configuration is consistent across environments and makes it easy to update the infrastructure when changes are needed.
Advanced Use Cases and Integrations
Beyond basic S3, Redshift, and OpenSearch delivery, Kinesis Firehose can be integrated with other AWS services to create complex data pipelines. For example, the observeinc/terraform-aws-kinesis-firehose module demonstrates how to create a Kinesis Firehose delivery stream towards Observe, a observability platform. This module creates the Firehose delivery stream, as well as a role and any required policies. An S3 bucket is also created to store messages that failed to be delivered to Observe.
hcl
module "observe_kinesis_firehose" {
source = "observeinc/kinesis-firehose/aws"
name = "observe-kinesis-firehose"
observe_collection_endpoint = "https://<id>.collect.observeinc.com"
observe_token = var.observe_token
}
The module supports submodules for various use cases, including:
- Subscribe CloudWatch Logs to Kinesis Firehose
- Collect CloudWatch Metrics Stream
- Collect EventBridge
- Collect EKS Fargate logs
The module also supports specifying a Kinesis Data Stream to act as a source to the Kinesis Firehose delivery stream. This is useful for scenarios where data is first captured in a Kinesis Data Stream and then delivered to multiple destinations using Firehose.
The module requires the following Terraform providers:
| Name | Version |
|---|---|
| terraform | >= 1.1.9 |
| aws | >= 5.0 |
| random | >= 3.0.0 |
The resources created by the module include:
| Name | Type |
|---|---|
| awscloudwatchlogstream.httpendpoint_delivery | resource |
| awscloudwatchlogstream.s3delivery | resource |
| awsiampolicy.firehose_cloudwatch | resource |
| awsiampolicy.firehose_s3 | resource |
| awsiampolicy.kinesis_firehose | resource |
| awsiampolicy.put_record | resource |
| awsiamrole.firehose | resource |
| awsiamrolepolicyattachment.firehose_cloudwatch | resource |
| awsiamrolepolicyattachment.firehose_s3 | resource |
| awsiamrolepolicyattachment.kinesis_firehose | resource |
| awskinesisfirehosedeliverystream.this | resource |
| awss3bucket.bucket | resource |
| awss3bucket_acl.bucket | resource |
| awss3bucketlifecycleconfiguration.retention | resource |
| awss3bucketownershipcontrols.bucket | resource |
| randomstring.bucketsuffix | resource |
The module accepts the following inputs:
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| cloudwatchloggroup | The CloudWatch group for logging. Providing this value enables logging | string | "" | false |
This module provides a robust solution for sending logs and metrics to Observe, with the flexibility to use an existing S3 bucket if needed.
Monitoring and Operations
Kinesis Firehose provides built-in CloudWatch metrics that can be used to monitor the health and performance of delivery streams. These metrics include records per second, bytes per second, and error counts. Terraform can be used to configure CloudWatch alarms based on these metrics, ensuring that issues with the data pipeline are detected and addressed promptly.
For example, the following Terraform configuration creates a CloudWatch alarm for a Kinesis stream:
```hcl
resource "awscloudwatchmetricalarm" "example" {
alarmname = "example"
comparisonoperator = "GREATERTHAN"
evaluationperiods = "1"
metricname = "WriteProvisionedThroughput"
namespace = "AWS/Kinesis"
period = "60"
statistic = "Average"
threshold = "10"
dimensions = {
StreamName = awskinesisstream.provisioned.name
}
alarmactions = [var.snstopic_arn]
}
```
This alarm triggers when the average write provisioned throughput exceeds 10, and it sends a notification to the specified SNS topic. By monitoring these metrics, organizations can ensure that their data pipelines are operating efficiently and reliably.
Conclusion
The aws_kinesis_firehose_delivery_stream resource in Terraform provides a powerful and flexible way to manage real-time data pipelines in AWS. By supporting multiple destination types, including S3, Redshift, and OpenSearch, and offering features such as data transformation with Lambda and CloudWatch monitoring, it addresses a wide range of use cases for data ingestion and analytics. The ability to encapsulate these configurations in reusable Terraform modules ensures consistency and scalability across environments. As data volumes continue to grow, the need for efficient and reliable data pipelines becomes increasingly critical. By leveraging Terraform and Kinesis Firehose, organizations can build robust, scalable, and maintainable data infrastructure that meets the demands of modern applications and analytics.