Обложка статьи «Что такое Ansible и как его использовать»

Что такое Ansible и как его использовать

Автор оригинала — Ахмед Фараг, программный инженер в tajawal.com

Автор перевода — Вадим Сычёв

Что такое Ansible?

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

Ключевые особенности Ansible

  • Безагентное. В клиенте не установлено программное обеспечение или агент, который общается с сервером.
  • Идемпотентное. Независимо от того, сколько раз вы вызываете операцию, результат будет одинаковым.
  • Простое и расширяемое. Ansible написано на Python и использует YAML для написания команд. Оба языка считаются относительно простыми в изучении.

Установка и запуск Ansible

# ubuntu
sudo apt-get install ansible
#mac-OS
brew install ansible

Инструкцию по установке на другие ОС можно найти здесь.

Структура Ansible

Модули

Это небольшие программы, выполняющие определённую работу на сервере. Например, вместо запуска этой команды:

sudo apt-get install htop

Мы можем использовать модуль apt и установить htop:

- name: Install htop
apt: name=htop

Использование модуля даст вам возможность узнать, установлен он или нет.

Плагины

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

Инвентаризация хостов

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

В простейшем виде он может содержать одну строку:

35.178.45.231  ansible_ssh_user=ubuntu

Playbooks

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

group_vars

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

Роли

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

Обработчики

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

Теги

Если у вас playbook с большим объёмом, может быть полезно иметь возможность запускать только определённую часть его конфигурации.

Демо «Реальное приложение»

Цель этой демонстрации — установить приложение Laravel в VPS. Для этого используем lightsail.

Последовательность действий для создания и запуска Laravel APP:

    1. Создайте экземпляр Ubuntu Lightsail.
    2. Установите зависимости Ansible на ваш VPS.
    3. Добавьте SSH-ключи в Git.
    4. Выполните сборку хостов и ansible.cfg.
    5. Определите роль в Ansible.
    6. Определите обработчик в Ansible.
    7. Установите модули PHP.
    8. Установите Nginx.
    9. Добавьте default-конфигурацию Nginx.
    10. Добавьте переменные для управления учётными данными БД, хоста, URL-адресом источника GitHub и переменными .env.
    11. Используйте Ansible-Vault.
    12. Создайте базу данных MySql, имя пользователя и пароль.
    13. Клонируйте кодовую базу в ваш VPS.
    14. Сгенерируйте .env.
    15. Создайте playbook.

Рассмотрим каждый пункт подробнее.

Создание экземпляра Ubuntu Lightsail

Перейдите на панель управления Lightsail и нажмите «Создать экземпляр».

Изображение в статье «Что такое Ansible и как его использовать»

Выберите свою любимую ОС.

Изображение в статье «Что такое Ansible и как его использовать»

Выберите «Добавить скрипт запуска», который запускается после создания вашего экземпляра. Не забудьте получить SSH-ключ.

Изображение в статье «Что такое Ansible и как его использовать»

Установка зависимостей Ansible на нашем VPS

Добавьте эти sh-команды для установки зависимостей Ansible:

sudo add-apt-repository ppa:deadsnakes/ppa -y
sudo apt-get update
sudo apt-get install -y python2.7 python3 python-pip

Изображение в статье «Что такое Ansible и как его использовать»Изображение в статье «Что такое Ansible и как его использовать»

Теперь у нас есть готовый экземпляр, перейдём к построению Ansible Project.

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

Вы должны добавить свой сервер id_rsa.pub к своим ключам GitHub SSH, войдя в свой сервер.

# Подключитесь к вашему серверу через SSH и запустите
ssh-keygen
sudo chmod -R 644 .ssh/id_rsa
cat .ssh/id_rsa.pub

# Добавьте результат команды в аккаунт Git
# github settings=> SSH keys => Add new Key
# bitbucket settings=> ssh-keys => Add new Key

Сборка хостов и ansible.cfg

hosts.ini

[aws]
# Ваш IP сервера
127.0.0.39

ansible.cfg

[defaults]
hostfile = hosts.ini
# configure log dir
log_path= logs/ansible-log.log

