The complete CloudFormation Template (CFT) for creating VPC Interface Endpoints, Route 53 Private Hosted Zone, and CNAME records for Kafka brokers within an AWS environment. Each endpoint is given a friendly DNS name (like broker1.bgt.pulse.ABC
) that points to its corresponding endpoint's DNS name within the VPC.
CloudFormation Template
AWSTemplateFormatVersion: '2010-09-09'Description: CloudFormation template to create VPC endpoints and Route 53 resources for Kafka brokers in ABC environment.
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
Default: "vpc-0example000000000" # Replace with your default VPC ID
Description: The ID of the VPC where the endpoints and Route 53 hosted zone will be created.
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>
Default:
- "subnet-0example000000000" # Replace with your default subnet IDs
- "subnet-0example000000000"
- "subnet-0example000000000"
Description: List of subnet IDs where the endpoints should be created. Must be in 3 Availability Zones.
Broker1ServiceName:
Type: String
Default: "com.amazonaws.vpc.us-east-1.vpce-svc-aaaaaaaaaaaa"
Description: Service name for Broker1.
Broker2ServiceName:
Type: String
Default: "com.amazonaws.vpc.us-east-1.vpce-svc-bbbbbb"
Description: Service name for Broker2.
Broker3ServiceName:
Type: String
Default: "com.amazonaws.vpc.us-east-1.vpce-svc-ccccccc"
Description: Service name for Broker3.
Dc1ServiceName:
Type: String
Default: "com.amazonaws.vpc.us-east-1.vpce-svc-ddddddd"
Description: Service name for DC1.
Resources:
# VPC Endpoints
Broker1VPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcEndpointType: Interface
VpcId: !Ref VpcId
ServiceName: !Ref Broker1ServiceName
SubnetIds: !Ref SubnetIds
PrivateDnsEnabled: true
TagSpecifications:
- ResourceType: vpc-endpoint
Tags:
- Key: Name
Value: broker1.bgt.pulse.ABC
Broker2VPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcEndpointType: Interface
VpcId: !Ref VpcId
ServiceName: !Ref Broker2ServiceName
SubnetIds: !Ref SubnetIds
PrivateDnsEnabled: true
TagSpecifications:
- ResourceType: vpc-endpoint
Tags:
- Key: Name
Value: broker2.bgt.pulse.ABC
Broker3VPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcEndpointType: Interface
VpcId: !Ref VpcId
ServiceName: !Ref Broker3ServiceName
SubnetIds: !Ref SubnetIds
PrivateDnsEnabled: true
TagSpecifications:
- ResourceType: vpc-endpoint
Tags:
- Key: Name
Value: broker3.bgt.pulse.ABC
Dc1VPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcEndpointType: Interface
VpcId: !Ref VpcId
ServiceName: !Ref Dc1ServiceName
SubnetIds: !Ref SubnetIds
PrivateDnsEnabled: true
TagSpecifications:
- ResourceType: vpc-endpoint
Tags:
- Key: Name
Value: dc1.bgt.pulse.ABC
# Route 53 Private Hosted Zone
PrivateHostedZone:
Type: AWS::Route53::HostedZone
Properties:
Name: "bgt.pulse.ABC" # Replace with your desired domain name
VPCs:
- VPCId: !Ref VpcId
VPCRegion: "us-east-1" # Change to your VPC region
HostedZoneConfig:
Comment: "Private hosted zone for Kafka brokers"
# Route 53 DNS Records for VPC Endpoints
Broker1DNSRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref PrivateHostedZone
Name: "broker1.bgt.pulse.ABC"
Type: CNAME
TTL: "300"
ResourceRecords:
- !GetAtt Broker1VPCEndpoint.DnsEntries[0].DnsName
Broker2DNSRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref PrivateHostedZone
Name: "broker2.bgt.pulse.ABC"
Type: CNAME
TTL: "300"
ResourceRecords:
- !GetAtt Broker2VPCEndpoint.DnsEntries[0].DnsName
Broker3DNSRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref PrivateHostedZone
Name: "broker3.bgt.pulse.ABC"
Type: CNAME
TTL: "300"
ResourceRecords:
- !GetAtt Broker3VPCEndpoint.DnsEntries[0].DnsName
Dc1DNSRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref PrivateHostedZone
Name: "dc1.bgt.pulse.ABC"
Type: CNAME
TTL: "300"
ResourceRecords:
- !GetAtt Dc1VPCEndpoint.DnsEntries[0].DnsName
Outputs:
Broker1EndpointDNS:
Description: The DNS name for broker1 endpoint
Value: !GetAtt Broker1VPCEndpoint.DnsEntries[0].DnsName
Broker2EndpointDNS:
Description: The DNS name for broker2 endpoint
Value: !GetAtt Broker2VPCEndpoint.DnsEntries[0].DnsName
Broker3EndpointDNS:
Description: The DNS name for broker3 endpoint
Value: !GetAtt Broker3VPCEndpoint.DnsEntries[0].DnsName
Dc1EndpointDNS:
Description: The DNS name for dc1 endpoint
Value: !GetAtt Dc1VPCEndpoint.DnsEntries[0].DnsName
Explanation of Key Components:
- VPC
Endpoints (Broker1VPCEndpoint, Broker2VPCEndpoint, etc.): These
resources create the VPC Interface Endpoints for each Kafka broker and dc1
service.
- Route
53 Private Hosted Zone (PrivateHostedZone): This hosted zone allows
you to manage the DNS within your VPC for the specified domain (e.g., bgt.pulse.ABC).
- CNAME
Records (Broker1DNSRecord, Broker2DNSRecord, etc.): Each record maps a
user-friendly name (e.g., broker1.bgt.pulse.ABC) to the actual DNS of the
VPC endpoint.
- Outputs:
Provides the DNS names of each endpoint as output values after stack
deployment.
Usage Notes
- Update
the default values (like VpcId, SubnetIds, and Service Names)
as per your environment.
- This
template assumes you are deploying it in the us-east-1 region. Adjust VPCRegion
if needed.
Deploying this CloudFormation
stack will create VPC Interface Endpoints, a Route 53 private hosted zone, and
DNS records within your AWS environment, enabling you to use friendly DNS names
for each broker in your private VPC network.
Terraform configuration for creating VPC Interface
Endpoints, Route 53 Private Hosted Zone, and CNAME records
for Kafka brokers within an AWS environment.
provider "aws" {
region =
"us-east-1" # Adjust as needed
}
variable "vpc_id" {
type = string
default =
"vpc-0example000000000" #
Replace with your VPC ID
}
variable "subnet_ids" {
type = list(string)
default =
["subnet-0example000000000", "subnet-0example000000000",
"subnet-0example000000000"] #
Replace with your subnet IDs
}
variable "domain_name" {
type = string
default =
"bgt.pulse.ABC" # Replace with
your desired domain name
}
variable "broker1_service_name" {
type = string
default =
"com.amazonaws.vpc.us-east-1.vpce-svc-aaaaaaaaaaaa" # Replace with your Broker1 service name
}
variable "broker2_service_name" {
type = string
default =
"com.amazonaws.vpc.us-east-1.vpce-svc-bbbbbb" # Replace with your Broker2 service name
}
variable "broker3_service_name" {
type = string
default =
"com.amazonaws.vpc.us-east-1.vpce-svc-ccccccc" # Replace with your Broker3 service name
}
variable "dc1_service_name" {
type = string
default =
"com.amazonaws.vpc.us-east-1.vpce-svc-ddddddd" # Replace with your DC1 service name
}
# VPC Endpoints
resource "aws_vpc_endpoint" "broker1" {
vpc_id = var.vpc_id
service_name = var.broker1_service_name
vpc_endpoint_type =
"Interface"
subnet_ids = var.subnet_ids
private_dns_enabled
= true
tags = {
Name =
"broker1.${var.domain_name}"
}
}
resource "aws_vpc_endpoint" "broker2" {
vpc_id = var.vpc_id
service_name = var.broker2_service_name
vpc_endpoint_type =
"Interface"
subnet_ids = var.subnet_ids
private_dns_enabled
= true
tags = {
Name =
"broker2.${var.domain_name}"
}
}
resource "aws_vpc_endpoint" "broker3" {
vpc_id = var.vpc_id
service_name = var.broker3_service_name
vpc_endpoint_type =
"Interface"
subnet_ids = var.subnet_ids
private_dns_enabled
= true
tags = {
Name =
"broker3.${var.domain_name}"
}
}
resource "aws_vpc_endpoint" "dc1" {
vpc_id = var.vpc_id
service_name = var.dc1_service_name
vpc_endpoint_type =
"Interface"
subnet_ids = var.subnet_ids
private_dns_enabled
= true
tags = {
Name =
"dc1.${var.domain_name}"
}
}
# Route 53 Private Hosted Zone
resource "aws_route53_zone"
"private_zone" {
name =
var.domain_name
vpc {
vpc_id =
var.vpc_id
}
}
# Route 53 CNAME Records for each VPC Endpoint
resource "aws_route53_record"
"broker1_cname" {
zone_id =
aws_route53_zone.private_zone.zone_id
name = "broker1.${var.domain_name}"
type = "CNAME"
ttl = 300
records =
[aws_vpc_endpoint.broker1.dns_entry.0.dns_name]
}
resource "aws_route53_record"
"broker2_cname" {
zone_id =
aws_route53_zone.private_zone.zone_id
name = "broker2.${var.domain_name}"
type = "CNAME"
ttl = 300
records =
[aws_vpc_endpoint.broker2.dns_entry.0.dns_name]
}
resource "aws_route53_record"
"broker3_cname" {
zone_id =
aws_route53_zone.private_zone.zone_id
name = "broker3.${var.domain_name}"
type = "CNAME"
ttl = 300
records =
[aws_vpc_endpoint.broker3.dns_entry.0.dns_name]
}
resource "aws_route53_record"
"dc1_cname" {
zone_id =
aws_route53_zone.private_zone.zone_id
name = "dc1.${var.domain_name}"
type = "CNAME"
ttl = 300
records =
[aws_vpc_endpoint.dc1.dns_entry.0.dns_name]
}
output "broker1_endpoint_dns" {
description =
"The DNS name for broker1 endpoint"
value =
aws_vpc_endpoint.broker1.dns_entry.0.dns_name
}
output "broker2_endpoint_dns" {
description =
"The DNS name for broker2 endpoint"
value =
aws_vpc_endpoint.broker2.dns_entry.0.dns_name
}
output "broker3_endpoint_dns" {
description =
"The DNS name for broker3 endpoint"
value =
aws_vpc_endpoint.broker3.dns_entry.0.dns_name
}
output "dc1_endpoint_dns" {
description =
"The DNS name for dc1 endpoint"
value =
aws_vpc_endpoint.dc1.dns_entry.0.dns_name
}
Explanation
- VPC
Endpoints (aws_vpc_endpoint resources): Creates VPC Interface
Endpoints for each Kafka broker and dc1, using the specified service_name,
vpc_id, and subnet_ids.
- Route
53 Private Hosted Zone (aws_route53_zone): Creates a private hosted
zone for the domain specified in domain_name, making it accessible only
within the specified VPC.
- CNAME
Records (aws_route53_record resources): Creates a CNAME record in the
private hosted zone for each VPC endpoint (e.g., broker1.bgt.pulse.ABC),
pointing it to the DNS name of the respective endpoint.
- Outputs:
Provides the DNS names of each endpoint, allowing you to access them
easily after deployment.
Usage Notes
- Adjust
vpc_id, subnet_ids, and service names to match your environment.
- This
configuration assumes the us-east-1 region; adjust the provider
region if needed.
This Terraform configuration
enables you to manage your AWS resources with a similar setup as the provided
CloudFormation template, allowing access to Kafka brokers via user-friendly DNS
names in a VPC.
AWS CDK (Cloud Development Kit) stack written in Python that
creates the same resources as the previous Terraform and CloudFormation
templates: VPC Interface Endpoints, Route 53 Private Hosted Zone, and CNAME
records for Kafka brokers.
AWS CDK (Python) Code
To get started, make sure you have AWS CDK installed, and
initialize a Python CDK project by running:
cdk init app --language python
Then, add the following dependencies to requirements.txt:
aws-cdk-lib
constructs
Then, run pip install -r requirements.txt to install
dependencies.
Next, create the following CDK stack in lib/my_kafka_stack.py:
from aws_cdk import (
Stack,
aws_ec2 as ec2,
aws_route53 as
route53,
aws_route53_targets as targets,
)
from constructs import Construct
class MyKafkaStack(Stack):
def __init__(self,
scope: Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# Parameters
for VPC, Subnets, and Service Names
vpc_id =
"vpc-0example000000000" #
Replace with your VPC ID
subnet_ids =
["subnet-0example000000000", "subnet-0example000000000",
"subnet-0example000000000"] #
Replace with your subnet IDs
domain_name =
"bgt.pulse.ABC" # Replace with
your domain name
# Kafka Broker
Service Names
broker1_service_name = "com.amazonaws.vpc.us-east-1.vpce-svc-aaaaaaaaaaaa" # Replace with actual service name
broker2_service_name = "com.amazonaws.vpc.us-east-1.vpce-svc-bbbbbb" # Replace with actual service name
broker3_service_name = "com.amazonaws.vpc.us-east-1.vpce-svc-ccccccc" # Replace with actual service name
dc1_service_name = "com.amazonaws.vpc.us-east-1.vpce-svc-ddddddd" # Replace with actual service name
# Fetch
existing VPC
vpc =
ec2.Vpc.from_lookup(self, "ExistingVPC", vpc_id=vpc_id)
# VPC Endpoint
for Broker 1
broker1_endpoint = ec2.InterfaceVpcEndpoint(
self,
"Broker1Endpoint",
vpc=vpc,
service=ec2.InterfaceVpcEndpointService(broker1_service_name, 443),
subnets=ec2.SubnetSelection(subnets=[ec2.Subnet.from_subnet_id(self,
f"Subnet{i+1}", subnet_id) for i, subnet_id in
enumerate(subnet_ids)]),
private_dns_enabled=True
)
# VPC Endpoint
for Broker 2
broker2_endpoint = ec2.InterfaceVpcEndpoint(
self,
"Broker2Endpoint",
vpc=vpc,
service=ec2.InterfaceVpcEndpointService(broker2_service_name, 443),
subnets=ec2.SubnetSelection(subnets=[ec2.Subnet.from_subnet_id(self,
f"Subnet{i+1}", subnet_id) for i, subnet_id in
enumerate(subnet_ids)]),
private_dns_enabled=True
)
# VPC Endpoint
for Broker 3
broker3_endpoint = ec2.InterfaceVpcEndpoint(
self,
"Broker3Endpoint",
vpc=vpc,
service=ec2.InterfaceVpcEndpointService(broker3_service_name, 443),
subnets=ec2.SubnetSelection(subnets=[ec2.Subnet.from_subnet_id(self,
f"Subnet{i+1}", subnet_id) for i, subnet_id in
enumerate(subnet_ids)]),
private_dns_enabled=True
)
# VPC Endpoint
for DC1
dc1_endpoint =
ec2.InterfaceVpcEndpoint(
self,
"DC1Endpoint",
vpc=vpc,
service=ec2.InterfaceVpcEndpointService(dc1_service_name, 443),
subnets=ec2.SubnetSelection(subnets=[ec2.Subnet.from_subnet_id(self,
f"Subnet{i+1}", subnet_id) for i, subnet_id in
enumerate(subnet_ids)]),
private_dns_enabled=True
)
# Route 53
Private Hosted Zone
private_hosted_zone = route53.PrivateHostedZone(
self,
"PrivateHostedZone",
zone_name=domain_name,
vpc=vpc
)
# CNAME
Records for each broker
route53.CnameRecord(
self,
"Broker1Cname",
zone=private_hosted_zone,
record_name=f"broker1.{domain_name}",
domain_name=broker1_endpoint.vpc_endpoint_dns_entries[0]
)
route53.CnameRecord(
self,
"Broker2Cname",
zone=private_hosted_zone,
record_name=f"broker2.{domain_name}",
domain_name=broker2_endpoint.vpc_endpoint_dns_entries[0]
)
route53.CnameRecord(
self,
"Broker3Cname",
zone=private_hosted_zone,
record_name=f"broker3.{domain_name}",
domain_name=broker3_endpoint.vpc_endpoint_dns_entries[0]
)
route53.CnameRecord(
self,
"DC1Cname",
zone=private_hosted_zone,
record_name=f"dc1.{domain_name}",
domain_name=dc1_endpoint.vpc_endpoint_dns_entries[0]
)
Steps to Deploy
- Save
the code in lib/my_kafka_stack.py.
- In app.py,
add the following to import and instantiate the stack:
from aws_cdk import App
from my_kafka_stack import MyKafkaStack
app = App()
MyKafkaStack(app, "MyKafkaStack")
app.synth()
3. Deploy
the stack:
cdk deploy