Быстрое конфигурирование серверов с Ansible

26.01.23

Администрирование - Администрирование веб-серверов

Всю рутину по обновлению платформы, настройке веб-серверов и серверов хранилищ на всем парке серверов компании можно автоматизировать с помощью удобочитаемых YAML-скриптов Ansible. О том, как написать сценарии такой автоматизации, чтобы запускать их параллельно для группы серверов, на митапе «Инструменты автоматизации рутины в 1С-разработке» рассказал ведущий разработчик компании ПИК Digital Павел Комаров.

 

 

В моем докладе пойдет речь про автоматизацию рутины, которую мы выполняем на наших серверах 1С, SQL и сервере хранилища. Сюда относятся такие операции как:

  • обновление платформы;

  • удаление и установка служб;

  • регистрация компонент консоли и пр.

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

 

Что такое Ansible и чем он отличается от других похожих систем?

 

 

 

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

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

  • Puppet

  • Chef

  • Saltstack

  • Ansible

Я остановился на Ansible, потому что меня подкупила его безагентность. Это очень важный критерий – чтобы на удаленные хосты не нужно было ничего ставить, хотя с Windows потом оказалось, что есть маленький нюанс.

У Ansible есть ряд преимуществ:

  • У него простой синтаксис – все сценарии автоматизации пишутся на YAML.

  • Сам Ansible написан на Python, его можно дорабатывать с помощью собственных дополнительных модулей.

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

  • В отличие от остальных систем (они еще называются pull-системы), Ansible использует push-mode. Мы пишем сценарий, отправляем его на центральный узел, и оттуда изменения проталкиваются (push) и применяются удаленных узлах.

  • Ansible имеет большое количество встроенных модулей.

  • Большинство этих модулей является идемпотентными с точки зрения многократного выполнения. Т.е. если нам потребуется несколько раз выполнить одну и ту же операцию, результат первоначального применения не изменится. Например, если у нас по сценарию создается какой-то пользователь, то при повторном выполнении этого шага, Ansible просто проверит, что он уже создан, и продолжит выполнение. А в скриптах это нужно было бы дополнительно обрабатывать.

 

 

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

Важное ограничение: в качестве управляющего узла не может выступать машина с операционной системой Windows – поддерживается только Linux.

В качестве удаленных хостов может выступать машина с любой операционной системой. Чтобы получить туда доступ, главное, чтобы там был установлен Python, и, если это Windows, на нем должен быть установлен PowerShell версии не ниже 3.0.

 

 

По требованиям к центральному узлу и к хостам.

  • Центральный узел – требуется установка Ansible, самого Python и средства, с помощью которого мы будем общаться с удаленными узлами.

  • На Windows-хостах должен быть установлен PowerShell версии не ниже 3.0 и работать служба WinRM (Windows Remote Management). Тут разработчики Ansible позаботились о нас, сделали скрипт на PowerShell, который всю необходимую настройку за нас выполнит. Запустили – и хост готов.

  • А с Linux хостами еще проще – Python во всех дистрибутивах есть, SSH-есть. Зная логин и пароль или пробросив SSH-ключи, можно подключиться к любому хосту.

 

Установка и запуск

 

 

Для установки на центральном узле можно использовать несколько вариантов:

  • Либо через родной менеджер пакетов поставить – сейчас Ansible уже входит в большинство дистрибутивов Linux.

  • Если нам потребуется подключение к Windows-хостам, нам потребуется еще дополнительно поставить Python-овскую библиотеку pywinrm. Она устанавливается через пакетный менеджер Python (по команде sudo pip install pywinrm).

  • Также Ansible можно сразу поставить через пакетный менеджер Python со всеми зависимостями по команде (по команде sudo pip install ansible).

  • И для самых ленивых есть docker-образ со свежими версиями https://hub.docker.com/r/jmal98/ansiblecm/ . Docker build, docker run и все – у нас готовая управляющая нода. Плюс в Visual Studio Code есть расширение для работы с Docker, через которое можно взаимодействовать с контейнером управляющей ноды. Это позволит писать и запускать сценарии на своей рабочей машине.

