开始使用Django Ansible部署的方法

361 阅读6分钟

开始使用Django Ansible部署

将应用程序部署到生产环境是一个复杂的过程,需要许多配置和测试。想象一下,你想把你的应用程序的一个新版本部署到生产中。如果你能确保新版本是稳定的并且与现有版本兼容,那将会有所帮助。

你将需要为每个应用程序版本重复部署步骤。如果你想多次将你的应用程序部署到生产中,手动部署会变得很累。这就是ansible发挥作用的地方。它为我们提供了自动部署过程的能力。

在这篇文章中,我们将部署一个Django应用程序到生产中。除了Django框架和ansible,我们还将使用Nginxwebserver。

先决条件

在你开始这篇文章之前,你需要对以下内容有基本的了解。

  1. [Django]。
  2. [Nginx]。
  3. [Python]编程语言和[Python 3]安装在你的机器上。

应用程序设置

我们将建立一个预算管理应用API,它将允许我们创建、更新和删除预算。

  1. 通过执行以下命令为我们的项目创建一个新的工作目录。

    mkdir deployment
    
  2. 创建一个新的虚拟环境。

    virtualenv deployment/venv
    
  3. 创建一个新的Django项目。

    django-admin startproject budgetmanager
    
  4. Django将代码组织成较小的单元,称为应用程序。我们将创建一个名为budget 的新应用。

    django-admin startapp budget
    
  5. 由于我们要创建RESTful APIS,我们需要通过安装Django REST框架

    pip install django-rest-framework
    

模型

Django模型是代表数据库表的对象。例如,我们将创建一个映射到数据库中budgets 表的预算模型。

budget 应用程序中,在models.py ,添加以下代码。

