Добрый день.
Как уже отмечалось ранее, Windows Azure представляет собой облачную операционную систему, реализующую парадигму PaaS: разработчик получает платформу (API) для создания информационных систем и место для их размещения. Практически любая информационная система строится из кирпичиков двух типов: сервис и хранилище данных. Если создание хранилищ в Azure – зачастую однократная операция, то сервисы обновляются постоянно (внесение новой функциональности, исправление багов). Обновлять сервисы в Azure можно через web-интерфейс, но это не всегда удобно. Почему?
Предпосылки для автоматизации и постановка задачи
В Azure большие системы обычно представлены, как минимум, в трех лицах (имена условны): Live (c ней работают пользователи), Test (пространство для тестирования) и Dev (разработка). Далее, более-менее серьезная система состоит из нескольких сервисов, каждый из которых выполняет свою функцию. Например, обработка входного трафика, базовый функционал, web-интерфейс и т.п. И, наконец, в каждом пространстве для сервисов есть слоты Production и Staging – для более удобной отладки и минимизации простоя системы при переходе с одной версии на другую. Каждый сервис представлен, как минимум, двумя файлами: программный код в виде бинарного пакета (*.cspkg) и текстовый конфигурационный файл (*.cscfg). Содержимое конфигурационного файла меняется в зависимости от места разрмещения сервиса и его настроек.
Задача: автоматизировать внесение изменений в конфигурационные файлы и развертывание сервисов в облаке.
Работа с конфигурационными файлами
Конфигурационный файл для сервиса может выглядеть так:
<?xml version="1.0"?> <ServiceConfiguration serviceName="YourServiceName" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration"> <Role name="Controller"> <Instances count="5" /> <ConfigurationSettings> <Setting name="keepalive" value="true" /> <Setting name="Storage" value="StorageName:::StorageAccessKey"/> <Setting name="Logs" value="LogLocation:::LogAccessKey"/> </ConfigurationSettings> </Role> <Role name="BasicFunctions"> <Instances count="3" /> <ConfigurationSettings> <Setting name="Connections" value="ConnNumber" /> <Setting name="Storage" value="StorageName:::StorageAccessKey"/> </ConfigurationSettings> </Role> </ServiceConfiguration>
Одни параметры могут оставаться неизменными для любого варианта развертывания, другие параметры меняются при каждом варианте. Для трансформации конфигурационного файла можно воспользоваться XSLT/XPath, передавая входные значения в качестве параметров. Вот пример преобразования:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sc="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" exclude-result-prefixes="sc" version="1.0"> <xsl:param name="Connections" select="'7'"/> <xsl:param name="Storage" select="'dfltwthstore:::yARsaf523as5uoaarOY539=='"/> <xsl:param name="Logs" select="'dfltlogstore:::R2afFEsrT4eeFT8sWadsUf=='"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="sc:Setting[@name = 'Connections']/@value"> <xsl:attribute name="{name()}"> <xsl:value-of select="$Connections"/> </xsl:attribute> </xsl:template> <xsl:template match="sc:Setting[@name = 'Storage']/@value"> <xsl:attribute name="{name()}"> <xsl:value-of select="$Storage"/> </xsl:attribute> </xsl:template> <xsl:template match="sc:Setting[@name = 'Logs']/@value"> <xsl:attribute name="{name()}"> <xsl:value-of select="$Logs"/> </xsl:attribute> </xsl:template> </xsl:stylesheet>
В качестве трансформатора можно воспользоваться утилитой msxsl.exe:
msxsl.exe configurationtemplate.cscfg service.xsl -o configuration.cscfg Connections=8
Если в командной строке заданы параметры (в нашем случае Connections=8), то они переопределяют значения параметров, по умолчанию заданных в xsl-листе.
На выходе получим:
<?xml version="1.0" encoding="UTF-16"?><ServiceConfiguration serviceName="YourServiceName" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration"> <Role name="Controller"> <Instances count="5"></Instances> <ConfigurationSettings> <Setting name="keepalive" value="true"></Setting> <Setting name="Storage" value="dfltwthstore:::yARsaf523as5uoaarOY539=="></Setting> <Setting name="Logs" value="dfltlogstore:::R2afFEsrT4eeFT8sWadsUf=="></Setting> </ConfigurationSettings> </Role> <Role name="BasicFunctions"> <Instances count="3"></Instances> <ConfigurationSettings> <Setting name="Connections" value="8"></Setting> <Setting name="Storage" value="dfltwthstore:::yARsaf523as5uoaarOY539=="></Setting> </ConfigurationSettings> </Role> </ServiceConfiguration>
Автоматизация развертывания сервиса
Для решения задачи воспользуемся PowerShell-командлетами, входящими в состав пакета Windows Azure Service Management CmdLets. Перед началом работы нам потребуется создать сертификат и разместить его в облаке (подробности в картинках). После этого нужно подготовить свой скрипт, не забыв задать значения параметров, которые необходимы для его работы. Как и в случае с конфигурационным файлом, меняющиеся параметры нужно передавать из командной строки или зачитывать из конфигурационного файла. Для компактности изложения в примере ниже передаются два параметра (слот и метка), а остальные параметры заданы в теле скрипта.
param([string]$slot, [string]$label) if (!$slot) { $slot='Staging' } if (!$label) { $label='NoName' } $cert = Get-Item cert:\CurrentUser\My\0B47A3C9DB926E0D98211C45A1096231EACB57C0 $sub = "9bd4773c-2346-5c34-7a6b-d45b782da12c" $servicename = 'controller' $storagename = 'controllerstorage' $package = "d:\deployment\test\controller\controllerservice.cspkg" $config = "d:\deployment\test\controller\ServiceConfiguration.cscfg" Add-PSSnapin AzureManagementToolsSnapIn Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub | Get-Deployment -Slot $slot | Set-DeploymentStatus 'Suspended' | Get-OperationStatus -WaitToComplete Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub | Get-Deployment -Slot $slot | Remove-Deployment | Get-OperationStatus -WaitToComplete New-Deployment -serviceName $servicename -storageserviceName $storagename -subscriptionId $sub -certificate $cert -slot $slot -package $package -configuration $config -label $label | Get-OperationStatus -WaitToComplete Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub | Get-Deployment -Slot $slot | Set-DeploymentStatus 'Running' | Get-OperationStatus -WaitToComplete
Запуск:
powershell .\service.ps1 -slot 'Production' -label '2010-02-15-b'
Что делает скрипт: останавливает сервис, удаляет его, размещает новую версию и запускает сервис. В составе пакета azurecmdlets есть и другие полезные командлеты. Командлеты снабжены подробным описанием.
Собираем воедино
У нас есть кирпичики. Теперь из них можно построить систему. Вот один из вариантов:
1. создается система каталогов. Каталоги первого уровня: пространства развертывания (к примеру, Live, Test, Dev). В каждом из этих каталогов размещаются подкаталоги сервисов (например, Test\Сontroller, Test\BasicFunctions). В этих подкаталогах размещаются соответствующие пакеты сервисов и файлы с конфигурационными параметрами. Например, ночной билд сервиса Сontroller попадает в Dev\Controller для первичной проверки. Или же пакет из Test\BasicFunctions попадает в Live\BasicFunctions после полноценного тестирования.
2. создается скрипт deploy.cmd, который работает так:
deploy.cmd Test – обновить все сервисы в пространстве Test
deploy.cmd Test Controller BasicFunctions – обновить cервисы Controller и BasicFunctions в пространстве Test, а остальные сервисы оставить без изменений.
Скрипт deploy.cmd заходит в соответствующие каталоги и для каждого сервиса считывает конфигурационные параметры, выполняет xsl-преобразование и запуск powershell-скрипта.
Безусловно, следует предусмотреть хранение всех выпущенных версий билдов и конфигурационных файлов, а также обработку ошибок. Но это уже совсем другая история. Оставайтесь с нами и зовите друзей. До встречи.
Update: продолжение истории.
Что такое качество программного обеспечения и как его улучшить: теория и практика, задачи и решения, подводные камни и обходные пути.
Pingback : OpenQuality.ru | Качество программного обеспечения | August 16, 2010
[…] в базовой части приложения, работающего на платформе Windows Azure, проявляется сбой при большом количестве записей в […]
Pingback : OpenQuality.ru | Качество программного обеспечения | September 23, 2010
[…] примере развертывания сервисов в Azure есть серьезный […]