Ansible Master
Предварительная настройка
Установка пакетов
sudo apt install -y ansible sshpass dpkg-dev apt-utils git
Создание структуры проекта
sudo mkdir -p /opt/ansible
sudo chown $USER: /opt/ansible
cd /opt/ansible
mkdir -p inventory/production/group_vars playbooks roles/offline_packages/{tasks,defaults} logs
git init
echo -e "logs/\n*.retry\n.vault_pass" > .gitignore
Файл ansible.cfg
ansible.cfg
cat > /opt/ansible/ansible.cfg <<'EOF'
[defaults]
inventory = inventory/production/hosts.yml
roles_path = roles
remote_user = ansible
private_key_file = ~/.ssh/ansible_ed25519
host_key_checking = False
forks = 20
retry_files_enabled = False
interpreter_python = auto_silent
log_path = logs/ansible.log
[privilege_escalation]
become = True
become_method = sudo
[ssh_connection]
pipelining = True
EOF
Генерация SSH-ключа
ssh-keygen -t ed25519 -f ~/.ssh/ansible_ed25519 -N "" -C "ansible-master"
Генерация inventory файла
scan-inventory.sh
cat > /opt/ansible/scan-inventory.sh <<'EOF'
#!/bin/bash
# Использование: ./scan-inventory.sh [подсеть] [исключения]
set -euo pipefail
NET=${1:-192.168.10.0/24}
EXCLUDE=${2:-192.168.10.1} # сам сервер и другие адреса через запятую
OUT=/opt/ansible/inventory/production/hosts.yml
TMP=$(mktemp)
[ -f "$OUT" ] && cp "$OUT" "$OUT.bak.$(date +%F_%H%M)"
nmap -n -p 22 --open --exclude "$EXCLUDE" -oG - "$NET" \
| awk '/22\/open/{print $2}' | sort -V > "$TMP"
{
echo "all:"
echo " children:"
echo " astra_clients:"
echo " hosts:"
while read -r ip; do
echo " pc-${ip//./-}: { ansible_host: $ip }"
done < "$TMP"
} > "$OUT"
echo "Найдено хостов с SSH: $(wc -l < "$TMP") -> $OUT"
rm -f "$TMP"
EOF
chmod +x /opt/ansible/scan-inventory.sh
Запуск скрипта сканирования сети
/opt/ansible/scan-inventory.sh 192.168.10.0/24 192.168.10.1
Файл bootstrap
Создаёт на клиентах пользователя ansible с ключом и sudo. Он выполняется один раз под admin.
bootstrap.yml
cat > playbooks/bootstrap.yml <<'EOF'
---
- name: Создать служебного пользователя ansible
hosts: astra_clients
become: true
tasks:
- name: Пользователь ansible
ansible.builtin.user:
name: ansible
shell: /bin/bash
create_home: true
- name: Публичный ключ
ansible.posix.authorized_key:
user: ansible
key: "{{ lookup('file', '~/.ssh/ansible_ed25519.pub') }}"
- name: sudo без пароля
ansible.builtin.copy:
dest: /etc/sudoers.d/ansible
content: "ansible ALL=(ALL) NOPASSWD:ALL\n"
mode: "0440"
validate: "visudo -cf %s"
EOF
Единый playbook
site.yml
cat > playbooks/site.yml <<'EOF'
---
# 1. Кто уже пускает под ansible
- name: Проверка доступа под учёткой ansible
hosts: astra_clients
gather_facts: false
become: false
tasks:
- name: Проверить вход
ansible.builtin.ping:
ignore_unreachable: true
register: access_check
- name: Разложить хосты по группам access_ok / access_missing
ansible.builtin.group_by:
key: "access_{{ 'missing' if (access_check.unreachable | default(false)) else 'ok' }}"
# 2. Пароль admin спрашиваем только если есть новые ПК
- name: Запрос пароля admin
hosts: localhost
connection: local
gather_facts: false
become: false
tasks:
- name: Ввод пароля
when: groups['access_missing'] | default([]) | length > 0
block:
- name: Пароль admin
ansible.builtin.pause:
prompt: "Пароль admin на новых клиентах ({{ groups['access_missing'] | length }} шт.)"
echo: false
register: admin_pw
- name: Запомнить пароль на время прогона
ansible.builtin.set_fact:
bootstrap_password: "{{ admin_pw.user_input }}"
no_log: true
# 3. Создание учётки ansible на новых ПК
- name: Bootstrap новых клиентов
hosts: access_missing
gather_facts: false
become: true
vars:
ansible_user: admin
ansible_password: "{{ hostvars['localhost'].bootstrap_password }}"
ansible_become_password: "{{ hostvars['localhost'].bootstrap_password }}"
roles:
- bootstrap
# 4. Пакеты на всех
- name: Офлайн-установка пакетов
hosts: astra_clients
become: true
serial: 10
roles:
- offline_packages
EOF