Задача – добавить подключение data-диска к виртуальной машине во время развёртывания Azure Resource Group с виртуальной машиной, смонтировать диск к файловой системе и запустить Prometheus с использованием этого диска для хранения данных.
Содержание
Azure data disk
Диск уже есть.
Используем Azure CLI v2 из Docker образа:
[simterm]
$ docker run -v ~/Work/BER.JM/azure-infrastructure/:/root/azure-infrastructure/ -it azuresdk/azure-cli-python
[/simterm]
Логинимся:
[simterm]
bash-4.3# az login
[/simterm]
Проверяем диски:
[simterm]
bash-4.3# az disk list -g europe-jm --query '[*].{Name:name,Gb:diskSizeGb,Tier:accountType}' --output table Name Gb --------------------------- ---- jenkinsworkspaces 100 jm-monitoring-data-disk-dev 10
[/simterm]
(Azure в новой CLI тупо копирует всё от AWS CLI – даже --query
…)
Azure template
Шаблон уже есть – см. пост Azure: provisioning с Resource Manager, Jenkins и Groovy.
Теперь – надо обновить ресурс, описывающий виртуальную машину и добавить подключение существующего диска.
Сейчас ресурс выглядит так:
... { "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')]" }, "osProfile": { "computerName": "[variables('vmName')]", "adminUsername": "[parameters('adminUserName')]", "linuxConfiguration": { "disablePasswordAuthentication": "true", "ssh": { "publicKeys": [ { "path": "[variables('sshKeyPath')]", "keyData": "[parameters('sshKeyData')]" } ] } } }, "storageProfile": { "imageReference": { "publisher": "[variables('imagePublisher')]", "offer": "[variables('imageOffer')]", "sku": "[variables('ubuntuOSVersion')]", "version": "latest" }, "osDisk": { "createOption": "FromImage" } }, "networkProfile": { "networkInterfaces": [ { "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]" } ] } } } ...
В parameters
шаблона добавляем параметр с указанием диска:
... "vmdatadiskname": { "type": "string", "metadata": { "description": "Existing data disk resource ID to be attached to VM." } } ...
В файле параметров указываем значение:
... "vmdatadiskname": { "value": "/subscriptions/0a4f2b9c-***-***-***-40b17ef8c3ab/resourceGroups/europe-jm/providers/Microsoft.Compute/disks/jm-monitoring-data-disk-dev" } ...
К ресурсу виртуальной машины добавляем подключение диска:
... "dataDisks": [ { "lun": 0, "createOption": "Attach", "caching": "None", "diskSizeGB": 10, "managedDisk": { "id": "[parameters('vmdatadiskname')]" } } ] ...
В результате – ресурс виртуальной машины полностью теперь будет выглядеть так:
... { "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')]" }, "osProfile": { "computerName": "[variables('vmName')]", "adminUsername": "[parameters('adminUserName')]", "linuxConfiguration": { "disablePasswordAuthentication": "true", "ssh": { "publicKeys": [ { "path": "[variables('sshKeyPath')]", "keyData": "[parameters('sshKeyData')]" } ] } } }, "storageProfile": { "imageReference": { "publisher": "[variables('imagePublisher')]", "offer": "[variables('imageOffer')]", "sku": "[variables('ubuntuOSVersion')]", "version": "latest" }, "osDisk": { "createOption": "FromImage" }, "dataDisks": [ { "lun": 0, "createOption": "Attach", "caching": "None", "diskSizeGB": 10, "managedDisk": { "id": "[parameters('vmdatadiskname')]" } } ] }, "networkProfile": { "networkInterfaces": [ { "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]" } ] } } } ...
Сохраняем в репозиторий, запускаем provision в Jenkins на уже развёрнутую группу ресурсов – ARM должен обновить вирутальную машину и подключить к ней диск:
[simterm]
$ git status On branch master Your branch is up-to-date with 'origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: jm-monitoring/jm-monitoring.json ... $ git add jm-monitoring/jm-monitoring.json && git commit -m "data disk attach" && git push
[/simterm]
Билд в Jenkins:
... info: Resource 'jm-monitoring-dev-vm' of type 'Microsoft.Compute/virtualMachines' provisioning status is Running info: Resource 'jm-monitoring-dev-nic' of type 'Microsoft.Network/networkInterfaces' provisioning status is Succeeded info: Resource 'jm-monitoring-dev-ip' of type 'Microsoft.Network/publicIPAddresses' provisioning status is Succeeded info: Resource 'jm-monitoring-dev-vnet' of type 'Microsoft.Network/virtualNetworks' provisioning status is Succeeded info: Resource 'jm-monitoring-dev-nsg' of type 'Microsoft.Network/networkSecurityGroups' provisioning status is Succeeded ... info: Resource 'jm-monitoring-dev-vm' of type 'Microsoft.Compute/virtualMachines' provisioning status is Succeeded info: Resource 'jm-monitoring-dev-nic' of type 'Microsoft.Network/networkInterfaces' provisioning status is Succeeded info: Resource 'jm-monitoring-dev-ip' of type 'Microsoft.Network/publicIPAddresses' provisioning status is Succeeded info: Resource 'jm-monitoring-dev-vnet' of type 'Microsoft.Network/virtualNetworks' provisioning status is Succeeded info: Resource 'jm-monitoring-dev-nsg' of type 'Microsoft.Network/networkSecurityGroups' provisioning status is Succeeded data: DeploymentName : jenkins-jm-monitoring-azure-ENV-DEV-provisioning-14 data: ResourceGroupName : jm-monitoring-dev data: ProvisioningState : Succeeded data: Timestamp : Thu Oct 12 2017 09:38:01 GMT+0000 (UTC) data: Mode : Incremental ... info: [1mgroup deployment create[22m command [1m[32mOK[39m[22m [Pipeline] } [Pipeline] // stage [Pipeline] } $ docker stop --time=1 31c06c78359ca60182e19af5cd7df161e07c4da4cfe95b3500a504a1f2b4a614 $ docker rm -f 31c06c78359ca60182e19af5cd7df161e07c4da4cfe95b3500a504a1f2b4a614 [Pipeline] // withDockerContainer [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS
Проверяем data-диск сервера:
[simterm]
bash-4.3# az vm show --resource-group jm-monitoring-dev --name jm-monitoring-dev-vm --query '{storageProfile:storageProfile.dataDisks}' { "storageProfile": [ { "caching": "None", "createOption": "Attach", "diskSizeGb": 10, "image": null, "lun": 0, "managedDisk": { "id": "/subscriptions/0a4f2b9c-***-***-***-40b17ef8c3ab/resourceGroups/europe-jm/providers/Microsoft.Compute/disks/jm-monitoring-data-disk-dev", "resourceGroup": "europe-jm", "storageAccountType": "Standard_LRS" }, "name": "jm-monitoring-data-disk-dev", "vhd": null } ] }
[/simterm]
diskSizeGB
– надо бы тоже вынести в параметры для production.
Логинимся на сервер, проверяем там:
[simterm]
admin@jm-monitoring-dev-vm:~$ lsblk /dev/sdc NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdc 8:32 0 10G 0 disk └─sdc1 8:33 0 10G 0 part
[/simterm]
ОК – диск есть, всё хорошо.
Ansible
Монтирование диска
Установка Prometheus и роли описаны в посте Ansible: роли для Docker Compose, Prometheus и node_exporter.
Аналогичную задачу – монтирование диска из Ansible – описывал в посте Ansible: RTFM Jenkins provision.
Имя раздела и каталог монтирования вынесем в переменные роли prometheus
.
В файл jm-monitoring/ansible/jm-monitoring/roles/prometheus/vars/main.yml
добавляем две переменные:
prometheus_data_volume: "/dev/sdc1" prometheus_data_mount_path: "/prometheus-data"
Далее, в файле jm-monitoring/ansible/jm-monitoring/roles/prometheus/tasks/main.yml
добавляем создание каталога и монтирование диска:
... - name: Create "{{ prometheus_data_mount_path }}" directory file: path: "{{ prometheus_data_mount_path }}" owner: root group: root mode: 0755 state: directory - name: Mount volume "{{ prometheus_data_volume }}" mount: path: "{{ prometheus_data_mount_path }}" src: "{{ prometheus_data_volume }}" state: mounted fstype: ext4 ...
Сохраняем изменения в репозиторий:
[simterm]
$ git status ... modified: jm-monitoring/ansible/jm-monitoring/roles/prometheus/tasks/main.yml modified: jm-monitoring/ansible/jm-monitoring/roles/prometheus/vars/main.yml
[/simterm]
Запускаем Jenkins билд:
... TASK [prometheus : Create "/prometheus-data" directory] *********************** sudo -H -S -n ok: [dev.monitoring.domain.ms] TASK [prometheus : Mount EBS "/dev/sdc1"] ************************************** sudo -H -S -n changed: [dev.monitoring.domain.ms] TASK [prometheus : Start Prometheus service] *********************************** sudo -H -S -n ok: [dev.monitoring.domain.ms]
Обновление Prometheus docker-compose.yml
Последний шаг – подключить каталог /prometheus-data/
с данными к Docker-контейнеру, в котором запускается Prometheus.
По умолчанию – он хранит данные в каталоге /prometheus/
:
[simterm]
root@jm-monitoring-dev-vm:~# docker exec -ti prometheus_prometheus_1 ls -l /prometheus total 4576 drwx------ 2 root root 4096 Oct 2 11:42 00 drwx------ 2 root root 4096 Oct 3 19:47 01 drwx------ 2 root root 4096 Oct 2 15:17 02 drwx------ 2 root root 4096 Oct 2 11:45 03 ...
[/simterm]
Запуск описан в файле jm-monitoring/ansible/jm-monitoring/roles/prometheus/files/docker-compose.yml
.
Что бы использовать в нём переменные ({{ prometheus_data_mount_path }}
) – перемещаем его в templates
:
[simterm]
$ mkdir jm-monitoring/ansible/jm-monitoring/roles/prometheus/templates $ mv jm-monitoring/ansible/jm-monitoring/roles/prometheus/files/docker-compose.yml jm-monitoring/ansible/jm-monitoring/roles/prometheus/templates/docker-compose.yml.j2
[/simterm]
Обновляем jm-monitoring/ansible/jm-monitoring/roles/prometheus/templates/docker-compose.yml.j2
– добавляем монтирование volume /prometheus-data/
с хоста в каталог /prometheus/
контейнера:
version: '2' services: prometheus: network_mode: "host" image: prom/prometheus expose: - 9090 ports: - 9090:9090 volumes: - /etc/prometheus/:/etc/prometheus/ - {{ prometheus_data_mount_path }}:/prometheus
Обновляем jm-monitoring/ansible/jm-monitoring/roles/prometheus/tasks/main.yml
– в задаче Copy compose file меняем Ansible модуль copy
на template
:
... - name: Copy compose file template: src: templates/docker-compose.yml.j2 dest: "{{ prometheus_home }}/docker-compose.yml" owner: "{{ prometheus_user }}" group: "{{ prometheus_group }}" mode: 0644 ...
Повторяем билд Jenkins и проверяем данные в каталоге на хосте мониторинга:
[simterm]
root@jm-monitoring-dev-vm:~# ls -l /prometheus-data/ total 36 drwxr-xr-x 2 root root 4096 Oct 12 10:54 archived_fingerprint_to_metric drwxr-xr-x 2 root root 4096 Oct 12 10:54 archived_fingerprint_to_timerange -rw-r--r-- 1 root root 0 Oct 12 10:54 DIRTY drwxr-xr-x 2 root root 4096 Oct 12 10:54 labelname_to_labelvalues drwxr-xr-x 2 root root 4096 Oct 12 10:54 labelpair_to_fingerprints drwx------ 2 root root 16384 Oct 12 10:27 lost+found -rw-r--r-- 1 root root 2 Oct 12 10:54 VERSION
[/simterm]
Проверяем сам контейнер:
[simterm]
# docker inspect prometheus_prometheus_1 ... "Mounts": [ { "Type": "bind", "Source": "/prometheus-data", "Destination": "/prometheus", "Mode": "rw", "RW": true, "Propagation": "rprivate" }, { "Type": "bind", "Source": "/etc/prometheus", "Destination": "/etc/prometheus", "Mode": "rw", "RW": true, "Propagation": "rprivate" } ], ...
[/simterm]
Данные node_exporter
в самом Prometheus:
Готово.
Ссылки по теме
Azure: Azure Resource Manager provisioning и Jenkins в Docker
Azure: подключение дополнительного диска к VM и миграция Jenkins
Azure: provisioning с Resource Manager, Jenkins и Groovy