В предыдущей статье мы с помощью Terraform создали 3 виртуальных сервера, объединённых маршрутизируемой сетью в VMware Cloud Director для развертывания на них Production ready Django-стека.
Тема непростая, особенно для новичков, поэтому статья про установку Django-стека с помощью Ansible состоит из 2 частей:
- в этой части разберёмся как работает Django-стек от и до, научимся устанавливать его на одну машину, поймем, что такое Application-сервер и как работает Gunicorn.
- во второй части научимся устанавливать Django-стек с помощью Ansible и познакомимся с альтернативным путём установки — без Ansible.
Начнем с матчасти — разберемся с тем как работает Django-стек, а потом научимся устанавливать его в ручном режиме на одну машину. Поехали!
Как работает Django-стек?
Классический Django-стек состоит из 4 базовых элементов: Web-сервера, WSGI-сервера, самого Django и СУБД. Часто его расширяют и добавляют ещё ПО для работы с безопасностью и памятью, но мы рассмотрим принцип работы классической схемы.
Графически схема работы Django-стека выглядит так:
Разберем подробнее работу каждого элемента стека:
- Веб-сервер, в нашем случае Nginx, принимает и обрабатывает HTTP-запрос браузера, затем передаёт его в Application-сервер — Gunicorn.
- Gunicorn получает данные от Nginx, разбирает их и исходя из своей конфигурации по протоколу WSGI передаёт их в Django.
- Django обрабатывает полученные данные и возвращает результат работы обратно в Gunicorn, а он в свою очередь отдаёт результат в Nginx, который возвращает клиенту готовую HTML-страницу.
Общение между Application-сервером и Django происходит по протоколу WSGI — Web Server Gateway Interface. Это специальный протокол для запуска Python-скриптов. У него есть несколько важных особенностей:
- Application-сервер и исполняемые скрипты запускаются в одном процессе и должны быть написаны на одном языке программирования.
- Скрипты, которые обрабатывают запросы, загружаются в оперативную память заранее и из них вызываются либо функции, либо классы — так называемые callable-объекты.
Django берёт на себя всё, что связано с роутингом URL и логикой обработки запросов, также Django стандартизирует внутреннюю архитектуру Web-приложений, в которых реализуется основная бизнес-логика проекта.
Обратите внимание, по умолчанию Nginx слушает 80 порт, но его можно перенастроить. Будьте внимательны при работе с портами, в Unix-системах есть разделение портов по привилегиям. Порты ниже 1024 являются привилегированными, чтобы работать с ними программа должна быть запущена от имени суперпользователя.
Из исторически сложившихся сочетаний портов и назначений можно отметить:
- 20, 21 — FTP;
- 22 — SSH;
- 25 — SMTP;
- 80 порт — HTTP;
- 443 — HTTPS.
Для большей наглядности и понимания взаимодействия всех элементов Django-стека — развернем его в ручном режиме на одном виртуальном сервере.
Django и Gunicorn
Для установки Django-стека воспользуемся быстрым и бюджетным виртуальным сервером на базе Open source под управлением Ubuntu 20. Подключимся к нему по SSH и начнем установку. Устанавливать Django мы будем в виртуальную среду — это наиболее желательный сценарий, в таком случае не затрагиваются глобальные настройки сервера и появляется возможность управлять разными версиями одних и тех же пакетов в разных проектах.
Установка Django и Gunicorn
Установка и тестирование Django и Gunicorn должно идти в определенной последовательности во избежание критических ошибок:
- Сначала обновим apt-репозитории и установим необходимые для корректной работы Django и Gunicorn Python-пакеты:
sudo apt update && apt install -y zlib1g-dev libbz2-dev libreadline-dev llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev liblzma-dev python3-dev python-pil python3-lxml libxslt-dev libffi-dev libssl-dev python-dev gnumeric libsqlite3-dev libpq-dev libxml2-dev libxslt1-dev libjpeg-dev libfreetype6-dev libcurl4-openssl-dev python-libxml2 python3-venv imagemagick graphicsmagick imagemagick-6.q16hdri
Установка может занять значительное время. Объем устанавливаемых пакетов порядка 1,7 Gb. Это стоит учесть при выборе размера дискового пространства.
- После завершения установки пакетов, можно создавать директорию для будущего проекта. Мы создадим папку для проекта по пути: /var/www/django_test. Внутри директории проекта создадим директорию с виртуальным окружением: python3 -m venv [название виртуального окружения]. У нас оно называется env.
- Активируем виртуальное окружение командой source env/bin/activate. В левой части строки терминала появится название виртуального окружения:
- Теперь можно установить Django, Gunicorn и модуль для подключения Django к PSQL:
pip3 install django
pip3 install psycopg2
pip3 install gunicorn
Создание тестового проекта и настройка Django
В первую очередь необходимо убедиться в работоспособности Django. Для этого создадим тестовый проект, затем можно будет импортировать проекты с GitHub.
- Находясь в директории проекта выполните команду django-admin startproject [название проекта]. В нашем случае проект называется django_test. В результате выполнения команды развернется схожая структура:
Обратите внимание, что при создании проекта, Django автоматически создает одноименное приложение. На скриншоте проект и одноименное приложение подчеркнуты красным.
Это приложение точка входа в проект. В нём содержатся файлы с расширением .wsgi, именно к нему будет подключаться Gunicorn.
-
Теперь создадим первое Django-приложение. Для этого перейдем на уровень проекта (django_test) и вызовем скрипт manage.py с директивой startapp: python3 manage.py startapp [название приложения]. Мы назвали приложение first. Теперь структура проекта test_project выглядит так:
-
Активируем Django-приложение, внесением его в список зарегистрированных приложений. Это делается через файл settings.py, находящейся в одноименном приложении проекта. В нашем случае — test_project.
В файл нужно внести следующие данные:
- В список ALLOWED_HOSTS вносятся 2 IP-адреса: IP-адрес виртуального сервера и внутренний сети. Это нужно для того, чтобы избежать ошибки disallowed hosts при запуске Django;
- В список INSTALLED_APPS вносятся все созданные приложения.
-
С помощью встроенного development-сервера Django проверим работоспособность приложения — выполним команду python3 manage.py runserver 0.0.0.0:8000, находясь на уровне одноименного с проектом приложения — test_project. Виртуальное окружение должно быть активировано!
Если всё сделано правильно — вы увидите вывод следующего вида:
Теперь можно перейти в браузер и обратиться к Django: введите IP-адрес сервера и порт, который слушает Django. Браузер откроет дефолтную страницу Django.
Отлично! Django работает исправно. Теперь Настроим Gunicorn.
Настройка Gunicorn
Gunicorn — это Application-сервер для запуска Web-приложений написанных на Python. Основная его задача — это работа в режиме демона и поддержка постоянной работы Web-приложений.
Пошаговая настройка Gunicorn может выглядеть так:
-
Сначала создадим конфигурационный файл с настройками Gunicorn в формате .py. Мы назвали его gunicorn_config.py. Он размещается в директории одноименного приложения проекта.
Конфигурационный файл содержит следующие данные:
command = "/var/www/django_test/env/bin/gunicorn" #путь расположения Gunicorn
python_path = "/var/www/django_test/test_project/test_project" #путь к разводящему приложению
bind = "0.0.0.0:8001" #Порт, который будет слушать Django
workers = 5 # Кол-во запущенных процессов
user = "www" #Пользователь, от имени которого будет запущен Django
raw_env = "DJANGO_SETTINGS_MODULE=test_project.settings" #Переменная окружения с setting.pyТут мы указали bind = "0.0.0.0:8001". Это сделано в демонстрационных целях, чтобы протестировать работу Gunicorn и его связку с Nginx. В дальнейшем, конечно, мы изменим этот параметр на 127.0.0.1:8001.
-
После создания конфигурационного файла, можно создать скрипт запуска Gunicorn в формате .sh и разместить его на уровне проекта. Мы создали скрипт gunicorn.sh.
Скрипт может содержать следующие:
#!/bin/bash
source /var/www/django_test/env/bin/activate #активация виртуального окружения
exec gunicorn -c "/var/www/django_test/test_project/test_project/gunicorn_config.py" test_project.wsgi #запуск Gunicorn с указанием конфигурационного и wsgi файловПосле сохранения скрипта, на него нужно навесить права на запуск командой chmod +x [название файла] и добавить нового пользователя в систему командой adduser www. Теперь можно запустить скрипт: source gunicorn.sh.
Если всё сделано верно — вы увидите следующий отчёт Gunicorn:
Отлично! Теперь сделаем Gunicorn демоном.
Делаем из Gunicorn демона
Gunicorn должен постоянно работать, перезагружаться в случае сбоя и автоматически загружаться при старте виртуального сервера или после перезагрузки.
Воспользуемся systemd для создания демон-процесса (юнита) Gunicorn:
-
Создадим файл gunicorn.service в директории /etc/systemd/system и поместим в него следующие данные:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=www #Пользователь, от чьего имени будет выполнен процесс
Group=www-data #Группа пользователей, от чьего имени будет выполнен процесс
WorkingDirectory= /var/www/django_test/test_project #Рабочая директория процесса
ExecStart= /var/www/django_test/test_project/gunicorn.sh #Программа для запуска
Restart=on-failure #Условие перезапуска процесса
[Install]
WantedBy=multi-user.targetСохраним файл и навесим на него 775 права командой chmod 775 gunicorn.service. Обновим список юнитов командой systemctl daemon-reload.
-
Запустим вновь созданный юнит командой systemctl startgunicorn и проверим статус его работы — system status gunicorn. Если всё сделано правильно, вывод команды будет следующим:
Теперь командой system enable gunicorn установим автозапуск Gunicorn при перезагрузке сервера. Проверим доступность Gunicorn — обратимся через браузер по IP-адресу сервера на порт 8001.
Браузер отобразит дефолтную страницу Django:
Теперь, когда Django и Gunicorn настроены и работают исправно можно установить и настроить Nginx и PostgreSQL.
Установка и настройка Nginx
В Django-стеке установка и настройка Nginx — самый простой этап:
- Устанавливаем Nginx из стандартных репозиториев Linux: apt install nginx.
- Создадим очень простой конфигурационный файл для Nginx в директории /etc/nginx/sites-available. Укажем в нём только порт прослушивания, домен и условия для проксирования:
server {
listen 80; #Порт прослушивания
server_name 93.159.221.5; #Название домена
location / {
proxy_pass http://0.0.0.0:8001; #Проксирование на IP-адрес
}
}В качестве домена (server_name) мы указали IP-сервера, так делать можно, если у вас нет зарегистрированного домена или нет доступа к файлу hosts.
- Сохраним файл (наш конфиг называется django) и создадим символьную ссылку для активации конфигурационного файла: sudo ln -s /etc/nginx/sites-available/django /etc/nginx/sites-enabled/. Ссылку на дефолтный конфиг можно удалить: rm /etc/nginx/sites-enabled/default.
- Перезапускаем Nginx командой systemctl restart nginx и вводим в поисковую строку браузера: [IP-адрес сервера]:80. Откроется дефолтная страница Django.
Теперь, когда Django, Gunicorn и Nginx настроены и работают, можно установить и настроить PostgreSQL.
Установка и настройка PostgreSQL
PostgreSQL так же как и Nginx устанавливается из стандартных репозиториев Linux командой sudo apt -y install postgresql. По умолчанию установится PostgreSQL 10, чтобы установить более новый PostgreSQL — нужно добавить репозиторий и выполнить установку. Вот, например, команды установки PostgreSQL 11:
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - ; \
RELEASE=$(lsb_release -cs) ; \
echo "deb http://apt.postgresql.org/pub/repos/apt/ ${RELEASE}"-pgdg main | sudo tee /etc/apt/sources.list.d/pgdg.list ; \
sudo apt update ; \
sudo apt -y install postgresql-11 ; \
По умолчанию PostgreSQL запускается от имени postgres. Сменим пароль для этого пользователя и создадим новую базу данных:
sudo passwd postgres #Сменя пароля для пользователя postgres
su - postgres #Логин в PostgreSQL пользователем postgres
export PATH=$PATH:/usr/lib/postgresql/10/bin #Экспорт пути для работы с createdb
createdb --encoding UNICODE dtb_db --username postgres #Создание базы данных dtb_db
exit #выход из PosgreSQL
Теперь нужно создать нового пользователя, из-под которого в PSQL будет заходить Django и назначить ему права на создание БД, а также дать все права на управление только что созданной БД:
sudo -u postgres psql #Логинимся в PSQL под пользователем posgres
create user dc with password 'Django_Connecter'; #Создаём пользователя dc с паролем 'Django_Connecter
ALTER USER dc CREATEDB; #Разрешаем пользователю dc создавать БД
grant all privileges on database dtb_db to dc; #Выдаём все права пользователю dc на базу dtb_db
\c dtb_db #Переход в базу данных dtb_db
GRANT ALL ON ALL TABLES IN SCHEMA public to dc; #Дать все права пользователю dc на создание таблиц
GRANT ALL ON ALL SEQUENCES IN SCHEMA public to dc; #Дать все права пользователю dc на создание последовательностей
GRANT ALL ON ALL FUNCTIONS IN SCHEMA public to dc; #Дать все права пользователю dc на создание функций
\q #Выход из БД
exit #Выход из PSQl
Пропишем данные для подключения Django с PSQL. Изменения вносятся в файл settings.py в список DATABASES. Вот что следует указать:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2', #Движок для подключения
'NAME': 'dtb_db', #Название БД для подключения
'USER': 'dc', # Пользователь для подключения к БД
'PASSWORD': 'Django_Connecter', #Пароль пользователя dc
'HOST': '127.0.0.1', #IP на котором хостится PSQL
'PORT': '5432' #Порт, который прослушивает PSQL
}
}
Теперь выполним миграции в БД:
./manage.py makemigrations
./manage.py migrate
Если все данные для подключения Django к PSQL были внесены верно, вы увидите следующий вывод:
Эти строчки означают, что миграция прошла успешно и соединение Django с PSQL работает исправно. На этом установка и настройка Django-стека на один сервер окончена. Соберем теперь всё воедино.
Собираем все знания о Django воедино
Для понимания взаимодействия элементов Django-стека между собой возьмем схему работы Django-стека, которую мы приводили в начале статьи и дополним ее командами, конфигурационными файлами и настройками Django.
Расширенная схема работы Django-стека с посерверным разделением может выглядеть так:
Кликнете по картинке, чтобы рассмотреть её детально.
Такая цепочка взаимодействий кажется сложной и длинной, однако у нее есть ряд существенных преимуществ:
- Отказоустойчивость — элементы Django-стека могут быть разнесены по разным серверам, на которых реализована система мониторинга и инициализации. Например, systemd.
- Масштабируемость — некоторые элементы Django-стека, такие, как Web-серверы и серверы баз данных, могут дублироваться в зависимости от нагрузки на серверы.
- Гибкость — Django-стек позволяет гибко настраивать каждый свой элемент и предоставляет возможность полностью их менять. Например, вы можете использовать SQLite вместо PostgreSQL или Apache вместо Nginx.
- Расширяемость — Django-стек не ограничивается базовым набором элементов. Можно интегрировать и дополнительные элементы. Например, Redis — система управления NoSQL базами данных, Memcached — сервис кэширования данных в оперативной памяти.
Теперь, когда мы узнали достаточно о том, как работают и взаимодействуют между собой базовые элементы Django-стека, мы можем пойти дальше — разделить Django-стек на заранее созданные с помощью Terraform 3 сервера.
Рекомендуем ознакомиться с предыдущими статьями, они помогут вам более детально разобраться в работе Terraform и Ansible:
Terraform на практике
Управляем VMware Cloud Director по API с помощью Terraform.
YAML для начинающих
Разбираем синтаксис YAML и пишем конфигурационные файлы на нём.
Работа с Ansible
Разворачиваем LEMP стек на VPS под управлением Ubuntu 18.