Planetahost VPS
Перейти к основному контенту

Ansible #12: Массовая настройка Linux-серверов

intro-Ansible-12-Mass-Configuration-of-Linux-Servers-planetahost.png

Подробности урока
Уровень сложности Лёгкий
Права root Требуются
Требования Терминал Linux
Категория Установка ПО
Совместимость с ОС Debian, Ubuntu
Примерное время чтения  20 мин

Введение

В предыдущей статье мы настроили отдельного пользователя, SSH-ключ и безопасный доступ к серверу. Теперь соберем все эти действия в единый сценарий.

Представим, что необходимо подготовить сразу несколько новых Linux-серверов. На каждом из них нужно выполнить примерно один и тот же набор операций:

  • обновить список пакетов;

  • установить базовые утилиты;

  • настроить часовой пояс;

  • установить и запустить необходимые системные службы;

  • создать пользователя для администрирования;

  • добавить SSH-ключ;

  • настроить sudo;

  • привести SSH к единому состоянию;

  • задать hostname.

Вручную это означает подключаться к каждому серверу и повторять одни и те же команды. С Ansible достаточно описать необходимое состояние один раз и запустить один Playbook.

Подготовка Inventory

Для примера возьмем три сервера:

[web]
web1 ansible_host=192.168.88.40
web2 ansible_host=192.168.88.41

На новых серверах Ansible пока подключается под root.

Проверяем доступ:

ansible -i inventory web -m ping -u root

Если все серверы доступны:

изображение.png

можно переходить к подготовке.

Обновление списка пакетов

Начнем с обновления информации о пакетах:

- name: Обновление списка пакетов
  ansible.builtin.apt:
    update_cache: true

Для Debian и Ubuntu этого достаточно, чтобы обновить локальный индекс APT.

Саму полную систему на этом этапе обновлять необязательно. В инфраструктуре обновление пакетов и первоначальная настройка сервера часто являются отдельными процессами.

Установка базовых пакетов

На новом сервере обычно нужны хотя бы базовые инструменты:

- name: Установка базовых пакетов
  ansible.builtin.apt:
    name:
      - curl
      - wget
      - vim
      - htop
      - unzip
      - ca-certificates
    state: present

Здесь используется список пакетов.

Ansible самостоятельно проверит, установлены ли они уже. Поэтому повторный запуск Playbook не будет каждый раз устанавливать пакеты заново.

Настройка часового пояса

Для серверов важно использовать одинаковый часовой пояс.

Например, установим:

Europe/Moscow

Для этого можно использовать модуль community.general.timezone.

Если коллекция еще не установлена:

ansible-galaxy collection install community.general

После этого добавляем:

- name: Настройка часового пояса
  community.general.timezone:
    name: Europe/Moscow

Проверить результат на сервере можно:

timedatectl

Настройка времени

Для корректной работы журналов, сертификатов, баз данных и систем мониторинга серверы должны иметь правильное время. На Debian и Ubuntu можно использовать systemd-timesyncd.

Установим и запустим его:

- name: Установка systemd-timesyncd
  ansible.builtin.apt:
    name: systemd-timesyncd
    state: present

- name: Запуск синхронизации времени
  ansible.builtin.service:
    name: systemd-timesyncd
    state: started
    enabled: true

После этого проверить состояние можно:

timedatectl status

Создание административного пользователя

Теперь создадим пользователя deploy.

- name: Создание пользователя deploy
  ansible.builtin.user:
    name: deploy
    shell: /bin/bash
    create_home: true
    state: present

Добавим его в группу sudo:

- name: Добавление deploy в группу sudo
  ansible.builtin.user:
    name: deploy
    groups: sudo
    append: true

При необходимости устанавливаем сам sudo:

- name: Установка sudo
  ansible.builtin.apt:
    name: sudo
    state: present

Добавление SSH-ключа

Для входа под deploy используем SSH-ключ.

В начале Playbook можно определить переменную:

vars:
  ssh_public_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@pc"

Затем добавить ключ:

- name: Добавление SSH-ключа
  ansible.posix.authorized_key:
    user: deploy
    state: present
    key: "{{ ssh_public_key }}"

