Описание сетапа развёртывания группы ресурсов Azure с одной виртуальной машиной для будущего мониторинга проекта.
В этой части – создание Azure Resource Manager шаблона, настройка Jenkins и примеры Groovy скриптов.
Далее – провижен NGINX и Prometheus с Ansbile. Ещё позже – Grafana.
Все файлы и скрипты хранятся в Github.
Содержание
Подготовка
Используем готовый шаблон от Azure отсюда>>>.
Переименовываем файлы:
[simterm]
$ mv azuredeploy.json jm-monitoring.json $ mv azuredeploy.parameters.json jm-monitoring.parameters.json
[/simterm]
Добавляем RSA ключ:
[simterm]
$ mkdir .ssh $ cp ~/.ssh/setevoy_main_pub_openssh .ssh/jm-monitoring.pub $ cp ~/.ssh/setevoy_main_priv_openssh .ssh/jm-monitoring
[/simterm]
Логинимся:
[simterm]
$ azure login
[/simterm]
Создаём группу ресурсов:
[simterm]
$ azure group create -n jm-monitoring-dev -l westeurope ... info: group create command OK
[/simterm]
Обновление ARM шаблона
Сначала обновляем параметры.
vmSize
из variables
переносим в parameters
, что бы иметь возможность менять тип интанса для Dev и Prod (хотя можно было бы использовать какой-то mapping, по аналогии с AWS CloudFormation – но тратить на это время желания и необходимости нет):
... "vmSize": { "type": "string", "defaultValue": "Standard_DS1", "metadata": { "description": "SSH rsa public key file as a string." } } ...
Обновляем переменные. Мне не нравятся имена, генерируемые Azure – имя ресурса, включающее имя группы выглядит приятнее и понятнее.
Т.е. используем функцию concat()
и подставляем имя группы ресурсов и тип ресурса: "[concat(resourceGroup().name,'-RESOURCETYPE')]"
.
Тут же меняем ОС с Ubuntu 14 на Ubuntu 16:
... "variables": { "vmName": "[concat(resourceGroup().name,'-vm')]", "ubuntuOSVersion": "16.04.0-LTS", "uniqueDnsLabelPrefix": "[concat(resourceGroup().name,'-ip')]", ... "addressPrefix": "10.0.0.0/16", "subnet1Name": "[concat(resourceGroup().name,'-subnet')]", ... "nicName": "[concat(resourceGroup().name,'-nic')]", "publicIPAddressName": "[concat(resourceGroup().name,'-ip')]", ... "virtualNetworkName": "[concat(resourceGroup().name,'-vnet')]", "networkSecurityGroupName": "[concat(resourceGroup().name,'-nsg')]", ... }, ...
Обновляем ресурс “Microsoft.Compute/virtualMachines” – vmSize
был в переменных, теперь в параметрах – "[parameters('vmSize')]"
:
... { "apiVersion": "2016-04-30-preview", "type": "Microsoft.Compute/virtualMachines", "name": "[variables('vmName')]", "location": "[variables('location')]", "dependsOn": [ "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]" ], "properties": { "hardwareProfile": { "vmSize": "[parameters('vmSize')]" }, ...
Запускаем тестовый деплой группы:
[simterm]
$ azure group deployment create --resource-group jm-monitoring-dev \ > --name init \ > --template-file jm-monitoring.json \ > --parameters-file jm-monitoring.parameters.json info: Executing command group deployment create + Initializing template configurations and parameters + Creating a deployment info: Created template deployment "init" + Waiting for deployment to complete ... info: group deployment create command OK
[/simterm]
Хорошо, всё готово:
Логинимся, проверяем:
[simterm]
$ ssh -i .ssh/jm-monitoring jmadmin@13.***.***.62 ... Are you sure you want to continue connecting (yes/no)? yes ... jmadmin@jm-monitoring-dev-vm:~$
[/simterm]
Отлично.
Network security group
Обновим NSG, разрешим доступ по SSH только с одного IP и добавим доступ по 80 и 443, тоже с одного IP.
Возвращаемся к шаблону, обновляем ресурс “Microsoft.Network/networkSecurityGroups”:
... { "apiVersion": "[variables('apiVersion')]", "type": "Microsoft.Network/networkSecurityGroups", "name": "[variables('networkSecurityGroupName')]", "location": "[variables('location')]", "properties": { "securityRules": [ { "name": "SSH_Work_Allow", "properties": { "description": "Locks inbound down to ssh default port 22.", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "22", "sourceAddressPrefix": "194.***.***.45", "destinationAddressPrefix": "*", "access": "Allow", "priority": 120, "direction": "Inbound" } }, { "name": "HTTP_Work_Allow", "properties": { "description": "Locks inbound down to HTTP default port 80.", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "80", "sourceAddressPrefix": "194.***.***.45", "destinationAddressPrefix": "*", "access": "Allow", "priority": 130, "direction": "Inbound" } }, { "name": "HTTPS_Work_Allow", "properties": { "description": "Locks inbound down to HTTPS default port 443.", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "443", "sourceAddressPrefix": "194.***.***.45", "destinationAddressPrefix": "*", "access": "Allow", "priority": 140, "direction": "Inbound" } } ] } }, ...
Сохраняем, повторяем деплой (не уверен, что ARM разрешит обновить так правила в NSG):
[simterm]
$ azure group deployment create --resource-group jm-monitoring-dev --name NSG_Update --template-file jm-monitoring.json --parameters-file jm-monitoring.parameters.json
[/simterm]
Гуд – всё обновилось.
Jenkins
Для Jenkins используем Jenkins Pipeline плагин и Groovy скрипты.
Основной скрипт jm-monitoring-dev-provision.groovy
содержит фукнции:
#!/usr/bin/env groovy def templateValidate(infraUrl='1', env='2', resGroup='3', templateFile='4', paramFile='5') { docker.image('microsoft/azure-cli').inside('-v /var/run/docker.sock:/var/run/docker.sock') { git branch: "${BRANCH}", credentialsId: 'jm-github', url: "${infraUrl}" stage('Temlate validate') { sh "azure login -v -u ${AZURUSER} -p ${AZUREPASS}" sh "azure account set -v ${SUBSCRIPTION}" sh "azure group template validate -g ${resGroup} -f jm-monitoring/${templateFile} -e jm-monitoring/${paramFile}" } } } def environmentUpdate(infraUrl='1', env='2', resGroup='3', templateFile='4', paramFile='5', tag='6') { docker.image('microsoft/azure-cli').inside('-v /var/run/docker.sock:/var/run/docker.sock') { git branch: "${BRANCH}", credentialsId: 'jm-github', url: "${infraUrl}" stage('Environment update') { sh "azure login -v -u ${AZURUSER} -p ${AZUREPASS}" sh "azure account set -v ${SUBSCRIPTION}" sh "azure group deployment create -n ${tag} -g ${resGroup} -f jm-monitoring/${templateFile} -e jm-monitoring/${paramFile}" } } } def verify(msg='1') { stage 'Verify' input id: 'Deploy', message: "${msg}", ok: 'Deploy!' } return this
(не забываем return this
)
И скрипт провижена самого окружения:
#!/usr/bin/env groovy node { TAG = "${env.BUILD_TAG}" INFRAURL = 'https://github.com/jm/azure-infrastructure.git' RESGROUP = "${RESGROUP}" TMPL = "${TMPL}" PARAMS = "${PARAMS}" dir('buildscripts') { git branch: 'master', credentialsId: 'jm-github', url: 'https://github.com/jm/jm-jenkins.git' } git branch: "${BRANCH}", credentialsId: 'jm-github', url: "${INFRAURL}" def provision = load 'buildscripts/jm-monitoring-provision.groovy' provision.templateValidate("${INFRAURL}", "${ENV}", "${RESGROUP}", "${TMPL}", "${PARAMS}") provision.verify('Is Verify OK? Proceed with an environment deployment?') provision.environmentUpdate("${INFRAURL}", "${ENV}", "${RESGROUP}", "${TMPL}", "${PARAMS}", "${TAG}") }
Параметры в пайплайне Jenkins-а выглядят так:
Собственно – по Jenkins-у тут всё.
Запускаем, повторяем деплой, убеждаемся что всё работает: