Задача: создать Resource Group в Azure, которая будет включать в себя виртуальную машину с Jenkins-ом.
Jenkins будет запускаться в Docker-контейнере, и подгружать $JENKINS_HOME
с внешнего диска, подключенного к виртуальной машине.
Получившийся шаблон можно посмотреть тут>>>.
Диск уже создан, имеет файловую систему и данные с текущего интанса Jenkins:
[simterm]
$az disk list ... { "accountType": "Premium_LRS", "creationData": { "createOption": "Empty", "imageReference": null, "sourceResourceId": null, "sourceUri": null, "storageAccountId": null }, "diskSizeGb": 100, "encryptionSettings": null, "id": "/subscriptions/0a4f2b9c-***-***-***-40b17ef8c3ab/resourceGroups/EUROPE-JM/providers/Microsoft.Compute/disks/jenkinsworkspaces", "location": "westeurope", "name": "jenkinsworkspaces", "osType": null, "ownerId": "/subscriptions/0a4f2b9c-***-***-***-40b17ef8c3ab/resourceGroups/jm-jenkins/providers/Microsoft.Compute/virtualMachines/jm-jenkins-vm", "provisioningState": "Succeeded", "resourceGroup": "EUROPE-JM", "tags": null, "timeCreated": "2017-02-27T11:38:22.992122+00:00", "type": "Microsoft.Compute/disks" }, ...
[/simterm]
Содержание
Azure Resource Manager шаблон
Параметры
За основу возьмём шаблон 101-vm-simple-linux.
Первым делом – обновляем параметры. Для нашей сети требуется добавить набор правил фаервола, для доступа из определённых сетей.
Выносим их в параметры.
В файл самого шаблона – добавляем:
... "CiklumNET": { "type": "string", "defaultValue": "194.***-***.45/32" }, "BerlinNET": { "type": "string", "defaultValue": "37.***-***.130/32" }, "Github": { "type": "string", "defaultValue": "192.30.252.0/22" }, "SetevoyHome": { "type": "string", "defaultValue": "176.***-***.79" }, ...
В файл с параметрами:
... "CiklumNET": { "value": "194.***-***.45/32" }, "BerlinNET": { "value": "37.***-***.130/32" }, "Github": { "value": "192.30.252.0/22" }, "SetevoyHome": { "value": "176.***-***.79" } } ...
Заодно – обновляем значения остальных параметров, например:
... "dnsLabelPrefix": { "value": "jm-jenkins" }, ...
Переменные
Обновляем значения для переменных, например:
... "OSDiskName": "jm-jenkins-os-disk", "nicName": "jm-jenkins-nic", ...
Кроме того – т.к. имеющийся диск является Managed диском и тип диска – Standard_LRS, то необходимо изменить тип виртуальной машины, т.к. Managed Disks поддерживаются только машинами уровня DS2 и выше. Больше деталей о типах ВМ – тут>>>, про Managed disks – тут>>> и несколько ссылок – в конце поста.
Меняем значение переменной:
... "vmSize": "Standard_DS2_v2", ...
Блок variables
получается таким:
... "variables": { "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'jm')]", "dataDisk1VhdName": "jm-jenkins-data-disk", "imagePublisher": "Canonical", "imageOffer": "UbuntuServer", "OSDiskName": "jm-jenkins-os-disk", "nicName": "jm-jenkins-nic", "NSGName": "jm-jenkins-nsg", "addressPrefix": "10.0.0.0/16", "subnetName": "jm-jenkins-subnet", "subnetPrefix": "10.0.0.0/24", "storageAccountType": "Standard_LRS", "publicIPAddressName": "jm-jenkins-pub-ip", "publicIPAddressType": "Dynamic", "vmStorageAccountContainerName": "vhds", "vmName": "jm-jenkins-vm", "vmSize": "Standard_DS2_v2", "virtualNetworkName": "jm-jenkins-vnet", "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]", "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]" }, ...
Network Security Group
Переходим к ресурсам.
Добавляем создание Network Security Group, в properties
которой указываем правила доступа, используя сети из параметров, которые были добавлены в начале.
Полностью ресурс будет выглядеть так:
... { "apiVersion": "2015-06-15", "type": "Microsoft.Network/networkSecurityGroups", "name": "[variables('NSGName')]", "location": "[resourceGroup().location]", "tags": { "displayName": "NSG - Remote Access" }, "properties": { "securityRules": [ { "name": "AllowSSHAll", "properties": { "description": "Allow SSH", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "22", "sourceAddressPrefix": "*", "destinationAddressPrefix": "*", "access": "Allow", "priority": 100, "direction": "Inbound" } }, { "name": "CiklumAllowAll", "properties": { "description": "Ciklum Allow All", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "*", "sourceAddressPrefix": "[parameters('CiklumNET')]", "destinationAddressPrefix": "*", "access": "Allow", "priority": 110, "direction": "Inbound" } }, { "name": "BerlinAllowAll", "properties": { "description": "Berlin Allow All", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "*", "sourceAddressPrefix": "[parameters('BerlinNET')]", "destinationAddressPrefix": "*", "access": "Allow", "priority": 120, "direction": "Inbound" } }, { "name": "Github", "properties": { "description": "Github Allow HTTP", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "80", "sourceAddressPrefix": "[parameters('Github')]", "destinationAddressPrefix": "*", "access": "Allow", "priority": 130, "direction": "Inbound" } }, { "name": "ArsenyHomeAllowAll", "properties": { "description": "Arseny home Allow All", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "*", "sourceAddressPrefix": "[parameters('SetevoyHome')]", "destinationAddressPrefix": "*", "access": "Allow", "priority": 140, "direction": "Inbound" } } ] } }, ...
Подключение Managed диска к создаваемой VM
Обновляем ресурс Microsoft.Compute/virtualMachines, и меням значение для dataDisks
.
Исходные данные:
... "dataDisks": [ { "diskSizeGB": "1023", "lun": 0, "createOption": "Empty" } ] ...
Указываем подключение своего диска:
... "dataDisks": [ { "lun": 0, "createOption": "Attach", "caching": "None", "diskSizeGB": 100, "managedDisk": { "id": "/subscriptions/0a4f2b9c-***-***-***-40b17ef8c3ab/resourceGroups/europe-jm/providers/Microsoft.Compute/disks/jenkinsworkspaces" } } ] ...
Установка Docker и запуск Jenkins
Для завершения провижена – требуется смонтировать диск, установить Docker и запустить Jenkins.
Для этого используем скрипт, который хранится в Azure Storage Account Blob-storage:
#!/usr/bin/env bash sudo curl https://get.docker.com/ | bash sudo usermod -aG docker serverdmin mkdir /jenkins mount /dev/sdc1 /jenkins/ docker run -tid -p 80:8080 -v /jenkins:/jenkins -v /var/run/docker.sock:/var/run/docker.sock -e JENKINS_HOME='/jenkins' --name jenkins jenkins
Для вызова этого скрипта из ARM-шаблона – используем расширение CustomScript из Microsoft.Azure.Extensions.
В resources
нашего шаблона – добавляем:
... { "type": "Microsoft.Compute/virtualMachines/extensions", "name": "[concat(variables('vmName'),'/DockerInstall')]", "apiVersion": "2015-05-01-preview", "location": "[resourceGroup().location]", "dependsOn": [ "[concat('Microsoft.Compute/virtualMachines/', variables('vmName'))]" ], "properties": { "publisher": "Microsoft.Azure.Extensions", "type": "CustomScript", "typeHandlerVersion": "2.0", "autoUpgradeMinorVersion": true, "settings": { "fileUris": [ "https://utils.blob.core.windows.net/scripts/jenkins_provision.sh" ], "commandToExecute": "bash jenkins_provision.sh" }, "protectedSettings": { "storageAccountName": "jmutils", "storageAccountKey": "tOkXJ*****T66Bw==" } } } ...
На этом подготовка шаблона завершена.
Создаём группу:
[simterm]
$ azure group create -l westeurope -n jm-jenkins Finalizing -f jm-jenkins_v2.json -e jm-jenkins_v2.parameters.json
[/simterm]
Логи
CustomScript
сработал раза с десятого. Для поиска проблем – на созданной машине проверяем три лога:
/var/log/azure/custom-script/handler.log
/var/lib/waagent/custom-script/download/0/stdout
/var/lib/waagent/custom-script/download/0/stderr
[simterm]
# tail -f /var/lib/waagent/custom-script/download/0/std* /var/log/azure/custom-script/handler.log
==> /var/lib/waagent/custom-script/download/0/stderr <==
194637a1b12c: Pull complete
f5405da54999: Pull complete
66c5531af30f: Pull complete
c61bd2df6e6a: Pull complete
85969c669ffc: Pull complete
a22b8d2b56ba: Pull complete
11b90bc5b10c: Pull complete
351c841a8598: Pull complete
Digest: sha256:2bfbdb2c2606a3fa036bd7c0392003cd5aeb45978cc7fa05ba14b0412b4e9a1c
Status: Downloaded newer image for jenkins:latest
==> /var/lib/waagent/custom-script/download/0/stdout <==
Experimental: false
If you would like to use Docker as a non-root user, you should now consider
adding your user to the “docker” group with something like:
sudo usermod -aG docker your-user
Remember that you will have to log out and back in for this to take effect!
ec93c63beeaeba788096fda4965a44311a88123ae77e2b1a25ae1693276e7046
==> /var/log/azure/custom-script/handler.log <==
time=2017-02-28T11:54:41Z version=v2.0.2/git@494f22e-clean operation=enable seq=0 event=”validated configuration”
time=2017-02-28T11:54:41Z version=v2.0.2/git@494f22e-clean operation=enable seq=0 event=”creating output directory” path=/var/lib/waagent/custom-script/download/0
time=2017-02-28T11:54:41Z version=v2.0.2/git@494f22e-clean operation=enable seq=0 event=”created output directory”
time=2017-02-28T11:54:41Z version=v2.0.2/git@494f22e-clean operation=enable seq=0 files=1
time=2017-02-28T11:54:41Z version=v2.0.2/git@494f22e-clean operation=enable seq=0 file=0 event=”download start”
time=2017-02-28T11:54:42Z version=v2.0.2/git@494f22e-clean operation=enable seq=0 file=0 event=”download complete” output=/var/lib/waagent/custom-script/download/0
time=2017-02-28T11:54:42Z version=v2.0.2/git@494f22e-clean operation=enable seq=0 event=”executing command” output=/var/lib/waagent/custom-script/download/0
time=2017-02-28T11:55:40Z version=v2.0.2/git@494f22e-clean operation=enable seq=0 event=”executed command” output=/var/lib/waagent/custom-script/download/0
time=2017-02-28T11:55:40Z version=v2.0.2/git@494f22e-clean operation=enable seq=0 event=enabled
time=2017-02-28T11:55:40Z version=v2.0.2/git@494f22e-clean operation=enable seq=0 event=end
[/simterm]
И проверяем работу самого Jenkins:
[simterm]
$ curl http://np4zgtqmq5c76.westeurope.cloudapp.azure.com/ <html><head><meta http-equiv='refresh' content='1;url=/login?from=%2F'/><script>window.location.replace('/login?from=%2F');</script></head><body style='background-color:white; color:white;'> Authentication required
[/simterm]
Готово.
Ссылки по теме
Comparing AWS Cloudformation and Azure Resource Manager
Announcing general availability of Managed Disks and larger Scale Sets
About disks and VHDs for Azure Linux VMs