Статические веб-сайты снова стали популярными в наши дни. Генераторы веб-сайтов, такие как Jekyll, Hugo или Gatsby, позволяют довольно легко комбинировать шаблоны и страницы уценки для создания статических файлов HTML. Статические активы проще всего обслуживать и кэшировать, поэтому вся настройка оказывается быстрой и экономичной.

Многие платформы предлагают услуги по размещению таких статических веб-сайтов. В этом посте объясняются шаги по созданию инфраструктуры для этого в Microsoft Azure.

Настройка инфраструктуры для обслуживания статического веб-сайта не кажется такой уж сложной, но если учесть сертификаты HTTPS, сети распространения контента и присоединение к пользовательскому домену, интеграция всех компонентов может быть довольно сложной.

К счастью, это задача, в которой Pulumi сияет. Подход Pulumi, ориентированный на код, не только упрощает настройку и обслуживание облачных ресурсов, но и избавляет от необходимости интеграции нескольких сервисов.

Обзор

Наша цель — создать статический веб-сайт с собственным доменом. В этой статье я буду использовать воображаемый demo.pulumi.com. В 2019 году мой веб-сайт должен поддерживать HTTPS, поэтому нам также нужно создать собственный сертификат TLS.

Окончательное решение состоит из нескольких служб Azure:

  • Статические файлы будут храниться в контейнере больших двоичных объектов в аккаунте хранения.
  • В учетной записи хранения будет включена функция статического веб-сайта для некоторых основных правил перезаписи URL.
  • Мы поместим Azure CDN Endpoint перед контейнером для поддержки личного домена через TLS.
  • Azure CDN будет самостоятельно управлять сертификатом TLS.
  • У нашего пользовательского DNS-провайдера будет правило, указывающее на конечную точку CDN (это шаг вручную)

На приведенной ниже схеме показано взаимодействие этих компонентов:

Давайте разберемся, как настроить каждый компонент с помощью Pulumi.

Группа ресурсов

Давайте запустим новую программу Pulumi, импортируем пакеты Pulumi и определим новую группу ресурсов:

import * as pulumi from "@pulumi/pulumi";
import * as azure from "@pulumi/azure";
const resourceGroup = new azure.core.ResourceGroup("demo-rg", {
    location: azure.WestEurope, 
});

Учетная запись хранения

Учетная запись хранения будет содержать активы нашего статического веб-сайта:

const storageAccount = new azure.storage.Account("demopulumi", {
    resourceGroupName: resourceGroup.name,
    accountReplicationType: "LRS",
    accountTier: "Standard",
    accountKind: "StorageV2",
});

Единственный трюк здесь — убедиться, что тип учетной записи — V2; в противном случае он не будет поддерживать функцию статического веб-сайта.

Размещение статического веб-сайта в хранилище Azure

Любой контейнер хранилища может быть представлен как конечная веб-точка. Однако это недостаточно гибко. URL-адрес всегда будет включать имя контейнера и точное имя файла, поэтому пользователю придется запрашивать https://demo.pulumi.com/containername/index.html вместо простого https://demo.pulumi.com/.

Включение статического хостинга веб-сайтов в службе хранилища Azure улучшает этот процесс. Автоматически создается специальный контейнер $web, который также имеет специальную обработку для документов index и 404.

Плохая новость заключается в том, что хостинг статического веб-сайта не является частью API Azure Resource Manager и, следовательно, недоступен в готовых шаблонах ARM, Terraform или Pulumi. Мы можем включить эту функцию с помощью Azure CLI, поэтому решение состоит в том, чтобы создать динамический ресурс Pulumi, который позволяет работать с Pulumi, делегируя работу CLI. Вы можете найти полный исходный код динамического ресурса в этом примере, но использование довольно тривиально:

const staticWebsite = new StorageStaticWebsite("demopulumi-static", 
    { accountName: storageAccount.name }, 
    { parent: storageAccount }
); 
export const staticEndpoint = staticWebsite.endpoint;

Последняя строка экспортирует конечную точку статического веб-сайта. Он будет выглядеть примерно так: https://demopulumi01234abc.z6.web.core.windows.net/ — личного домена пока нет, но он уже работает — как только мы развернем там несколько статических файлов.

Статические файлы

Теперь пришло время загрузить статические файлы в контейнер $web BLOB-объектов.

Для этой демонстрации я создал папку wwwroot с двумя файлами: index.html и 404.html. Я могу загрузить эти файлы с помощью следующего фрагмента Pulumi:

["index.html", "404.html"].map(name => 
    new azure.storage.Blob(name, {
        name, 
        resourceGroupName: resourceGroup.name,
        storageAccountName: storageAccount.name,
        storageContainerName: staticWebsite.webContainerName,
        type: "block",
        source: `./wwwroot/${name}`,
        contentType: "text/html",
    })
);

На практике ваш статический веб-сайт может содержать сотни или тысячи файлов. В этот момент вы можете захотеть отделить операцию загрузки файла от Pulumi и сделать ее отдельным шагом в конвейере CI/CD.

Azure CDN

Чтобы сделать файлы статического веб-сайта доступными через наш личный домен и HTTPS, нам нужно создать конечную точку Azure CDN и указать ее на учетную запись хранения:

const cdn = new azure.cdn.Profile("demo-cdn", {
    resourceGroupName: resourceGroup.name,
    sku: "Standard_Microsoft", 
});
const endpoint = new azure.cdn.Endpoint("demo-cdn-ep", {
    name: "demopulumi",
    resourceGroupName: resourceGroup.name,
    profileName: cdn.name,
    isHttpAllowed: true,
    isHttpsAllowed: true,
    originHostHeader: staticWebsite.hostName,
    origins: [{ name: "blobstorage",
       hostName: staticWebsite.hostName,
    }], 
});
export const cdnEndpoint = pulumi.interpolate`https:

Я указал явное имя для конечной точки CDN: demopulumi. Это имя должно быть глобально уникальным, поскольку оно является частью URL-адреса конечной точки https://demopulumi.azureedge.net. Пожалуйста, выберите пользовательское имя перед запуском программы.

Я указал происхождение CDN на имя статического веб-сайта с помощью staticWebsite.hostName. Как обычно, легко связать ресурсы в коде Pulumi!

Возможно, вам придется подождать несколько минут, прежде чем ваш контент станет видимым, так как конфигурация CDN не выполняется немедленно. Я установил isHttpAllowed на true, потому что HTTP доступен раньше, чем HTTPS; не стесняйтесь отключать его для вашей производственной конфигурации.

Настройте правило DNS для домена

Вероятно, вы зарегистрировали свой домен у какого-то стороннего провайдера. Следуйте инструкциям вашего провайдера, чтобы настроить правило CNAME для DNS веб-сайта. Для личного домена demo.pulumi.com запись CNAME demo будет связана с конечной точкой demopulumi.azureedge.net.

Записи CNAME не поддерживают голые домены, такие как pulumi.com. Если вы хотите настроить домен верхнего уровня для обслуживания со статического веб-сайта Azure, вам придется использовать псевдонимную запись DNS, которая не поддерживается некоторыми провайдерами DNS. Пожалуйста, уточните у своего провайдера доступные варианты.

Следующий шаг предполагает, что запись CNAME настроена; в противном случае произойдет сбой с ошибкой проверки.

Пользовательский домен и TLS

Последним шагом является указание нашего пользовательского домена на конечную точку CDN и предоставление сертификата TLS для включения поддержки HTTPS. Опять же, эти операции не являются частью поверхности ARM API, поэтому для их поддержки был создан еще один динамический ресурс.

Использование довольно простое, просто убедитесь, что вы используете свой собственный домен в следующем фрагменте:

const customDomain = new CDNCustomDomainResource("cdn-custom-domain", {
    resourceGroupName: resourceGroup.name,
    customDomainHostName: "demo.pulumi.com",
    profileName: cdn.name,
    endpointName: endpoint.name,
    httpsEnabled: true, 
}, 
{ parent: endpoint });

Оживи!

И мы закончили! Запустите pulumi up и убедитесь, что все ресурсы успешно созданы.

Начните тестирование с staticEndpoint — он станет доступен первым. cdnEndpoint может сначала вернуть несколько 404, наберитесь терпения. Затем попробуйте свой личный домен с HTTP. Наконец, для регистрации сертификата TLS требуется довольно много времени, поэтому вернитесь через час или около того, чтобы протестировать HTTPS.

Хотя «статический веб-сайт» может показаться простым, мы прошли довольно сложный процесс, чтобы связать все компоненты вместе. Некоторые службы и функции Azure проще автоматизировать, чем другие, но в итоге мы объединили их все в одну целостную программу Pulumi для размещения статического веб-сайта, обслуживаемого через HTTPS и всемирной CDN. В этом сила языка программирования общего назначения, примененного к задаче автоматизации сложной инфраструктуры. Как только повторно используемые компоненты будут установлены, надежное и воспроизводимое развертывание станет реальностью.

Первоначально опубликовано на https://blog.pulumi.com.