Установка 1С используя Ansible

HOWTO. Как быстро обновить платформу на серверах 1С, если у Вас их парк.

Представьте, что у Вас 20 серверов 1С и пришло время обновления релиза платформы. Нужно на каждом сервере установить новую версию платформы, удалить старую, поднять службу агента сервера и т.д. Накапливается масса рутинных операций. Есть несколько вариантов решения. Пойдем от сложного к простому:

  1. Вручную 
  2. Полуавтоматический — подготовить скрипт установки и выполнить его на каждой машине
  3. Автоматический — воспользоваться системой удаленного управления конфигурациями, т.е. с одной машины дать всем серверам команду на выполнение скрипта установки  

В статье будет показано как использовать Ansible для подобного рода задач.

Ansible — система управления конфигурациями, написанная на Python, с использованием декларативного языка разметки для описания конфигураций. Используется для автоматизации настройки и развертывания программного обеспечения. Обычно используется для управления Linux-узлами, но Windows также поддерживается.

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

Пойдем по порядку:

В качестве управляющей ноды (где будет установлен Ansible) может выступать только машина с ОС Linux. Поддерживается большинство дистрибутивов. В качестве хостов (где будут выполняться сценарии) могут выступать как Linux, так и Windows машины.

В примере, на управляющей ноде установлена ОС CentOS 7

Установка Ansible:

sudo yum install ansible

Подготовка файла Inventory:

Файл Inventory содержит в себе список хостов, к которым Ansible может подключиться. По умолчанию это файл /etc/ansible/hosts. 
Файл имеет гибкую настройку, мы будем использовать следующую сигнатуру указания хостов.

[group_name]

server_ip

Добавим в него два сервера и объединим их в группу [appservers] 

[appservers]

192.168.0.15
192.168.0.16

Подготовка Windows хоста для работы с Ansible:

Если в случае с Linux хостами доступ к ним осуществляется по SSH и все работает “из коробки”, то для того чтобы Ansible мог управлять Windows хостами, нужно на них включить службу удаленного управления (WS-Management). 
В репозитории Ansible есть PowerShell скрипт который выполнит всю предварительную настройку Windows хоста:

https://github.com/ansible/ansible/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1

Запускаем скрипт на Windows машине

powershell.exe -File ConfigureRemotingForAnsible.ps1

Более подробную информацию по настройке Windows хоста можно посмотреть тут:

https://docs.ansible.com/ansible/latest/user_guide/windows_setup.html

Настройка подключения Ansible к группам хостов:

После того как мы подготовили файл Inventory и настроили хост машины, нужно указать параметры подключения к этим машинам (под каким пользователем, через что подключаемся). Настройки подключения хранятся в каталоге /etc/ansible/group_vars
Для каждой группы создается одноименный файл, в котором указываются параметры подключения.

Создаем каталог:

mkdir /etc/ansible/group_vars

Создаем файл с именем нашей группы appservers:

vi /etc/ansible/group_vars/appservers

И вводим в него следующие параметры:

ansible_user: ansible
ansible_port: 5985
ansible_connection: winrm
ansible_winrm_transport: credssp
ansible_winrm_server_cert_validation: ignore

Теперь, ко всем хостам группы appservers, Ansible будет подключаться используя вышеуказанные параметры. Пароль от пользователя ansible мы также можем указать в файле appservers добавив строку:

ansible_password: p@ssw0rd

В целях безопасности мы этого не делаем и запрашивать пароль будем в момент запуска сценария, указав ключ —ask-pass

Проверка подключения Ansible к группе хостов:

Для проверки подключения будем использовать модуль win_ping. Все модули которые могут выполнятся на Windows хостах начинаются с префикса win_. Подробное описание всех модулей можно найти в официальном сайте. 

Выполняем команду

ansible appservers -m win_ping

В случае успешного подключения получим сообщение

192.168.0.15 | SUCCESS => {
"changed": false,
"ping": "pong"
}

Плэйбуки (сценарии) Ansible

Playbook (файл сценариев) — это файл, в котором описываются действия, которые нужно выполнить на какой-то группе хостов. Сценарии описываются в формате YAML

Плэйбук представляет собой набор задач (tasks). Каждая задача выполняется определенным модулем.

В плэйбуке по установке сервера 1С использованы следующие модули:

  • win_service — модуль для работы со службами
  • set_fact — модуль для работы с переменными
  • win_package — модуль установки/удаления пакетов Windows

Отдельно стоит отметить шифрование паролей в плэйбуке. Для этого используется ansible-vault (зашифрованное хранилище)

Чтобы поместить пароль в хранилище воспользуемся следующей командой:

echo -n "p@ssw0rd" | ansible-vault encrypt_string

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

