Задача — добавить подключение 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





