Recherche de site Web

Automatisation des déploiements Django avec Fabric et Ansible


Dans le dernier article, nous avons couvert toutes les étapes nécessaires pour développer et déployer avec succès une application Django sur un seul serveur. Dans ce didacticiel, nous allons automatiser le processus de déploiement avec Fabric (v1.12.0) et Ansible (v2.1.3) pour résoudre ces problèmes :

  1. Mise à l'échelle : lorsqu'il s'agit de faire évoluer une application Web pour gérer des milliers de requêtes quotidiennes, s'appuyer sur un seul serveur n'est pas une bonne approche. En termes simples, à mesure que le serveur approche de l'utilisation maximale du processeur, cela peut entraîner des temps de chargement lents, ce qui peut éventuellement conduire à une panne du serveur. Pour surmonter ce problème, l'application doit être mise à l'échelle pour s'exécuter sur plusieurs serveurs afin que les serveurs puissent de manière cumulative gérer les requêtes simultanées entrantes.
  2. Redondance : le déploiement manuel d'une application Web sur un nouveau serveur implique beaucoup de travail répété avec plus de risques d'erreur humaine. L'automatisation du processus est essentielle.

Plus précisément, nous automatiserons :

  1. Ajouter un nouvel utilisateur non root
  2. Configuration du serveur
  3. Extraire le code de l'application Django à partir d'un dépôt GitHub
  4. Installer les dépendances
  5. Démoniser l'application

Installation et configuration

Commencez par créer une nouvelle gouttelette Digital Ocean, en vous assurant d'utiliser l'image Fedora 25. Ne configurez pas de clé SSH préconfigurée ; nous automatiserons ce processus plus tard via un script Fabric. Étant donné que le processus de déploiement doit être évolutif, créez un référentiel distinct pour héberger tous les scripts de déploiement. Créez un nouveau répertoire de projet localement, puis créez et activez un virtualenv à l'aide de Python 2.7x.

Pourquoi Python 2.7 ? Fabric ne prend PAS en charge Python 3. Ne vous inquiétez pas : nous utiliserons Python 3.5 lors du provisionnement du serveur.

$ mkdir automated-deployments
$ cd automated-deployments
$ virtualenv env
$ source env/bin/activate

Configuration du tissu

Fabric est un outil utilisé pour automatiser les commandes shell de routine sur SSH, que nous utiliserons pour :

  1. Configurer les clés SSH
  2. Renforcer les mots de passe des utilisateurs
  3. Installer les dépendances Ansible
  4. Mettre à niveau le serveur

Commencez par installer Fabric :

$ pip install fabric==1.12.0

Créez un nouveau dossier appelé « prod » et ajoutez-y un nouveau fichier appelé fabfile.py pour contenir tous les scripts Fabric :

# prod/fabfile.py

import os
from fabric.contrib.files import sed
from fabric.api import env, local, run
from fabric.api import env

# initialize the base directory
abs_dir_path = os.path.dirname(
    os.path.dirname(os.path.abspath(__file__)))


# declare environment global variables

# root user
env.user = 'root'

# list of remote IP addresses
env.hosts = ['<remote-server-ip>']

# password for the remote server
env.password = '<remote-server-password>'

# full name of the user
env.full_name_user = '<your-name>'

# user group
env.user_group = 'deployers'

# user for the above group
env.user_name = 'deployer'

# ssh key path
env.ssh_keys_dir = os.path.join(abs_dir_path, 'ssh-keys')

Prenez note des commentaires en ligne. Assurez-vous d'ajouter l'adresse IP de votre serveur distant à la variable env.hosts. Mettez également à jour env.full_name_user. Attendez de mettre à jour env.password ; nous y reviendrons sous peu. Examinez toutes les variables env : elles sont entièrement personnalisables en fonction de la configuration de votre système.

Configurer les clés SSH

Ajoutez le code suivant à fabfile.py :

