Продолжение сетапа из AWS: создание стека в AWS – bash-скрипт и CloudFormation шаблон.
Далее потребуется добавить Ansible playbook и роли для настройки хоста.
В принципе — ничего особенно отличного от того, что описано в постах серии RTFM migration, например — Ansible: миграция RTFM 2.9 – монтирование EBS и настройка NGINX на Bastion.
Что надо будет выполнить:
- добавить роль
common
, в которой будет выполняться:- монтирование data-диска (EBS)
- установка набора утилит —
mailutils
,curl
,dnsutils
,telnet
,unzip
- установка
hostname
- копирование
.bashrc
и.vimrc
на хост - настройка таймзоны
- настройка почтового ящика
root
- роль
exim
для настройки отправки уведомлений - роль
nginx
, понятно для чего (пока без SSL) - роль
manala.logrotate
- роль
jnv.unattended-upgrades
А далее можно будет приступить к созданию ролей для самого стека Prometheus.
Содержание
hosts
Начинаем с создания файла hosts
.
Имени для сервера пока нет, поэтому используем IP:
[all:vars] data_volume_mount_path="/data" [btrm-mon-dev] 52.***.***.233 [btrm-mon-dev:vars] data_volume_id="/dev/xvdb" set_hostname="btrm-mon-dev"
Тут:
data_volume_mount_path
, которая будет указывать на точку монтирования подключаемого EBSdata_volume_id
— сам диск EBS, который подключается к системе CloudFormationset_hostname
— будет задано в качестве имени хоста
playbook
Теперь создадим файл плейбука — btrm-monitoring-ansible-provision.yml
, пока только с одной ролью common
:
- hosts: all become: true roles: - role: common
роль common
Создаём роль common — добавляем каталоги:
[simterm]
$ mkdir -p roles/common/{tasks,files}
[/simterm]
В roles/common/tasks
создаём файл main.yml
с одной задачей — вызывать модуль ping
:
- name: Execute ping ping:
Время тестить!
Вызываем ansible-playbook
:
[simterm]
$ ansible-playbook -i hosts --limit=btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem btrm-monitoring-ansible-provision.yml PLAY [all] **** TASK [Gathering Facts] **** fatal: [52.***.***.233]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey).\r\n", "unreachable": true} to retry, use: --limit @/home/username/Work/btrm-monitoring/ansible/btrm-monitoring-ansible-provision.retry PLAY RECAP **** 52.***.***.233 : ok=0 changed=0 unreachable=1 failed=0
[/simterm]
ОК, отлично.
Имя пользователя. На хосте запущен AWS AMI с Debian, добавляем admin
как ansible_ssh_user
в hosts
:
[all:vars] data_volume_mount_path="/data" ansible_ssh_user=admin ...
Повторяем:
[simterm]
$ ansible-playbook -i hosts --limit=btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem btrm-monitoring-ansible-provision.yml PLAY [all] **** TASK [Gathering Facts] **** ok: [52.***.***.233] TASK [common : Execute ping] **** ok: [52.***.***.233] PLAY RECAP **** 52.***.***.233 : ok=2 changed=0 unreachable=0 failed=0
[/simterm]
Работает.
Хорошо, поехали дальше — добавляем задачи для роли common
.
parted
Первой задачей будет создать раздел на диске /dev/xvdb
, если его ещё нет.
Для этого надо будет установить саму утилиту parted
, а раз так — то установим сразу всё необходимое.
Обновляем roles/common/tasks/main.yml
, убираем ping
, добавляем задачи — обновить кеш apt
, потом обновить все установленные пакеты, потом установить набор дефолтных утилит:
- name: Upgrade all packages to the latest version apt: update_cache: yes upgrade: yes - name: Install common packages package: name: "{{ item }}" state: present with_items: - mailutils - curl - dnsutils - telnet - unzip - parted
Третьей задачей вызываем parted
и создаём раздел номер 1 на диске из переменной data_volume_id
:
... - name: Create partiniom on {{ data_volume_id }} parted: device: "{{ data_volume_id }}" number: 1 state: present
Проверяем разделы на хосте сейчас:
[simterm]
$ ansible -i hosts btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem -a lsblk 52.***.***.233 | SUCCESS | rc=0 >> NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 8G 0 disk └─xvda1 202:1 0 8G 0 part / xvdb 202:16 0 8G 0 disk
[/simterm]
Проверяем синтаксис плейбука:
[simterm]
$ ansible-playbook -i hosts --syntax-check --limit=btrm-mon-dev btrm-monitoring-ansible-provision.yml playbook: btrm-monitoring-ansible-provision.yml
[/simterm]
И запускаем применение common
:
[simterm]
$ ansible-playbook -i hosts --limit=btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem btrm-monitoring-ansible-provision.yml PLAY [all] **** TASK [Gathering Facts] **** ok: [52.***.***.233] TASK [common : Upgrade all packages to the latest version] **** [WARNING]: Could not find aptitude. Using apt-get instead. ok: [52.***.***.233] TASK [common : Install common packages] **** changed: [52.***.***.233] => (item=mailutils) ok: [52.***.***.233] => (item=curl) changed: [52.***.***.233] => (item=dnsutils) changed: [52.***.***.233] => (item=telnet) changed: [52.***.***.233] => (item=unzip) changed: [52.***.***.233] => (item=parted) TASK [common : Create partition on /dev/xvdb] **** changed: [52.***.***.233] PLAY RECAP **** 52.***.***.233 : ok=4 changed=2 unreachable=0 failed=0
[/simterm]
Проверяем разделы теперь:
[simterm]
$ ansible -i hosts btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem -a lsblk 52.***.***.233 | SUCCESS | rc=0 >> NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 8G 0 disk └─xvda1 202:1 0 8G 0 part / xvdb 202:16 0 8G 0 disk └─xvdb1 202:17 0 8G 0 part
[/simterm]
Раздел 1 на диске xvdb
создан — /dev/xvdb1
.
filesystem
Далее — создаём файловую систему на /dev/xvdb1
, используем модуль filesystem
:
... - name: Create a ext4 filesystem on /dev/{{ data_volume_id }}1 filesystem: fstype: ext4 dev: "{{ data_volume_id }}1"
Запускаем, проверяем:
[simterm]
$ ansible-playbook -i hosts --limit=btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem btrm-monitoring-ansible-provision.yml ... TASK [common : Create partition on /dev/xvdb] **** ok: [52.***.***.233] TASK [common : Create a ext4 filesystem on /dev/xvdb1] **** changed: [52.***.***.233] PLAY RECAP **** 52.***.***.233 : ok=5 changed=1 unreachable=0 failed=0
[/simterm]
mount
Следующим шагом — надо создать каталог /data
, и смонтировать в него раздел /dev/xvdb1
.
Используем file
для создания каталога и mount
— для монтирования диска:
... - name: Create {{ data_volume_mount_path }} directory file: path: "{{ data_volume_mount_path }}" state: directory mode: 0755 recurse: yes - name: Mount data-volume {{ data_volume_id }}1 to {{ data_volume_mount_path }} mount: path: "{{ data_volume_mount_path }}" src: "{{ data_volume_id }}1" state: mounted fstype: ext4
Запускаем:
[simterm]
$ ansible-playbook -i hosts --limit=btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem btrm-monitoring-ansible-provision.yml ... TASK [common : Create /data directory] **** changed: [52.***.***.233] TASK [common : Mount data-volume /dev/xvdb1 to /data] **** changed: [52.***.***.233] PLAY RECAP **** 52.***.***.233 : ok=7 changed=2 unreachable=0 failed=0
[/simterm]
Проверяем:
[simterm]
$ ansible -i hosts btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem -a "ls -l /data" 52.***.***.233 | SUCCESS | rc=0 >> total 16 drwx------ 2 root root 16384 тра 10 15:29 lost+found
[/simterm]
hostname
hostname
Следующим шагом надо поменять имя хоста на значение, указанное в переменной set_hostname
нашего файла hosts
.
Кроме того, что бы задать имя хоста — надо отредактировать /etc/hosts
, но т.к. это AWS EC2 — то /etc/hosts
будет перезаписано, ибо при перезагрузке задаётся стартап-скриптами (см. Update Etc Hosts). Что бы отключить это — надо изменить файл /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg
и значение manage_etc_hosts
в нём с True на False.
Добавляем ещё три задачи — задать имя хоста, добавить его в /etc/hosts
для резолва на 127.0.0.1, и отключить обновление /etc/hosts
:
... - name: Set hostname hostname: name: "{{ set_hostname }}" - name: Add hostname to /etc/hosts lineinfile: dest: /etc/hosts regexp: '^127\.0\.0\.1[ \t]+localhost' line: "127.0.0.1 localhost {{ set_hostname }}" state: present - name: Update /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg lineinfile: dest: /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg regexp: '^manage_etc_hosts: true' line: "manage_etc_hosts: false" state: present
Проверяем имя сейчас:
[simterm]
$ ansible -i hosts btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem -a hostname 52.***.***.233 | SUCCESS | rc=0 >> ip-10-0-1-82
[/simterm]
Запускаем:
[simterm]
$ ansible-playbook -i hosts --limit=btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem btrm-monitoring-ansible-provision.yml ... TASK [common : Set hostname] **** changed: [52.***.***.233] TASK [common : Add hostname to /etc/hosts] **** changed: [52.***.***.233] TASK [common : Update /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg] **** changed: [52.***.***.233] PLAY RECAP **** 52.***.***.233 : ok=10 changed=4 unreachable=0 failed=0
[/simterm]
Проверяем сейчас:
[simterm]
$ ansible -i hosts btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem -a hostname 52.***.***.233 | SUCCESS | rc=0 >> btrm-mon-dev
[/simterm]
Отлично.
timezone
Время выставляем с помощью модуля timezone
:
... - name: Set timezone to Europe/Kiev timezone: name: Europe/Kiev
root mail
Настраиваем почту для root
.
В файл плейбука btrm-monitoring-ansible-provision.yml
добавляем блок переменных и переменную notify_email
:
- hosts: all vars: notify_email: [email protected] ...
В roles/common/tasks/main.yml
добавляем обновление /etc/aliases
и вызов newaliases
:
... - name: Change root mailbox lineinfile: dest: /etc/aliases regexp: '^root: ' line: "root: {{ notify_email }}" state: present - name: Update mail aliases shell: newaliases
Прочее
Последним для этой роли осталось скопировать .bashrc
и .vimrc
.
В roles/common/files/
добавляем файл bashrc
:
PS1='\t \[[\e[0;COLORm\]\u\[\e[m\]@\e[0;37m\]\h\[\e[m\] \[\e[1;34m\]\w\[\e[m\]]\[\e[0;31m\] \$\[\e[m\]\[\e[0;37m\] ' export EDITOR=vim # aliases alias osupgrade="sudo apt-get update && sudo apt-get upgrade"
И vimrc
:
set tabstop=4 set shiftwidth=4 set softtabstop=4 set expandtab set paste set smartindent syntax on
Добавляем их копирование:
... - name: Copy .bashrc to root copy: src: files/bashrc dest: /root/.bashrc - name: Set username color in /root/.bashrc replace: path: /root/.bashrc regexp: 'COLOR' replace: '31' - name: Copy .bashrc to admin copy: src: files/bashrc dest: /home/admin/.bashrc - name: Set username color in /home/admin/.bashrc replace: path: /home/admin/.bashrc regexp: 'COLOR' replace: '32' - name: Copy .vimrc to root copy: src: files/vimrc dest: /root/.vimrc - name: Copy .vimrc to admin copy: src: files/vimrc dest: /home/admin/.vimrc
Запускаем все последние изменения:
[simterm]
$ !416 ansible-playbook -i hosts --limit=btrm-mon-dev --private-key=../../aws-credentials/btrm-mon.pem btrm-monitoring-ansible-provision.yml ... TASK [common : Update /etc/cloud/cloud.cfg.d/01_debian_cloud.cfg] **** changed: [52.***.***.233] TASK [common : Change root mailbox] **** changed: [52.***.***.233] TASK [common : Update mail aliases] **** changed: [52.***.***.233] TASK [common : Set timezone to Europe/Kiev] **** changed: [52.***.***.233] TASK [common : Copy .bashrc to root] **** changed: [52.***.***.233] TASK [common : Set username color in /root/.bashrc] **** changed: [52.***.***.233] TASK [common : Copy .bashrc to admin] **** changed: [52.***.***.233] TASK [common : Set username color in /home/admin/.bashrc] **** changed: [52.***.***.233] TASK [common : Copy .vimrc to root] **** changed: [52.***.***.233] TASK [common : Copy .vimrc to admin] **** changed: [52.***.***.233] PLAY RECAP **** 52.***.***.233 : ok=19 changed=10 unreachable=0 failed=0
[/simterm]
ОК.
В целом с ролью common
на этом закончили.
роль exim
Ещё одной ролью будет роль для настройки exim
на отправку почты с хоста (учитывая, что это хост мониторинга — весьма актуальная задача).
Создаём каталоги:
[simterm]
$ mkdir -p roles/exim/{tasks,templates}
[/simterm]
Создаём два шаблона — mailname.j2
с указанием имени хоста, которое будет использоваться MTA при отправке писем, и update-exim4.conf.conf.j2
, в котором указываются настройки для Exim, что бы он мог отправлять почту «в мир (см. Exim: Mailing to remote domains not supported и Ansible: миграция RTFM 2.10 – Let’s Encrypt, NGINX SSL, hostname и exim).
Файл roles/exim/templates/mailname.j2
содержит одну строку:
{{ inventory_hostname }}
Файл update-exim4.conf.conf.j2
немного побольше:
dc_eximconfig_configtype='internet' dc_other_hostnames='"{{ inventory_hostname }}"' dc_local_interfaces='127.0.0.1 ; ::1' dc_readhost='' dc_relay_domains='' dc_minimaldns='false' dc_relay_nets='' dc_smarthost='' CFILEMODE='644' dc_use_split_config='false' dc_hide_mailname='' dc_mailname_in_oh='true' dc_localdelivery='mail_spool'
В файл roles/exim/tasks/main.yml
добавляем их добавление на сервер:
- name: Update Exim4 settings template: src=templates/update-exim4.conf.conf.j2 dest=/etc/exim4/update-exim4.conf.conf - name: Update mailname template: src=templates/mailname.j2 dest=/etc/mailname
И туда же добавляем ещё три задачи — смена FROM для root
, перезапуск exim
для применения новго файла настроек, и отправку тестового письма:
... - name: Change root FROM address lineinfile: dest: /etc/email-addresses regexp: '^root: ' line: "root: root@{{ inventory_hostname }}" state: present - name: Exim4 restart service: name=exim4 state=restarted - name: Send test email shell: echo "Eximt4 config complete" | mailx -s "{{ inventory_hostname }} Exim4 test" "{{ notify_email }}"
Добавляем роль exim
в плейбук:
- hosts: all vars: notify_email: [email protected] become: true roles: - role: common - role: exim
Запускаем, проверяем тестовое письмо:
роль nginx
В этой роли выполним установку NGINX и копирование файла настроек самого NGINX и файла виртуалхоста.
Для сервера уже добавлен домен, который будем использовать в NGINX — dev.monitor.domain.tld, он же добавлен в hosts
.
Создаём каталоги:
[simterm]
$ mkdir -p roles/nginx/{tasks,templates}
[/simterm]
В roles/nginx/templates/
добавляем nginx.conf.j2
:
user www-data; worker_processes auto; pid /var/run/nginx.pid; events { worker_connections 1024; } http { sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH !RC4"; ssl_session_cache shared:SSL:10m; ssl_session_timeout 1h; ssl_stapling on; ssl_stapling_verify on; ssl_dhparam /etc/nginx/dhparams.pem; server_tokens off; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; log_format proxy '[$time_local] $remote_addr - $server_name to: ' '$upstream_addr: $request upstream_response_time ' '$upstream_response_time msec $msec request_time $request_time'; gzip on; gzip_disable "msie6"; include /etc/nginx/conf.d/*.conf; }
Он нам нужен для настроек SSL и добавления ssl_dhparam
.
Сюда же добавляем шаблон для виртуахоста — roles/nginx/templates/dev.monitor.domain.tld.conf.j2
:
server { listen 80; server_name {{ inventory_hostname }}; access_log /var/log/nginx/{{ inventory_hostname }}-access.log proxy; error_log /var/log/nginx/{{ inventory_hostname }}-error.log warn; location / { root html; index index.html index.htm; } }
Он пока минимальный, SSL и upstream добавим позже.
Добавляем задачи — в файле roles/nginx/tasks/main.yml
выполняем установку NGINX, замену его конфига, генерацию ключа Diffie Hellman, копирование конфига виртуалхоста и перезагрузку конфигов NGINX:
- name: Install Nginx package: name: nginx state: latest - name: Replace NGINX config template: src=templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf - name: Generate dhparams shell: openssl dhparam -out /etc/nginx/dhparams.pem 2048 args: creates: /etc/nginx/dhparams.pem - name: Add NGINX {{ inventory_hostname }} virtualhost config template: src=templates/{{ inventory_hostname }}.conf.j2 dest=/etc/nginx/conf.d/{{ inventory_hostname }}.conf - name: Service NGINX reload service: name=nginx state=restarted
В btrm-monitoring-ansible-provision.yml
добавляем роль nginx
:
... roles: - role: common - role: exim - role: nginx
Запускаем, проверяем:
[simterm]
$ curl -I dev.monitor.domain.com HTTP/1.1 200 OK Server: nginx Date: Mon, 14 May 2018 11:39:34 GMT ...
[/simterm]
Отлично.
роль logrotate
Тут всё просто — используем готовую роль из Ansible Galaxy — manala.logrotate
.
В btrm-monitoring-ansible-provision.yml
добавляем:
... ... - role: manala.logrotate manala_logrotate_configs: - file: nginx config: - /var/log/nginx/*.log: - size: 100M - missingok - rotate: 5 - compress - delaycompress: - notifempty - create: 0640 www-data adm - sharedscripts - daily - postrotate systemctl reload nginx.service - endscript
Создаём файл requirements.yml
, добавляем зависимость:
- src: manala.logrotate
роль unattended-upgrades
Аналогично с ролью unattended-upgrades
— используем jnv.unattended-upgrades
, добавляем её в requirements.yml
:
- src: manala.logrotate - src: jnv.unattended-upgrades
И в btrm-monitoring-ansible-provision.yml
, с настройками:
... - role: jnv.unattended-upgrades unattended_mail: "{{ notify_email }}" unattended_automatic_reboot: true unattended_automatic_reboot_time: 05:00 unattended_clean_interval: 10
Загружаем роли:
[simterm]
$ ansible-galaxy install —ignore-certs -r requirements.yml
[/simterm]
И запускаем выполнение плейбука с последними обновлениями:
[simterm]
$ ansible-playbook -i hosts —limit=btrm-mon-dev —private-key=../../aws-credentials/btrm-mon.pem btrm-monitoring-ansible-provision.yml
[/simterm]
Проверяем:
[simterm]
root@btrm-mon-dev:/home/admin# cat /etc/apt/apt.conf.d/50unattended-upgrades | grep Upgr // Unattended-Upgrade::Origins-Pattern controls which packages are Unattended-Upgrade::Origins-Pattern { Unattended-Upgrade::Package-Blacklist { Unattended-Upgrade::Mail "[email protected]"; Unattended-Upgrade::Automatic-Reboot "true"; Unattended-Upgrade::Automatic-Reboot-Time "05:00";
[/simterm]
Готово.
В следующей части добавим роли для запуска самого Prometheus, Alertmanager и Grafana, потом к ним добавим екпортёры и настроим первые алерты.