Определение роли в Ansible

Используем модуль Ping, чтобы убедиться, что хост работает, после чего нужно обновить все пакеты и установить два модуля: git и htop.

---
- ping: ~
###
- name: Update apt packages
  apt:
    update_cache: yes
##
- name: Install GIT VCS
  apt:
    name: git
    state: latest
##
- name: Install htop
  apt: name=htop

Определение обработчика

---
- name: Restart PHP-FPM
  service:
    name: php{{php_version}}-fpm
    state: restarted
    ####
- name: Restart Nginx
  service:
    name: nginx
    state: restarted

Установка модулей PHP

Чтобы вызвать обработчик в Ansible, мы должны использовать notify: Restart PHP-FPM, имена обработчиков должны быть уникальными.

В этом руководстве мы определили php как тег, поэтому, например, если вы хотите запустить только эту задачу из своего playbook, вам необходимо выполнить её с —tags = ”php”, которая будет исполнять только её.

---
- name: Install PHP {{php_version}} PPA Repo
  apt_repository:
    repo: 'ppa:ondrej/php'
  tags:
    - php
  ##
- name: Install PHP {{php_version}}
  apt: name=php{{php_version}} state=latest
  ##
- name: Install PHP packages
  become: true
  apt:
    name: "{{ item }}"
    state: latest
  with_items:
    - php{{php_version}}-curl
    - php{{php_version}}-fpm
    - php{{php_version}}-intl
    - php{{php_version}}-mysql
    - php{{php_version}}-xml
    - php{{php_version}}-mbstring
  notify: Restart PHP-FPM
  tags:
    - php

Установка Nginx

- name: Install Nginx web server
  apt:
    name: nginx
    state: latest
  notify: Restart Nginx
  tags:
    - nginx

###
- name: Update nginx config files
  become: true
  template:
    src: templates/nginx.conf
    dest: "/etc/nginx/sites-available/default"
  tags:
    - nginx
  notify: Restart Nginx

###
- name: link nginx config
  become: true
  file:
    src: "/etc/nginx/sites-available/default"
    dest: "/etc/nginx/sites-enabled/default"
    state: link
  tags:
    - nginx
  notify: Restart Nginx

Добавление default-конфигурации Nginx

server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;
		server_name {{ server_name }};
        root  {{ app_work_dir }}public;

            location / {
        try_files $uri $uri/ /index.php?$args;
        index  index.php index.html index.htm;
    }

    if (!-d $request_filename) {
        rewrite ^/(.*)/$ /$1 permanent;
    }

    location =https://cdn.tproger.ru/favicon.ico {
        access_log     off;
        log_not_found  off;
    }

    location ~ \.php$ {
        try_files $uri $uri/ /index.php?$args;
        index index.php index.html index.htm;

        fastcgi_pass unix:/var/run/php/php{{php_version}}-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  {{app_work_dir}}public$fastcgi_script_name;
        fastcgi_param  APPLICATION_ENV testing;
        fastcgi_param  PATH /usr/bin:/bin:/usr/sbin:/sbin;
        fastcgi_intercept_errors on;
        include        fastcgi_params;
    }
}

vars.yml

---
##@ref https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html#variables-and-vaults
ansible_ssh_user: "ubuntu"
current_user: "ubuntu"
server_name: "app_name"

repo_git_url: "app_github_url"
ansible_ssh_private_key_file: "ssh_dir"
php_version: 7.2
app_work_dir: /var/www/app_name/

#mysql config
mysql_host: "mysql_host"
mysql_db: app_name
mysql_user: sql_user
mysql_pass: sql_pass

#other config
cache_driver: file
session_driver: file
app_env: production
app_debug: false
app_key: "your_app_key"
app_name: "app_name"
app_url: "your_app_url"

Примечание: Рекомендуется использовать ansible-vault для шифрования и дешифрования переменных.

Как использовать Ansible-Vault

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

touch .vault_pass.txt
echo 'YOUR_CONFIG_PASS' > .vault_pass.txt

Чтобы зашифровать переменные, используйте:

ansible-vault encrypt group_vars/vars.yml --vault-password-file .vault_pass.txt

Чтобы расшифровать переменные, используйте:

ansible-vault decrypt group_vars/vars.yml --vault-password-file .vault_pass.txt

Создание базы данных MySql, имени пользователя и пароля

- mysql_user:
    name: "{{mysql_user}}"
    password: "{{mysql_pass}}"
    priv: '*.*:ALL'
    state: present
  tags:
     - mysql-db

     ##
- name:  Create APP DB database
  mysql_db: name="{{mysql_db}}" state=present login_user="{{mysql_user}}" login_password="{{mysql_pass}}"

mysql_user и mysql_pass определены внутри vars.yml.

Клонирование кодовой базы

- name: update repo - pull the latest changes
  git:
    repo: "{{repo_git_url}}"
    dest: "{{app_work_dir}}"
    update: yes
    version: master
    accept_hostkey: yes
    key_file: /home/{{current_user}}/.ssh/id_rsa
  tags:
    - code-deploy

repo_git_url и app_work_dir определены внутри vars.yml.

Генерирование .env

Ansible использует шаблонизатор Jinja2 для динамических выражений и доступа к переменным. Создадим файл env.conf.

APP_ENV={{app_env}}
APP_DEBUG={{app_debug}}
APP_KEY={{app_key}}
APP_URL={{app_url}}
APP_NAME={{app_name}}

DB_HOST={{mysql_host}}
DB_DATABASE={{mysql_db}}
DB_USERNAME={{mysql_user}}
DB_PASSWORD={{mysql_pass}}

CACHE_DRIVER={{cache_driver}}
SESSION_DRIVER={{session_driver}}

Определим role, чтобы переместить этот шаблон в директорию нашего приложения.

---
- name: Copy lara env file
  become: true
  template:
    src: templates/env.conf
    dest: "{{app_work_dir}}/.env"
  tags:
    - env-file

Создание playbook

---
- hosts: aws
#common options between modules
  sudo: yes
  gather_facts: no

  vars_files:
    - ./group_vars/vars.yml
  roles:
    - misc
    - php
    - mysql
    - redis
    - nginx
    - bootstrap-app
    - code-deploy
    ###
  handlers:
    - include: handlers/main.yml

Как видно, мы определили aws как хост для этого playbook, и sudo yes даёт нам возможность выполнять команду как пользователю sudo. У нас есть vars_files, где мы храним наши vars. Мы установили roles, каждая role выполняет определённую задачу. И, наконец, у нас есть handlers, которые содержат все обработчики проекта.

Запуск playbook

#ansible-playbook playbookName
ansible-playbook code-deploy.yml

# Запуск с конкретными тегами
ansible-playbook playbook.yml --tags="env-files,php"

# Если вы используете ansible-valut
ansible-playbook code-deploy.yml --vault-password-file  .vault_pass.txt

Полная структура проекта

├── ansible.cfg
├── code-deploy.yml
├── files
│   └── dump.sql
├── group_vars
│   └── vars.yml
├── handlers
│   └── main.yml
├── hosts.ini
├── logs
│   └── ansible-log.log
├── roles
│   ├── bootstrap-app
│   │ └── tasks
│   │     └── main.yml
│   ├── code-deploy
│   │ ├── tasks
│   │ │   ├── config-files.yml
│   │ │   └── main.yml
│   │ └── templates
│   │     └── env.conf
│   ├── misc
│   │ └── tasks
│   │     └── main.yml
│   ├── mysql
│   │ └── tasks
│   │     ├── config.yml
│   │     └── main.yml
│   ├── nginx
│   │ ├── tasks
│   │ │   └── main.yml
│   │ └── templates
│   │     └── nginx.conf
│   ├── php
│   │ └── tasks
│   │     └── main.yml
│   └── redis
│       └── tasks
│           └── main.yml
├── scripts
│   ├── install_composer.sh
│   └── startup.sh
└── site.yml

Дополнительные материалы

Перевод статьи «Ansible In Action»

Как Яндекс использует ваши данные и машинное обучение для персонализации сервисов — читать и смотреть YaC 2019.