Azureの上でSSLで静的な内容を主催すること


我々のクライアントが小さなウェブサイト展開のために我々に来ることは、いくぶん一般的です.彼らは着陸ページ、または1つのページのアプリの後、彼らはすぐに最小限のコストで何かを置くことができます.

オプションがあります


Azureは我々のプラットフォームとして静的コンテンツを展開する多くの方法を提供しています.我々は、以前はtalked about some ways to host simple pagesを持っていますが、今回は、BYSドメインとSSLをミックスにスローし、アップグレード可能性を評価し、コストを比較しましょう.我々が我々のために設定した1つの余分の目標は、我々がより我々のプロセスを合理化することができるように、各々のオプションのためにterraformを通してIACを構築することになっていました.
BYIドメインは手動設定と妥当性検査を必要とするので、手動でDNSゾーンを作成し、テラフォームを実行する前にそれを検証し、コードを自動的に我々の実験のために子ゾーンを作成させました.本当のセットアップは異なるかもしれません.

ストレージ+ CDN


最初の方法は、それがHTTPまたはHTTPS経由でコンテナのコンテンツを提供することができますazureストレージアカウント機能に依存します.この機能のための操作コストはありません.this designの欠点はカスタムドメインのマネージSSL CERTSのサポートが不足していることです.規定されたアーキテクチャはこれの前にCDNを加えることによってこのあたりで働きます、そして、我々は関連したコストが単純な静的なページのために無視できそうであるとわかりました(我々は標準的な出口料金の上で100 GBにつき0.13ドルを話しています).それは、出口法案自体が潜在的にblow out if left uncheckedことができます.

自動化について


スイッチング静的なウェブサイト機能はconsidered a data plane exerciseですので、腕のテンプレートはほとんど助けています.しかし、terraformはこれをサポートしています.
resource "azurerm_storage_account" "main" {
  name                     = "${replace(var.prefix, "/[-_]/", "")}${lower(random_string.storage_suffix.result)}"
  resource_group_name      = azurerm_resource_group.main.name
  location                 = azurerm_resource_group.main.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

  static_website { // magic
    index_document = "index.html"
  }
}
terraformでもう一つのきちんとしたもの、それは余分なステップなしで記憶にファイルをアップロードするのを許します:
resource "azurerm_storage_blob" "main" {
  name                   = "index.html"
  storage_account_name   = azurerm_storage_account.main.name
  storage_container_name = "$web"
  type                   = "Block"
  content_type           = "text/html"
  source                 = "./content/index.html"
}
第二に、CDNはカスタムドメインのために2つのCNNameドメインを働かなければなりません:サブドメイン自体と確認のための1つの余分.あまり複雑ではないので、両方ともスクリプトを実行する必要があります.
resource "azurerm_dns_cname_record" "static" {
  name                = "storage-account"
  zone_name           = azurerm_dns_zone.static.name
  resource_group_name = azurerm_resource_group.main.name
  ttl                 = 60
  record              = azurerm_cdn_endpoint.main.host_name
}

resource "azurerm_dns_cname_record" "static_cdnverify" {
  name                = "cdnverify.storage-account"
  zone_name           = azurerm_dns_zone.static.name
  resource_group_name = azurerm_resource_group.main.name
  ttl                 = 60
  record              = "cdnverify.${azurerm_cdn_endpoint.main.host_name}"
}
最後に、CDNは、カスタムドメインを展開するには少し時間がかかります(検証で立ち往生するようです)-私たちはこの手順を完了するために10分かかりました.

静的Webアプリ


これはおそらくAzureの静的コンテンツをホストする最も適切な方法です.それだけでなく、コンテンツを提供するサポート、それも内蔵機能と認証が付属しています.我々はまた、ボックスのうちのCDN機能を取得し、それの上に自由層で使用可能です.これは間違いなく私たちの選択のプラットフォームです.
私たちは既にcovered Static Web Appsを持っているので、我々は簡単にterraformでそれを自動化に触れるでしょう.ここで唯一の合併症は、ネイティブ242479142は完全にリソースを立ち上げることができるが、コンテンツを展開する方法についてのアイデアがないことです.コンテンツを手動でアップロードする方法がないので、我々はdocker deploymentを選びました.パイプラインに戻るのはちょっとハックだった.これは本質的に内容変更時に実行するシェルスクリプトである.
resource "null_resource" "publish_swa" {
    triggers = {
      script_checksum = sha1(join("", [for f in fileset("content", "*"): filesha1("content/${f}")])) // recreate resource on file checksum change. This will always trigger a new build, so we don't care about the state as much
    }
    provisioner "local-exec" {
        working_dir = "${path.module}"
        interpreter = ["bash", "-c"]
        command = <<EOT
docker run --rm -e INPUT_AZURE_STATIC_WEB_APPS_API_TOKEN=${azurerm_static_site.main.api_key} -e DEPLOYMENT_PROVIDER=DevOps -e GITHUB_WORKSPACE=/working_dir -e INPUT_APP_LOCATION=. -v `pwd`/content:/working_dir mcr.microsoft.com/appsvc/staticappsclient:stable ./bin/staticsites/StaticSitesClient upload --verbose true
EOT
    }
// the block above assumes static content sits in `./content` directory. Using `pwd` with backticks is particularly important as terraform attempts parsing ${pwd} syntax, while we need to pass it into the shell
    depends_on = [
      azurerm_static_site.main
    ]
}