В результате выполнения команды получим пароль в зашифрованном виде:

!vault | $ANSIBLE_VAULT;1.1;AES256 64396632346366373434356466396230364121656130363134316537306339643265656637366565
3763393238623632663732623034313738386561356232320a333766336638646137316463363031
66666435333939663832353937623638643764336662343834663338623666653965366233343536
3232633839646337300a333935333663613864306230343538653837353936373564623636366664
3537

Теперь вместо пароля мы можем указывать данную строку.

Пример плэйбука по установке платформы:

 
---
# Playbook для обновления релиза платформы на серверах приложений

- name: Install 1C Enterprise Application Server
hosts: appservers

# Переменные доступные плэйбуку
vars:
v8version: 8.3.15.1565
server_agent_srv_name: '1C:Enterprise 8.3 Server Agent'
server_agent_params: '-srvc -agent -regport 1541 -port 1540 -range 1560:1591 -d "C:Program Files1cv8srvinfo" -debug'
ras_srv_name: '1C:Remote Administation Service (RAS)'
platform_distr_path: \1CПлатформа8_3_15_1565setup.exe
bin_path: C:Program Files1cv8{{ v8version }}in
srv_1c_pwd: !vault |
$ANSIBLE_VAULT;1.1;AES256
64396632346366373434356466396230364121656130363134316537306339643265656637366565
3763393238623632663732623034313738386561356232320a333766336638646137316463363031
66666435333939663832353937623638643764336662343834663338623666653965366233343536
3232633839646337300a333935333663613864306230343538653837353936373564623636366664
3537
tasks:
- name: Test connection
win_ping:

# Проверка наличия службы сервера 1С
- name: Check if a server agent service is installed
win_service:
name: '{{ server_agent_srv_name }}'
register: server_agent_srv_info

# Проверка наличия службы удаленного администрирования RAS
- name: Check if a RAS service is installed
win_service:
name: '{{ ras_srv_name }}'
register: ras_srv_info

# Остановка службы сервера 1С
- name: Stop server agent service
win_service:
name: '{{ server_agent_srv_name }}'
state: stopped
when: server_agent_srv_info.exists

# Остановка службы службы удаленного администрирования RAS
- name: Stop RAS service
win_service:
name: '{{ ras_srv_name }}'
state: stopped
when: ras_srv_info.exists

# Удаление службы сервера 1С
- name: Remove server agent service
win_service:
name: '{{ server_agent_srv_name }}'
state: absent
when: server_agent_srv_info.exists

# Сохранение параметров службы сервера 1С (?<=ragent.exes).*(?=")
- name: Save server agent params
set_fact:
server_agent_params: "{{ server_agent_srv_info.path | regex_search('(?<=ragent.exe\s).*(?=")') }}"
when: server_agent_srv_info.exists

# Удаление службы удаленного администрирования RAS
- name: Remove RAS service
win_service:
name: '{{ ras_srv_name }}'
state: absent
when: ras_srv_info.exists

# Удаление платформы
- name: Uninstall 1C Enterpise 8.3
win_package:
product_id: '{24877BC3-0D30-4F0E-A840-EDB9DBB30D47}' # HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstall
state: absent

# Установка сервера 1С
- name: Install 1C Enterprise Application Server
win_package:
path: '{{ platform_distr_path }}'
product_id: '{24877BC3-0D30-4F0E-A840-EDB9DBB30D47}'
arguments: 'DESIGNERALLCLIENTS=1 THINCLIENTFILE=0 THINCLIENT=1 WEBSERVEREXT=1 SERVER=1 CONFREPOSSERVER=0 CONVERTER77=0 SERVERCLIENT=1 LANGUAGES=RU'

# Создание службы агента сервера 1С
- name: Create a new server agent service
win_service:
name: '{{ server_agent_srv_name }}'
path: '{{ bin_path }}
agent.exe {{ server_agent_params }}'
start_mode: auto
username: srv_1c
password: '{{ srv_1c_pwd }}'

# Создание службы удаленного администрирования RAS
- name: Create a new RAS service
win_service:
name: '{{ ras_srv_name }}'
path: '{{ bin_path }}
as.exe cluster --service --port=1545 localhost:1540'
start_mode: auto

Запуск плэйбука:

ansible-playbook playbook.yml --ask-vault-pass --ask-pass

Ключ —ask-vault-pass потребует ввода пароля от зашифрованного хранилища

Ключ —ask-pass потребует ввода пароля от учетной записи под которой ansible подключается к хост машине (в нашем случае это УЗ ansible)

Лог выполнения:

 
PLAY [Install 1C Enterprise Application Server] ***************************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************************************************
ok: [192.168.0.15]

