Эта статья про то, как перестать бегать по клиентским машинам, открывать по десять RDP-окон и вручную чинить то, что должно работать автоматически.

Мы переехали семьей из другой страны, и пока занимались получением гражданства, я устроился на работу с довольно минималистичной IT-инфраструктурой. Команда небольшая, ресурсов мало, и многое приходилось делать вручную. Ни домена, ни мониторинга, ни централизованных инструментов - всё через Radmin, по одной машине за раз. Парк - 75 рабочих станций. Любая задача ощущалась как квест.

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

Ну ок. Раз никто не хочет дать ресурсы - сделаю сам. Нашёл старый компьютер, сдул с него пыль и развернул на нём Ubuntu Server 24.04 LTS и решил на этом построить автоматизацию. Описывать установку смысла нет - гайды в интернете есть на каждый шаг.


1. Ставим Ansible

А на клиентских Windows запускаем официальный скрипт для настройки WinRM:

После этого начинается самое интересное - создаём инвентарь, группируем офисы, выстраиваем структуру.


Структура проекта, которую будем расширять

project/
|---inventory.yml
|---group_vars/
|      |--windows.yml
|---playbooks/
|      |--ping.yml

Теперь наш inventory.yml

all:
  children:
    windows:
      children:
        Office_A:
        Office_B:
        Office_C:
 
    Office_A:
      hosts:
        winhost101.local:
          ansible_host: 10.10.1.101
          fullname: "Сотрудник А101"
        winhost102.local:
          ansible_host: 10.10.1.102
          fullname: "Сотрудник А102"
        winhost103.local:
          ansible_host: 10.10.1.103
          fullname: "Сотрудник А103"
 
    Office_B:
      hosts:
        winhost201.remote:
          ansible_host: 203.0.113.51
          ansible_winrm_port: 10086
          fullname: "Офис B - Рабочее место 1"
        winhost202.remote:
          ansible_host: 203.0.113.51
          ansible_winrm_port: 10087
          fullname: "Офис B - Рабочее место 2"
          
    Office_C:
      hosts:
        winhost301.remote:
          ansible_host: 198.51.100.52
          ansible_winrm_port: 10086
          fullname: "Офис C - Рабочее место 1"
 

Чтобы не дублировать настройки на каждом хосте, создаём group_vars/windows.yml

ansible_user: Admin
ansible_password: Pa$$w0rd
ansible_port: 5986
ansible_connection: winrm
ansible_winrm_transport: basic
ansible_winrm_server_cert_validation: ignore

Ну вот у нас есть инвентарь и включен WinRM, логично сделать самый базовый тест - убедиться, что Ansible реально может зайти на машины в playbooks/ping.yml.

---
- name: Ping all Windows hosts
  hosts: windows
  tasks:
    - name: ping
      win_ping:

Запуск:

ansible-playbook -i inventory.yml playbooks/ping.yml

2. Поднимаем Zabbix в Docker

Когда управление Windows через Ansible заработало, следующая логичная штука - нормальный мониторинг. Без него автоматизация превращается в игру “угадай, что сломалось”. Да, можно вручную проверять, но мы уже уехали с ручников - пора ставить Zabbix

Минимальный рабочий docker-compose.yml

services:
  db:
   image: postgres:15
   environment:
     POSTGRES_USER: zabbix
     POSTGRES_PASSWORD: zabbix
     POSTGRES_DB: zabbix
   volumes:
     - ./db:/var/lib/postgresql/data
   restart: always
  
  zabbix-server:
    image: zabbix/zabbix-server-pgsql:alpine-latest
    environment:
      DB_SERVER_HOST: db
      POSTGRES_USER: zabbix
      POSTGRES_PASSWORD: zabbix
      POSTGRES_DB: zabbix
    depends_on:
      - db
    ports:
      - "10051:10051"
    restart: always
 
  zabbix-web:
    image: zabbix/zabbix-web-apache-pgsql:alpine-latest
    environment:
      DB_SERVER_HOST: db
      POSTGRES_USER: zabbix
      POSTGRES_PASSWORD: zabbix
      POSTGRES_DB: zabbix
      PHP_TZ: Asia/Novosibirsk
      ZBX_SERVER_HOST: zabbix-server
      ZBX_SERVER_PORT: 10051
    ports:
      - "8080:8080"
    depends_on:
      - zabbix-server
    restart: always
 
  agent:
    image: zabbix/zabbix-agent:alpine-latest
    ports:
      - "10050:10050"
    environment:
      ZBX_SERVER_HOST: zabbix-server
    depends_on:
      - zabbix-server
    restart: always

P.S.

Осознаю, что в крупных организациях подобные системы обычно строят иначе: используют выделенные серверы, раздельные роли и более сложную архитектуру. Это действительно правильный подход, когда есть ресурсы и возможность проектировать инфраструктуру “как в учебнике”.

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