Блог компании Microsoft

Развертывание приложений в Azure Stack и Microsoft Azure

Azure Stack представляет собой программно-аппаратный комплекс (интегрированную систему), который позволяет запускать и использовать подмножество сервисов Microsoft Azure. Поскольку при этом физически Azure Stack может быть расположен в вашем дата-центре или дата-центре вашего провайдера, то можно сказать, что сервисы Azure становятся доступными локально. Не все сервисы, еще раз подчеркну, а лишь подмножество, которое на текущий момент включает в себя: Azure IaaS (VMs, VM Scale Sets, Virtual Networks, Gateways, Load Balancers, Linux / Windows containers, Blobs, Tables, Queues), Azure PaaS (Web Apps, API Apps, Azure Functions).

Технический обзор Azure Stack вы можете найти в этой статье и вебкасте, записанном мною на основе Technical Preview 3. Кроме того, много свежей информации ожидается в ходе конференции «Платформа цифрового бизнеса», которая пройдет 30 ноября 2017 года в Москве.
Здесь же я хотел бы сосредоточиться на реализации одного из гибридных сценариев — развертывании приложения в Azure и Azure Stack.
Появление Azure Stack действительно позволяет реализовать ряд интересных гибридных сценариев, например:
  • У вас есть облачное приложение, скажем, Web App, которое безо всякого изменения кода вы можете развернуть как в Azure, так и в Azure Stack. Например, отладка и тестирование в Azure, production-вариант — в Azure Stack.
  • У вас есть приложение, компоненты которого вы размещаете в разных облаках. Например, есть frontend и база данных, изначально запущенные в Azure Stack. При увеличении нагрузки на приложение дополнительные экземпляры frontend-а поднимаются в Azure, а Traffic Manager распределяет входящие подключения между объектами в Azure и Azure Stack. База при этом все время располагается локально в Azure Stack.
Это список можно продолжать, и, думаю, по мере распространения Azure Stack будут появляться новые интересные схемы. Но сегодня рассмотрим более детально первый из перечисленных сценариев.
Для начала давайте обсудим, какую особенность привносит в этот сценарий Azure Stack. Если у меня есть «обычное» приложение, ничто не мешает мне запустить его внутри виртуальной машины или контейнера в любом облаке, в том числе в Azure Stack. Но если приложение изначально разрабатывалось как облачное, использовало сервисы Azure, например, блобы, PaaS-сервисы и пр., для обеспечения эластичности и масштабируемости, его нельзя просто так перенести в локальную инфраструктуру. Уже хотя бы потому, что блобы, облачные APIs, недоступны локально.
И здесь самое время отметить одну из главных особенностей Azure Stack — он использует ту же модель управления ресурсами (Azure Resource Manager, ARM) и те же программные интерфейсы, что и публичное облако Microsoft.
Как следствие, если приложение использует подмножество сервисов и APIs, доступных в Azure Stack, оно может быть перенесено из Azure в Azure Stack и наоборот вообще без изменения кода, либо с минимальными изменениями, типа замены connection string.
Использование единой модели управления ресурсами обеспечивает еще одно интересное преимущество подобной гибридизации — унифицированный процесс развертывания. Напомню, в Azure вы можете описать среду (environment), необходимую для вашего приложения, с помощью так называемых ARM-шаблонов — файлов, использующих JSON-нотацию и в декларативном виде описывающих все артефакты, их количество и расположение для приложения. ARM-шаблоны реализуют подход Infrastructure as Code и одинаково применимы как к публичному облаку Microsoft, так и к AzureStack. Иными словами, подготовив один шаблон для приложения, вы дальше можете указать, в каком облаке его (точнее то, что в нем описано) развернуть. Здесь есть несколько нюансов, но о них позже.
Именно такой вариант гибридного развертывания я и хочу проиллюстрировать. И поскольку фокус будет на развертывании, а не на коде приложении, то роль приложения будет выполнять самая простая виртуальная машина с Windows Server. Но точно также эта концепция применима и к любым другим сколь угодно сложным многозвенным приложениям с Web Apps, базами данных и прочими компонентами, которые поддерживаются Azure Resource Manager.
Задача сводится к двум основным шагам:
  1. Подготовка шаблона, совместимого с Azure Stack;
  2. Подготовка скрипта, который развернет этот шаблон в нужное облако.
В большинстве случаев вам не придется создавать ARM-шаблон с нуля. Довольное большое количество примеров, в том числе именно для Azure Stack, можно найти в репозитории Azure на GitHub и взять за основу. Я именно так и поступил, итоговый шаблон azureHybrid.json можно посмотреть в моем репозитории. Здесь отмечу лишь наиболее принципиальные моменты.
В описании любого ресурса в теле ARM-шаблона есть обязательное поле apiVersion. Ниже приведен фрагмент описания ресурса Microsoft.Compute/virtualMachines с этим полем.
"apiVersion": "[variables('computeApiVersion')]",
"type": "Microsoft.Compute/virtualMachines",
"name": "[parameters('vmName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
     "[resourseId('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
     "[resourceId('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
],
В Azure изменения функциональных возможностей происходят быстрее, чем в Azure Stack, соответственно, быстрее появляются новые версии программных интерфейсов. Если взять любой шаблон, созданный для Azure, и попытаться развернуть его в Azure Stack, с большой вероятностью вы получите ошибку, даже при условии, что в шаблоне описаны только сервисы, доступные и в Azure, и в Azure Stack. Причина в различии версий используемых API. Например, многие ажуровские шаблоны используют так называемые управляемые диски (Managed Disk) в качестве виртуальных жестких дисков ВМ. В то время как в Azure Stack этот тип дисков пока не реализован, и необходимо использовать традиционный механизм учетных записей хранения (Storage Account).
apiVersion позволяет создавать совместимые с двумя облаками шаблоны. В этой статье вы можете найти полный перечень версий API, поддерживаемых в настоящий момент Azure Stack. В приведенном в качестве примера шаблоне номера версий я вынес в раздел переменных для удобства редактирования.
"variables": {
   "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'sa61')]",
   "nicName": "[concat(parameters('vmName'), '-nic01')]",
   "publicIPAddressName": "[concat(parameters('vmName'), '-ip01')]",
   "networkSecurityGroupName": "[concat(parameters('vmName'), '-nsg01')]",
   "virtualNetworkName": "azure61-vnet01",
   "addressPrefix": "10.0.0.0/16",
   "subnetName": "[concat(variables('virtualNetworkName'), '-subnet01')]",
   "subnetPrefix": "10.0.0.0/24",
   "subnetRef": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworkName'), variables('subnetName'))]",
   "computeApiVersion": "2015-06-15",
   "networkApiVersion": "2015-05-01-preview",
   "storageApiVersion": "2015-06-15",
},
И при этом надо помнить, что в разных версиях API описание того или иного объекта может отличаться (названия полей, обязательность полей и пр.). Это первый и самый важный нюанс создания шаблона, который планируется использовать в разных облаках. Именно поэтому AzureStack-QuickStart-Templates, а не Azure-QuickStart-Templates рекомендованы в качестве основы для экспериментов. Хотя при определенных навыках можно пользоваться и последним более богатым репозиторием.
Теперь, когда готов шаблон и файл параметров (azureHybrid.parameters.json в моем случае, в нем все более-менее очевидно), давайте разберёмся, как разворачивать шаблон в разные облака. Сделать это можно с помощью PowerShell на Windows-системах или CLI на любых других, включая Windows. Я в данном случае остановлюсь на PowerShell и замечу, что для выполнения определенных административных задач, связанных с настройкой самого Azure Stack, PowerShell обязателен.
Для начала развернем наше приложение в Azure. Пример скрипта можно найти в файлеDeployTemplateToAzure.ps1. В скрипте есть три основные команды, который нам интересны.
Login-AzureRmAccount -Credential $AadCred
Собственно, подключает нас к подписке в Azure.
New-AzureRmResourceGroup     -Name $ResourceGroupName `
                             -Location $ResourceGroupLocation `
                             -Verbose `
                             -Force
Создает ресурсную группу с нужным именем в регионе, заданном параметром -Location.
New-AzureRmResourceGroupDeployment       -Name $DeploymentName `
                                         -ResourceGroupName $ResourceGroupName `
                                         -TemplateUri $TemplateUri `
                                         -TemplateParameterUri $TemplateParameterUri `
                                         -Verbose
Наконец, именно эта команда запускает развертывание в созданной ресурсной группе на основе ARM-шаблона и файла параметров. Вместо TemplateUri и TemplateParameterUri можно использовать параметры TemplateFile и TemplateParameterFile, если шаблоны располагаются локально в файловой системе.
Скрипт DeployTemplateToMAS.ps1 разворачивает тот же шаблон в Azure Stack. Разберемся, в чем здесь особенности.
Во-первых, в качестве расположения в параметре $ResourceGroupLocation вместо региона Azure указано значение «local». В перспективе Azure Stack также будет поддерживать множество регионов. Применительно к конкретной организации регион может представлять собой набор подсетей, связанных каналами со сравнительно небольшими задержками — два соседних ЦОД-а, несколько площадок в рамках города и пр. Что такое «небольшие задержки» каждая компания определяет для себя самостоятельно. Пока же Azure Stack поддерживает только один регион, и для Azure Stack Development Kit (ASDK) — тестовой (evaluation) версии, доступной бесплатно для всех желающих — значение этого поля всегда «local».
Во-вторых, Azure Stack расположен в вашем датацентре / датацентре провайдера. Поэтому необходимо каким-то образом указать в скрипте, к какому экземпляру Azure Stack, или даже более обще, к какому экземпляру облака нам необходимо подключиться. Для этого существует понятие окружения Azure (AzureEnvironment). Если, скажем, запустить команду Login-AzureRmAccount без параметров, то по умолчанию в качестве environment подразумевается публичное облако Microsoft Azure. Если же добавить ключ -EnvironmentName, то следующая команда в качестве облака будет подразумевать Azure Germany:
Login-AzureRmAccount -EnvironmentName AzureGermanCloud 
Это облако представляет собой изолированный экземпляр Azure и, соответственно, отдельный экземпляр Azure Resource Manager со своей точкой входа, которую принято называть ARM Endpoint.
Azure Stack (один или несколько, объединенных в единое облако) — это тоже отдельный экземпляр Azure Resource Manager со своей точкой входа. Просто если для Azure Germany или Azure Government точки входа известны, то для каждого конкретного облака Azure Stack точку входа надо явно указать. А заодно и дать имя новому окружению (environment), чтобы в дальнейшем было удобно на это окружение ссылаться. В случае ASDK точка входа всегда имеет одно и тоже значение: https://management.local.azurestack.external. Для каждого коммерческого развертывания Azure Stack свой уникальный ARM Endpoint задается на этапе преднастройки. Теперь несложно понять смысл команды
Add-AzureRMEnvironment    -Name "AzureStackUser" `
                          -ArmEndpoint https://management.local.azurestack.external
которая создает окружение с именем «AzureStackUser» и соответствующей точкой подключения.
Как и в публичном облаке, в облаке Azure Stack может существовать множество подписок для разных клиентов (отделов, департаментов, проектных команд и пр.). И надо указать, в какой подписке мы собираемся развернуть описанные в ARM-шаблоне объекты. Для этого в переменной $TenantID сохраняется результат выполнения команды Get-AzsDirectoryTenantId:
$TenantID = Get-AzsDirectoryTenantId	-AADTenantName "contosomsspb.onmicrosoft.com" `
                                        -EnvironmentName "AzureStackUser"
Теперь все готово к тому, чтобы выполнить подключение к требуемому экземпляру Azure Stack и нужной подписке в нём. Используется уже знакомая команда Login-AzureRmAccount с параметрами, задающими помимо credentials ещё ARM Endpoint и подписку:
Login-AzureRmAccount	-EnvironmentName "AzureStackUser" `
                        -TenantId $TenantID `
                        -Credential $AadCred
В-третьих, в самом начале скрипта вы видите подключение модуля PowerShell:
Import-Module .\Connect\AzureStack.Connect.psm1
Действительно, прежде чем использовать команды для работы с Azure Stack, необходимо установить соответствующий модуль PowerShell, а затем подключить его упомянутой командой. Подробную инструкцию по установке инструментов PowerShell для Azure Stack можно найти здесь.
Таким образом, применяя корректные версии API, мы подготовили совместимый с Azure и Azure Stack шаблон, описывающий наше приложение. А манипулируя точками подключения и идентификаторами подписок, научились разворачивать это шаблон в нужное облако. И конечно, никто не мешает модифицировать код так, чтобы остался одни скрипт, который умеет работать с обоими облаками.
В заключение приведу основную ссылку на раздел сайта Microsoft, посвященный Azure Stack. Оттуда легко перейти к документации, скачиванию ASDK или форуму, где можно задать вопросы и найти решения проблем, с которыми уже кто-то столкнулся до вас.
Как выглядит конфигурация интегрированной системы на пример HPE, можно посмотреть в недавно опубликованной статье на Хабре.
Также напомню, что по Azure существует сертификация, которая на текущий момент включает три экзамена (для разработчиков, ИТ-специалистов и архитекторов):
А в январе 2018 года этот список пополнится новым экзаменом, посвященным как раз вопросам построения гибридных облаков.
Пробуйте Azure Stack, стройте гибридные структуры для решения ваших задач, делитесь опытом и новыми идеями гибридизации.
Александр Шаповал
эксперт по стратегическим технологиям Microsoft
30 ноября состоится конференция «Платформа цифрового бизнеса»
Комментарии 1
  • +1
    В принципе, задумка дизайнера как бы понятна — облака и сервера на фоне заголовка, ну да, просто совместили два понятия, что уж тут, но моя первая мысль была: «Это ж как надо было ЦОД нагрузить, что бы серваки задымились так!» Потом только сообразил в чем глубина замысла )

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.