Ansible 2.2 и Windows через WinRM: IIS, Firewall и DNS без единого PowerShell вручную
Ansible 2.2 вышел с заметно улучшенной поддержкой Windows через WinRM. Конфигурируем IIS, Windows Firewall и DNS без прямого PowerShell-скрипта на сервере.
Ansible 2.2 вышел с расширенной поддержкой Windows через WinRM, новыми модулями для облачных провайдеров и улучшенной работой с сетевыми устройствами
Ansible 2.2 вышел, и главное что нас интересовало в анонсе - это Windows. Не как дополнительная возможность «и на Windows тоже можно», а как реально пригодный инструмент для повседневной работы с Windows-серверами через WinRM.
До 2.2 Windows-поддержка в Ansible была неполной: модули были, WinRM-подключение работало, но периодически нужно было делать вещи, которые просто не покрывались готовыми модулями. Скрипт на PowerShell - и забыли. С одной стороны удобно, с другой - это дыра в идемпотентности: win_shell выполняет команду каждый раз при запуске, и «было ли изменение» уже не ответить.
Как это работает вообще
Для работы с Windows Ansible использует WinRM - Windows Remote Management, стандартный протокол удалённого управления от Microsoft. На Linux-стороне нужен python-пакет pywinrm, на Windows - настроенный WinRM-listener. Никакого агента, никакой установки чего-то постороннего на целевой сервер.
Конфигурация инвентаря минимальная:
[windows]
win-srv-01.example.ru
[windows:vars]
ansible_user=Administrator
ansible_password={{ vault_win_password }}
ansible_connection=winrm
ansible_winrm_transport=ntlm
ansible_winrm_server_cert_validation=ignore
ansible_winrm_server_cert_validation=ignore - это для внутреннего PKI где сертификаты самоподписанные или выданы корпоративным CA которого нет в доверенных на ansible-хосте. Для production с нормальным PKI лучше добавить CA в доверенные и убрать этот параметр.
Что в 2.2 появилось нового
Набор Windows-модулей в 2.2 стал заметно шире. Из того что нам нужно прямо сейчас:
win_iis_websiteиwin_iis_webapppool. Управление IIS-сайтами и пулами приложений. Создать сайт, настроить привязку к порту и SSL-сертификату, запустить или остановить - безappcmdи без PowerShell-скриптов вручную.win_firewall_rule. Правила Windows Firewall. Раньше это был классическийwin_shell: netsh advfirewall..., и idempotency там условная - каждый запуск playbook создавал дубликат правила или падал с ошибкой если правило уже есть.win_service. Не новый модуль, но в 2.2 он стал надёжнее - раньше бывали ситуации когда статус службы возвращался некорректно.
Конкретный playbook: разворачиваем IIS-сайт
Задача реальная: новый Windows Server 2016, нужно поднять IIS-сайт на 443 с конкретным SSL-сертификатом, настроить application pool с нужной учёткой, пробросить правило в Firewall.
- name: Настройка IIS-сайта
hosts: windows
gather_facts: false
tasks:
- name: Установить роль IIS
win_feature:
name: Web-Server
state: present
include_management_tools: yes
- name: Создать application pool
win_iis_webapppool:
name: MyAppPool
state: started
attributes:
processModel.userName: "DOMAIN\\svc_webapp"
processModel.password: "{{ vault_svc_password }}"
processModel.identityType: 3
- name: Создать сайт
win_iis_website:
name: MyApp
state: started
port: 443
ssl: yes
ip: "*"
application_pool: MyAppPool
physical_path: 'C:\inetpub\myapp'
- name: Открыть порт 443 в Firewall
win_firewall_rule:
name: "Allow HTTPS MyApp"
localport: 443
action: allow
direction: in
protocol: tcp
state: present
enabled: yes
При первом запуске - всё создаётся. При повторном - Ansible проверяет текущее состояние, видит что сайт уже есть в нужной конфигурации, и ничего не меняет. changed: 0. Именно это и нужно от инструмента автоматизации.
Где идемпотентность ещё не идеальна
Честно: не везде всё работает так как хочется. win_iis_website плохо понимает изменения SSL-биндинга - если нужно сменить сертификат на сайте, модуль не всегда корректно определяет что биндинг изменился и нужно обновление. Приходится убирать биндинг вручную или через win_shell как временное решение.
win_firewall_rule тоже иногда создаёт дубликаты если запускать playbook под разными пользователями - правила хранятся с привязкой к контексту и модуль не всегда их корректно сравнивает. Мелочь, но неприятная.
Структура: Linux управляет Windows
Интересный момент который поначалу вызывает вопросы у коллег: сам Ansible запускается на Linux (или Mac), а целевые хосты - Windows. Это немного непривычно, если раньше всегда работал с PSRemoting или RSAT. Но на практике это удобно: единый ansible-контроллер управляет и Linux, и Windows хостами, playbook-и лежат в одном Git-репозитории, и логика примерно одинаковая вне зависимости от ОС целевого сервера.
Для управляемых инфраструктур это особенно полезно на смешанных средах - когда у клиента часть серверов Linux, часть Windows, и нужно единообразие в подходе к изменениям.
DNS через Ansible
Управление DNS-записями на Windows-сервере пока живёт через win_shell с PowerShell. Готового идемпотентного модуля для DNS в 2.2 нет, поэтому пишем задачу руками:
- name: Добавить A-запись для нового сервера
win_shell: |
if (-not (Get-DnsServerResourceRecord -ZoneName example.ru -Name "{{ inventory_hostname_short }}" -RRType A -ErrorAction SilentlyContinue)) {
Add-DnsServerResourceRecord -ZoneName example.ru -A -Name "{{ inventory_hostname_short }}" -IPv4Address "{{ ansible_host }}"
}
Идемпотентность ручная - проверяем наличие записи перед добавлением. Некрасиво, но работает. Нормальный модуль для DNS-записей в планах у сообщества, пока его нет.
Где сейчас
Мы перевели несколько Windows-серверов в managed-режим через Ansible 2.2. Пока это тестовые и pre-production окружения, но поведение стабильное. Основные ручные операции при разворачивании нового Windows-сервера - установка ролей, настройка IIS, правила Firewall, DNS - уже покрыты playbook-ами.
Остаётся несколько вещей которые ещё живут как win_shell с PowerShell внутри: всё что касается AD - создание пользователей, группы, GPO. Модули есть, но мы их не тестировали достаточно, чтобы доверять в production. Следующий шаг - разобраться с win_domain_user и понять, насколько это уже рабочее.
- Ansible 2.1: сетевые модули и конфигурация Cisco в Git · 25 июля 2016
- PowerShell 5.1 в Windows Server 2016: переписываем bat-скрипты администрирования · 10 августа 2016