terraform {
required_version = ">= 1.5.0"
required_providers {
ybm = {
source = "yugabyte/ybm"
version = "~> 1.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}
###############################################################################
# Variables
###############################################################################
variable "ybm_api_key" {
description = "YugabyteDB Aeon API key."
type = string
sensitive = true
}
variable "ybm_cluster_id" {
description = "ID of the YugabyteDB Aeon cluster."
type = string
}
variable "aeon_region" {
description = "Azure region containing the YugabyteDB Aeon cluster region."
type = string
default = "westus3"
}
variable "azure_location" {
description = "Azure region containing the application VNet."
type = string
default = "westus3"
}
variable "azure_resource_group_name" {
description = "Resource group where the private endpoint and DNS resources will be created."
type = string
}
variable "application_vnet_name" {
description = "Name of the existing application VNet."
type = string
}
variable "private_endpoint_subnet_name" {
description = "Name of the existing subnet where the private endpoint will be created."
type = string
}
variable "private_endpoint_name" {
description = "Name of the Azure private endpoint."
type = string
default = "yugabyte-aeon-private-endpoint"
}
variable "tags" {
description = "Tags to add to the Azure resources."
type = map(string)
default = {
ManagedBy = "Terraform"
Service = "YugabyteDB-Aeon"
}
}
###############################################################################
# Providers
###############################################################################
provider "ybm" {
host = "cloud.yugabyte.com"
use_secure_host = true
auth_token = var.ybm_api_key
}
provider "azurerm" {
features {}
}
###############################################################################
# Discover the Current Azure Subscription
###############################################################################
data "azurerm_client_config" "current" {}
###############################################################################
# Look Up the Existing Application VNet
###############################################################################
data "azurerm_virtual_network" "application" {
name = var.application_vnet_name
resource_group_name = var.azure_resource_group_name
}
###############################################################################
# Look Up the Existing Private Endpoint Subnet
###############################################################################
data "azurerm_subnet" "private_endpoint" {
name = var.private_endpoint_subnet_name
virtual_network_name = data.azurerm_virtual_network.application.name
resource_group_name = var.azure_resource_group_name
}
###############################################################################
# Create the Private Service Endpoint in YugabyteDB Aeon
###############################################################################
resource "ybm_private_service_endpoint" "azure" {
cluster_id = var.ybm_cluster_id
region = var.aeon_region
security_principals = [
data.azurerm_client_config.current.subscription_id
]
}
###############################################################################
# Create the Azure Private Endpoint
###############################################################################
resource "azurerm_private_endpoint" "yugabyte" {
name = var.private_endpoint_name
location = var.azure_location
resource_group_name = var.azure_resource_group_name
subnet_id = data.azurerm_subnet.private_endpoint.id
custom_network_interface_name = "${var.private_endpoint_name}-nic"
private_service_connection {
name = "${var.private_endpoint_name}-connection"
# The Aeon service name is the Azure Private Link service alias.
private_connection_resource_alias = (
ybm_private_service_endpoint.azure.service_name
)
# The remote Private Link service is owned by YugabyteDB.
is_manual_connection = true
request_message = "Connect this endpoint to YugabyteDB Aeon"
}
tags = var.tags
}
###############################################################################
# Create the Private DNS Zone
###############################################################################
resource "azurerm_private_dns_zone" "yugabyte" {
name = "azure.yugabyte.cloud"
resource_group_name = var.azure_resource_group_name
tags = var.tags
}
###############################################################################
# Link the Private DNS Zone to the Application VNet
###############################################################################
resource "azurerm_private_dns_zone_virtual_network_link" "yugabyte" {
name = "yugabyte-aeon-vnet-link"
resource_group_name = var.azure_resource_group_name
private_dns_zone_name = azurerm_private_dns_zone.yugabyte.name
virtual_network_id = data.azurerm_virtual_network.application.id
# We only need DNS resolution. VM auto-registration is not required.
registration_enabled = false
tags = var.tags
}
###############################################################################
# Extract the Record Name from the Aeon PSE Host
###############################################################################
locals {
pse_dns_record_name = trimsuffix(
ybm_private_service_endpoint.azure.host,
".azure.yugabyte.cloud"
)
}
###############################################################################
# Map the PSE Host to the Azure Private Endpoint IP
###############################################################################
resource "azurerm_private_dns_a_record" "yugabyte" {
name = local.pse_dns_record_name
zone_name = azurerm_private_dns_zone.yugabyte.name
resource_group_name = var.azure_resource_group_name
ttl = 300
records = [
azurerm_private_endpoint.yugabyte
.private_service_connection[0]
.private_ip_address
]
}
###############################################################################
# Outputs
###############################################################################
output "azure_subscription_id" {
description = "Azure subscription authorized to access the Aeon PSE."
value = data.azurerm_client_config.current.subscription_id
}
output "yugabyte_pse_endpoint_id" {
description = "ID of the YugabyteDB Aeon Private Service Endpoint."
value = ybm_private_service_endpoint.azure.endpoint_id
}
output "yugabyte_pse_state" {
description = "State of the YugabyteDB Aeon Private Service Endpoint."
value = ybm_private_service_endpoint.azure.state
}
output "yugabyte_pse_host" {
description = "Private YugabyteDB Aeon hostname."
value = ybm_private_service_endpoint.azure.host
}
output "yugabyte_pse_service_alias" {
description = "Azure Private Link service alias published by Aeon."
value = ybm_private_service_endpoint.azure.service_name
}
output "azure_private_endpoint_id" {
description = "ID of the Azure private endpoint."
value = azurerm_private_endpoint.yugabyte.id
}
output "azure_private_endpoint_ip" {
description = "Private IP address assigned to the Azure private endpoint."
value = (
azurerm_private_endpoint.yugabyte
.private_service_connection[0]
.private_ip_address
)
}
output "yugabyte_private_dns_name" {
description = "Private DNS hostname used to connect to YugabyteDB Aeon."
value = join(".", [
azurerm_private_dns_a_record.yugabyte.name,
azurerm_private_dns_zone.yugabyte.name
])
}