Подробнее установка на центральном узле прописана в документации Ansible.

 

Подготовка хоста на Windows

 

 

На слайде приведен скрипт PowerShell для настройки хоста с Windows (подробнее о настройке Windows-хоста для работы с Ansible можно прочитать в документации).

$url = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"

$file = "$env:temp\ConfigureRemotingForAnsible.ps1"

(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)

powershell.exe -ExecutionPolicy ByPass -File $file

Запустили. Если все прошло без ошибок, то хост настроен.

 

 

Если работа Ansible через Windows Remote Management вас не устраивает, с версии 2.8 у нас появилась возможность работать с Windows-хостами через пакет OpenSSH.

На слайде показано, как установить пакет openssh через модуль win_chocolatey Ansible.

 

 

 

Как Ansible определяет, к каким хостам он может подключаться? Для этого есть специальный файл – inventory.

По умолчанию, он лежит на управляющей машине по пути /etc/ansible/hosts

Поддерживается описание как списком, так и в формате YAML (документация).

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

 

Библиотека модулей

 

 

Что интересного можно запускать на удаленных хостах?

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

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

Читать сценарии очень удобно. А, как мы знаем, пишем код мы реже, чем читаем.

 

 

Модули можно выполнять отдельно в так называемом Ad-hoc-режиме. Или собирать в операции (play), а затем в Playbook.

 

Демонстрация работы с Ansible через Ad-hoc-команды

 

 

Демонстрационный стенд состоит из трех машин – две на Windows и одна – управляющая нода на CentOS.

Чтобы настроить Windows-хосты для работы с Ansible, запускаем на них скрипт ConfigureRemotingForAnsible.ps1 (как его запустить было продемонстрировано ранее).

 

 

Здесь осуществляется подготовка и запуск службы Windows Remote Management. На этом настройка на Windows-хосте закончена.

 

 

Теперь идем на наш управляющий узел – я покажу, как в нем настроен файл hosts, который находится по пути /etc/ansible/hosts.

 

 

Здесь указаны две наши windows-машины – 1cdevops01 и 1cdevops02, которые объединены в группу [onecservers].

 

 

Клонируем к себе репозиторий с примерами скриптов и рассмотрим его структуру.

В корне репозитория есть папка group_vars. В ней лежит файл onecservers – в котором хранятся параметры для подключения к группе серверов с таким именем.

 

 

Когда Ansible будет подключаться к хостам группы onecservers (нашим Windows-хостам), он будет использовать эти параметры.

ansible_user: devops

ansible_connection: winrm

ansible_winrm_server_cert_validation: ignore

Т.е. он будет подключаться под пользователем devops через winrm, не используя никакие сертификаты (ansible_winrm_server_cert_validation: ignore).

Посмотрим, как отработают примеры.

 

 

Первый пример у нас – это модуль win_ping.

Перейдем в корень репозитория и просто пропингуем наши два windows хоста командой:

ansible onecservers -m win_ping --ask-pass

Параметр --ask-pass означает, что Ansible сейчас запросит пароль, под которым я подключусь к удаленным хостам.

Вот мы получили ответ от каждой машины – pong и все зеленое.

 

 

Дальше мы выполним команду whoami на удаленных хостах

ansible onecservers -m win_command -a whoami.exe --ask-pass

Ansible вывел результат выполнения этой команды.

 

 

Дальше – пример про идемпотентность. Используя модуль win_service я создам на сервере тестовую службу Ansible_example_service командой.

ansible onecservers -m win_service -a 'name=Ansible_example_service path=C:\temp\ state=stopped' --ask-pass

 

 

Перейдем на удаленный узел 1cdevops01 и проверим, что в списке появилась служба Ansible_example_service.

 

 

Еще раз выполним команду – теперь она показана зеленым. Свойства changed = false, exists = true. Это значит, что Ansible пропустил ее выполнение – идемпотентность заключается в том, что при повторном выполнении результат первоначального применения не изменяется.

 

 

Дальше – удалим эту службу. Тоже используя модуль win_service.

 

 

Все, служба удалилась. Т.е. одним модулем win_service мы управляем службами на удаленных хостах.

 

Первый Playbook

 

 

Теперь – про Playbook. Это – сценарий, где описываются действия, которые мы будем выполнять на какой-то группе хостов.

Playbook состоит из набора Play (операций). Play является ключевым элементом Playbook – он связывает хосты с задачами, которые будут на них выполняться.

Дальше – задача. Это как раз вызов конкретного модуля – то, что мы сейчас вызывали, например, win_service. В задаче обязательно указывается имя и модуль, который будет вызываться.

 

 

Теперь, чтобы уметь читать плейбуки, немного про правила написания YAML-файлов.

Файл начинается с трех дефисов.

  • Дальше идет перечисление play – наших операций.

  • Как и все списки в YAML, оно начинается с одинарного дефиса, а дальше – все отступы идут с одинаковым расстоянием от начала строки.

  • Комментарий начинается с символа #, а словарь описывается в виде «ключ: значение».

Здесь у нас операция с именем «install and start onec server» будет выполняться на группе хостов onecservers под пользователем root.

Дальше перечислены задачи, которые будут выполняться в этой операции. Там будет установлен 1С и запущены службы.

 

 

Небольшое резюме по плейбукам для понимания:

  • Сценарий (Playbook) содержит одну или несколько операций (Play)

  • Операции связывают множество хостов с задачами, выполняемыми на них.

  • Каждой задаче соответствует один модуль. Несколько модулей нельзя в одной задаче вызывать.

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

А дальше – вооружаемся документацией по модулям и начинаем автоматизировать всю нашу рутину.

 

 

Вот так выглядит плейбук для модуля win_ping. Сценарий, из одной операции, внутри которой одна задача – вызов модуля win_ping.

 

 

Давайте вызовем ее. Плэйбуки запускаются через отдельную консольную утилиту ansible-playbook:

ansible-playbook ping.yml --ask-pass

Мы воспроизвели ранее продемонстрированный пример с пингом, только через плейбуки.

Чуть позже покажу вам, как использовать плейбук на примере развертывания сервера 1С. Но до этого расскажу про роли.

 

Механизм ролей

 

 

Когда у нас сервер выполняет одновременно несколько ролей – например, он и сервер 1С, и SQL-сервер (такое часто встречается), мы можем написать большой сценарий, в котором сначала опишем шаги установки сервера 1С, потом – установки SQL-сервера. Это будет огромная портянка. А что если мне нужен будет только сервер 1С или SQL?

Для таких случаев в Ansible есть механизм ролей. Он позволяет разбить сложный сценарий на отдельные части, на роли. Роль определяет некоторую функциональность.

В нашем случае это будет отдельно роль на сервер 1С, отдельно роль на SQL-сервер.

А дальше в сценариях указывается, что группа серверов onecservers у нас является только серверами 1С, а группа серверов onecsqlservers – и серверами 1С, и SQL-серверами. А внутри роли уже отдельные плейбуки.

 

 

Как сделать роль?

Мы можем в корне нашего репозитория, где лежат плейбуки, создать папку roles. Там создать каталог для нашей роли и в соответствии с регламентированной структурой Ansible выстроить для роли такую структуру каталогов. Либо воспользоваться инструментом ansible-galaxy, который всю эту структуру выстроит автоматически одной командой:

ansible-galaxy init onec-server

Нам останется только написать соответствующий код в нужных обработчиках.

Теперь посмотрим на роль сервера 1С и пробежимся по этим каталогам – что в каждом лежит и для чего.

 

 

В папке defaults хранятся переменные, которые можно переопределять в процессе выполнения плейбука.

