ADG Оставить заявку
Блог Автоматизация 5 мин чтения

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 и понять, насколько это уже рабочее.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.