アプリケーションサービス


最後に、最も高価で、デフォルトで地方の冗長性も提供しない完全にオーバーエンジニアリングされたアプローチが来ます.アプリケーションサービスを使用すると、単純な静的なページをホスティングするためのセンスはありませんが、コンテナやサーバー側のレンダリングWebアプリケーションのようなより高度なシナリオのパターンとして便利になる可能性があります.

建築ノート


この運動のために、我々は単純なnginx docker containerで我々の内容を主催することを選びました.カスタムドメインとSSLサポートによるLinuxアプリサービス計画は、20ドル/月から始まるので、彼らは安くありません.私たちはコンテナ登録をスキャフォールドし始めました.そこで、我々はアプリケーションサービスが起動時にそれを引っ張ることができるように小さなコンテナをプッシュしました.
FROM nginx:alpine
WORKDIR /usr/share/nginx/html/
COPY index.html .
COPY ./nginx.conf /etc/nginx/nginx.conf # there's minimal nginx config, check out github
EXPOSE 80 # we only care to expose HTTP endpoint, so no certs are needed for nginx at this stage
我々は、そのシンプルさと低いオーヘッドのために我々の点を説明するためにNginxを選びました.しかし、私たちがちょうど何についても包含することができるので、このメソッドはより複雑な展開に役立ちます.

resource "null_resource" "build_container" {
    triggers = {
      script_checksum = sha1(join("", [for f in fileset("content", "*"): filesha1("content/${f}")])) // the operation will kick in on change to any of the files in content directory
    }

// normal build-push flow for private registry
    provisioner "local-exec" { command = "docker login -u ${azurerm_container_registry.acr.admin_username} -p ${azurerm_container_registry.acr.admin_password} ${azurerm_container_registry.acr.login_server}" }
    provisioner "local-exec" { command = "docker build ./content/ -t ${azurerm_container_registry.acr.login_server}/static-site:latest" }
    provisioner "local-exec" { command = "docker push ${azurerm_container_registry.acr.login_server}/static-site:latest" }
    provisioner "local-exec" { command = "docker logout ${azurerm_container_registry.acr.login_server}" }
    depends_on = [
      azurerm_container_registry.acr
    ]
}

resource "azurerm_app_service" "main" {
  name                = "${var.prefix}-app-svc"
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
  app_service_plan_id = azurerm_app_service_plan.main.id

  app_settings = {
    WEBSITES_ENABLE_APP_SERVICE_STORAGE = false // this is required for Linux app service plans
    DOCKER_REGISTRY_SERVER_URL      = azurerm_container_registry.acr.login_server // the convenience of rolling ACR with terraform is that we literally have all the variables already available
    DOCKER_REGISTRY_SERVER_USERNAME = azurerm_container_registry.acr.admin_username // App Service uses admin account to pull container images from ACR. We have to enable it when defining the resource
    DOCKER_REGISTRY_SERVER_PASSWORD = azurerm_container_registry.acr.admin_password
  }

  site_config {
    linux_fx_version = "DOCKER|${azurerm_container_registry.acr.name}.azurecr.io/static-site:latest"
    always_on        = "true" // this is also required on Linux app service plans
  }

  depends_on = [
    null_resource.build_container
  ]
}

結論


この演習を通して、使用するサービスの決定行列を少し構築しました.
アプリケーションサービス
保管口座
静的Webアプリ
目的に合う
本当に


Authn/authz
アプリケーション内で行うことができます

組み込みOpenID接続
グローバルスケール

✅ ( CDN経由)

消費APIへのパスをアップグレードする
✅(DIY)

✅ (組み込み関数やBYO関数)
出口交通を除く(1か月につき)ランニングコストを示す
20ドル+
$ 0 (記憶のための支払い)しかし、CDNは転送されるGBあたりのコストを負います
$ 0または9ドル(余分な機能のためのプレミアム層)
ツールのサポート
どちらの腕またはterraformで重要な問題もありません
腕の静的ウェブサイトを有効にすることは厄介です
ローカルマシンから展開する公式の方法はありません(しかし、確実に回避できます).必要なci/cd githubまたはado
いつものように、フルコードは符号化としてGitHub、インフラストラクチャにあります.