Поиск по сайту:

Как автоматизировать первоначальную настройку нескольких серверов Ubuntu 22.04 с помощью Ansible


Автор выбрал программу Write for DOnations.

Введение

книги по автоматизации.

Ansible работает без агентов, поэтому вам не нужно устанавливать какие-либо компоненты Ansible на серверы, на которых вы хотите запускать Ansible. Эти серверы являются узлами Ansible и должны работать под управлением Windows. Подсистема для Linux (WSL) установлена.

В этом руководстве вы будете использовать Ansible для автоматизации начальной настройки нескольких серверов Ubuntu 22.04. Вы выполните следующие задачи начальной настройки на всех серверах:

  • Обновление установленных пакетов
  • Добавление пользователя без полномочий root с правами администратора
  • Включение доступа по SSH для этого пользователя без полномочий root
  • Включение брандмауэра
  • Изменение порта для доступа по SSH и использование брандмауэра для защиты от атак грубой силы и повышения общей безопасности серверов
  • Отключение удаленного входа для учетной записи root
  • Убедиться, что важные службы активны.
  • Удаление зависимостей пакетов, которые больше не требуются

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

Предпосылки

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

  • Ansible установлен на машине, которая будет действовать как ваш управляющий узел, это может быть ваша локальная машина или удаленный сервер Linux. Чтобы установить Ansible, выполните шаг 1 официального руководства по установке Ansible, если это необходимо для других операционных систем.
    • Если вашим управляющим узлом является удаленный сервер Ubuntu 22.04, не забудьте также настроить его с помощью пары ключей SSH.
    • Git установлен на управляющем узле. Следуйте руководствам How To Install Git для популярных дистрибутивов Linux.
    • (Необязательно) В разделе «Настройка редактора Ansible Vault» в руководстве «Как использовать Ansible Vault» измените текстовый редактор, связанный с переменной оболочки EDITOR. В этом руководстве в качестве редактора для Ansible Vault будет использоваться nano.

    Два или более серверов Ubuntu 22.04 и общедоступный IPv4-адрес каждого сервера. Предварительная настройка не требуется, так как вы будете использовать Ansible для автоматизации настройки на шаге 5, но у вас должен быть SSH-доступ к этим серверам с упомянутого выше узла управления Ansible. Если вы используете дроплеты DigitalOcean, вы найдете IPv4-адрес в разделе «Общедоступная сеть» каждого сервера на вкладке «Сеть» на панели инструментов.

    • Если вашим управляющим узлом является удаленный сервер Ubuntu 22.04, обязательно используйте ssh-copy-id для подключения пары ключей к хостам.

    Шаг 1 — Изменение файла конфигурации клиента SSH на вашем узле управления

    На этом шаге вы измените директиву в файле конфигурации SSH-клиента вашего управляющего узла. После внесения этого изменения вам больше не будет предлагаться принять отпечаток ключа SSH удаленных компьютеров, так как они будут приниматься автоматически. Ручное принятие отпечатков ключей SSH для каждой удаленной машины может быть утомительным, поэтому эта модификация решает проблему масштабирования при использовании Ansible для автоматизации начальной настройки нескольких серверов.

    Хотя вы можете использовать модуль Ansible known_hosts для автоматического принятия отпечатка ключа SSH для одного хоста, в этом руководстве рассматривается несколько хостов, поэтому более эффективно изменить файл конфигурации клиента SSH на узле управления ( как правило, ваш локальный компьютер).

    Для начала запустите терминальное приложение на своем узле управления и с помощью nano или вашего любимого текстового редактора откройте файл конфигурации клиента SSH:

    1. sudo nano /etc/ssh/ssh_config

    Найдите строку, содержащую директиву StrictHostKeyChecking. Раскомментируйте его и измените значение, чтобы оно выглядело следующим образом:

    ...
       StrictHostKeyChecking accept-new
    ...
    

    Сохраните и закройте файл. Вам не нужно перезагружать или перезапускать демон SSH, потому что вы только изменили файл конфигурации клиента SSH.

    Примечание. Если вы не хотите постоянно менять значение StrictHostKeyChecking с ask на accept-new, вы можете вернуть его к значению по умолчанию. после запуска playbook на шаге 7. Хотя изменение значения будет означать, что ваша система автоматически принимает отпечатки ключей SSH, она будет отклонять последующие подключения с тех же хостов, если отпечатки изменятся. Эта функция означает, что изменение accept-new не представляет такой большой угрозы безопасности, как изменение значения этой директивы на no.

    Теперь, когда вы обновили директиву SSH, вы начнете настройку Ansible, что вы сделаете на следующих шагах.

    Шаг 2 — Настройка файла Ansible Hosts

    Файл hosts Ansible (также называемый файлом inventory) содержит информацию о хостах Ansible. Эта информация может включать имена групп, псевдонимы, доменные имена и IP-адреса. По умолчанию этот файл находится в каталоге /etc/ansible. На этом шаге вы добавите IP-адреса хостов Ansible, которые вы развернули, в разделе «Предварительные требования», чтобы вы могли запускать на них свой плейбук Ansible.

    Для начала откройте файл hosts с помощью nano или вашего любимого текстового редактора:

    1. sudo nano /etc/ansible/hosts

    После вводных комментариев в файл добавить следующие строки:

    ...
    
    host1 ansible_host=host1-public-ip-address
    host2 ansible_host=host2-public-ip-address
    host3 ansible_host=host3-public-ip-address
    
    [initial]
    host1
    host2
    host3
    
    [ongoing]
    host1
    host2
    host3
    

    host1, host2 и host3 являются псевдонимами для каждого хоста, на котором вы хотите автоматизировать первоначальную настройку сервера. Использование псевдонимов упрощает обращение к хостам в других местах. ansible_host — это переменная соединения Ansible, в данном случае указывающая на IP-адреса целевых хостов.

    initial и congoing — примеры имен групп для хостов Ansible. Выбирайте имена групп, чтобы было легко узнать, для чего используются хосты. Группировка хостов таким образом позволяет обращаться к ним как к единому блоку. Хосты могут принадлежать более чем к одной группе. Хосты в этом руководстве были назначены на две разные группы, потому что они будут использоваться в двух разных плейбуках: initial для первоначальной настройки сервера на шаге 8.

    hostN-public-ip-address — это IP-адрес для каждого хоста Ansible. Обязательно замените host1-public-ip-address и последующие строки IP-адресами серверов, которые будут частью автоматизации.

    Когда вы закончите изменять файл, сохраните и закройте его.

    Определение хостов в файле инвентаризации помогает указать, какие хосты будут настроены с помощью автоматизации Ansible. На следующем шаге вы клонируете репозиторий с образцами плейбуков, чтобы автоматизировать настройку нескольких серверов.

    Шаг 3 — Клонирование репозитория первоначальной настройки сервера Ansible Ubuntu

    На этом шаге вы клонируете образец репозитория из GitHub, содержащий необходимые файлы для этой автоматизации.

    Этот репозиторий содержит три файла для примера многосерверной автоматизации: initial.yml, ongoing.yml и vars/default.yml. Файл initial.yml – это основной сборник сценариев, содержащий сценарии и задачи, которые вы будете запускать на хостах Ansible для первоначальной настройки. Файл ongoing.yml содержит задачи, которые вы будете запускать на хостах для текущего обслуживания после первоначальной настройки сервера. Файл vars/default.yml содержит переменные, которые будут вызываться в обоих плейбуках на шаге 8.

    Чтобы клонировать репозиторий, введите следующую команду:

    1. git clone https://github.com/do-community/ansible-ubuntu.git

    В качестве альтернативы, если вы добавили свой ключ SSH в свою учетную запись GitHub, вы можете клонировать репо, используя:

    1. git@github.com:do-community/ansible-ubuntu.git

    Теперь у вас будет папка с именем ansible-ubuntu в вашем рабочем каталоге. Переоденьтесь в него:

    1. cd ansible-ubuntu

    Это будет ваш рабочий каталог для остальной части этого руководства.

    На этом шаге вы получили образцы файлов для автоматизации нескольких серверов Ubuntu 22.04 с помощью Ansible. Чтобы подготовить файлы с информацией, относящейся к вашим хостам, вы затем обновите файл vars/default.yml для работы с вашей системой.

    Шаг 4 — Изменение переменных Ansible

    В этом сборнике сценариев будет указана некоторая информация для автоматизации, которую со временем может потребоваться обновить. Размещение этой информации в одном файле переменных и вызов переменных в книгах воспроизведения будет более эффективным, чем их жесткое кодирование в книгах воспроизведения, поэтому вы будете изменять переменные в файле vars/default.yml, чтобы они соответствовали вашим предпочтения и потребности в настройке на этом шаге.

    Для начала откройте файл с помощью nano или вашего любимого текстового редактора:

    1. nano vars/default.yml

    Вы просмотрите содержимое файла, которое включает следующие переменные:

    create_user: sammy
    
    ssh_port: 5995
    
    copy_local_key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"
    

    Значение переменной create_user должно быть именем пользователя sudo, который будет создан на каждом хосте. В данном случае это sammy, но вы можете назвать пользователя как угодно.

    Переменная ssh_port содержит порт SSH, который вы будете использовать для подключения к хостам Ansible после установки. Порт по умолчанию для SSH — 22, но его изменение значительно уменьшит количество автоматических атак на ваши серверы. Это изменение является необязательным, но оно повысит уровень безопасности ваших хостов. Вы должны выбрать менее известный порт, который находится между 1024 и 65535 и который также не используется другим приложением на узлах Ansible. В этом примере вы используете порт 5995.

    Примечание. Если на вашем управляющем узле установлен дистрибутив Linux, выберите для него число выше 1023 и grep в /etc/services. Например, запустите grep 5995 /etc/services, чтобы проверить, используется ли 5995. Если вывода нет, то порт в этом файле не существует, и вы можете присвоить его переменной. Если ваш управляющий узел не является дистрибутивом Linux и вы не знаете, где найти его эквивалент в вашей системе, вы можете обратиться к реестру имен служб и номеров портов транспортных протоколов.

    Переменная copy_local_key ссылается на файл открытого ключа SSH вашего управляющего узла. Если имя этого файла id_rsa.pub, вам не нужно вносить никаких изменений в эту строку. В противном случае измените его, чтобы он соответствовал файлу открытого ключа SSH вашего управляющего узла. Вы можете найти файл в каталоге ~/.ssh вашего узла управления. Когда вы запускаете основной плейбук на шаге 5 и после создания пользователя с привилегиями sudo, контроллер Ansible скопирует файл открытого ключа в домашний каталог пользователя, что позволит вам войти в систему как этот пользователь. через SSH после первоначальной настройки сервера.

    Когда вы закончите изменять файл, сохраните и закройте его.

    Теперь, когда вы присвоили значения переменным в vars/default.yml, Ansible сможет вызывать эти переменные при выполнении плейбуков на шаге 8. На следующем шаге вы будете использовать Ansible Vault для создания и защиты пароля для пользователя, который будет создан на каждом хосте.

    Шаг 5 — Использование Ansible Vault для создания зашифрованного файла паролей

    Ansible Vault используется для создания и шифрования файлов и переменных, на которые можно ссылаться в плейбуках. Использование Ansible Vault гарантирует, что конфиденциальная информация не будет передаваться в виде открытого текста при выполнении плейбука. На этом шаге вы создадите и зашифруете файл, содержащий переменные, значения которых будут использоваться для создания пароля для пользователя sudo на каждом хосте. Используя Ansible Vault таким образом, вы гарантируете, что пароль не будет упоминаться открытым текстом в книгах воспроизведения во время и после первоначальной настройки сервера.

    Находясь в каталоге ansible-ubuntu, используйте следующую команду, чтобы создать и открыть файл хранилища:

    1. ansible-vault create secret

    При появлении запроса введите и подтвердите пароль, который будет использоваться для шифрования файла secret. Это пароль хранилища. Вам понадобится пароль хранилища при запуске плейбуков на шаге 8, поэтому не забывайте его.

    После ввода и подтверждения пароля хранилища файл secret откроется в текстовом редакторе, связанном с переменной окружения EDITOR оболочки. Добавьте эти строки в файл, заменив значения для type_a_strong_password_here и type_a_salt_here:

    1. password: type_a_strong_password_here
    2. password_salt: type_a_salt_here

    Значение переменной password будет фактическим паролем для пользователя sudo, которого вы создадите на каждом хосте. Переменная password_salt использует в качестве значения salt. Шаг 8.

    Примечание. В ходе тестирования мы обнаружили, что соль, состоящая только из числовых символов, приводила к проблемам с запуском плейбука на шаге 8. Однако соль, состоящая только из буквенных символов, работала. Буквенно-цифровая соль также должна работать. Имейте это в виду, когда будете указывать соль.

    Когда вы закончите изменять файл, сохраните и закройте его.

    Теперь вы создали зашифрованный файл паролей с переменными, которые будут использоваться для создания пароля для пользователя sudo на хостах. На следующем шаге вы автоматизируете первоначальную настройку серверов, указанных на шаге 2, запустив основной плейбук Ansible.

    Шаг 6 — Запуск основной пьесы против ваших хостов Ansible

    На этом этапе вы будете использовать Ansible для автоматизации первоначальной настройки серверов, указанных в файле инвентаризации. Вы начнете с просмотра задач, определенных в основном сборнике сценариев. Затем вы запустите плейбук против хостов.

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

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

    1. nano initial.yml

    Играть 1:

    Первый раздел файла содержит следующие ключевые слова, влияющие на поведение воспроизведения:

    - name: Initial server setup tasks
      hosts: initial
      remote_user: root
      vars_files:
        - vars/default.yml
        - secret
    ...
    

    название — это краткое описание воспроизведения, которое будет отображаться в терминале во время воспроизведения. Ключевое слово hosts указывает, какие хосты являются целевыми для воспроизведения. В этом случае шаблон, переданный ключевому слову, представляет собой имя группы хостов, указанное вами в файле /etc/ansible/hosts на шаге 2. Вы используете remote_user ключевое слово, чтобы сообщить контроллеру Ansible имя пользователя для входа на хосты (в данном случае root). Ключевое слово vars_files указывает на файлы, содержащие переменные, на которые будет ссылаться воспроизведение при выполнении задач.

    При такой настройке контроллер Ansible попытается войти на хосты как пользователь root через SSH-порт 22. Для каждого хоста, на который он может войти, он сообщит об ответе ok. В противном случае он сообщит, что сервер недоступен, и начнет выполнять задачи воспроизведения для любого хоста, на который можно войти. Если вы выполняли эту настройку вручную, эта автоматизация заменяет вход на хост с использованием ssh root@host-ip-address.

    За разделом ключевых слов следует список задач, которые должны выполняться последовательно. Как и в игре, каждая задача начинается с названия, которое дает краткое описание того, что задача должна выполнить.

    Задача 1: Обновить кеш

    Первая задача в playbook обновляет базу данных пакетов:

    ...
    - name: update cache
      ansible.builtin.apt:
        update_cache: yes
    ...
    

    Эта задача обновит базу данных пакетов с помощью модуля ansible.builtin.apt, поэтому он определяется с помощью update_cache: yes. Эта задача выполняет то же самое, что и при входе на сервер Ubuntu и вводе sudo apt update, что часто является прелюдией к обновлению всех установленных пакетов.

    Задача 2: обновить все установленные пакеты

    Вторая задача в плейбуке обновляет пакеты:

    ...
    - name: Update all installed packages
      ansible.builtin.apt:
        name: "*"
        state: latest
    ...
    

    Как и первая задача, эта задача также вызывает модуль ansible.builtin.apt. Здесь вы убедитесь, что все установленные пакеты обновлены, используя подстановочный знак для указания пакетов (name: *) и state: last, что было бы эквивалентно войдите на свои серверы и выполните команду sudo apt upgrade -y.

    Задача 3. Убедитесь, что служба NTP запущена

    Третья задача в плейбуке гарантирует, что демон Network Time Protocol (NTP) активен:

    ...
    - name: Make sure NTP service is running
      ansible.builtin.systemd:
        state: started
        name: systemd-timesyncd
    ...
    

    Эта задача вызывает модуль ansible.builtin.systemd, чтобы убедиться, что systemd-timesyncd, демон NTP, работает (состояние: запущено). Вы запускаете такую задачу, когда хотите, чтобы ваши серверы сохраняли одинаковое время, что может помочь запустить распределенное приложение на этих серверах.

    Задача 4: Убедитесь, что у нас есть группа sudo

    Четвертая задача в плейбуке проверяет наличие группы sudo:

    ...
    - name: Make sure we have a 'sudo' group
      ansible.builtin.group:
        name: sudo
        state: present
    ...
    

    Эта задача вызывает модуль ansible.builtin.group, чтобы проверить, существует ли на хостах группа с именем sudo (состояние: присутствует). Поскольку ваша следующая задача зависит от наличия группы sudo на хостах, эта задача проверяет существование групп sudo, поэтому вы можете быть уверены, что следующая задача не завершится ошибкой. .

    Задача 5: Создайте пользователя с привилегиями sudo

    Пятая задача в плейбуке создает пользователя без полномочий root с привилегиями sudo:

    ...
    - name: Create a user with sudo privileges
      ansible.builtin.user:
        name: "{{ create_user }}"
        state: present
        groups: sudo
        append: true
        create_home: true
        shell: /bin/bash
        password: "{{ password | password_hash('sha512', password_salt) }}"
        update_password: on_create
    ...
    

    Здесь вы создаете пользователя на каждом хосте, вызывая модуль ansible.builtin.user и добавляя группу sudo в группы пользователей. Имя пользователя получается из значения переменной create_user, которое вы указали в vars/default.yml. Эта задача также гарантирует, что для пользователя будет создан домашний каталог, которому будет назначена надлежащая оболочка.

    Используя параметр password и комбинацию пароля и соли, которые вы установили в алгоритме криптографического хеширования SHA-512, генерируется хешированный пароль для пользователя. Вместе с файлом хранилища secret пароль никогда не передается контроллеру в открытом виде. С помощью update_password вы гарантируете, что хешированный пароль будет установлен только при первом создании пользователя. Если вы повторно запустите playbook, пароль не будет восстановлен.

    Задача 6: Установить авторизованный ключ для удаленного пользователя

    Шестая задача в playbook устанавливает ключ для вашего пользователя:

    ...
    - name: Set authorized key for remote user
      ansible.posix.authorized_key:
        user: "{{ create_user }}"
        state: present
        key: "{{ copy_local_key }}"
    ...
    

    В этой задаче вы копируете свой открытый SSH-ключ на хосты, вызывая ansible.posix.authorized_key. Значение user — это имя пользователя, созданное на хостах в предыдущей задаче, а key указывает на копируемый ключ. Обе переменные определены в файле var/default.yml. Эта задача имеет тот же эффект, что и запуск команды ssh-copy-id вручную.

    Задача 7: отключить удаленный вход для root

    Седьмая задача в плейбуке отключает удаленный вход для пользователя root:

    ...
    - name: Disable remote login for root
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        state: present
        regexp: '^PermitRootLogin yes'
        line: 'PermitRootLogin no'
    ...
    

    Затем вы вызываете модуль ansible.builtin.lineinfile. Эта задача ищет строку, начинающуюся с PermitRootLogin, в файле /etc/ssh/sshd_config, используя регулярное выражение (regexp), а затем заменяет со значением line. Эта задача гарантирует, что удаленный вход с использованием учетной записи root не будет выполнен после запуска воспроизведения в этой книге воспроизведения. Только удаленный вход с учетной записью пользователя, созданной в задаче 6, будет успешным. Отключив удаленный вход в систему root, вы гарантируете, что только обычные пользователи могут войти в систему, и что для получения прав администратора потребуется метод повышения привилегий, обычно sudo.

    Задача 8: Изменить порт SSH

    Восьмая задача в плейбуке изменяет порт SSH:

    ...
    - name: Change the SSH port
      ansible.builtin.lineinfile:
        path: /etc/ssh/sshd_config
        state: present
        regexp: '^#Port 22'
        line: 'Port "{{ ssh_port }}"'
    ...
    

    Поскольку SSH прослушивает хорошо известный порт 22, он, как правило, подвергается автоматическим атакам, нацеленным на этот порт. Изменяя порт, который прослушивает SSH, вы уменьшаете количество автоматических атак на хосты. Эта задача использует тот же модуль ansible.builtin.lineinfile для поиска строки, которая начинается с regexp в файле конфигурации демона SSH, и изменяет ее значение на значение < параметрстрока. Новый номер порта, который прослушивает SSH, будет номером порта, который вы присвоили переменной ssh_port на шаге 4. После перезапуска хостов в конце этого воспроизведения вы не сможете войти в систему. к хостам через порт 22.

    Задача 9: UFW — разрешить SSH-подключения

    Девятая задача в плейбуке разрешает SSH-трафик:

    ...
    - name: UFW - Allow SSH connections
      community.general.ufw:
        rule: allow
        port: "{{ ssh_port }}"
    ...
    

    Здесь вы вызываете шаг 4. Эта задача эквивалентна ручному запуску команды ufw allow 5995/tcp.

    Задача 10: Защита от перебора SSH

    Десятая задача защищает от атак грубой силы:

    ...
    - name: Brute-force attempt protection for SSH
      community.general.ufw:
        rule: limit
        port: "{{ ssh_port }}"
        proto: tcp
    ...
    

    При повторном вызове модуля community.general.ufw эта задача использует ограничивающее скорость rule, чтобы отказать в доступе для входа в систему с IP-адреса, потерпевшего шесть или более неудачных попыток подключения к Порт SSH в течение 30 секунд. Параметр proto указывает на целевой протокол (в данном случае TCP).

    Задача 11: UFW — запретить другой входящий трафик и включить UFW

    Одиннадцатая задача включает брандмауэр:

    ...
    - name: UFW - Deny other incoming traffic and enable UFW
      community.general.ufw:
        state: enabled
        policy: deny
        direction: incoming
    ...
    

    По-прежнему полагаясь на модуль community.general.ufw в этой задаче, вы включаете брандмауэр (состояние: включено) и устанавливаете политику по умолчанию, которая запрещает весь входящий трафик.

    Задача 12: Удалите зависимости, которые больше не требуются

    Двенадцатая задача в этой пьесе очищает зависимости пакетов:

    ...
    - name: Remove dependencies that are no longer required
      ansible.builtin.apt:
        autoremove: yes
    ...
    

    При повторном вызове модуля ansible.builtin.apt эта задача удаляет зависимости пакетов, которые больше не требуются на сервере, что эквивалентно запуску команды sudo apt autoremove. вручную.

    Задача 13. Перезапустите демон SSH.

    Тринадцатая задача в этом плейбуке перезапускает SSH.

    ...
    - name: Restart the SSH daemon
      ansible.builtin.systemd:
        state: restarted
        name: ssh
    

    Последняя задача вызывает модуль ansible.builtin.systemd для перезапуска демона SSH. Этот перезапуск необходимо выполнить, чтобы изменения, внесенные в файл конфигурации демона, вступили в силу. Эта задача имеет тот же эффект, что и перезапуск демона с помощью sudo systemctl restart ssh.

    Первоначальное подключение к хостам осуществлялось через порт 22 как root, но более ранние задачи изменили номер порта и отключили удаленный вход root, поэтому вам необходимо перезапустить SSH. демон на данном этапе пьесы. Во втором воспроизведении будут использоваться другие учетные данные для подключения (имя пользователя вместо root и вновь определенный номер порта, отличный от 22).

    Игра 2: Перезагрузка хостов после первоначальной настройки

    Эта игра начинается после успешного завершения последней задачи в игре 1. На него влияют следующие ключевые слова:

    ...
    - name: Rebooting hosts after initial setup
      hosts: initial
      port: "{{ ssh_port }}"
      remote_user: "{{ create_user }}"
      become: true
      vars_files:
        - vars/default.yml
        - ~/secret
      vars:
        ansible_become_pass: "{{ password }}"
    ...
    

    Шаблон, передаваемый ключевому слову hosts, представляет собой имя группы initial, указанное в файле /etc/ansible/hosts на шаге 4.

    В первом воспроизведении контроллер Ansible вошел на хосты как пользователь root. Поскольку удаленный вход в систему root отключен при первом воспроизведении, теперь вам нужно указать пользователя, под которым должен войти контроллер Ansible. Ключевое слово remote_user указывает контроллеру Ansible войти на каждый хост как пользователь sudo, созданный в задаче 5 первого воспроизведения.

    Ключевое слово become указывает, что повышение привилегий будет использоваться для выполнения задачи на определенных хостах. Это ключевое слово указывает контроллеру Ansible использовать привилегии root для выполнения задач на хостах, когда это необходимо. В этом случае контроллер примет привилегии суперпользователя, используя sudo. Ключевое слово ansible_become_pass устанавливает пароль для повышения привилегий, то есть пароль, который будет использоваться для получения привилегий root. В этом случае он указывает на переменную с паролем, который вы настроили с помощью Ansible Vault на шаге 5.

    Помимо указания на файл vars/default.yml, ключевое слово vars_files также указывает на файл secret, настроенный на шаге 5, который сообщает контроллеру Ansible, где найти переменную password.

    После раздела ключевых слов находится единственная задача, которая будет выполняться в этой игре.

    Задача 14: Перезагрузите все хосты

    Примечание. Хотя это первая задача второй игры, она имеет номер 14, потому что Ansible Controller видит ее не как задачу 1 игры 2, а как задачу 14 игры.

    Последняя задача плейбука перезагрузит все хосты:

    ...
    - name: Reboot all hosts
      ansible.builtin.reboot:
    

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

    Полный файл playbook выглядит так:

    - name: Initial server setup tasks
      hosts: initial
      remote_user: root
      vars_files:
        - vars/default.yml
        - secret
    
      tasks:
        - name: update cache
          ansible.builtin.apt:
            update_cache: yes
    
        - name: Update all installed packages
          ansible.builtin.apt:
            name: "*"
            state: latest
    
        - name: Make sure NTP service is running
          ansible.builtin.systemd:
            state: started
            name: systemd-timesyncd
    
        - name: Make sure we have a 'sudo' group
          ansible.builtin.group:
            name: sudo
            state: present
    
        - name: Create a user with sudo privileges
          ansible.builtin.user:
            name: "{{ create_user }}"
            state: present
            groups: sudo
            append: true
            create_home: true
            shell: /bin/bash
            password: "{{ password | password_hash('sha512', password_salt) }}"
            update_password: on_create
    
        - name: Set authorized key for remote user
          ansible.builtin.authorized_key:
            user: "{{ create_user }}"
            state: present
            key: "{{ copy_local_key }}"
    
        - name: Disable remote login for root
          ansible.builtin.lineinfile:
            path: /etc/ssh/sshd_config
            state: present
            regexp: '^PermitRootLogin yes'
            line: 'PermitRootLogin no'
    
        - name: Change the SSH port
          ansible.builtin.lineinfile:
            path: /etc/ssh/sshd_config
            state: present
            regexp: '^#Port 22'
            line: 'Port "{{ ssh_port }}"'
    
        - name: UFW - Allow SSH connections
          community.general.ufw:
            rule: allow
            port: "{{ ssh_port }}"
    
        - name: Brute-force attempt protection for SSH
          community.general.ufw:
            rule: limit
            port: "{{ ssh_port }}"
            proto: tcp
    
        - name: UFW - Deny other incoming traffic and enable UFW
          community.general.ufw:
            state: enabled
            policy: deny
            direction: incoming
    
        - name: Remove dependencies that are no longer required
          ansible.builtin.apt:
            autoremove: yes
    
        - name: Restart the SSH daemon
          ansible.builtin.systemd:
            state: restarted
            name: ssh
    
    - name: Rebooting hosts after initial setup
      hosts: initial
      port: "{{ ssh_port }}"
      remote_user: "{{ create_user }}"
      become: true
      vars_files:
        - vars/default.yml
        - secret
      vars:
        ansible_become_pass: "{{ password }}"
    
      tasks:
        - name: Reboot all hosts
          ansible.builtin.reboot:
    

    Закончив просмотр файла, сохраните и закройте его.

    Примечание. Вы можете добавлять новые задания в книгу или изменять существующие. Однако изменение файла YAML может привести к его повреждению, поскольку YAML чувствителен к пробелам, поэтому будьте осторожны, если вы решите отредактировать какой-либо аспект файла. Чтобы узнать больше о работе с плейбуками Ansible, следуйте нашей серии статей о том, как писать плейбуки Ansible.

    Теперь вы можете запустить playbook. Сначала проверьте синтаксис:

    1. ansible-playbook --syntax-check --ask-vault-pass initial.yml

    Вам будет предложено ввести пароль хранилища, который вы создали на шаге 5. Если после успешной аутентификации нет ошибок с синтаксисом YAML, вывод будет таким:

    Output
    playbook: initial.yml

    Теперь вы можете запустить файл с помощью следующей команды:

    1. ansible-playbook --ask-vault-pass initial.yml

    Вам снова будет предложено ввести пароль хранилища. После успешной аутентификации контроллер Ansible войдет на каждый хост как пользователь root и выполнит все задачи в плейбуке. Вместо того, чтобы запускать команду ssh root@node-ip-address на каждом сервере отдельно, Ansible подключается ко всем узлам, указанным в /etc/ansible/hosts, а затем выполняет задачи в playbook.

    Для примеров хостов в этом руководстве Ansible потребовалось около трех минут, чтобы выполнить задачи на трех хостах. Когда задачи будут выполнены, вы получите вывод, подобный следующему:

    Output
    PLAY RECAP ***************************************************************************************************** host1 : ok=16 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host2 : ok=16 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host3 : ok=16 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

    Каждая задача и раздел ключевого слова игры, которые успешно оцениваются, будут учитываться в числе в столбце ok. При 14 задачах в двух играх, все из которых успешно оценены, количество составляет 16. Из оцененных задач только 11 привели к изменениям на серверах, представленным столбцом changed.

    Счетчик unreachable показывает количество хостов, на которые контроллер Ansible не смог войти. Ни одна из задач не завершилась неудачей, поэтому счетчик failed равен 0.

    Задача пропускается, когда условие, указанное в задаче, не выполняется (обычно с параметром when). В этом случае никакие задачи не пропускаются, но это будет применимо на шаге 8.

    Последние два столбца (recued и ignored) относятся к обработке ошибок, указанных для воспроизведения или задачи.

    Теперь вы успешно автоматизировали первоначальную настройку нескольких серверов Ubuntu 22.04, используя Ansible для выполнения одной команды, которая выполняет все задачи, указанные в playbook.

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

    (Необязательно) Шаг 7 — Проверка настройки сервера вручную

    Чтобы подтвердить вывод отчета об игре в конце предыдущего шага, вы можете войти на один из ваших хостов, используя учетные данные, которые были настроены ранее для проверки установки. Эти действия необязательны для целей обучения, поскольку отчет Ansible сообщает о точном выполнении.

    Начните с входа на один из хостов с помощью следующей команды:

    1. ssh -p 5995 sammy@host1-public-ip-address

    Вы используете параметр -p, чтобы указать на пользовательский номер порта, который вы настроили для SSH на шаге 6. Если вы можете войти на хост как этот пользователь через этот порт, вы знаете, что Ansible успешно выполнила эти задачи.

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

    1. sudo apt update

    Если вам будет предложено ввести пароль, и вы сможете пройти аутентификацию с помощью пароля, который вы настроили для пользователя на шаге 5, вы можете подтвердить, что Ansible успешно выполнил задачи по созданию пользователя и установке пароля пользователя.

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

    (Необязательно) Шаг 8 — Использование Ansible для текущего обслуживания хостов

    В плейбуке начальной настройки сервера, который был выполнен на шаге 3, вы также вытащили плейбук ongoing.yml, который можно использовать для дальнейшего обслуживания. На этом шаге вы запустите плейбук ongoing.yml, чтобы автоматизировать текущее обслуживание хостов, настроенных в этом руководстве.

    Перед запуском сборника сценариев вы просмотрите каждую задачу. Для начала откройте файл с помощью nano или вашего любимого текстового редактора:

    1. nano ongoing.yml

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

    Играть 1:

    Следующие ключевые слова в первом разделе файла влияют на поведение воспроизведения:

    - hosts: ongoing
      port: "{{ ssh_port }}"
      remote_user: "{{ create_user }}"
      become: true
      vars_files:
        - vars/default.yml
        - secret
      vars:
        ansible_become_pass: "{{ password }}"
    ...
    

    За исключением группы, переданной ключевому слову hosts, это те же самые ключевые слова, которые использовались во втором воспроизведении схемы установки.

    После ключевых слов идет список задач, которые нужно выполнить последовательно. Как и в пособии по настройке, каждая задача в пособии по обслуживанию начинается с name, которое дает краткое описание того, что задача будет выполнять.

    Задача 1: Обновить кеш

    Первая задача обновляет базу данных пакета:

    ...
    - name: update cache
      ansible.builtin.apt:
        update_cache: yes
    ...
    

    Эта задача обновит базу данных пакетов с помощью модуля ansible.builtin.apt, поэтому он определяется с помощью update_cache: yes. Эта задача выполняет то же самое, что и при входе на сервер Ubuntu и вводе sudo apt update, что часто является прелюдией к установке пакета или обновлению всех установленных пакетов.

    Задача 2: обновить все установленные пакеты

    Вторая задача обновляет пакеты:

    ...
    - name: Update all installed packages
      ansible.builtin.apt:
        name: "*"
        state: latest
    ...
    

    Как и первая задача, эта задача также вызывает модуль ansible.builtin.apt. Здесь вы гарантируете, что все установленные пакеты обновлены, используя подстановочный знак для указания пакетов (name: *) и state: last, что было бы эквивалентно войдите на свои серверы и выполните команду sudo apt upgrade -y.

    Задача 3. Убедитесь, что служба NTP запущена

    Третья задача в плейбуке обеспечивает настройку демона NTP:

    ...
    - name: Make sure NTP service is running
      ansible.builtin.systemd:
        state: started
        name: systemd-timesyncd
    ...
    

    Активные службы на сервере могут выйти из строя по разным причинам, поэтому вы должны убедиться, что такие службы остаются активными. Эта задача вызывает модуль ansible.builtin.systemd, чтобы убедиться, что systemd-timesyncd, демон NTP, остается активным (состояние: запущено).

    Задача 4: UFW — работает ли он?

    Четвертая задача проверяет состояние брандмауэра UFW:

    ...
    - name: UFW - Is it running?
      ansible.builtin.command: ufw status
        register: ufw_status
    ...
    

    Вы можете проверить состояние брандмауэра UFW в Ubuntu с помощью команды sudo ufw status. В первой строке вывода будет указано либо Status: active, либо Status: inactive. Эта задача использует модуль ansible.builtin.command для запуска той же команды, а затем сохраняет (register) вывод в ufw_status. переменная. Значение этой переменной будет запрошено в следующей задаче.

    Задача 5: UFW — включить UFW и запретить входящий трафик

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

    ...
    - name: UFW - Enable UFW and deny incoming traffic
      community.general.ufw:
        state: enabled
      when: "'inactive' in ufw_status.stdout"
    ...
    

    Эта задача вызывает модуль community.general.ufw для включения брандмауэра только тогда, когда термин inactive появляется в выходных данных ufw_status. переменная. Если брандмауэр активен, то условие когда не выполняется, и задача помечается как пропущенная.

    Задача 6. Удалите зависимости, которые больше не требуются

    Шестая задача в этом плейбуке очищает зависимости пакетов:

    ...
    - name: Remove dependencies that are no longer required
      ansible.builtin.apt:
        autoremove: yes
    ...
    

    Эта задача удаляет зависимости пакетов, которые больше не требуются на сервере, путем вызова модуля ansible.builtin.apt, что эквивалентно запуску команды sudo apt autoremove.

    Задача 7: проверьте, требуется ли перезагрузка

    Седьмая задача проверяет, требуется ли перезагрузка:

    ...
    - name: Check if reboot required
      ansible.builtin.stat:
        path: /var/run/reboot-required
      register: reboot_required
    ...
    

    В Ubuntu вновь установленный или обновленный пакет будет сигнализировать о том, что для вступления в силу изменений, которые были введены при установке или обновлении, требуется перезагрузка, путем создания файла /var/run/reboot-required. Вы можете проверить, существует ли этот файл, используя команду stat /var/run/reboot-required. Эта задача вызывает модуль ansible.builtin.stat, чтобы сделать то же самое, а затем сохраняет (register) вывод в reboot_required. переменная. Значение этой переменной будет запрошено в следующей задаче.

    Задача 8: Перезагрузите компьютер, если требуется

    Восьмая задача при необходимости перезагрузит сервер:

    ...
    - name: Reboot if required
      ansible.builtin.reboot:
      when: reboot_required.stat.exists == true
    

    Запрашивая переменную reboot_required из задачи 7, эта задача вызывает модуль ansible.builtin.reboot для перезагрузки хостов только когда существует /var/run/reboot-required. Если требуется перезагрузка и перезагружается хост, задача помечается как измененная. В противном случае Ansible отмечает его как пропущенный в обзоре игры.

    Полный файл playbook для текущего обслуживания будет выглядеть следующим образом:

    - hosts: ongoing
      port: "{{ ssh_port }}"
      remote_user: "{{ create_user }}"
      become: true
      vars_files:
        - vars/default.yml
        - secret
      vars:
        ansible_become_pass: "{{ password }}"
    
      tasks:
        - name: update cache
          ansible.builtin.apt:
            update_cache: yes
    
        - name: Update all installed packages
          ansible.builtin.apt:
            name: "*"
            state: latest
    
        - name: Make sure NTP service is running
          ansible.builtin.systemd:
            state: started
            name: systemd-timesyncd
    
        - name: UFW - Is it running?
          ansible.builtin.command: ufw status
          register: ufw_status
          
        - name: UFW - Enable UFW and deny incoming traffic
          community.general.ufw:
            state: enabled
          when: "'inactive' in ufw_status.stdout"
    
        - name: Remove dependencies that are no longer required
          ansible.builtin.apt:
            autoremove: yes
    
        - name: Check if reboot required
          ansible.builtin.stat:
            path: /var/run/reboot-required
          register: reboot_required
    
        - name: Reboot if required
          ansible.builtin.reboot:
          when: reboot_required.stat.exists == true
    

    Закончив просмотр файла, сохраните и закройте его.

    Примечание. Вы можете добавлять новые задачи или изменять существующие задачи в playbook. Однако изменение файла YAML может привести к его повреждению, поскольку YAML чувствителен к пробелам, поэтому будьте осторожны, если вы решите отредактировать какой-либо аспект файла. Чтобы узнать больше о работе с плейбуками Ansible, следуйте нашей серии статей о том, как писать плейбуки Ansible.

    Теперь вы можете запустить файл. Сначала проверьте синтаксис:

    1. ansible-playbook --syntax-check --ask-vault-pass ongoing.yml

    Вам будет предложено ввести пароль хранилища, который вы создали на шаге 5. Если после успешной аутентификации нет ошибок с синтаксисом YAML, вывод будет таким:

    Output
    playbook: ongoing.yml

    Теперь вы можете запустить файл с помощью следующей команды:

    1. ansible-playbook --ask-vault-pass ongoing.yml

    Вам будет предложено ввести пароль хранилища. После успешной аутентификации контроллер Ansible войдет на каждый хост как sammy (или указанное вами имя пользователя) для выполнения задач в playbook. Вместо запуска команды ssh -p 5995 sammy@host_ip_address на каждом сервере отдельно, Ansible подключается к узлам заданный группой congoing в /etc/ansible/hosts, а затем выполняет задачи в playbook.

    Если команда завершится успешно, будет напечатан следующий вывод:

    Output
    PLAY RECAP ***************************************************************************************************** host1 : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 host2 : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0 host3 : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0

    В отличие от сводки воспроизведения для первоначальной настройки сервера, в этой сводке воспроизведения отмечены две задачи, которые были пропущены, поскольку условие, установленное для каждой задачи с параметром when, не было выполнено.

    Вы можете использовать этот плейбук для обслуживания хостов без необходимости входа на каждый хост вручную. Когда вы создаете и устанавливаете приложения на хостах, вы можете добавлять задачи в playbook, чтобы вы также могли управлять этими приложениями с помощью Ansible.

    Заключение

    В этом руководстве вы использовали Ansible для автоматизации первоначальной настройки нескольких серверов Ubuntu 22.04. Вы также запустили дополнительный сценарий для текущего обслуживания этих серверов. Автоматизация Ansible — это инструмент для экономии времени, когда вам нужно настроить приложение, такое как MinIO, в распределенном или кластерном режиме.

    Более подробная информация об Ansible доступна на странице Управление конфигурацией 101: Написание Ansible Playbooks.