Ansible: миграция RTFM 2.11 – хост Services – установка PHP, PHP-FPM

Автор: | 24/03/2018

Продолжаем миграцию.

Предыдущие посты:

  1. AWS: миграция RTFM 2.1 – CloudFormation для EC2 c Jenkins
  2. Ansible: миграция RTFM 2.2 – RTFM Jenkins provision
  3. AWS: миграция RTFM 2.3 – инфраструктура для RTFM и создание CloudFormation шаблона – VPC, subnets, EC2
  4. Jenkins: миграция RTFM 2.4 – Jenkins Pipeline для CloudFormation RTFM стека
  5. AWS: миграция RTFM 2.5 – настройка NAT на Bastion EC2 как замена NAT Gateway
  6. Jenkins: миграция RTFM 2.6 – Jenkins Pipeline для Ansible
  7. AWS: миграция RTFM 2.7 – CloudFormation и Ansible – наcтройка NAT
  8. Ansible: миграция RTFM 2.8 – logrotate, unattended-upgrades и Let’s Encrypt для Bastion хоста
  9. Ansible: миграция RTFM 2.9 – монтирование EBS и настройка NGINX на Bastion
  10. Ansible: миграция RTFM 2.10 – Let’s Encrypt, NGINX SSL, hostname и exim

После последнего поста по теме – в конце февраля я сделал ещё несколько минорных изменений и по закончил по сути с хостом Bastion – добавил всякую мелочь в роль common, типа копирования .vimrc и настройки email для root, файл на начало написания этого поста выглядел так>>>.

Теперь можно приступить к настройке первого из “внутренних” серверов – начну с Services, т.к. он будет основным из всех трёх по количеству служб, которые на нём будут работать.

Сегодня планируется выполнить:

  • монтирование data-диска для EC2 Services
  • создать плейбук для Services, добавить общие роли
  • добавить роль для установки PHP-FPM

В целом схема сейчас вырисовывается такая:

(забегая наперёд: нет – пришлось прикручивать AWS EFS)

Получившаяся в результате роль есть в Гитхабе, пока в отдельном бранче, тут>>>, как и другие изменения, которые были сделаны в процессе написания этого поста.

data-disk

Сейчас EBS подключен (во время создания CloudFormation стека), но раздела на нём ещё нет:

[simterm]

admin@ip-10-0-129-186:~$ lsblk 
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]

admin@ip-10-0-129-186:~$ sudo -s
root@ip-10-0-129-186:/home/admin# echo ';' | sfdisk /dev/xvdb
Checking that no-one is using this disk right now ... OK

Disk /dev/xvdb: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

>>> Created a new DOS disklabel with disk identifier 0x3b80211b.
/dev/xvdb1: Created a new partition 1 of type 'Linux' and of size 8 GiB.
/dev/xvdb2: Done.

New situation:

Device     Boot Start      End  Sectors Size Id Type
/dev/xvdb1       2048 16777215 16775168   8G 83 Linux

The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

[/simterm]

Создаём файловую систему:

[simterm]

root@ip-10-0-129-186:/home/admin# mkfs.ext4 /dev/xvdb1
mke2fs 1.43.4 (31-Jan-2017)
Creating filesystem with 2096896 4k blocks and 524288 inodes
Filesystem UUID: 88efc795-f541-470e-808e-df2e48534061
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done

[/simterm]

Проверяем:

[simterm]

root@ip-10-0-129-186:/home/admin# lsblk 
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]

С диском на этом пока всё – остальное выполнит Ansbile.

Services inventory

Домен services.dev.rtfm.co.ua уже добавлен, и направлен на IP в приватной сети:

[simterm]

$ dig services.dev.rtfm.co.ua +short
10.0.129.186

[/simterm]

Пока – вручную, у регистратора, Freehost.com.ua, потом rtfm.co.ua мигрирует на AWS Route53, и IP будет задаваться через CloudFormation.

Теперь добавим Services хост в inventory файл – hosts:

...
[rtfm-services-dev]
services.dev.rtfm.co.ua
...

Т.к. доступ к нему будет только через Bastion хост – добавим переменную ansible_ssh_common_args, подробнее – в посте Ansible: подключение в приватную сеть через Bastion хост:

...
[rtfm-services-dev:vars]
ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q [email protected] -i {{ host_key }}"'
data_volume_id="/dev/xvdb1" 
set_hostname="rtfm-services-dev"

В data_volume_id – указываем разел data-диска, см. тут>>>, а в set_hostname – имя хоста, см. тут>>>.

Проверяем:

[simterm]

$ ansible -i hosts rtfm-services-dev --extra-vars host_key="/home/setevoy/Work/RTFM/Bitbucket/aws-credentials/rtfm-dev.pem" --private-key=/home/setevoy/Work/RTFM/Bitbucket/aws-credentials/rtfm-dev.pem -m ping
services.dev.rtfm.co.ua | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

[/simterm]

Через --extra-vars передаём переменную, в которой указывается ключ для авторизации на серверах.

ОК, подключение есть – можно создавать плейбук.

Services playbook

Начало плейбука будет аналогично уже созданному для Bastion – добавляем в него роль common, которая выполнит настройку хоста, можно его вообще скопировать:

[simterm]

$ cp rtfm-blog-ansible-bastion-provision.yml rtfm-blog-ansible-services-provision.yml

[/simterm]

Далее в Jenkins будет отдельная задача, в которой через переменную ${ansiblePlaybookFile} будет передаваться имя файла плейбука rtfm-blog-ansible-services-provision.yml.

Убираем лишнее, оставляем роли:

  • common: подключение data-диска, установка пакетов типа curl, mailx, настройка имени хоста и т.д.
  • exim: для отправки уведомлений
  • amplify: NGINX Amplify мониторинг – хотя NGINX тут нет, но будет выводить данные о системе + потом добавится PHP-FPM, а Amplify его умеет
  • manala.logrotate: для ротации логов, только меняем nginx на mysql
  • jnv.unattended-upgrades: для апдейтов системы

Получается так:

- hosts: all
  become:
    true
  roles:
    - role: common
      notify_email: [email protected]
    - role: exim
    - role: amplify
    - role: manala.logrotate
      manala_logrotate_configs:
        - file: mysql
          config:
            - /var/log/mysql/*.log:
              - size: 100M
              - missingok
              - rotate: 5
              - compress
              - delaycompress:
              - notifempty
              - create: 0640 mysql root
              - sharedscripts
              - daily
              - postrotate
                  systemctl reload mysql.service
              - endscript
    - role: jnv.unattended-upgrades
      unattended_mail: [email protected]
      unattended_automatic_reboot: true
      unattended_automatic_reboot_time: 05:00
      unattended_clean_interval: 10

Ansible: условия выполнения – register и when

Для роли amplify тут надо сделать небольшое изменение: т.к. на Services не будет NGINX и каталога /etc/nginx/conf.d, то задача Copy stub_status.conf будет фейлиться и “ронять” весь провижен.

Что бы избежать этого – обновляем роль amplify, файл roles/amplify/tasks/main.yml, добавляем задачу Check /etc/nginx/conf.d directory в которой используем `register` для создания переменной nginx_conf_d:

...
- name: Check /etc/nginx/conf.d directory
  stat:
    path: /etc/nginx/conf.d
  register: nginx_conf_d
...

Следующей задачей тут добавим немного вывода на консоль:

...
- debug:
    msg: "/etc/nginx/conf.d found"
  when:  nginx_conf_d.stat.islnk is defined
...

Собственно – вот условие выполнения:

when: nginx_conf_d.stat.islnk is defined

Если каталог найден – то задача выполняется.

Аналогично применяем условие в Copy stub_status.conf:

...
- name: Copy stub_status.conf
  copy:
    src: files/stub_status.conf
    dest: /etc/nginx/conf.d/stub_status.conf
  when: nginx_conf_d.stat.islnk is defined
...

Проверяем синтаксис:

[simterm]

$ ansible-playbook --syntax-check --limit=rtfm-services-dev --private-key=../../Bitbucket/aws-credentials/rtfm-dev.pem rtfm-blog-ansible-services-provision.yml

playbook: rtfm-blog-ansible-services-provision.yml

[/simterm]

Что бы не указывать сейчас host_key каждый раз – закинем его в переменную (в Jenkins будет в параметрах):

[simterm]

$ HOST_KEY=”/home/setevoy/Work/RTFM/Bitbucket/aws-credentials/rtfm-dev.pem”

[/simterm]

И ключ для Amplify-агента:

[simterm]

$ API_KEY=967c***ce31

[/simterm]

Запускаем выполнение:

[simterm]

$ ansible-playbook --limit=rtfm-services-dev --extra-vars "host_key=$HOST_KEY api_key=$API_KEY" --private-key=$HOST_KEY rtfm-blog-ansible-services-provision.yml

[/simterm]

Данные в NGINX Amplify:

Ansible PHP и PHP-FPM

Одним из основных сервисов на Services будет PHP-FPM.

Конфиги будут храниться на подключаемом data-диске, поэтому в роль Ansible надо добавить только его установку и копирование дефолтного файла настроек.

Создадим свою роль для установки и настройки PHP и PHP-FPM:

[simterm]

$ mkdir -p roles/php-fpm/{tasks,templates,files}

[/simterm]

Добавляем main.yml, описываем установку пакетов:

- name: Install PHP related packages
  apt: name={{item}} state=present
  with_items:
       - php
       - php-mysql  
       - php-fpm
       - php-curl

Актуальная на сегодня версия PHP – 7, все пакеты установятся для неё.

Добавляем роль в rtfm-blog-ansible-services-provision.yml:

...
    - role: php-fpm

Запускаем для проверки, потом добавим остальное:

[simterm]

$ !801
ansible-playbook --limit=rtfm-services-dev --extra-vars "host_key=$HOST_KEY api_key=$API_KEY" --private-key=$HOST_KEY rtfm-blog-ansible-services-provision.yml
...
TASK [php-fpm : Install PHP related packages] ****
changed: [services.dev.rtfm.co.ua] => (item=[u'php', u'php-mysql', u'php-fpm', u'php-curl'])

PLAY RECAP ****
services.dev.rtfm.co.ua    : ok=44   changed=12   unreachable=0    failed=0

[/simterm]

ОК, проверяем на хосте:

[simterm]

16:41:51 [root@rtfm-services-dev /home/admin] # php --version
PHP 7.0.27-0+deb9u1 (cli) (built: Jan  5 2018 13:51:52) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.0.27-0+deb9u1, Copyright (c) 1999-2017, by Zend Technologies

[/simterm]

Проверяем порты:

[simterm]

16:46:43 [root@rtfm-services-dev /home/admin] # netstat -anp | grep php
unix  2      [ ACC ]     STREAM     LISTENING     152742   29175/php-fpm: mast  /run/php/php7.0-fpm.sock
unix  3      [ ]         STREAM     CONNECTED     152741   29175/php-fpm: mast  
unix  3      [ ]         STREAM     CONNECTED     152740   29175/php-fpm: mast

[/simterm]

Сейчас PHP-FPM слушает только локальные сокеты, но т.к. NGINX и PHP у нас на разных хостах – надо включить TCP порты.

Добавляем конфиг для пула rtfm-dev, создаём каталог в /data, который находится на подключенном EBS и где будут храниться все конфиги хостов:

[simterm]

# mkdir /data/data-php-fpm.d

[/simterm]

В нём добавляем конфиг /data/data-php-fpm.d/dev.rtfm.co.ua.conf:

[dev.rtfm.co.ua]

user = rtfm
group = rtfm

listen = 10.0.129.188:9000
listen.allowed_clients = 10.0.1.81

listen.owner = www-data
listen.group = www-data

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
;pm.process_idle_timeout = 10s;
;pm.max_requests = 500
catch_workers_output = yes
chdir = /
pm.status_path = /status

slowlog = /var/log/php/dev.rtfm.co.ua-php-slow.log
php_flag[display_errors] = off
php_admin_value[display_errors] = 'stderr'
php_admin_value[error_log] = /var/log/php/dev.rtfm.co.ua-php-error.log
php_admin_flag[log_errors] = on
php_admin_value[session.save_path] = /var/lib/php/sessions/rtfm
php_admin_value[upload_max_filesize] = 64M
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/sessions

Тут сразу видно – чего не хватает в роли php-fpm:

  • на хосте Services нет пользователя rtfm
  • и нет каталога /var/log/php/
  • php7-fpm не использует конфиги из /data/data-php-fpm.d/

И тут загвоздка… Добавить создание пользователей можно через роль Ansible, но она у меня в Github-е, а светить всех пользователей – идея так себе.

Наверно решение будет передавать через --extra-vars Python-список, в который передавать список имён пользователей из параметров джобы Jenkins-а, а потом в цикле создавать их?

Попробуем.

Добавляем в roles/php-fpm/tasks/main.yml:

...
- name: Create PHP-FPM users
  user: name={{ item }}
  with_items:
    - "{{ php_users }}"

В rtfm-blog-ansible-services-provision.yml можно закомментировать всё, кроме - role: php-fpm, что бы не тратить время на нежуные пока операции.

Запускаем с добавлением переменной php_users, в которой списком передаём двух (пока) пользователей:

[simterm]

$ ansible-playbook --limit=rtfm-services-dev --extra-vars "host_key=$HOST_KEY api_key=$API_KEY php_users=['rtfm','testuser']" --private-key=$HOST_KEY rtfm-blog-ansible-services-provision.yml
...
TASK [php-fpm : Create PHP-FPM users] ****
changed: [services.dev.rtfm.co.ua] => (item=rtfm)
changed: [services.dev.rtfm.co.ua] => (item=testuser)

[/simterm]

Проверяем на хосте:

[simterm]

17:11:50 [root@rtfm-services-dev /home/admin] # tail -2 /etc/passwd
rtfm:x:1001:1001::/home/rtfm:
testuser:x:1002:1002::/home/testuser:

[/simterm]

ОК, работает.

Вообще надо посмотреть в сторону того, что бы передавать все extra-vars через файл, который будет храниться в приватном репозитории Bibuket, как это происходит с ключами доступа для инстансов – см. Jenkins: миграция RTFM 2.6 – Jenkins Pipeline для Ansible: там в groovy-скриптах используется переменная ANSIBLE_BB_CREDENTIALS_REPO_URL, в которой передаётся Bitbuket репозиторий. Jenkins во время выполнения джобы клонирует этот репозиторий к себе, и использует из него ключи доступа.

Аналогично можно будет сделать для всех секретных переменных, но не сейчас. Ссылка на документацию тут>>>.

Возвращаемся к php-fpm.

Следующим надо добавить создание каталога /var/log/php/, в роль php-fpm добавляем:

- name: Create PHP-FPM logs directory
  file:
    path=/var/log/php
    state=directory

И теперь добавить *.conf файлы из каталога /data/data-php-fpm.d/ в /etc/php/7.0/fpm/php-fpm.conf.

Используем lineinfile:

...
- name: Add /data/data-php-fpm.d/ to /etc/php/7.0/fpm/php-fpm.conf
  lineinfile:
    dest: /etc/php/7.0/fpm/php-fpm.conf
    insertafter: '^include=/etc/php/7.0/fpm/pool.d/*.conf'
    line: 'include=/data/data-php-fpm.d/*.conf'
    state: present

Последним – перезапускаем php-fpm на хосте:

...
- name: php7.0-fpm restart
  service:
    name=php7.0-fpm
    state=restarted

Тут, кстати, сразу возможная бага в будущем: когда unattended-upgrades обновит PHP-FPM на хосте – имя сервиса поменяется, и при запуске Ansible на этой задаче упадёт провижен. Но будем решать проблемы по мере возникновения, пока хочется закончить с общей настройкой.

Проверяем:

[simterm]

$ !815
ansible-playbook --syntax-check --limit=rtfm-services-dev rtfm-blog-ansible-services-provision.yml

playbook: rtfm-blog-ansible-services-provision.yml

[/simterm]

Запускаем:

[simterm]

$ !819
ansible-playbook --limit=rtfm-services-dev --extra-vars "host_key=$HOST_KEY api_key=$API_KEY php_users=['rtfm','testuser']" --private-key=$HOST_KEY rtfm-blog-ansible-services-provision.yml

PLAY [all] ****

TASK [Gathering Facts] ****
ok: [services.dev.rtfm.co.ua]

TASK [php-fpm : Install PHP related packages] ****
ok: [services.dev.rtfm.co.ua] => (item=[u'php', u'php-mysql', u'php-fpm', u'php-curl'])

TASK [php-fpm : Create PHP-FPM users] ****
ok: [services.dev.rtfm.co.ua] => (item=rtfm)
ok: [services.dev.rtfm.co.ua] => (item=testuser)

TASK [php-fpm : Create PHP-FPM logs directory] ****
changed: [services.dev.rtfm.co.ua]

TASK [php-fpm : Add /data/data-php-fpm.d/ to /etc/php/7.0/fpm/php-fpm.conf] *****
changed: [services.dev.rtfm.co.ua]

TASK [php-fpm : php7.0-fpm restart] ****
changed: [services.dev.rtfm.co.ua]

PLAY RECAP ****
services.dev.rtfm.co.ua    : ok=6    changed=3    unreachable=0    failed=0

[/simterm]

Проверяем порты:

[simterm]

17:40:24 [root@rtfm-services-dev /home/admin] # netstat -anp | grep php
tcp        0      0 10.0.129.188:9000       0.0.0.0:*               LISTEN      5458/php-fpm: maste 
unix  2      [ ACC ]     STREAM     LISTENING     197923   5458/php-fpm: maste  /run/php/php7.0-fpm.sock
unix  3      [ ]         STREAM     CONNECTED     197921   5458/php-fpm: maste  
unix  3      [ ]         STREAM     CONNECTED     197922   5458/php-fpm: maste

[/simterm]

Пул php-fpm:

[simterm]

17:42:52 [root@rtfm-services-dev /home/admin] # ps aux | grep php-fpm
root      5458  0.0  3.2 295480 32840 ?        Ss   17:41   0:00 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf)
www-data  5459  0.0  0.7 295472  7376 ?        S    17:41   0:00 php-fpm: pool www
www-data  5460  0.0  0.7 295472  7376 ?        S    17:41   0:00 php-fpm: pool www
rtfm      5461  0.0  0.9 295692  9544 ?        S    17:41   0:00 php-fpm: pool dev.rtfm.co.ua
rtfm      5462  0.0  0.9 295692  9544 ?        S    17:41   0:00 php-fpm: pool dev.rtfm.co.ua

[/simterm]

Теперь проверим как NGINX работает с PHP-FPM.

На Services добавляем файл phpinfo.php:

[simterm]

# echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php

[/simterm]

Переходим на хост Bastion, обновляем конфиг /data/data-nginx.d/dev.rtfm.co.ua.conf, добавляем апстрим к Services и добавляем location php, приводим конфиг к такому виду:

upstream services-dev-php-fpm {
    server 10.0.129.188:9000;
}

server {

    listen 80;
    server_name dev.rtfm.co.ua;
    return 301 https://dev.rtfm.co.ua$request_uri;
}

server {

    server_name dev.rtfm.co.ua;

    listen 443 ssl;

    access_log /var/log/nginx/dev.rtfm.co.ua-access.log proxy;
    error_log /var/log/nginx/dev.rtfm.co.ua-error.log notice;

    ssl_certificate /data/letsencrypt/live/dev.rtfm.co.ua/fullchain.pem;
    ssl_certificate_key /data/letsencrypt/live/dev.rtfm.co.ua/privkey.pem;

    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    add_header X-Content-Type-Options nosniff;

    root /var/www/html;

    index index.html index.htm index.nginx-debian.html;

    location ~ /.well-known {
        allow all;
    }

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ .php$ { 
        include /etc/nginx/fastcgi_params; 
        fastcgi_index index.php; 
        fastcgi_pass services-dev-php-fpm; 
        fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name; 
    }
}

Проверяем, перезапускаем:

[simterm]

17:47:29 [root@rtfm-bastion-dev /etc/nginx] # nginx -t && service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok                                                                                                                                                                              
nginx: configuration file /etc/nginx/nginx.conf test is successful

[/simterm]

Проверяем:

[simterm]

$ curl -I https://dev.rtfm.co.ua/phpinfo.php
HTTP/1.1 504 Gateway Time-out
Server: nginx
Date: Sat, 24 Mar 2018 15:51:14 GMT
Content-Type: text/html
Content-Length: 176
Connection: keep-alive

[/simterm]

Эм… Ну, ОК, – не удивлён 🙂

Пробуем telnet:

[simterm]

17:53:18 [root@rtfm-bastion-dev /etc/nginx] # telnet 10.0.129.188 9000
Trying 10.0.129.188...
telnet: Unable to connect to remote host: Connection timed out

[/simterm]

И вспоминаем про Security Group в rtfm-blog-cf-template.json, где на Services с Bastion разрешён только порт 22:

...
    "ServicesSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      ...
        "GroupDescription" : "Enable SSH access from Bastion",
        "SecurityGroupIngress" : [

          {
            "IpProtocol" : "tcp",
            "FromPort" : "22",
            "ToPort" : "22",
            "SourceSecurityGroupId" : { "Ref" : "BastionSecurityGroup" },
            "Description": "Allow SSH from Bastion"
          }
...

Открываем быстренько доступ через AWS Console:

Пробуем telnet ещё раз:

[simterm]

17:55:47 [root@rtfm-bastion-dev /etc/nginx] # telnet 10.0.129.188 9000
Trying 10.0.129.188...
Connected to 10.0.129.188.
Escape character is '^]'.
Connection closed by foreign host.

[/simterm]

ОК, пробуем файл:

Гуд, работает.

И тут до меня дошло, что часть файлов-то будет обслуживаться NGINX, а часть – PHP-FPM. Более того – NGINX будет искать файлы сначала у себя, и вообще на бекенд должен отдавать только файлы *.php (налицо недостаточное планирование архитектуры заранее, хотя мысль о файлах мелькала, но решение отложил “на потом”).

А значит что? А значит, что у Services и Bastion должна быть общая расшаренная папка, в которой будут храниться файлы сайтов, какой-то EFS, примонтированный к обоим интансам. А EBS диски, которые подключены в /data – будут только содержать конфиги (и SSL ключи для Let’s Encrypt на Bastion).

Попробуем сейчас вручную, уже в следующий раз – надо обновить CloudFormation шаблоны – добавить 9000 порт и EFS.

Добавление EFS

Создаём новую Security Group для EFS, к которой есть доступ из групп Bastion-а и Services – она будет подключена к сетевому интерфейсу EFS:

Создаём EFS:

 

 

На Bastion и Services устанавливаем nfs-common:

[simterm]

# apt install nfs-common

[/simterm]

На обоих создаём каталог:

[simterm]

# mkdir /efswptest

[/simterm]

И на обоих подключаем EFS:

[simterm]

# mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 10.0.1.199:/ /efswptest/

[/simterm]

Проверяем – создаём файл с Services:

[simterm]

19:05:06 [root@rtfm-services-dev /home/admin] # touch /efswptest/test.file

[/simterm]

Проверяем его наличие на Bastion:

[simterm]

19:04:51 [root@rtfm-bastion-dev /home/admin] # ls -l /efswptest/
total 4
-rw-r--r-- 1 root root 0 Mar 24 19:05 test.file

[/simterm]

(надо в common добавить настройку времени)

Загружаем архив WordPress:

[simterm]

# wget https://wordpress.org/latest.zip

[/simterm]

Распаковываем, и переносим всё в /efswptest/:

[simterm]

19:07:31 [root@rtfm-services-dev /home/admin] # unzip latest.zip
19:07:31 [root@rtfm-services-dev /home/admin] # cp -r wordpress/* /efswptest/

[/simterm]

Обновляем root в /data/data-nginx.d/dev.rtfm.co.ua.conf:

...
    add_header X-Content-Type-Options nosniff;

    root /efswptest/;

    index index.html index.htm index.nginx-debian.html;
...

Перезагружаем конфиги NGINX:

[simterm]

19:09:56 [root@rtfm-bastion-dev /home/admin] # service nginx reload

[/simterm]

Проверяем:

Вот только меня берут сомнения по поводу быстродействия такой системы – через EFS… Хотя статика планируется быть в AWS CloudFront, так что может быть всё будет не слишком печально.

В общем – будем посмотреть. Проведу нагрузочные тесты, если будет плохо – то придётся PHP-FPM таки запускать на Bastion, на одном хосте с NGINX и пользовать единый EBS раздел, как это есть сейчас, а Services будет для OpenVPN, почты и прочего.

Значит, следующими задачами будут:

  1. протестировать скорость работы того же WordPress, используя NGINX+PHP-FPM на разных хостах и код  в EFS, и оба сервиса и код локально
  2. если использовать EFS – то добавить создание ресурса EFS и его Secutirty Group в CloudFormation
  3. если не использовать EFS – то вынести роль PHP в плейбук Bastionrtfm-blog-ansible-bastion-provision.yml
  4. обновить Jenkins билды – добавить провижен Services

Пока всё.