Если коллекция ansible.posix еще не установлена:

ansible-galaxy collection install ansible.posix

Настройка sudo

Создадим отдельное правило:

- name: Создание каталога sudoers.d
  ansible.builtin.file:
    path: /etc/sudoers.d
    state: directory
    owner: root
    group: root
    mode: '0755'

- name: Разрешение sudo без пароля
  ansible.builtin.copy:
    dest: /etc/sudoers.d/deploy
    content: "deploy ALL=(ALL) NOPASSWD: ALL\n"
    owner: root
    group: root
    mode: '0440'

Теперь пользователь deploy сможет выполнять административные команды через sudo.

Например:

sudo systemctl restart nginx

Настройка SSH

После того как пользователь и SSH-ключ созданы, можно отключить небезопасные варианты входа.

Запретим SSH-вход под root:

- name: Запрет входа root через SSH
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^#?PermitRootLogin'
    line: 'PermitRootLogin no'
    validate: '/usr/sbin/sshd -t -f %s'
  notify: Перезапуск SSH

Отключим авторизацию по паролю:

- name: Отключение авторизации по паролю
  ansible.builtin.lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^#?PasswordAuthentication'
    line: 'PasswordAuthentication no'
    validate: '/usr/sbin/sshd -t -f %s'
  notify: Перезапуск SSH

Handler:

handlers:
  - name: Перезапуск SSH
    ansible.builtin.service:
      name: ssh
      state: restarted

Как и в предыдущей статье, обязательно проверяем новый SSH-доступ до закрытия текущего root-сеанса.

Настройка hostname

Для нескольких серверов полезно задать понятные имена.

В Inventory можно добавить:

[servers]
server1 ansible_host=192.168.88.40 hostname=web-01
server2 ansible_host=192.168.88.41 hostname=web-02
server3 ansible_host=192.168.88.42 hostname=web-03

А в Playbook:

- name: Настройка hostname
  ansible.builtin.hostname:
    name: "{{ hostname }}"

Теперь каждый сервер получит собственное имя.

Проверить его можно:

hostnamectl
Масштабируйте автоматизацию на несколько серверов
Проверьте автоматическую подготовку целой группы Linux-серверов: установку пакетов, настройку времени, hostname, пользователей и SSH. Несколько VDS помогут собрать полноценный стенд и увидеть, как Ansible упрощает типовые административные задачи.
Развернуть инфраструктуру

Полный Playbook

Теперь объединим всё в один сценарий.

---
- name: Первоначальная настройка Linux-серверов
  hosts: servers

  vars:
    ssh_public_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@pc"

  tasks:
    - name: Обновление списка пакетов
      ansible.builtin.apt:
        update_cache: true

    - name: Установка базовых пакетов
      ansible.builtin.apt:
        name:
          - curl
          - wget
          - vim
          - htop
          - unzip
          - ca-certificates
          - sudo
        state: present

    - name: Настройка часового пояса
      community.general.timezone:
        name: Europe/Moscow

    - name: Установка systemd-timesyncd
      ansible.builtin.apt:
        name: systemd-timesyncd
        state: present

    - name: Запуск синхронизации времени
      ansible.builtin.service:
        name: systemd-timesyncd
        state: started
        enabled: true

    - name: Настройка hostname
      ansible.builtin.hostname:
        name: "{{ hostname }}"

    - name: Создание пользователя deploy
      ansible.builtin.user:
        name: deploy
        shell: /bin/bash
        create_home: true
        state: present

    - name: Добавление deploy в группу sudo
      ansible.builtin.user:
        name: deploy
        groups: sudo
        append: true

    - name: Добавление SSH-ключа
      ansible.posix.authorized_key:
        user: deploy
        state: present
        key: "{{ ssh_public_key }}"

    - name: Создание каталога sudoers.d
      ansible.builtin.file:
        path: /etc/sudoers.d
        state: directory
        owner: root
        group: root
        mode: '0755'

    - name: Разрешение sudo без пароля
      ansible.builtin.copy:
        dest: /etc/sudoers.d/deploy
        content: "deploy ALL=(ALL) NOPASSWD: ALL\n"
        owner: root
        group: root
        mode: '0440'

    - name: Запрет входа root через SSH
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^#?PermitRootLogin'
        line: 'PermitRootLogin no'
        validate: '/usr/sbin/sshd -t -f %s'
      notify: Перезапуск SSH

    - name: Отключение авторизации по паролю
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^#?PasswordAuthentication'
        line: 'PasswordAuthentication no'
        validate: '/usr/sbin/sshd -t -f %s'
      notify: Перезапуск SSH

  handlers:
    - name: Перезапуск SSH
      ansible.builtin.service:
        name: ssh
        state: restarted