def start_provision():
    """
    Start server provisioning
    """
    # Create a new directory for a new remote server
    env.ssh_keys_name = os.path.join(
        env.ssh_keys_dir, env.host_string + '_prod_key')
    local('ssh-keygen -t rsa -b 2048 -f {0}'.format(env.ssh_keys_name))
    local('cp {0} {1}/authorized_keys'.format(
        env.ssh_keys_name + '.pub', env.ssh_keys_dir))
    # Prevent root SSHing into the remote server
    sed('/etc/ssh/sshd_config', '^UsePAM yes', 'UsePAM no')
    sed('/etc/ssh/sshd_config', '^PermitRootLogin yes',
        'PermitRootLogin no')
    sed('/etc/ssh/sshd_config', '^#PasswordAuthentication yes',
        'PasswordAuthentication no')

    install_ansible_dependencies()
    create_deployer_group()
    create_deployer_user()
    upload_keys()
    set_selinux_permissive()
    run('service sshd reload')
    upgrade_server()

Cette fonction fait office de point d'entrée pour le script Fabric. En plus de déclencher une série de fonctions, chacune expliquée dans des étapes ultérieures, cela explicitement-

  • Génère une nouvelle paire de clés SSH à l'emplacement spécifié dans votre système local
  • Copie le contenu de la clé publique dans le fichier authorized_keys
  • Apport des modifications au fichier sshd_config distant pour empêcher la connexion root et désactiver l'authentification sans mot de passe.

Empêcher l'accès SSH pour l'utilisateur root est une étape facultative, mais elle est recommandée car elle garantit que personne ne dispose des droits de superutilisateur.

Créez un répertoire pour vos clés SSH à la racine du projet :

├── prod
│   └── fabfile.py
└── ssh-keys

Renforcer les mots de passe des utilisateurs

Cette étape comprend l'ajout de trois fonctions différentes, chacune exécutée en série pour configurer le renforcement du mot de passe SSH…

Créer un groupe de déployeurs

def create_deployer_group():
    """
    Create a user group for all project developers
    """
    run('groupadd {}'.format(env.user_group))
    run('mv /etc/sudoers /etc/sudoers-backup')
    run('(cat /etc/sudoers-backup; echo "%' +
        env.user_group + ' ALL=(ALL) ALL") > /etc/sudoers')
    run('chmod 440 /etc/sudoers')

Ici, nous ajoutons un nouveau groupe appelé deployers et lui accordons les autorisations sudo afin que les utilisateurs puissent exécuter des processus avec les privilèges root.

Créer un utilisateur

def create_deployer_user():
    """
    Create a user for the user group
    """
    run('adduser -c "{}" -m -g {} {}'.format(
        env.full_name_user, env.user_group, env.user_name))
    run('passwd {}'.format(env.user_name))
    run('usermod -a -G {} {}'.format(env.user_group, env.user_name))
    run('mkdir /home/{}/.ssh'.format(env.user_name))
    run('chown -R {} /home/{}/.ssh'.format(env.user_name, env.user_name))
    run('chgrp -R {} /home/{}/.ssh'.format(
        env.user_group, env.user_name))

Cette fonction-

  • Ajoute un nouvel utilisateur au groupe d'utilisateurs déployeurs, que nous avons défini dans la dernière fonction
  • Configure le répertoire SSH pour conserver les paires de clés SSH et accorde l'autorisation au groupe et à l'utilisateur d'accéder à ce répertoire

Télécharger les clés SSH

def upload_keys():
    """
    Upload the SSH public/private keys to the remote server via scp
    """
    scp_command = 'scp {} {}/authorized_keys {}@{}:~/.ssh'.format(
        env.ssh_keys_name + '.pub',
        env.ssh_keys_dir,
        env.user_name,
        env.host_string
    )
    local(scp_command)

Ici, nous-

  • Téléchargez les clés SSH générées localement sur le serveur distant afin que les utilisateurs non root puissent se connecter via SSH sans saisir de mot de passe.
  • Copiez la clé publique et les clés autorisées sur le serveur distant dans le répertoire ssh-keys nouvellement créé

Installer les dépendances Ansible

Ajoutez la fonction suivante pour installer les packages de dépendances pour Ansible :

