Использование Ansible и Windows
При использовании Ansible для управления Windows многие синтаксические правила и правила, применяемые к хостам Unix/Linux, действуют и для Windows, однако есть и некоторые отличия, связанные с такими компонентами, как разделители путей и задачи, специфичные для ОС. В этом документе рассматриваются особенности использования Ansible в Windows.
Сценарии использования
Ansible можно использовать для оркестрации множества задач на серверах Windows. Ниже приведены примеры и сведения о распространённых задачах.
Установка программного обеспечения
Ansible можно использовать для установки программного обеспечения тремя основными способами:
- С помощью модуля
win_chocolatey. Данные о программе загружаются из общедоступного репозитория Chocolatey по умолчанию. Вместо него можно использовать внутренние репозитории, задав параметрsource. - С помощью модуля
win_package. Он устанавливает программное обеспечение с помощью установщика MSI или .exe, расположенного по локальному/сетевому пути или URL-адресу. - С помощью модуля
win_commandилиwin_shellдля ручного запуска установщика.
Рекомендуется использовать модуль win_chocolatey, поскольку в нём реализована наиболее полная логика проверки того, установлен ли пакет и обновлён ли он до последней версии.
Ниже приведены примеры использования всех трёх вариантов для установки 7-Zip:
# Install/uninstall with chocolatey
- name: Ensure 7-Zip is installed through Chocolatey
win_chocolatey:
name: 7zip
state: present
- name: Ensure 7-Zip is not installed through Chocolatey
win_chocolatey:
name: 7zip
state: absent
# Install/uninstall with win_package
- name: Download the 7-Zip package
win_get_url:
url: https://www.7-zip.org/a/7z1701-x64.msi
dest: C:\temp\7z.msi
- name: Ensure 7-Zip is installed through win_package
win_package:
path: C:\temp\7z.msi
state: present
- name: Ensure 7-Zip is not installed through win_package
win_package:
path: C:\temp\7z.msi
state: absent
# Install/uninstall with win_command
- name: Download the 7-Zip package
win_get_url:
url: https://www.7-zip.org/a/7z1701-x64.msi
dest: C:\temp\7z.msi
- name: Check if 7-Zip is already installed
win_reg_stat:
name: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{23170F69-40C1-2702-1701-000001000000}
register: 7zip_installed
- name: Ensure 7-Zip is installed through win_command
win_command: C:\Windows\System32\msiexec.exe /i C:\temp\7z.msi /qn /norestart
when: 7zip_installed.exists == false
- name: Ensure 7-Zip is uninstalled through win_command
win_command: C:\Windows\System32\msiexec.exe /x {23170F69-40C1-2702-1701-000001000000} /qn /norestart
when: 7zip_installed.exists == true
Для некоторых установщиков, например Microsoft Office или SQL Server, требуется делегирование учётных данных или доступ к компонентам, ограниченный WinRM. Лучше всего обойти эти проблемы можно с помощью become в задаче. При использовании become Ansible запустит установщик так, как если бы его запустили на хосте в интерактивном режиме.
Примечание
Многие установщики неправильно передают сведения об ошибках через WinRM. В таких случаях, если проверено, что установка работает локально, рекомендуется использовать become.
Примечание
Некоторые установщики перезапускают службы WinRM или HTTP либо временно делают их недоступными, из-за чего Ansible считает систему недоступной.
Установка обновлений
Модули win_updates и win_hotfix можно использовать для установки обновлений или исправлений на хосте. Модуль win_updates используется для установки нескольких обновлений по категориям, а win_hotfix можно использовать для установки одного обновления или файла исправления, загруженного локально.
Примечание
Для модуля win_hotfix требуются командлеты PowerShell DISM. По умолчанию эти командлеты появились только в Windows Server 2012 и более новых версиях; на более старые хосты Windows их необходимо установить.
В следующем примере показано, как можно использовать win_updates:
- name: Install all critical and security updates
win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
register: update_result
- name: Reboot host if required
win_reboot:
when: update_result.reboot_required
В следующем примере показано, как использовать win_hotfix для установки одного обновления или исправления:
- name: Download KB3172729 for Server 2012 R2
win_get_url:
url: http://download.windowsupdate.com/d/msdownload/update/software/secu/2016/07/windows8.1-kb3172729-x64_e8003822a7ef4705cbb65623b72fd3cec73fe222.msu
dest: C:\temp\KB3172729.msu
- name: Install hotfix
win_hotfix:
hotfix_kb: KB3172729
source: C:\temp\KB3172729.msu
state: present
register: hotfix_result
- name: Reboot host if required
win_reboot:
when: hotfix_result.reboot_required
Настройка пользователей и групп
Ansible можно использовать для создания пользователей и групп Windows как локально, так и в домене.
Локально
Модули win_user, win_group и win_group_membership управляют локальными пользователями, группами и членством в группах Windows.
Ниже приведён пример создания локальных учётных записей и групп, которым разрешён доступ к папке на том же хосте:
- name: Create local group to contain new users
win_group:
name: LocalGroup
description: Allow access to C:\Development folder
- name: Create local user
win_user:
name: '{{ item.name }}'
password: '{{ item.password }}'
groups: LocalGroup
update_password: false
password_never_expires: true
loop:
- name: User1
password: Password1
- name: User2
password: Password2
- name: Create Development folder
win_file:
path: C:\Development
state: directory
- name: Set ACL of Development folder
win_acl:
path: C:\Development
rights: FullControl
state: present
type: allow
user: LocalGroup
- name: Remove parent inheritance of Development folder
win_acl_inheritance:
path: C:\Development
reorganize: true
state: absent
Домен
Модули win_domain_user и win_domain_group управляют пользователями и группами в домене. Ниже приведён пример проверки того, что группа пользователей домена создана:
- name: Ensure each account is created
win_domain_user:
name: '{{ item.name }}'
upn: '{{ item.name }}@MY.DOMAIN.COM'
password: '{{ item.password }}'
password_never_expires: false
groups:
- Test User
- Application
company: Ansible
update_password: on_create
loop:
- name: Test User
password: Password
- name: Admin User
password: SuperSecretPass01
- name: Dev User
password: '@fvr3IbFBujSRh!3hBg%wgFucD8^x8W5'
Выполнение команд
Если для задачи нет подходящего модуля, команду или скрипт можно выполнить с помощью модулей win_shell, win_command, raw и script.
Модуль raw просто удалённо выполняет команду PowerShell. Поскольку в raw нет оболочек-обёрток, которые Ansible обычно использует, become, async и переменные окружения не работают.
Модуль script выполняет скрипт с управляющего узла Ansible на одном или нескольких хостах Windows. Как и raw, script в настоящее время не поддерживает become, async или переменные окружения.
Модуль win_command используется для выполнения команды, представляющей собой исполняемый файл или пакетный файл, а модуль win_shell — для выполнения команд в оболочке.
Выбор Command или Shell
Модули win_shell и win_command можно использовать для выполнения одной или нескольких команд. Модуль win_shell запускается в процессе, похожем на оболочку, например PowerShell или cmd, поэтому ему доступны операторы оболочки, такие как <, >, |, ;, && и ||. В win_shell также можно запускать многострочные команды.
Модуль win_command просто запускает процесс вне оболочки. При этом он всё же может запускать команды оболочки, например mkdir или New-Item, передавая их исполняемому файлу оболочки, например cmd.exe или PowerShell.exe.
Ниже приведены примеры использования win_command и win_shell:
- name: Run a command under PowerShell
win_shell: Get-Service -Name service | Stop-Service
- name: Run a command under cmd
win_shell: mkdir C:\temp
args:
executable: cmd.exe
- name: Run multiple shell commands
win_shell: |
New-Item -Path C:\temp -ItemType Directory
Remove-Item -Path C:\temp -Force -Recurse
$path_info = Get-Item -Path C:\temp
$path_info.FullName
- name: Run an executable using win_command
win_command: whoami.exe
- name: Run a cmd command
win_command: cmd.exe /c mkdir C:\temp
- name: Run a vbs script
win_command: cscript.exe script.vbs
Примечание
Некоторые команды, например mkdir, del и copy, существуют только в оболочке CMD. Чтобы запустить их с помощью win_command, перед ними необходимо добавить cmd.exe /c.
Правила обработки аргументов
При выполнении команды через win_command действуют стандартные правила обработки аргументов Windows:
- Аргументы разделяются пробелами, которыми могут быть обычные пробелы или табуляция.
- Аргумент можно заключить в двойные кавычки
". Всё содержимое этих кавычек считается одним аргументом, даже если в нём есть пробельные символы. - Двойная кавычка, перед которой стоит обратная косая черта
\, интерпретируется как обычная двойная кавычка", а не как разделитель аргументов. - Обратные косые черты интерпретируются буквально, если непосредственно за ними не следует двойная кавычка; например,
\==\и\"==" - Если за чётным количеством обратных косых черт следует двойная кавычка, в аргументе используется по одной обратной косой черте на каждую пару, а двойная кавычка служит разделителем строки аргумента.
- Если за нечётным количеством обратных косых черт следует двойная кавычка, в аргументе используется по одной обратной косой черте на каждую пару, а двойная кавычка экранируется и становится буквальной двойной кавычкой в аргументе.
С учётом этих правил рассмотрим несколько примеров использования кавычек:
- win_command: C:\temp\executable.exe argument1 "argument 2" "C:\path\with space" "double \"quoted\""
argv[0] = C:\temp\executable.exe
argv[1] = argument1
argv[2] = argument 2
argv[3] = C:\path\with space
argv[4] = double "quoted"
- win_command: '"C:\Program Files\Program\program.exe" "escaped \\\" backslash" unquoted-end-backslash\'
argv[0] = C:\Program Files\Program\program.exe
argv[1] = escaped \" backslash
argv[2] = unquoted-end-backslash\
# Due to YAML and Ansible parsing '\"' must be written as '{% raw %}\\{% endraw %}"'
- win_command: C:\temp\executable.exe C:\no\space\path "arg with end \ before end quote{% raw %}\\{% endraw %}"
argv[0] = C:\temp\executable.exe
argv[1] = C:\no\space\path
argv[2] = arg with end \ before end quote\"
Дополнительные сведения см. в разделе экранирование аргументов.
Создание и запуск запланированной задачи
В WinRM действуют некоторые ограничения, из-за которых при выполнении определённых команд возникают ошибки. Один из способов обойти эти ограничения — выполнить команду через запланированную задачу. Запланированная задача — это компонент Windows, позволяющий запускать исполняемый файл по расписанию и от имени другой учётной записи.
В Ansible версии 2.5 появились модули, упрощающие работу с запланированными задачами в Windows. Ниже приведён пример запуска скрипта в качестве запланированной задачи, которая удаляет себя после выполнения:
- name: Create scheduled task to run a process
win_scheduled_task:
name: adhoc-task
username: SYSTEM
actions:
- path: PowerShell.exe
arguments: |
Start-Sleep -Seconds 30 # This isn't required, just here as a demonstration
New-Item -Path C:\temp\test -ItemType Directory
# Remove this action if the task shouldn't be deleted on completion
- path: cmd.exe
arguments: /c schtasks.exe /Delete /TN "adhoc-task" /F
triggers:
- type: registration
- name: Wait for the scheduled task to complete
win_scheduled_task_stat:
name: adhoc-task
register: task_stat
until: (task_stat.state is defined and task_stat.state.status != "TASK_STATE_RUNNING") or (task_stat.task_exists == False)
retries: 12
delay: 10
Примечание
Модули, использованные в приведённом выше примере, были обновлены или добавлены в Ansible версии 2.5.
Форматирование путей в Windows
Windows во многом отличается от традиционных операционных систем POSIX. Одно из главных отличий — замена / в качестве разделителя пути на \. Это может привести к серьёзным проблемам при написании плейбуков, поскольку в системах POSIX \ часто используется как символ экранирования.
Ansible поддерживает два разных синтаксиса, в каждом из которых по-разному обрабатываются разделители путей Windows:
Синтаксис YAML
При использовании синтаксиса YAML для задач действуют чёткие правила, определённые стандартом YAML:
- При использовании обычной строки (без кавычек) YAML не считает обратную косую черту символом экранирования.
- При использовании одинарных кавычек
'YAML не считает обратную косую черту символом экранирования. - При использовании двойных кавычек
"обратная косая черта считается символом экранирования, поэтому её нужно экранировать ещё одной обратной косой чертой.
Примечание
Заключайте строки в кавычки только при крайней необходимости или если этого требует YAML; в таком случае используйте одинарные кавычки.
Спецификация YAML определяет следующие последовательности экранирования:
-
\0,\\,\",\_,\a,\b,\e,\f,\n,\r,\t,\v,\L,\Nи\P— экранирование одного символа -
<TAB>,<SPACE>,<NBSP>,<LNSP>,<PSP>— специальные символы -
\x..— шестнадцатеричное экранирование из 2 цифр -
\u....— шестнадцатеричное экранирование из 4 цифр -
\U........— шестнадцатеричное экранирование из 8 цифр
Ниже приведены примеры записи путей Windows:
# GOOD tempdir: C:\Windows\Temp # WORKS tempdir: 'C:\Windows\Temp' tempdir: "C:\\Windows\\Temp" # BAD, BUT SOMETIMES WORKS tempdir: C:\\Windows\\Temp tempdir: 'C:\\Windows\\Temp' tempdir: C:/Windows/Temp
Следующий пример не сработает:
# FAILS tempdir: "C:\Windows\Temp"
В этом примере показано использование одинарных кавычек в случаях, когда они необходимы:
---
- name: Copy tomcat config
win_copy:
src: log4j.xml
dest: '{{tc_home}}\lib\log4j.xml'
Устаревший синтаксис key=value
Устаревший синтаксис key=value используется в командной строке для разовых команд или в плейбуках. Не рекомендуется использовать этот синтаксис в плейбуках, поскольку символы обратной косой черты нужно экранировать, что затрудняет чтение плейбуков. Устаревший синтаксис зависит от конкретной реализации в Ansible, а заключение значений в кавычки (одинарные или двойные) никак не влияет на их разбор Ansible.
Парсер Ansible для синтаксиса key=value parse_kv() обрабатывает следующие последовательности экранирования:
-
\,',",\a,\b,\f,\n,\r,\tи\v— экранирование одного символа -
\x..— шестнадцатеричное экранирование из 2 цифр -
\u....— шестнадцатеричное экранирование из 4 цифр -
\U........— шестнадцатеричное экранирование из 8 цифр -
\N{...}— символ Unicode по имени
Это означает, что в некоторых последовательностях обратная косая черта служит символом экранирования, поэтому обычно безопаснее экранировать обратную косую черту при использовании этого синтаксиса.
Ниже приведены примеры использования путей Windows с синтаксисом key=value:
# GOOD tempdir=C:\\Windows\\Temp # WORKS tempdir='C:\\Windows\\Temp' tempdir="C:\\Windows\\Temp" # BAD, BUT SOMETIMES WORKS tempdir=C:\Windows\Temp tempdir='C:\Windows\Temp' tempdir="C:\Windows\Temp" tempdir=C:/Windows/Temp # FAILS tempdir=C:\Windows\temp tempdir='C:\Windows\temp' tempdir="C:\Windows\temp"
Примеры с ошибками не приводят к сбою, но вместо \t подставляется символ <TAB>, в результате чего tempdir становится C:\Windows<TAB>emp.
Ограничения
С помощью Ansible в Windows нельзя:
- Обновить PowerShell
- Взаимодействовать с прослушивателями WinRM
Поскольку для нормальной работы WinRM требуется, чтобы службы были доступны и запущены, с помощью Ansible нельзя обновить PowerShell или взаимодействовать с прослушивателями WinRM. Оба этих действия приведут к сбою подключения. Технически этого можно избежать, используя async или запланированную задачу, однако эти методы ненадёжны, если выполняемый процесс нарушает базовое подключение, используемое Ansible. Поэтому такие действия лучше оставить для первоначальной настройки или выполнять до создания образа.
Разработка модулей Windows
Поскольку модули Ansible для Windows написаны на PowerShell, руководства по разработке модулей Windows значительно отличаются от руководств по разработке стандартных модулей. Дополнительные сведения см. в разделе Пошаговое руководство по разработке модулей Windows.
См. также
- Плейбуки Ansible
-
Введение в плейбуки
- Советы и рекомендации по Ansible
-
Советы и рекомендации по работе с плейбуками
- Список модулей Windows
-
Список модулей для Windows, все они реализованы на PowerShell
- Общение
-
Есть вопросы? Нужна помощь? Хотите поделиться идеями? Ознакомьтесь с руководством по общению в сообществе Ansible
© 2012–2018 Michael DeHaan
© 2018–2025 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/projects/ansible/latest/os_guide/windows_usage.html