Inventory с индивидуальными hostname

Для полного примера Inventory будет выглядеть так:

[servers]
server1 ansible_host=192.168.88.40 hostname=web-01
server2 ansible_host=192.168.88.41 hostname=web-02
server3 ansible_host=192.168.88.42 hostname=web-03

Теперь один и тот же Playbook можно применить сразу к трем серверам.

Установка необходимых коллекций

Перед запуском убедимся, что установлены используемые коллекции:

ansible-galaxy collection install ansible.posix community.general

Проверить установленные коллекции:

ansible-galaxy collection list

изображение.png

Проверка Playbook

Перед реальным запуском сначала проверяем синтаксис:

ansible-playbook -i inventory bootstrap.yml --syntax-check

изображение.png

Если ошибок нет, можно выполнить проверку в режиме --check:

ansible-playbook -i inventory bootstrap.yml -u root --check

И только после этого выполнить реальные изменения:

ansible-playbook -i inventory bootstrap.yml -u root

Что произойдет при запуске

Ansible пройдет по каждому серверу из группы servers.

Например:

server1
server2
server3

На каждом сервере будут выполнены одинаковые действия:

  1. Обновится индекс пакетов.

  2. Установятся необходимые утилиты.

  3. Настроится часовой пояс.

  4. Запустится синхронизация времени.

  5. Изменится hostname.

  6. Создастся пользователь deploy.

  7. Пользователь получит SSH-ключ.

  8. Настроится sudo.

  9. Будет изменена конфигурация SSH.

  10. SSH перезапустится только при необходимости.

В результате три новых сервера будут приведены к одному базовому состоянию.

изображение.png

Проверка результата

После завершения Playbook можно проверить серверы обычными командами.

Hostname:

hostnamectl

Пользователь:

id deploy

Часовой пояс:

timedatectl

Состояние времени:

timedatectl status

Проверка sudo:

sudo whoami

SSH:

ssh deploy@192.168.88.40

изображение.png

Повторный запуск

Попробуем запустить Playbook еще раз:

ansible-playbook -i inventory bootstrap.yml -u root

Если серверы уже находятся в нужном состоянии, большая часть задач должна завершиться со статусом:

ok

а не:

changed

Это особенно важно при массовой настройке.

Playbook можно запускать повторно после добавления нового сервера в Inventory - Ansible применит необходимые изменения только к нему.

Почему это удобно

Представим, что сегодня необходимо подготовить три сервера, завтра - еще пять, а через месяц - еще десять.

Вместо ручного выполнения десятков команд достаточно добавить новые серверы в Inventory:

[servers]
server1 ansible_host=192.168.88.40 hostname=web-01
server2 ansible_host=192.168.88.41 hostname=web-02
server3 ansible_host=192.168.88.42 hostname=web-03
server4 ansible_host=192.168.88.43 hostname=web-04
server5 ansible_host=192.168.88.44 hostname=web-05

и снова запустить тот же Playbook. Ansible самостоятельно подготовит новые серверы. При этом конфигурация остается описанной в одном месте и не зависит от того, сколько серверов необходимо настроить.

Заключение

В этой статье мы собрали единый Playbook для первоначальной подготовки нескольких Linux-серверов.

Теперь вместо ручной настройки каждого нового сервера можно добавить его в Inventory и запустить один сценарий. Ansible установит необходимые пакеты, настроит время и hostname, создаст административного пользователя, добавит SSH-ключ и приведет SSH-конфигурацию к заданному состоянию.

В следующей статье рассмотрим AWX: установим веб-интерфейс для управления Ansible, подключим Git-репозиторий и научимся запускать Playbook через браузер.