I am encountering challenges when attempting to create a PostgreSQL flexible server with a private endpoint in Azure using Terraform. Additionally, I have attached a Network Security Group (NSG) to the subnet associated with the PostgreSQL flexible server. Below, I have included the Terraform script and the error message I am receiving.
"azurerm_private_dns_zone" "postgres_dns_zone" {
name = "${var.project_name}${var.environment}.postgres.database.azure.com"
resource_group_name = var.resource_group
tags = var.tags
}
resource "azurerm_postgresql_flexible_server" "db" {
name = "${var.project_name}${var.environment}postgres"
resource_group_name = var.resource_group
location = var.location
administrator_login = var.db_admin
administrator_password = random_password.postgres_password.result
sku_name = var.db_sku
zone = var.zone
version = var.db_version
delegated_subnet_id = var.subnet_id
private_dns_zone_id = azurerm_private_dns_zone.postgres_dns_zone.id
storage_mb = var.db_storage
backup_retention_days = 7
geo_redundant_backup_enabled = false
public_network_access_enabled = false
dynamic "high_availability" {
for_each = var.enable_ha ? [1] : []
content {
mode = "ZoneRedundant"
standby_availability_zone = var.ha_zone
}
}
depends_on = [azurerm_private_dns_zone.postgres_dns_zone]
tags = var.tags
}
resource "azurerm_postgresql_flexible_server_configuration" "postgis" {
name = "azure.extensions"
server_id = azurerm_postgresql_flexible_server.db.id
value = "POSTGIS"
}
# Link private DNS zone with the VNet for PostgreSQL
resource "azurerm_private_dns_zone_virtual_network_link" "pg_dns_vnet_link" {
name = "${azurerm_postgresql_flexible_server.db.name}-vnetlink.com"
resource_group_name = var.resource_group
private_dns_zone_name = azurerm_private_dns_zone.postgres_dns_zone.name
virtual_network_id = var.vnet_id
tags = var.tags
depends_on = [ azurerm_postgresql_flexible_server.db ]
}
# Private endpoint for PostgreSQL
resource "azurerm_private_endpoint" "postgres_private_endpoint" {
name = "${azurerm_postgresql_flexible_server.db.name}-private-endpoint"
resource_group_name = var.resource_group
location = var.location
subnet_id = var.subnet_id
tags = var.tags
private_service_connection {
name = "${azurerm_postgresql_flexible_server.db.name}-Connection"
is_manual_connection = false
private_connection_resource_id = azurerm_postgresql_flexible_server.db.id
subresource_names = ["postgresqlServer"]
}
private_dns_zone_group {
name = "${azurerm_postgresql_flexible_server.db.name}-private-dns-zone-group"
private_dns_zone_ids = [
azurerm_private_dns_zone.postgres_dns_zone.id
]
}
depends_on = [ azurerm_postgresql_flexible_server.db, azurerm_private_dns_zone.postgres_dns_zone ]
}
But getting the below error:
Error: creating Private Endpoint (Subscription: "727b8f7b-c809-4a2d-b850-1308092ab3ed"
│ Resource Group Name: "controltower-dev-rg"
│ Private Endpoint Name: "controltowerdevpostgres-private-endpoint"): performing CreateOrUpdate: unexpected status 400 (400 Bad Request) with error: PrivateEndpointFeatureNotSupportedOnServer: Call to Microsoft.DBforPostgreSQL/flexibleServers failed. Error message: The given server controltowerdevpostgres does not support private endpoint feature. Please create a new server that is private endpoint capable. Refer to https://aka.ms/pgflex-pepreview for more details.
│
│ with module.DB.azurerm_private_endpoint.postgres_private_endpoint,
│ on ..modulesdatabasedb.tf line 59, in resource "azurerm_private_endpoint" "postgres_private_endpoint":
│ 59: resource "azurerm_private_endpoint" "postgres_private_endpoint" {
2
Create Azure Postgres Server with private endpoint using terraform
While creating a Postgres Server with private endpoint we need to make sure that the SKU and region we select show support the feature requirement.
Before running the deployment, we can make sure the configuration of PostgreSQL should be in confirmed by the commands given below.
az postgres flexible-server list-skus --location <your location> --output table
I tried a demo configuration with the configuration that suitable to achieve this requirement as mentioned below.
Configuration:
resource "azurerm_resource_group" "main" {
name = "vinay-pg-rg"
location = "westeurope"
}
resource "azurerm_virtual_network" "main" {
name = "vksb-pg-vnet"
address_space = ["10.88.0.0/16"]
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
}
resource "azurerm_subnet" "main" {
name = "vksb-pg-main-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.88.2.0/24"]
private_endpoint_network_policies = "Enabled"
service_endpoints = ["Microsoft.Sql"]
}
resource "azurerm_network_security_group" "main" {
name = "vksb-pg-main-nsg"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
security_rule {
name = "PostgreSQL"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "5432"
source_address_prefix = "0.0.0.0/0"
destination_address_prefix = "*"
}
security_rule {
name = "HTTPS"
priority = 110
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "0.0.0.0/0"
destination_address_prefix = "*"
}
}
resource "azurerm_subnet_network_security_group_association" "main" {
subnet_id = azurerm_subnet.main.id
network_security_group_id = azurerm_network_security_group.main.id
}
resource "azurerm_private_dns_zone" "postgres_dns_zone" {
name = "privatelink.postgres.database.azure.com"
resource_group_name = azurerm_resource_group.main.name
}
resource "azurerm_postgresql_flexible_server" "main" {
name = "vksb-postgresql"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
version = "16"
sku_name = "B_Standard_B2s"
administrator_login = "sqladmin"
administrator_password = "yourpassword"
storage_mb = 32768
storage_tier = "P4"
public_network_access_enabled = false
}
resource "azurerm_private_dns_zone_virtual_network_link" "main" {
name = "vksb-postgresql-main-vnet-link"
resource_group_name = azurerm_resource_group.main.name
private_dns_zone_name = azurerm_private_dns_zone.postgres_dns_zone.name
virtual_network_id = azurerm_virtual_network.main.id
depends_on = [azurerm_subnet.main, azurerm_virtual_network.main]
}
resource "azurerm_private_endpoint" "main" {
name = "vksb-postgresql-main"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
subnet_id = azurerm_subnet.main.id
private_service_connection {
name = "vksb-postgresql-psc"
private_connection_resource_id = azurerm_postgresql_flexible_server.main.id
subresource_names = ["postgresqlServer"]
is_manual_connection = false
}
private_dns_zone_group {
name = azurerm_postgresql_flexible_server.main.name
private_dns_zone_ids = [azurerm_private_dns_zone.postgres_dns_zone.id]
}
depends_on = [azurerm_postgresql_flexible_server.main, azurerm_subnet.main]
}
resource "azurerm_postgresql_flexible_server_database" "db" {
name = "vksb-pg-main-db"
server_id = azurerm_postgresql_flexible_server.main.id
charset = "UTF8"
collation = "en_US.utf8"
lifecycle {
prevent_destroy = false
}
depends_on = [azurerm_postgresql_flexible_server.main]
}
Deployment:
Refer:
https://azure.microsoft.com/en-us/explore/global-infrastructure/products-by-region/
https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-networking-private
https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-networking-private-link