def install_ansible_dependencies():
    """
    Install the python-dnf module so that Ansible
    can communicate with Fedora's Package Manager
    """
    run('dnf install -y python-dnf')

Gardez à l'esprit que cela est spécifique à la distribution Fedora Linux, car nous utiliserons le module DNF pour installer les packages, mais cela peut varier selon la distribution.

Réglez SELinux en mode permissif

La fonction suivante définit SELinux en mode permissif. Ceci est fait pour surmonter toute erreur potentielle Nginx 502 Bad Gateway.

def set_selinux_permissive():
    """
    Set SELinux to Permissive/Disabled Mode
    """
    # for permissive
    run('sudo setenforce 0')

Encore une fois, ceci est spécifique à la distribution Fedora Linux.

Mettre à niveau le serveur

Enfin, mettez à niveau le serveur :

def upgrade_server():
    """
    Upgrade the server as a root user
    """
    run('dnf upgrade -y')
    # optional command (necessary for Fedora 25)
    run('dnf install -y python')
    run('reboot')

Verification sanitaire

Avec cela, nous en avons terminé avec le script Fabric. Avant de l'exécuter, assurez-vous de vous connecter en SSH au serveur en tant que root et de modifier le mot de passe :

$ ssh root@<server-ip-address>
You are required to change your password immediately (root enforced)
Changing password for root.
(current) UNIX password:
New password:
Retype new password:

Assurez-vous de mettre à jour env.password avec le nouveau mot de passe. Quittez le serveur et revenez au terminal local, puis exécutez Fabric :

$ fab -f ./prod/fabfile.py start_provision

Si tout s'est bien passé, de nouvelles clés SSH seront générées et il vous sera demandé de créer un mot de passe (assurez-vous de le faire !) :

Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

Un certain nombre de tâches seront exécutées. Une fois l'utilisateur déployeur créé, vous serez invité à ajouter un mot de passe pour l'utilisateur.

[104.236.66.172] out: Changing password for user deployer.

-que vous devrez ensuite saisir lors du téléchargement des clés SSH :

deployer@104.236.66.172s password:

Une fois ce script terminé avec succès, vous ne pourrez plus vous connecter au serveur distant en tant qu'utilisateur root. Au lieu de cela, vous ne pourrez utiliser que l'utilisateur non root déployeur.

Essaye le:

$ ssh root@<server-ip-address>
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

Ceci est attendu. Puis, quand tu cours-

$ ssh -i ./ssh-keys/104.236.66.172_prod_key deployer@104.236.66.172

-vous devriez pouvoir vous connecter très bien :

[deployer@fedora-512mb-nyc2-01 ~]$

Introduction à Ansible

Ansible est un outil de gestion de configuration et de provisionnement utilisé pour automatiser les tâches de déploiement via SSH.

Vous pouvez lancer des tâches Ansible individuelles sur les serveurs d'applications à partir de votre shell et exécuter des tâches en déplacement. Les tâches peuvent également être combinées dans des Playbooks : une collection de plusieurs plays, où chaque play définit certaines tâches spécifiques requises pendant le processus de déploiement. Ils sont exécutés sur les serveurs d'applications pendant le processus de déploiement. Les playbooks sont écrits en YAML.

Manuels de jeu

Les playbooks se composent d’une architecture modulaire comme suit :

  1. Les hôtes précisent toutes les adresses IP ou noms de domaine de nos serveurs distants qui doivent être orchestrés. Les playbooks s'exécutent toujours sur un groupe ciblé d'hôtes.
  2. Les rôles sont divisés en sous-parties. Examinons quelques exemples de rôles :

    • Les tâches sont un ensemble de plusieurs tâches qui doivent être effectuées pendant le processus de déploiement.
    • Les gestionnaires fournissent un moyen de déclencher un ensemble d'opérations lorsqu'un module apporte une modification au serveur distant (mieux considéré comme des hooks).
    • Les modèles, dans ce contexte, sont généralement utilisés pour spécifier certains fichiers de configuration liés aux modules, comme nginx.
  3. Les variables sont simplement une liste de paires clé-valeur où chaque clé (une variable) est mappée à une valeur. Ces variables peuvent être utilisées dans les Playbooks comme espaces réservés.

Exemple de manuel de jeu

Examinons maintenant un exemple de Playbook à fichier unique :

---
# My Ansible playbook for configuring Nginx
- hosts: all

  vars:
    http_port: 80
    app_name: django_bootstrap

  tasks:
    - name: Install nginx
      dnf: name=nginx state=latest

    - name: Create nginx config file
      template: src=django_bootstrap.conf dest=/etc/nginx/conf.d/{{ app_name }}.conf
      become: yes
      notify:
        - restart nginx

  handlers:
    - name: Restart nginx
      service: name=nginx state=restarted enabled=yes
      become: yes

Ici, nous avons défini :

  • Hôtes en tant que hosts : all, ce qui indique que le Playbook s'exécutera sur tous les serveurs répertoriés dans le fichier inventory/hosts
  • Variables http_port : 80 et app_name : django_bootstrap à utiliser dans un modèle
  • Tâches pour installer nginx, configurer la configuration nginx (devenir indique que nous avons besoin de privilèges d'administrateur) et déclencher le gestionnaire de redémarrage
  • Handler afin de redémarrer le service nginx

Configuration du manuel de jeu

Maintenant, configurons un Playbook pour Django. Ajoutez un fichier deploy.yml dans le répertoire « prod » :

##
# This playbook deploys the whole app stack
##
- name: apply common configuration to server
  hosts: all
  user: deployer
  roles:
    - common

L'extrait ci-dessus regroupe les hôtes, les utilisateurs et les rôles Ansible.

Hôtes

Ajoutez un fichier hosts (format texte brut) au répertoire « prod » et répertoriez les serveurs sous leurs noms de rôle respectifs. Nous provisionnons ici un seul serveur :

[common]
<server-ip-address>

Dans l'extrait ci-dessus, common fait référence au nom du rôle. Sous les rôles, nous avons une liste d'adresses IP qui doivent être configurées. Assurez-vous d'ajouter l'adresse IP de votre serveur distant à la place de .

Variables

Nous définissons maintenant les variables qui seront utilisées par les rôles. Ajoutez un nouveau dossier dans « prod » appelé « group_vars », puis créez un nouveau fichier appelé all (format texte brut) dans ce dossier. Ici, spécifiez les variables suivantes pour commencer :

# App Name
app_name: django_bootstrap

# Deployer User and Groups
deployer_user: deployer
deployer_group: deployers

# SSH Keys Directory
ssh_dir: <path-to-your-ssh-keys>

Assurez-vous de mettre à jour . Pour obtenir le chemin correct, à la racine du projet, exécutez :

$ cd ssh-keys
$ pwd
/Users/michael.herman/repos/realpython/automated-deployments/ssh-keys

Une fois ces fichiers en place, nous sommes maintenant prêts à coordonner notre processus de déploiement avec tous les rôles qui doivent être exécutés sur le serveur.

Rôles du manuel de jeu

Encore une fois, les Playbooks sont simplement une collection de pièces différentes, et toutes ces pièces sont exécutées sous des rôles spécifiques. Créez un nouveau répertoire appelé « rôles » dans « prod ».

Avez-vous saisi le nom du rôle dans le fichier deploy.yml ?

Ensuite, dans le répertoire « rôles », ajoutez un nouveau répertoire appelé « commun » - le rôle. Les rôles se composent de « tâches », de « gestionnaires » et de « modèles ». Ajoutez un nouveau répertoire pour chacun.

Une fois cela fait, la structure de votre fichier devrait ressembler à ceci :

├── prod
│   ├── deploy.yml
│   ├── fabfile.py
│   ├── group_vars
│   │   └── all
│   ├── hosts
│   └── roles
│       └── common
│           ├── handlers
│           ├── tasks
│           └── templates
└── ssh-keys
    ├── 104.236.66.172_prod_key
    ├── 104.236.66.172_prod_key.pub
    └── authorized_keys

Tous les jeux sont définis dans un répertoire « tâches », commençant par un fichier main.yml. Ce fichier sert de point d'entrée pour toutes les tâches du Playbook. Il s'agit simplement d'une liste de plusieurs fichiers YAML qui doivent être exécutés dans l'ordre.

Créez ce fichier maintenant dans le répertoire « tâches », puis ajoutez-y ce qui suit :

##
# Configure the server for the Django app
##
- include: 01_server.yml
- include: 02_git.yml
- include: 03_postgres.yml
- include: 04_dependencies.yml
- include: 05_migrations.yml
- include: 06_nginx.yml
- include: 07_gunicorn.yml
- include: 08_systemd.yml
# - include: 09_fix-502.yml

Maintenant, créons chaque tâche. Assurez-vous d'ajouter un nouveau fichier pour chaque tâche au répertoire « tâches » et ajoutez le code qui l'accompagne à chaque fichier. Si vous vous perdez, référez-vous au dépôt.

01_server.yml

##
# Update the DNF package cache and install packages as a root user
##
- name: Install required packages
  dnf: name={{item}} state=latest
  become: yes
  with_items:
    - vim
    - fail2ban
    - python3-devel
    - python-virtualenv
    - python3-virtualenv
    - python-devel
    - gcc
    - libselinux-python
    - redhat-rpm-config
    - libtiff-devel
    - libjpeg-devel
    - libzip-devel
    - freetype-devel
    - lcms2-devel
    - libwebp-devel
    - tcl-devel
    - tk-devel
    - policycoreutils-devel

Ici, nous répertorions tous les packages système qui doivent être installés.

02_git.yml

##
# Clone and pull the repo
##
- name: Set up git configuration
  dnf: name=git state=latest
  become: yes

- name: Clone or pull the latest code
  git: repo={{ code_repository_url }}
        dest={{ app_dir }}

Ajoutez les variables suivantes au fichier group_vars/all :

# Github Code's Repo URL
code_repository_url: https://github.com/realpython/django-bootstrap

# App Directory
app_dir: /home/{{ deployer_user }}/{{app_name}}

Assurez-vous de fork puis de cloner le dépôt django-bootstrap, puis de mettre à jour la variable code_repository_url avec l'URL de votre fork.

03_postgres.yml

##
# Set up and configure postgres
##
- name: Install and configure db
  dnf: name={{item}} state=latest
  become: yes
  with_items:
    - postgresql-server
    - postgresql-contrib
    - postgresql-devel
    - python-psycopg2

- name: Run initdb command
  raw: postgresql-setup initdb
  become: yes

- name: Start and enable postgres
  service: name=postgresql enabled=yes state=started
  become: yes

- name: Create database
  postgresql_db: name={{ app_name }}
  become_user: postgres
  become: yes

- name: Configure a new postgresql user
  postgresql_user: db={{ app_name }}
                                name={{ db_user }}
                                password={{ db_password }}
                                priv=ALL
                                role_attr_flags=NOSUPERUSER
  become: yes
  become_user: postgres
  notify:
    - restart postgres

Mettez à jour group_vars/all avec la configuration de base de données nécessaire pour le playbook :

# DB Configuration
db_url: postgresql://{{deployer_user}}:{{db_password}}@localhost/{{app_name}}
db_password: thisissomeseucrepassword
db_name: "{{ app_name }}"
db_user: "{{ deployer_user }}"

Mettez à jour la variable db_password avec un mot de passe sécurisé.

Avez-vous remarqué que nous redémarrons le service postgres dans le fichier main.yml afin d'appliquer les modifications une fois la base de données configurée ? C'est notre premier gestionnaire. Créez un nouveau fichier appelé main.yml dans le dossier « handlers », puis ajoutez ce qui suit :

- name: restart postgres
  service: name=postgresql state=restarted
  become: yes

04_dependencies.yml

##
# Set up all the dependencies in a virtualenv required by the Django app
##
- name: Create a virtualenv directory
  file: path={{ venv_dir }} state=directory

- name: Install dependencies
  pip:    requirements={{ app_dir }}/requirements.txt
          virtualenv={{ venv_dir }}
          virtualenv_python=python3.5

- name: Create the .env file for running ad-hoc python commands in our virtualenv
  template: src=env.j2 dest={{ app_dir }}/.env
  become: yes

Mettez à jour group_vars/all comme ceci :

# Application Dependencies Setup
venv_dir: '/home/{{ deployer_user }}/envs/{{ app_name }}'
venv_python: '{{ venv_dir }}/bin/python3.5'

Ajoutez un modèle appelé env.j2 au dossier « templates » et ajoutez les variables d'environnement suivantes :

#!/bin/bash
export DEBUG="True"
export DATABASE_URL="postgresql://deployer:thisissomeseucrepassword@localhost/django_bootstrap"
export DJANGO_SECRET_KEY="changeme"
export DJANGO_SETTINGS_MODULE="config.settings.production"

Soyez très prudent avec les variables d'environnement et leurs valeurs dans env.j2 car celles-ci sont utilisées pour faire fonctionner le projet Django.

05_migrations.yml

##
# Run db migrations and get all static files
##
- name: Make migrations
  shell: ". {{ app_dir }}/.env; {{ venv_python }} {{ app_dir }}/manage.py makemigrations "
  become: yes

- name: Migrate database
  django_manage: app_path={{ app_dir }}
                                 command=migrate
                                 virtualenv={{ venv_dir }}

- name: Get all static files
  django_manage: app_path={{ app_dir }}
                                 command=collectstatic
                                 virtualenv={{ venv_dir }}
  become: yes

06_nginx.yml

##
# Configure nginx web server
##
- name: Set up nginx config
  dnf: name=nginx state=latest
  become: yes

- name: Write nginx conf file
  template: src=django_bootstrap.conf dest=/etc/nginx/conf.d/{{ app_name }}.conf
  become: yes
  notify:
    - restart nginx

Ajoutez la variable suivante à group_vars/all :

# Remote Server Details
server_ip: <remote-server-ip>
wsgi_server_port: 8000

N'oubliez pas de mettre à jour . Ajoutez ensuite le gestionnaire à handlers/main.yml :

- name: restart nginx
  service: name=nginx state=restarted enabled=yes
  become: yes

Ensuite, nous devons ajouter le modèle django_bootstrap.conf. Créez ce fichier dans le répertoire « templates », puis ajoutez le code :

upstream app_server {
    server 127.0.0.1:{{ wsgi_server_port }} fail_timeout=0;
}

server {
    listen 80;
    server_name {{ server_ip }};
    access_log /var/log/nginx/{{ app_name }}-access.log;
    error_log /var/log/nginx/{{ app_name }}-error.log info;

    keepalive_timeout 5;

    # path for staticfiles
    location /static {
            autoindex on;
            alias {{ app_dir }}/staticfiles/;
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://app_server;
            break;
        }
    }
}

07_gunicorn.yml

##
# Set up Gunicorn and configure systemd to execute gunicorn_start script
##
- name: Create a deploy directory
  file: path={{ deploy_dir }} state=directory
  become: yes

- name: Create the gunicorn_start script for running our app from systemd service
  template: src=gunicorn_start
                    dest={{ deploy_dir }}/gunicorn_start
  become: yes

- name: Make the gunicorn_start script executable
  raw: cd {{ deploy_dir }}; chmod +x gunicorn_start
  become: yes

Ajoutez plus de variables à groups_vars/all :

# Deploy Dir in App Directory
deploy_dir: '{{ app_dir }}/deploy'

# WSGI Vars
django_wsgi_module: config.wsgi
django_settings_module: config.settings.production
django_secret_key: 'changeme'
database_url: '{{ db_url }}'

Ajoutez le modèle gunicorn_start :

#!/bin/bash

### Define script variables

# Name of the app
NAME='{{ app_name }}'
# Path to virtualenv
VIRTUALENV='{{ venv_dir }}'
# Django Project Directory
DJANGODIR='{{ app_dir }}'
# The user to run as
USER={{ deployer_user }}
# The group to run as
GROUP={{deployer_group }}
# Number of worker processes Gunicorn should spawn
NUM_WORKERS=3
# Settings file that Gunicorn should use
DJANGO_SETTINGS_MODULE={{django_settings_module}}
# WSGI module name
DJANGO_WSGI_MODULE={{ django_wsgi_module }}


### Activate virtualenv and create environment variables

echo "Starting $NAME as `whoami`"
# Activate the virtual environment
cd $VIRTUALENV
source bin/activate
cd $DJANGODIR
# Defining the Environment Variables
export DJANGO_SECRET_KEY='{{ django_secret_key }}'
export DATABASE_URL='{{ db_url }}'
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH


### Start Gunicorn

exec gunicorn ${DJANGO_WSGI_MODULE}:application \
        --name $NAME \
        --workers $NUM_WORKERS \
        --user=$USER --group=$GROUP \
        --log-level=debug \
        --bind=127.0.0.1:8000

08_systemd.yml

##
# Set up systemd for executing gunicorn_start script
##
- name: write a systemd service file
  template: src=django-bootstrap.service
                    dest=/etc/systemd/system
  become: yes
  notify:
    - restart app
    - restart nginx

Ajoutez le modèle - django-bootstrap.service :

#!/bin/sh

[Unit]
Description=Django Web App
After=network.target

[Service]
PIDFile=/var/run/djangoBootstrap.pid
User={{ deployer_user }}
Group={{ deployer_group }}
ExecStart=/bin/sh {{ deploy_dir }}/gunicorn_start
Restart=on-abort

[Install]
WantedBy=multi-user.target

Ajoutez ce qui suit aux gestionnaires :