В каталоге files (он здесь не используется) хранятся файлы, которые будут выгружаться на хосты.

В каталоге handlers – обработчики, которые будут вызываться из задачи. Я этот каталог здесь тоже не использую.

 

 

В каталоге meta указываются зависимые роли, которые будут применены до основной роли – например, здесь на сервер 1С устанавливается пакетный менеджер chocolatey.

 

 

В каталоге tasks – это как раз те задачи, которые будут выполняться при развертывании роли. Рассмотрим их подробнее:

  • Модуль include подключит нам дополнительно задачи из файла find-services.yml при указанном здесь условии. Т.е. если значение onec_server_find_services is defined и оно равно True, то к основному сценарию будет добавлен еще и файл find-services.yml.

 

 

В файле find-services.yml сохраняются в переменные настройки служб сервера 1С и RAS.

 

 

  • Следующим шагом – поскольку перед тем, как выполнять main.yml, у нас на машине уже будет установлен choco, мы можем через модуль win_chocolatey_source добавить на узел внешний репозиторий с нашим пакетом 1С.

  • И потом через модуль win_chocolatey установить платформу с нужными для сервера 1С параметрами из этого пакета.

  • Модуль debug нужен для отладки – он выведет результат, который на предыдущем шаге был помещен в переменную onec_server_install_result.

 

 

  • Далее так же через пакетный менеджер будет установлена платформа, только уже другой разрядности.

  • Потом опять модуль debug.

  • Следом за ним два шага с уже знакомым нам модулем win_service: мы поднимем две службы – на сервер 1С и на сервер RAS.

  • Далее модуль win_shell – это просто вызов произвольной команды для регистрации консоли управления серверами.

  • И модуль win_template, который по шаблону заполняет файл nethasp.ini и копирует его на сервер. Модуль win_template использует питоновский шаблонизатор Jinja2, которому мы можем передать заготовку nethasp.ini.j2 из папки templates.

 

 

Например, я хочу поместить в nethasp.ini адреса HASP LM с аппаратными ключи, которые используются в компании.

 

 

Тогда я просто в файлике secrets.yml добавляю перечисление нужных мне серверов. И через модуль win_template весь перечень этих серверов добавится в итоговый nethasp.ini. Таким образом удобно создавать конфиг-файлы.

 

 

Благодаря последнему шагу этого плейбука nethasp.ini попадет к нам на сервер.

 

 

Теперь покажу, как все это работает. Запускаем плейбук onec-server.yml.

В самом плейбуке:

  • имя;

  • к каким серверам подключаться плейбуку;

  • файлик secrets, в котором можно задать секреты, используемые в плейбуках – это такой простой способ хранить секреты;

  • pre_tasks – задачи, которые выполняются перед запуском ролей – здесь создается временная директория;

  • и в разделе roles – параметры нашего плейбука (установи 1С-сервер версии 8.3.18.1128 на группе хостов onecservers).

 

Запуск сценариев

 

Запустим плейбук – перед запуском Windows-машины чистые, 1С на них нет.

 

 

За выполнением его шагов можно наблюдать в режиме реального времени. Если много серверов, все это очень красиво выглядит.

Создаются службы, регистрируется консоль, скопировался nethasp.ini – все, плейбук завершен.

 

 

Посмотрим ход всех операций с самого начала.

  • Задачу Gathering Facts можно отключить, это ресурсоемкая операция, где собирается дополнительная информация с хостов.

  • Дальше мы создаем временную директорию для Ansible.

  • Потом подключаемая роль из зависимостей проверила, установлен ли choco. Поскольку choco установлен, шаги его установки пропустились.

 

 

  • Дальше – получили информацию об уже установленных службах сервера 1С.

  • С помощью шага debug вывели сюда их параметры.

 

 

  • Удалили службы

 

 

  • Добавили внешний источник с пакетами платформы

  • Установили платформу

 

 

  • Создали службы.

  • Зарегистрировали консоль кластеров.

  • И перенесли nethasp.

Теперь посмотрим результат на машинах.

 

 

Службы у нас работают.

 

 

Консоль зарегистрирована.

Сервер готов.

 

Хранилище ролей Ansible

 

 

Если вам нужно установить какой-то опенсорсный продукт, то с большой вероятностью вы его найдете в хранилище ролей Ansible Galaxy – это что-то вроде GitHub.

Например, роль для установки choco я подсмотрел в одном из опубликованных пакетов.

Там даже есть роли для 1С – наши коллеги там тоже уже есть.

Установка роли из этого хранилища производится одной строкой:

ansible-galaxy install my_galaxy_role

Дальше все как обычно.

 

Полезные ссылки

 

Далее – по полезным ссылкам.

  1. Ansible documentation – обязательно изучите документацию. Там все четко по модулям расписано – какие входные, выходные параметры. Это маст хев.

  2. Запускаем Ansible | Хохштейн Лорин, Мозер Рене – хорошая книга на русском языке. С примерами, много полезного и интересного можно почерпнуть.

  3. How to build your inventory – фрагмент из документации.

  4. Роли для 1С – это моя статья на Инфостарте с открытым репозиторием https://github.com/komarovps/ansible-onec-windows , где есть роли на установку сервера 1С, обновления публикаций на веб-сервер, раскатки сервера терминалов и т.д. Там есть еще куда развиваться, но что-то почерпнуть можно.

Репозиторий, который демонстрировался в ходе доклада, размещен на GitHub по адресу https://github.com/komarovps/infostart-meetup-ansible.

 

Вопросы

 

Не очень понятно, почему Ansible безагентный. Python ведь все равно нужно ставить на целевых нодах.

Python нужен только на Linux-машинах. А он там, скорее всего, уже есть. На Windows-хостах единственный нюанс – нужно включить службу Windows Remote Management. Но это быстро решается групповыми политиками.

Вы показали, что плейбук выполняется по очереди. Но если серверов очень много, долго ждать каждого. Есть ли возможность параллельного выполнения?

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

Многие рассматривают Ansible как инструмент для управления и установкой ПО на серверах, а у меня был прикольный кейс, когда на моей машине потребовалось переустановить систему. И перед этим я на виртуалке нужный софт в виде плейбука собрал, отладил. И потом буквально за 20-30 минут раскатал на чистое железо.

Через тот же choco можно все интересные и нужные пакеты раскатывать. С Windows он очень спасает. Очень удобный пакетный менеджер.

Через WSL на Windows 10 можно ли управляющую систему Ansible запустить?

Не пробовал. Я знаю, что быстрее всего в Docker поднять контейнер и через него работать. Пробросить плейбуки и запускать.

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

Там есть режим стартовать с конкретного шага. Вообще Ansible очень интересный и мощный.

Как ни удивительно, прошли времена «красноглазия» и сейчас много опенсорсных инструментов типа Ansible работают из коробки достаточно легко без всяких бубнов.

Чем групповые политики не устроили?

Я не говорю, что групповые политики – это плохо. Но этими групповыми политиками же нужно будет что-то запускать. А скрипты настраивать не так удобно, как плейбуки.

 

*************

Статья написана по итогам доклада (видео), прочитанного на онлайн-митапе "DevOps в 1С: Инструменты автоматизации рутины в 1С-разработке".

 

10 - 12 октября 2024 года состоится конференция INFOSTART TECH EVENT, на которой прозвучит 130+ докладов.

Темы конференции:

  • Приемы, методы разработки и тестирования
  • DevOps-практики, управление инфраструктурой разработки
  • Интеграция и обмен данными
  • Идеи и тренды в разработке 
  • Администрирование серверов 1С и СУБД. HighLoad оптимизация  
  • Развитие технической команды. Личная эффективность разработчика 

INFOSTART TECH EVENT - крупнейшая профессиональная конференция для программистов 1С.


Подробнее о конференции.

 


См. также

Мониторинг Сервера Системный администратор Платформа 1С v8.3 Конфигурации 1cv8 Россия Абонемент ($m)

StartPlus и система контроля и сбора информации (настраиваем за час и пользуемся). Данное решение позволяет быстро собирать и анализировать различную информацию из разных источников данных (не обязательно серверов 1С). В любой момент можно менять состав сводной информации без сложной разработки на стороне 1С.

1 стартмани

вчера в 08:30    207    2    moolex    0    

2

Сервера Linux Системный администратор Россия Бесплатно (free)

Тема Ubuntu, PostgreSQL и 1С уже избитая. Но все же, следуя инструкциям всех мануалов, пришлось потратить около 3-х дней. И как результат — готовые скрипты для установки сервера 1С и PostgreSQL на свежей Ubuntu за 5 минут.

14.06.2024    1686    user1389975    10    

32

Мониторинг Сервера Системный администратор Программист Платформа 1С v8.3 Управляемые формы Абонемент ($m)

Размер, имя информационной базы из реестра кластера (файл 1CV8Clst.lst), дата последнего изменения файлов в каталоге баз (srvinfo\reg_*\uuid) центрального сервера. Отдельно показан размер индекса ППД (полнотекстовый поиск данных) и его актуальность. Полезна в случае, если у вас удалялись базы 1С и никто не озаботился удалением журналов регистрации.

1 стартмани

15.05.2024    914    12    MaximSh    0    

6

Администрирование веб-серверов Системный администратор Бесплатно (free)

В материале описан порядок действий по настройке Apache для работы по защищенному протоколу HTTPS c 1С на операционной системе РедОС с выпуском сертификата SSL.

09.05.2024    1415    artemusII    1    

9

Администрирование веб-серверов Системный администратор Программист Бесплатно (free)

Инструкция, как опубликовать веб-сервис с помощью OSPanel.

06.05.2024    964    lostcay    0    

5

Администрирование веб-серверов Системный администратор Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Статья описывает алгоритм установки, настройки и "сопряжения" с 1С веб-сервера Apache на РедОС. Статья, может, будет полезна тем, кто ищет в сети работающие алгоритмы установки веб-сервера и публикации на нем информационных баз 1С в контуре операционной системы РедОС. Помимо этого в статье рассмотрены некоторые спорные моменты, для анализа которых не удалось найти достаточно информации в сети.

25.04.2024    2187    artemusII    8    

18

Сервера Системный администратор Программист Платформа 1С v8.3 Россия Бесплатно (free)

Меня зовут Павел Белоусов, я работаю Ведущим программистом 1С в компании OCS Distribution. Хочу поделиться историей, как мы столкнулись с постоянными зависаниями dev-сервера 1C, каким образом решили проблему и какие любопытные уроки вынесли из ситуации.

12.04.2024    4025    pbelousov    57    

26
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. evn-zorin 33 27.01.23 21:41 Сейчас в теме
так много текста - пока вникнешь и поймёшь, проще по старинке всё руками поставить)
maksa2005; +1 Ответить
2. vikad 130 27.01.23 22:03 Сейчас в теме
(1)
Данная статья написана по итогам доклада (видео), прочитанного на онлайн-митапе "DevOps в 1С: Инструменты автоматизации рутины в 1С-разработке".

В целом достаточно изучить репозиторий демопримера https://github.com/komarovps/infostart-meetup-ansible и посмотреть видео выступления (ссылка приведена в процитированной фразе).
3. cdiamond 235 28.01.23 08:37 Сейчас в теме
(1) Для разовых работ смысла писать скрипты ansible нет. И их мало написать - отладка во много раз больше времени займет. Но когда у тебя серверов и рабочих станций сотни и тысячи то всё выглядит уже абсолютно по другому и смысл более чем есть.
4. evn-zorin 33 29.01.23 13:16 Сейчас в теме
(2) в этом случае имеет смысл
Оставьте свое сообщение