2021-08-03 如何使用 Terraform 配置 Azure App Service Custom domains and Certificate Thumbprint


本文想分享一个具体的配置方法,为了照顾对 Azure portal 和 Terraform 不熟悉的朋友,我将使用 UI 和 Code 对比的方式说明。

背景

我目前在开发一个人才管理(Talent Management)的 SaaS 产品。因为是一个 ToB 产品并且还在初级阶段,所以架构上没有那么复杂。依托云平台的水平扩展能力,我们采用“Single App Service, Multiple Custom domains” 的架构。

虽然架构很简单,但是本着“自动化一切可以被自动化的工作”的大原则,我还是使用了 Terraform。

为什么我想写这篇文章?

由于 Terraform 是一个通用工具,为了兼容不同云平台的资源和指令,不可避免的做了一些抽象。但是这种抽象导致了 Terraform 中资源名称和指令并不完全等于云平台(没错,这里就是想说 MicroSoft Azure)的资源名称和指令。

这种资源名称、指令以及构建流程的差异让不太熟练的我,花了好几个小时阅读官方文档、StackOverflow。而且我也不确定下一次我还能不能记得这些内容。

所以,我觉得有必要记录下来。

正文

UI:

Step 1: 在 DNS Zoon 中配置一个 CNAME 记录

依次进入 DNS zones > DNS zone 页面,点击 Record set,如图:

注意:record 应该是 CNAME

Step 2: 在 App Service 中配置 Custom domain

依次进入 App Services > App Service > Settings > Custom domains 页面,点击 Add custom domain,如图:

Step 3: 为 App Service 的 Custom domain 配置 Certificate Thumbprint

依次进入 App Services > App Service > Settings > TLS/SSL Settings,点击 Add TSL/SSL binding,如图:

Terraform:

data "azurerm_dns_zone" "app" {
  name                = "thaddeusjiang.work"
  resource_group_name = "thaddeusjiang-dev"
}

# Step 1: 添加 CNAME 记录
resource "azurerm_dns_cname_record" "app" {
  name                = var.subdomain
  zone_name           = data.azurerm_dns_zone.app.name
  resource_group_name = data.azurerm_dns_zone.app.resource_group_name
  ttl                 = 300
  record              = "saas-dev.thaddeusjiang.work"
}

data "azurerm_app_service" "app" {
  name                = "saas-dev"
  resource_group_name = "saas-dev"
}

resource "azurerm_dns_txt_record" "app" {
  name                = "asuid.${azurerm_dns_cname_record.app.name}"
  zone_name           = data.azurerm_dns_zone.app.name
  resource_group_name = data.azurerm_dns_zone.app.resource_group_name
  ttl                 = 300
  record {
    value = data.azurerm_app_service.app.custom_domain_verification_id
  }
}

# Step 2: 添加 Custom domain
resource "azurerm_app_service_custom_hostname_binding" "app" {
  hostname            = "${var.subdomain}.thaddeusjiang.work"
  app_service_name    = data.azurerm_app_service.app.name
  resource_group_name = data.azurerm_app_service.app.resource_group_name
  depends_on          = [azurerm_dns_txt_record.app]

  # Step 3: TLS/SSL bindings
  ssl_state  = "SniEnabled"
  thumbprint = "6F72D0121F88382D82C336793xxxxxxxxxxxxx"
}

参考: