Задача: создать 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