TASK [Test connection] ****************************************************************************************************************************************************************************
ok: [192.168.0.15]

TASK [Check if a server agent service is installed] ***********************************************************************************************************************************************
ok: [192.168.0.15]

TASK [Check if a RAS service is installed] ********************************************************************************************************************************************************
ok: [192.168.0.15]

TASK [Stop server agent service] ******************************************************************************************************************************************************************
ok: [192.168.0.15]

TASK [Stop RAS service] ***************************************************************************************************************************************************************************
ok: [192.168.0.15]

TASK [Remove server agent service] ****************************************************************************************************************************************************************
changed: [192.168.0.15]

TASK [Remove RAS service] *************************************************************************************************************************************************************************
changed: [192.168.0.15]

TASK [Uninstall 1C Enterpise 8.3] *****************************************************************************************************************************************************************
changed: [192.168.0.15]

TASK [Install 1C Enterprise Application Server] ***************************************************************************************************************************************************
changed: [192.168.0.15]

TASK [Create a new server agent service] **********************************************************************************************************************************************************
changed: [192.168.0.15]

TASK [Create a new RAS service] *******************************************************************************************************************************************************************
changed: [192.168.0.15]

PLAY RECAP ****************************************************************************************************************************************************************************************
192.168.0.15            : ok=13   changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Плэйбук выполнился без ошибок. Платформа обновлена, службы подняты.

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

Официальная документация Ansible: https://docs.ansible.com/

Репозиторий Ansible: https://github.com/ansible/ansible

