Введение

В данной статье я бы хотел рассмотреть проблему обновления PHP в виртуальной машине BitrixVM, и действия, которые возможно применить если выполнение переезда на машину с обновленным ПО невозможно. Надеюсь, что статья будет полезна для вас.

Предыстория

Несколько месяцев назад перед нами встала задача обновления PHP до версии 7.4 на одном из наших проектов. Проект был расположен внутри виртуальной машины с развернутой на ней BitrixVM версии 7.2.2. Заглянув в меню Битрикс при обращениях к скрипту /root/menu.sh было обнаружено, что обновление PHP невозможно без обновления Битрикс окружения. При этом само обновление окружения выполняется из бета репозиториев, так как текущая стабильная версия не поддерживала работу с PHP версии 7.4 согласно курсу:

https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=32&LESSON_ID=12862

Прошерстив форумы Битрикс, мы не нашли конкретного ответа, когда будет выполнено обновление BitrixVM до стабильной версии с поддержкой с PHP 7.4. В связи с чем, нами было принято решение обновить версию окружения до актуальной беты на одном из виртуальных серверов разработки, предварительно сделав snapshot.

Проблема BitrixVM в том, что это готовое решение, использующее Ansible скрипты для выполнения операций. При этом в случае нарушения работы скрипта операция будет прервана, а идентифицировать ошибку крайне сложно, как и понять на какой именно стадии она возникла.

BitrixVM хранит лог выполняемых задач по пути /opt/webdir/temp/, в ходе выполнения обновления окружения в логе возникали различные ошибки, вызывавшие нарушение процесса обновления. Поиск и решение подобных ошибок занимало достаточный период времени. Как пример, возникали ошибки подключения репозитория:

TASK [common : get server options] *********************************************

fatal: [96410.local]: FAILED! => {"failed": true, "msg": "The conditional check 'common_manage == 'update_packages'' failed. The error was: cannot import name shlex_quote\n\nThe error appears to have been in '/etc/ansible/roles/common/tasks/update_packages.yml': line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n# configure oldkernel limits\n- name: get server options\n  ^ here\n"} 

to retry, use: --limit @/etc/ansible/common.retry
4. Disable the repository permanently, so yum won't use it by default. Yum\n        will then just ignore the repository until you permanently enable it\n        again or use --enablerepo for temporary usage:\n\n            yum-config-manager --disable <repoid>\n        or\n            subscription-manager repos --disable=<repoid>\n\n     5. Configure the failing repository to be skipped, if it is unavailable.\n        Note that yum will try to contact the repo. when it runs most commands,\n        so will have to try and fail each time (and thus. yum will be be much\n        slower). If it is a very temporary problem though, this is often a nice\n 

Второй проблемой было то, что в случае если обновление из Бета репозиториев было выполнено неудачно и нарушало работу проекта, скрипты BitrixVM не предусматривают откат до стабильной версии, согласно информации:

https://dev.1c-bitrix.ru/learning/course/?COURSE_ID=37&TYPE=Y

 Обратного отката установленной бета-версии к текущей стабильной нет, т.е если вы перешли, например, на бету 7.4.13, то вернуться к стабильной 7.4.4 нельзя. В этом случае чтобы перейти на стабильную версию, нужно дождаться релиза стабильной версии, новее беты, или установить стабильную версию заново. Например для бета-версии 7.4.13, нужно ждать стабильную версию 7.5.

В нашем случае обновление несколько раз проходило неудачно, нарушалась работа всех сервисов, при этом идентифицировать проблему было крайне сложно в виду отсутствия подробного логирования, из-за чего приходилось откатывать состояние виртуальной машины из собранного ранее снэпшота.

Когда обновление до Бета версии прошло удачно, всплыла проблема при разворачивании новой версии PHP. Ansible роли виртуальной машины Битрикс предусматривают откат до предыдущей версии PHP, для этого в меню виртуальной машины есть, например следующие пункты:

Rollback PHP to version 5.6 
Rollback PHP to version 7.2

Однако на тестовом стенде мы также тестировали откат до предыдущих версий, эти операции также завершались различными ошибками. Ниже пример одной из них:

TASK [web : additional gathering facts] ****************************************

fatal: [96410.local]: FAILED! => {"changed": false, "module_stderr": "", "module_stdout": "{\"ansible_facts\":{\"bx_system_type\":\"10\",\"os_version\":\"7\",\"bx_memsystem_type\":\"8192\",\"bx_memory\":\"8009

812\",\"bx_version\":\"7.4-11\",\"bx_base_version\":\"7\",\"bx_package_name\":\"bitrix-env\",\"link_eth0\":\"yes\",\"speed_eth0\":\"\",\"addr_eth0\":\"176.57.215.253 92.53.127.54\",\"bx_bitrix_uid\":\"600\",\"rpm_bin\":\"/bin/rpm\",\"nginx_version\":\"1.12.2\",\"nginx_ssl\":\"ssl http2\",\"push_type\":\"nginx-push-stream-module\",\"push_status\":\"not_installed\",\"push_security_key\":\"\",\"push_host\":\"\",\"push_port\":\"\",\"push_pub\":\"/bitrix/pub/\",\"push_sub\":\"/bitrix/sub/\",\"push_subws\":\"/bitrix/subws/\",\"push_rest\":\"/bitrix/rest/\",\"nodejs_version\":\"not_installed\",\"nodejs_major_version\":\"not_installed\",\"push_server_version\":\"not_installed\",\"push_server_major_version\":\"not_installed\",\"nginx_push_module\":\"installed\",\"sphinx_version\":\"not_installed\",\"sphinx_type\":\"21\",\"mysql_version\":\"5.7.21\",\"mysql_mid_version\":\"7\",\"mysql_package\":\"Percona-Server-server\",\"mysql_service\":\"mysqld\",\"mysql_root_config\":\"/root/.my.cnf\",\"mysql_root_password\":\"set\",\"mysql_service_status\":\"active\",\"php_version\":\"not_installed\",\"php_union_version\":00,\"php_upgraded_versions\":[56,70,71,72,73,74],\"php_rollback_versions\":[],\"php_older_version\":0,\"php_mysql_ext\":\"\",\"bx_root_last_password_change\":\"Feb 28, 2018\",\"bx_last_password_change\":\"Feb 26, 2018\",\"firewalld_package\":\"installed\",\"firewalld_status\":\"not_running\",\"firewalld_bx_type\":\"not_installed\",\"firewalld_tolerance\":\"non_compatible\",\"iptables_status\":\"stateful\"}}", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 0} 

После нескольких часов работ и восстановлений состояния виртуальной машины из снэпшота, было принято решение отказаться от обновления окружения BitrixVM и развернуть отдельный сервер под управлением ОС Debian по общим стандартам с требуемым ПО. И выполнить переезд проектов на него.  От себя хочу добавить, что данный вариант, при выполнении работ по обновлению BitrixVM, считаем оптимальным, а именно переезд на новый сервер, либо с уже установленной новой версией BitrixVM, на борту, или на новый сервер под управлением другого дистрибутива Linux.    

После задача была закрыта и проект работал в штатном режиме. Однако, буквально через несколько месяцев перед нами вновь встала задача обновления PHP до версии 7.4 для BitrixVM, в этот раз с CRM Битрикс24 на борту. Ситуация усложнялась тем, что обновление необходимо было выполнить в течении нескольких дней, а сам сервер располагался физически в офисе заказчика, что означало для нас невозможность переезда на новую инфраструктуру в кратчайшие сроки.

Битрикс24 это CRM система, которая предполагает большой объем данных БД, что также усложняло переезд и сильно било по стоимости новой инфраструктуры. При этом проект, на котором необходимо было выполнить работы не предусматривал какого либо резервного контура.

Времени на детальное составление плана не было, первоначальным вариантом было выполнить обновление стандартными средствами Битрикс при этом на случай появления проблем, решить которые не удастся, использовать lvm snapshot для отката состояния сервера.

Также рассмотрен вариант разворачивания Docker контейнера c необходимой версией PHP7.4 и настроенный для работы с BitrixVM. Данный вариант показался для нас более выгодным, так как исключал все потенциальные проблемы, которые могли возникнуть при обновлении BitrixVM, а также предусматривал минимальный простой в работе проекта (в последствии простой был, однако он составил не более 5 минут, это то время, которое потребовалось для переключения Nginx для работы с Apache2 в контейнере).

Имея большой опыт работы с Docker мы не видели проблемы в разворачивании контейнера, также в отличии от BitrixVM, с Docker мы могли полностью контролировать процесс обновления, а в случае появления проблем изучать логи Apache в контейнере и сервисов установленных на сервере, которые более информативны, чем логи Ansible ролей виртуальной машины Битрикс. После небольших консультации внутри команды было принято решение развернуть контейнер. На сервере была установлена БитриксВМ 7.3.4, под управлением Centos7.4. Данные работы будут описаны в статье ниже. Я постарался максимально подробно описать проделанные нами шаги, для тех, кому это решение окажется полезным. Также в конце статьи будет приложена ссылка на github с конфигурацией контейнера.

Ход работ

Перед началом работ ставим пакеты docker-ce, docker-ce-cli, containerd.io для Centos7 согласно инструкции:

https://docs.docker.com/engine/install/centos/

После устанавливаем docker-compose (на момент публикации статьи актуальной версией является 1.29.2):

curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

Подготавливаем docker-compose файл где описываем контейнер. Контейнер был собран но основании php:7.4-apache, в Dockerfile были включены все необходимые PHP модули. За основу виртуального хоста Apache был взят оригинальный файл BitrixVM, с небольшими правками, учитывающими работу в контейнере. В частности, вам придется указать AssignUserId в конфигурации виртуального хоста Apache, в виду отсутствия пользователя bitrix в контейнере. Добавлю, что apache2 в нашем случае работает с модулем mpm_prefork настройки для которого также прокинуты в контейнер.

Для корректной работы в docker-compose файле потребуется прокинуть в контейнер стандартные директории площадки для bitrix. В целом блок volumes в нашем варианте выглядит следующим образом:

  volumes:
      - ./volumes/var/log/apache2:/var/log/apache2
      - ./volumes/etc/apache2/conf.d/nxs-std.conf:/etc/apache2/conf.d/nxs-std.conf:ro
      - ./volumes/etc/apache2/sites-enabled:/etc/apache2/sites-enabled:ro
      - ./volumes/etc/php/conf.d/nxs-std.ini:/usr/local/etc/php/conf.d/nxs-std.ini:ro
      - ./volumes/etc/apache2/mods-enabled/status.conf:/etc/apache2/mods-enabled/status.conf:ro
      - ./volumes/etc/apache2/mods-enabled/mpm_prefork.conf:/etc/apache2/mods-enabled/mpm_prefork.conf:ro
      - /tmp/php_sessions/:/tmp/php_sessions/
      - /tmp/php_upload/:/tmp/php_upload/
      - /home/bitrix/:/home/bitrix/
      - /var/log/httpd:/var/log/httpd/

Логи apache2 для площадки были прокинуты на сервер в стандартную директорию, что также учтено в виртуальном хосте:

CustomLog /var/log/httpd/site_access.log combined
ErrorLog /var/log/httpd/site_error.log

Логи самого apache2 в контейнере расположены в /volumes/var/log/apache2.

Также потребуется внести ряд правок в php.ini и прокинуть файл в контейнер, эти шаги я опишу ниже, в рамках части про Битрикс оптимизацию.

Для решения проблем с правами необходимо добавить в описание контейнера в docker-compose строки:

cap_add:
      - SYS_NICE
      - DAC_READ_SEARCH

Для удобства указания общения контейнера с сервером присваиваем ему IP:

    networks:
      default:
        ipv4_address: 172.24.1.4

и настраиваем сеть:

networks:
  default:
    driver: bridge
    ipam:
      config:
        - subnet: 172.24.1.0/29
    driver_opts:
      com.docker.network.bridge.name: "br2-php74" 

После потребуется добавить подсеть docker контейнера в список разрешенных для фаервола, в нашем случае правила выглядят так:

-A POSTROUTING -s 172.24.1.0/29 -j MASQUERADE
-A INPUT -s 172.24.1.0/29 -j ACCEPT
-A FORWARD -s 172.24.1.0/29 -j ACCEPT
-A FORWARD -d 172.24.1.0/29 -j ACCEPT

Для корректной отправки почты, необходимо будет настроить почтовый сервер таким образом, что бы он мог принимать и ретранслировать почту отправленную из контейнера. В нашем случае для отправки почты использовался exim настроенный для работы в режиме smarthost, поэтому потребовалось добавить адрес контейнера (172.24.1.4) в следующие строки:

domainlist local_domains = @ : localhost : 172.24.1.4
hostlist   relay_from_hosts = localhost : 172.24.1.4

Битрикс оптимизация

После того как контейнер был готов и запущен, перед переключением площадки необходимо было провести Битрикс оптимизацию, то есть устранить все ошибки в тестировании конфигурации. От себя добавлю, что до переноса в контейнер ошибок в тестировании конфигурации не было.

Для решения этих задач была создана отдельная тестовая площадка на основном сервере, в которую был помещен установочный скрипт Битрикс. Площадка развернута через стандартное меню Битрикс /root/menu.sh.

Для тестовой площадки настраиваем проксирование на уровне Nginx в контейнер, потребуется изменить переменную proxyserver в файлах виртуального хоста площадки.

set $proxyserver  "http://172.24.1.4:80";

После прокидываем созданный скриптом Битрикс  виртуальный хост для apache2 в контейнер, при этом обязательно указываем UID пользователя Bitrix:

AssignUserId #600 #600

В нашем случае apache2 работает на стандартном 80 порту в контейнере, поэтому в виртуальном хосте указываем:

<VirtualHost *:80>

После меняем параметры подключения к БД в файлах dbconn.php и .settings.php c 127.0.0.1 на 172.24.1.1

$DBHost = "172.24.1.1"; - для dbconn.php
'host' => '172.24.1.1', - для .settings.php

После внесения всех этих изменений переходим в административную панель тестовой площадки, а далее заходим в Проверка системы > Тестирование конфигурации. В первую очередь всплывет ошибка работы с сокетами, для ее решения прописываем в docker-compose.yml параметр extra_hosts, указав внешний IP сервера и доменное имя площадки:

extra_hosts:
 - "site.ru:EXTERNAL_IP"

Перезапускаем контейнер. Также для корректной отправки почты, потребуется указать в настройках PHP sendmail_path:

sendmail_path = "msmtp -t -i --host=172.24.1.1 --port=25 -f info@site.ru"

Прохождение проверки отправки почты внутри административной панели Битрикс еще не означает, что ваше письмо будет доставлено, поэтому рекомендуем также выполнить самостоятельную отправку письма c помощью скриптов площадки, а после проверить наличие письма в почтовом ящике и логи почтового сервера.

Остальные настройки стандартны и выполняются также как, если бы контейнера не было. Поэтому я не стану на них подробно останавливаться, достаточно сказать, что в настройках PHP должны присутствовать параметры:

mbstring.internal_encoding = UTF-8 
realpath_cache_size = 4096k
max_input_vars = 10000
allow_url_fopen = Off

Дополню, что в случае использования контейнера с Битрикс24 будет всплывать предупреждение вида:

Ошибка! Для гарантированной работы "1С-Битрикс24" необходимо его устанавливать на веб-окружении Битрикс, у вас используется собственное серверное окружение.

Предупреждение можно обойти, указав актуальную версию в виде переменной в скриптах Битрикс. В случае если вы используете продукт Управление сайтом, данного предупреждения не будет.

Также вы можете выполнить тестирование производительности конфигурации и анализ площадки с помощью сканера безопасности. В нашем случае цифры в тестировании конфигурации были практически идентичны как в случае с контейнером, так и без него.

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

Заключение

Целью данной статьи не является пропаганда такого решения, оно будет полезно тем, кому жизненно важно обновление PHP на текущем этапе работы проекта, при этом нет возможности переехать на новую инфраструктуру, а также нет уверенности в том, что обновление Битрикс из бета репозиториев пройдет гладко.

BitrixVM является простым в установке решением, однако в случае администрирования кастомной конфигурации решение проблем и проведение каких-либо обновлений проходит сильно проще.