from django.db import models
class Budget(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField()
    amount = models.PositiveIntegerField()
    date_creates = models.DateTimeField(auto_created=True, auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title

上面的代码片断包含了预算类和它的属性。__str__ 方法返回预算对象的一个字符串表示。

序列化器

Django序列化器用于将Django模型对象转换为JSON对象。Django REST框架提供了一种序列化和反序列化数据的方法。我们将创建一个序列化器,Django用它来序列化和反序列化预算模型。

  1. budget 应用程序中,创建一个名为serializers.py 的新文件。
  2. budget 应用程序中,在serializers.py ,添加以下代码。
from rest_framework import serializers
from budget.models import Budget

class BudgetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Budget
        fields = "__all__"
  • "__all__" 是一个特殊的关键字,代表模型的所有字段。

视图

Django视图是用来处理来自客户端的请求。因此,我们将创建一个视图,用来处理来自客户端的请求。

  1. budget 应用程序中,在views.py 文件中添加下面的代码片段。
from rest_framework.generics import ListAPIView
from rest_framework.generics import CreateAPIView
from rest_framework.generics import DestroyAPIView
from rest_framework.generics import UpdateAPIView

from budget.models import Budget
from budget.serializer import BudgetSerializer

class ListBudgetAPI(ListAPIView):
    """Retrieves all the budgets available in our database"""
    queryset = Budget.objects.all()
    serializer_class = BudgetSerializer

class CreateBudgetAPI(CreateAPIView):
    """Creates a new budget in our database"""
    queryset = Budget.objects.all()
    serializer_class = BudgetSerializer

class UpdateBudgetAPI(UpdateAPIView):
    """Update budget with the id sent through the request url path"""
    queryset = Budget.objects.all()
    serializer_class = BudgetSerializer

class DeleteBudgetAPI(DestroyAPIView):
    """Deletes a budget whose id has been sent through the url path"""
    queryset = Budget.objects.all()
    serializer_class = BudgetSerializer

URL配置

Django视图被映射到URL上。我们将创建一个URL配置文件,用于将视图映射到URL上。

  1. budget 应用程序中,创建一个名为urls.py 的新文件。
  2. urls.py 文件中添加以下代码片段。
from django.urls import path
from budget import views

urlpatterns = [
    path("", views.ListBudgetAPI.as_view(), name="budget_list"),
    path("create/", views.CreateBudgetAPI.as_view(), name="create_budget"),
    path("update/<int:pk>/", views.UpdateBudgetAPI.as_view(), name="update_budget"),
    path("delete/<int:pk>/", views.DeleteBudgetAPI.as_view(), name="delete_budget")
]

我们必须始终在位于项目根目录下的主urls.py 文件中添加各自应用程序的url 配置。

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/budget/', include("budget.urls")),
]

Ansible

Ansible使用yml 文件来配置你的服务器。Ansible的yml 文件也被称为playbooks 。在项目根目录下创建一个名为ansible 的新目录。

系统包

  1. ansible 目录中,创建一个名为packages.yml 的新文件。
  2. packages.yml 文件中加入下面的代码片段。
---
- hosts: all
  gather_facts: no
  tasks:
    - name: Running apt update
      apt: update_cache=yes
    - name: Installing required packages
      apt: name={{item}} state=present
      with_items:
        - fail2ban
        - git
        - python-pip
        - rdiff-backup
        - libpq-dev
        - uwsgi
        - uwsgi-plugin-python
        - nginx

上述文件包含我们的应用程序在服务器上运行所需的所有系统包。

更新

  1. ansible 目录中,创建一个名为update.yml 的新文件。
  2. 将以下代码添加到update.yml 文件中。
---
- hosts: all
  gather_facts: no
  tasks:
    - name: Runing system update
      apt: update_cache=yes
        upgrade=safe
      register: result
    - debug: var=result.stdout_lines

上面的playbook将在服务器上运行apt update 命令,并运行apt upgrade 命令。

生成SSH密钥

为了使我们的服务器能够连接到GitLab并拉取最新的代码,我们需要生成一个SSH密钥。Ansible将使用这个SSH密钥在我们的服务器和GitLab之间建立一个安全连接。

  1. ansible 目录下,创建一个名为generate_ssh_key.yml 的新文件。
  2. 将下面的代码片段添加到上面创建的generate_ssh_key.yml 文件中。
---
- hosts: all
  gather_facts: no
  tasks:
    - name: Create a new system user
      user: name=ubuntu generate_ssh_key=yes ssh_key_bits=2048 ssh_key_file=.ssh/id_rsa #creates a ssh key in .ssh/id_rsa file
    - name: Read SSH public key
      slurp: src=/home/ubuntu/.ssh/id_rsa.pub
      register: public_key
    - debug: msg="{{ public_key['content'] | b64decode }}"

上述游戏手册在我们的服务器上生成了一个SSH密钥,并将其存储在.ssh/id_rsa.pub 文件中。

部署

  1. ansible 目录中,创建一个名为deploy.yml 的新文件。
  2. 将下面的代码片段添加到deploy.yml 文件中。
---
- hosts: all
  become: yes
  become_user: ubuntu
  gather_facts: no

  tasks:
    - name: pull branch master
      git: repo={{ repo_url }}/{{ repo }}.git
        dest={{ repo_dir }}
        accept_hostkey=yes

- hosts: all
  gather_facts: no
  tasks:
    - name: install python requirements
      pip: requirements={{ repo_dir }}/requirements/production.txt extra_args=--upgrade

- hosts: all
  become: yes
  become_user: ubuntu
  gather_facts: no
  environment:
    DJANGO_SETTINGS_MODULE: "{{ django_project }}.settings.production"
    STATIC_ROOT: "{{ static_dir }}"

  tasks:
    - name: create static_root dir
      file: path={{ static_dir }} state=directory mode=0755
    - name: django collectstatic
      shell: ./manage.py collectstatic --noinput chdir={{ django_dir }}
    - name: django migrate
      shell: ./manage.py migrate --noinput chdir={{ django_dir }}
    - name: django loaddata
      shell: ./manage.py loaddata user chdir={{ django_dir }}

- hosts: all
  gather_facts: no
  tasks:
    - name: uwsgi restart
      service: name=uwsgi state=restarted

上面的配置将从GitLab中提取最新的代码并安装所需的Python包。它还将

  1. 创建static_root 目录并运行collectstatic 命令来收集所有静态文件。
  2. 运行migrate 命令来迁移数据库。
  3. 加载user 固定程序以填充数据库。
  4. 重新启动uwsgi 服务。

仓库配置

我们需要配置我们的服务器以连接到我们的版本库,从而获取最新的代码。

  1. ansible 目录中,创建一个名为hosts 的新文件。
  2. 将下面的代码片段添加到上面创建的hosts 文件中。
all:
    hosts: yourserver
    vars:
        repo_url: ssh://git@bitbucket.org/user
        repo: project
        home_dir: /home/ubuntu
        repo_dir: "{{ home_dir }}/{{ repo }}"
        django_dir: "{{ repo_dir }}/django"
        django_project: project
  • yourserver 改为你的服务器名称,把repo_url 改为你的版本库网址。

Ansible shell命令

为了将代码从版本库拉到服务器上,我们需要一个shell命令,从hosts 文件中读取配置,并使用提供的信息将代码从版本库拉到服务器上。

ansible 目录中,创建一个新的文件,名为ansible.sh 。添加以下代码。

#!/bin/bash
ansible-playbook -i ./hosts $1

上面的代码片断将运行服务器的ansible-playbook 命令。

使用以下命令执行ansible.sh 文件。

./ansible.sh generate_ssh_key.yaml

上面的命令在服务器上生成了一个 SSH 密钥,并将其保存在.ssh/id_rsa.pub 文件中;SSH 密钥也被添加到 Git 仓库中。

一旦SSH密钥被添加到Git仓库中,我们就可以把最新的代码拉到服务器上。执行下面的命令,从仓库中提取最新的代码,并将其部署到服务器上。

./ansible.sh packages.yaml
./ansible.sh update.yaml
./ansible.sh deploy.yaml

每当我们想更新我们的应用程序时,我们只需要执行下面的命令,从仓库拉出最新的代码并部署在服务器上。

./ansible.sh deploy.yaml

总结

我们在本教程中创建了一个预算管理应用程序,并使用Ansible将其部署到生产中。

试着在Django项目中使用Ansible实现自动化部署,以减少手动部署Django应用程序的时间。