- name: restart app
  service: name=django-bootstrap state=restarted enabled=yes
  become: yes

09_fix-502.yml

##
# Fix the 502 nginx error post deployment
#
- name: Fix nginx 502 error
  raw: cd ~; cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M mynginx; semodule -i mynginx.pp
  become: yes

Contrôle d'intégrité (final)

Avec virtualenv activé, installez Ansible localement :

$ pip install ansible==2.1.3

Créez un nouveau fichier appelé deploy_prod.sh à la racine du projet pour exécuter le playbook, en veillant à mettre à jour :

#!/bin/bash

ansible-playbook ./prod/deploy.yml --private-key=./ssh_keys<server-ip>_prod_key -K -u deployer -i ./prod/hosts -vvv

Exécutez ensuite la commande suivante pour exécuter le playbook :

$ sh deploy_prod.sh

Si des erreurs surviennent, consultez le terminal pour savoir comment les corriger. Une fois corrigé, exécutez à nouveau le script de déploiement. Une fois le script terminé, visitez l'adresse IP du serveur pour vérifier que votre application Web Django est en ligne et en cours d'exécution !

Assurez-vous de décommenter cette ligne dans prod/roles/common/tasks/main.yml si vous voyez l'erreur 502, qui indique qu'il y a un problème de communication entre nginx et Gunicorn :

# - include: 09_fix-502.yml

Ensuite, exécutez à nouveau le playbook.

Si vous exécutez le playbook plusieurs fois, assurez-vous de commenter la commande Exécuter initdb trouvée dans 03_postgres.yml car elle ne doit être exécutée qu'une seule fois. Sinon, des erreurs seront générées lors de la tentative de réinitialisation du serveur de base de données.

Conclusion

Cet article fournit une compréhension de base de la façon dont vous pouvez automatiser la configuration d'un serveur avec Fabric et Ansible. Les Playbooks Ansible sont particulièrement puissants puisque vous pouvez automatiser presque toutes les tâches sur le serveur via un fichier YAML. Espérons que vous puissiez maintenant commencer à écrire vos propres Playbooks et même les utiliser sur votre lieu de travail pour configurer des serveurs prêts pour la production.

Veuillez ajouter des questions et des commentaires ci-dessous. Le code complet peut être trouvé dans le référentiel de déploiements automatisés.

Articles connexes