Для удобства выложили конфигурацию нашего контейнера на GitHub, вы всегда можете ознакомится с ней по мере необходимости. Там же расположен отредактированный виртуальный хост площадки, все вносимые в PHP и Apache2 настройки и docker-compose.yml.

https://github.com/morgeshtern/php_bitrix_docker

В заключении от себя хочется сказать, что в процессе администрирования мы видим больше минусов, чем плюсов в разворачивании BitrixVM в качестве окружения, в частности это связано со следующими пунктами:

  • Сложность внесения каких-либо настроек в систему и установки нового ПО. Запутанность файлов конфигураций ПО в BitrixVM, а также использование ansible-скриптов для управления сервером через меню с псевдографическим интерфейсом приводит к тому, что внесение даже самых элементарных настроек требует большого количества времени со стороны администраторов, которое уходит именно на то, чтобы понять где именно необходимо внести данные изменения, чтобы в дальнейшем они не были перезаписаны ansible-скриптами, а так же не имели негативного влияния на работу других элементов системы.

  • В BitrixVM абсолютно все площадки работают из-под одного пользователя - bitrix. Соответственно ни о какой изоляции и соответственно безопасности проектов не может быть и речи (т.е. если используя какие-либо уязвимости в коде одного сайта, его взломают, то это будет означать, то злоумышленник получит доступ сразу ко всем остальным). Иными словами BitrixVM может подойти только тогда, когда на сервере работает только одна площадка.

  • В случае возникновения каких-либо проблем на сервере, на анализ и устранения причин неисправности уходит намного больше времени, чем при разборе ситуаций на кастомной настройке. В виду плохо настроенной системы логирования.

  • Также как показывает наш опыт, интеграция со сторонними сервисами в случае с BitrixVM зачастую очень сложна или невозможна.

Из плюсов такого решения могу отметить то, что конфигурация BitrixVM проста в первоначальной настройке. Однако рекомендовать это решение, можно разве что для простых проектов.

Комментарии (6)


  1. SignFinder
    03.09.2021 09:21
    +1

    Как минимум раньше образы BitrixVM собирались на базе CentOS, для которой есть сторонний репозиторий Remi https://blog.remirepo.net/pages/Config-en, позволяющий в две команды менять версию php.

    Из вашей статьи не увидел, что были какие-то ограничения, не позволяющие просто заменить версию php глобально в системе (хотя в remi есть возможность не трогать системный php, а устанавливать требуемую вам версию параллельно системной).


  1. alexey-m-ukolov
    03.09.2021 11:07

    Мы рассматривали отказ от BitrixVM в пользу Докера, но пока останавливает то, что периодически в Битрикс24 появляются какие-то совсем новые механизмы и в BitirxVM они начинают работать из коробки и уже сконфигурированными как надо. Как это потом реверс-инжинирить в Докер - не понятно.


    1. rpsv
      04.09.2021 18:25

      А что из "новых механизмов" появилось за последние лет 5, которые касались окружения, а не кода?


      1. alexey-m-ukolov
        05.09.2021 18:28

        Честно говоря, я не следил, поскольку желание перейти в Докер появилось недавно. Но вот на днях как раз обновлял PHP на сервере через BitrixVM и для этого пришлось обновить всё окружение и в новой версии появились в меню появились какие-то "Transformers". Не разбирался ещё что это такое.

        Ну и конфигов это тоже касается - поменяют какой-нибудь параметр в работе Push and Pull - ищи его потом...


  1. Mausglov
    03.09.2021 12:23

    Несколько месяцев назад ... через несколько месяцев перед нами вновь встала задача...

    Похоже, статья зрела долго :) Релиз Bitrix VM 7.5 состоялся почти полгода назад.
    На мой взгляд, самое сложное для повторения в Bitrix VM - это обеспечение работы Push&Pull


    1. Snooper
      05.09.2021 21:04
      +1

      Сейчас уже есть официальная документация по настройке push-сервера без bitrixVM.

      На список дистрибутивов можно не обращать особого внимания, инструкции несложно адаптируются под debian / ubuntu

      https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=32&CHAPTER_ID=020866&LESSON_PATH=3903.4862.20866