22 Comments

  1. Glebis

    Пойдем от сложного к простому:



    4. Политикой домена с запуском cmd скрипта с 2мя строками msiexec удаления — установки платформы + ещё 2 строки для удаления — установки RAS.

    Reply
  2. yaguarrr

    Запамятовал уже как, но раньше делали, что все клиенты стартутют из одной папки

    Reply
  3. Fox-trot

    (1) а ежели нет домена…. читаем статью?

    Reply
  4. Glebis

    (3) Если нет общего домена или домены не в лесе — то это, скорее всего, разные (независимые) организации. Будь я сотрудником безопасности этих организаций, у меня возникли бы вопросы. Например, о безопасности «поднятия хоста» удаленного управления на продакш сервере 1С, куда может в любой момент прилететь по ssh команда с правами администратора.

    По мне так намного «секьюрней» выполнять из планировщика заданий или автозагрузки системы ps1 файл в облаке (под локальным админом) который бы устанавливал msi файл из того же облака.

    Reply
  5. blackhole321

    Как откатить изменения, если что-то пошло не так?

    Reply
  6. sorb

    (4) если нет общего домена, то это, скорее всего магазины). На самом деле без vpn доступ по ssh (с каким-нибудь fail2ban) как раз мировая норма, в отличие от того же проброса 3389 наружу. Автор — молодчага, хотя бы просто потому, что бикоз хи кэн)

    Reply
  7. lopatrik

    (5) Отката нет, но можно описать сценарий по условию, на случай, если что-то пошло не так. Например, если служба не запустилась.

    Либо какие-то «бекапы» делать перед выполнением и возвращаться к ним опять же отдельными тасками.

    Reply
  8. blackhole321

    (7)

    без vpn доступ по ssh (с каким-нибудь fail2ban) как раз мировая норма

    А не проще родными средствами (PowerShell)?

    Reply
  9. sorb

    (9) ssh — транспортный протокол, pwsh — язык и среда исполнения, как одно заменяет другое? Если Вы имели в виду использование транспорта winrm или ipc$ через тот же psexec, то тут, конечно, вопрос личных предпочтений, кому как удобней)

    Reply
  10. blackhole321

    (10)Ну не придирайтесь :). Вы ведь поняли, что речь идет о средствах управления, а не о транспортном протоколе. Playbook из статьи как раз использует WinRM, а PowerShell может быть настроен через ssh так, что вопрос был в том, что не проще ли использовать штатное средство удаленного администрирования (PowerShell), которое уже входит в состав системы и настраивается несколькими строками (Enable-PSRemoting … или GPO etc.)?

    Ну и собственно:

    $session = New-PSSession -ComputerName «МойКомпьютер»

    Invoke-Command -Session $session -ScriptBlock МойКусокКода

    Или интерактивно:

    Enter-PSSession $session

    Ну и далее руками.

    Просто Вы написали, что круто, потому, что хи кен, а я спросил what is this for? 🙂

    Reply
  11. newgluk

    (9) не проще, если у вас часть серверов на Win, часть на Linux. Playbooks удобны тем, что весь зоопарк управляется единообразно.

    Reply
  12. newgluk

    автору — вы не пробовали ssh пару ключей (закрытый/открытый) для аутентификацци с Linux на Win? Хранить пароль в текстовике некошерно, а вводит вручную — лень 🙂

    Reply
  13. blackhole321

    (12)Согласен. Примерно это и хотел услышать. И наверное все определяется соотношением Windows и Linux серверов/рабочих станций. Полагаю, что если у вас 10500 серверов Windows и 20 Linux имеет смысл установить PowerShell на эти 20 серверов. Соответственно если 100500 серверов/рабочих станций Linux и 20 Windows, предлагаемая схема вполне рабочая.

    Reply
  14. newgluk

    (14)Ансибл сейчас на хайпе, у него куча готовых ролей, разного рода инструменты типа Ansible Tower и AWX. То есть, теоретически это удобнее чем самому писать скрипты на PS

    Reply
  15. blackhole321

    (15)Я так понимаю, ключевое слово — на хайпе 🙂 На мой взгляд, несколько странно платить деньги за операционную систему и не пользоваться предоставляемыми инструментами и возможностями, за которые вы заплатили.

    Ansible Tower — по моему совершенно не бесплатен, тогда уж надо сравнивать с System Center.

    То есть, теоретически это удобнее чем самому писать скрипты на PS

    Ну вот теоретически :), а практически — возникли ошибки при выполнении playbook, не стартовала служба или что-то еще, что Вы будете делать? Полагаю, что что-то типа $session = New-PSSession и.т.п. 🙂

    Reply
  16. newgluk

    (16)да, все так, для каждого кейса свой инструмент. если плейбук кривой, то да, цепляемся по ssh, стартуем службу руками, материмся, переписываем плейбук… Никакой магии. Но в целом, многие сейчас пропагандируют IAC, декларативное описание инфрастурктруры и все такое. А инструменты типа Ansible хорошо в эту идеологию укладываются.

    Reply
  17. blackhole321

    (17)IAC можно реализовать как в декларативном так и в процедурном стиле, тут наверное вопрос вкуса. Если хочется декларативного подхода, можно использовать DSC, который является штатной фичей ОС Windows и под капотом которого как и в случае с Ansible — все те же процедуры. Тут наверное стоит учесть размер инфрастуктуры. Если она небольшая — то это как из пушки по воробьям.

    Reply
  18. newgluk

    (18)если вы говорите про то, что нечего тащить инструментарий Linux на Win, если есть стабильные нативные решения, то я не спорю. Плясать потом с виртуалками или с Windows Subsystem Linux — то еще удовольствие. Другое дело, если у вас скажем 50 серверов на Linux и парочка на Win, и те скоро мигрируют…

    Reply
  19. blackhole321

    (19)Полностью с Вами согласен.

    Reply
  20. lopatrik

    (13) Изначально так и хотел сделать, но при работе через WinRM использование ssh ключей не поддерживается.

    В версии 2.8 добавили экспериментальный функционал по этому поводу. Как попробую, обязательно поделюсь опытом.

    Reply
  21. pumbaE

    такой режим подойтет только если уже вручную устанвливали сервер 1с и установленные компоненты уже сохранились в C:ProgramData1C1CEStart1CEStart.cfg

    при этом каждый раз надо искать product_id

    — name: put file msi info on remote
    tags: onec
    win_copy:
    src: files/getmsifile.ps1
    dest: C:1cinstallgetmsifileinfo.ps1
    
    — name: get msi product id
    win_shell: C:1cinstallgetmsifileinfo.ps1 -Path «C:1cinstall{{onec_version}}1CEnterprise 8.msi» -Property ProductCode
    register: productcode
    
    — name: unistall 1C {{ onec_version }}
    tags: onec
    win_package:
    path: C:1cinstall{{onec_version}}1CEnterprise 8.msi
    product_id: «{{ productcode.stdout_lines[0] }}»
    state: absent
    when: onec_reinstall
    
    — name: install 1C {{ onec_version }}
    tags: onec
    win_package:
    path: C:1cinstall{{onec_version}}1CEnterprise 8.msi
    state: present
    product_id: «{{ productcode.stdout_lines[0] }}»
    arguments: /L*V «C:1cinstall{{onec_version}}install.log»
    when: not onec_install.stat.exists or onec_reinstall
    
    

    Показать

    https://gist.github.com/pumbaEO/8667e0ed68574b1ab0c27d8060e89c97#file-getmsifile-ps1

    Reply
  22. blackhole321

    (22)




    src: files/getmsifile.ps1

    dest: C:1cinstallgetmsifileinfo.ps1

    — name: get msi product id

    win_shell: C:1cinstallgetmsifileinfo.ps1


    Вот и возникает вопрос, а нужен ли здесь Ansible?

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *