所在位置:

用 ansible的playbook模式来部署Flask

我们之前讲了一些 ansible-playbook的一些语法,今天就简单来讲一下用 ansible的playbook模式来部署Flask

一般部署 Flask 都是采用 nginx + redis + mysql + gunicorn(或者 uwsgi) 的,这里没有使用 supervisor,有需要可以自己加上,还有一些权限和配置都是以最简单的方式配置的,如果要部署到线上,还要加以修改,这里只是作为演示 ansible-playbook 的用法,下面是一些操作的步骤:

准备工作

  • 远程服务器的 ip 是 11.11.11.11,这里只测试一台服务器
  • 服务器的目录为 /root
  • 服务器的的目录 /root/blog 放了整个Flask的项目,这里没有使用 git 模块
  • ssh 免密码登录

创建项目的所有目录和文件

创建所有目录和文件
mkdir ansible-role-flask
cd ansible-role-flask

touch hosts playbook.yml

mkdir group_vars
touch group_vars/all

mkdir -p roles/{common,mysql,redis,nginx,gunicorn}/{handlers,tasks,templates}

touch roles/{common,mysql,redis,nginx,gunicorn}/{handlers,tasks}/main.yml

touch roles/nginx/templates/nginx.conf.j2

touch roles/gunicorn/templates/gunicorn.py.j2
整个项目目录结构如下:
├── group_vars
│   └── all
├── hosts
├── playbook.yml
└── roles
    ├── common
    │   ├── handlers
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   └── templates
    ├── gunicorn
    │   ├── handlers
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   └── templates
    │       └── gunicorn.py.j2
    ├── mysql
    │   ├── handlers
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   └── templates
    ├── nginx
    │   ├── handlers
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   └── templates
    │       └── nginx.conf.j2
    └── redis
        ├── handlers
        │   └── main.yml
        ├── tasks
        │   └── main.yml
        └── templates
roles 下面的目录说明:
  • roles/common 目录用来处理通用的功能,像安装 pip 、利用 git 处理文件上传和解压等等
  • roles/mysql 目录用来安装和配置 mysql 的
  • role/redis 目录用来安装和配置 redis
  • role/gunicorn 目录用来安装和配置 gunicorn
  • role/nginx 目录用来安装和配置 nginx

配置资源清单

修改 hosts 的文件,添加以下内容:

[webserver]
11.11.11.11

配置项目用到的变量

修改 group_vars/all 的文件,添加以下内容:

---
mysql_db_username: user
mysql_db_password: user
mysql_db: blog

remote_project_dir: /root/blog
remote_project_env: /root/blog/env
remote_project_gunicorn: /root/blog/gunicorn.py

playbook.yml 的内容

修改 playbook.yml 的文件,添加以下内容:

---
- hosts: webserver
  remote_user: root
  gather_facts: no
  roles:
    - { role: common }
    - { role: mysql }
    - { role: redis }
    - { role: gunicorn }
    - { role: nginx }

注意: 这里可以添加各种变量和标签之类的

安装 pip 和 Flask 的各种插件

修改 roles/common/tasks/main.yml,添加以下内容:

---
- name: Install pip and virtualenv package
  yum:
    name: "{{ item }}"
    state: present
  with_items:
    - epel-release
    - python-pip
    - libffi-devel
    - mysql-devel
    - openssl-devel
    - python-devel
    - python-setuptools
    - python-virtualenv

- name: Upgrade pip and  setuptools
  pip:
    chdir: "{{ remote_project_dir }}"
    virtualenv: "{{ remote_project_env }}"
    virtualenv_command: virtualenv
    name: "{{ item }}"
    state: latest
  with_items:
    - pip
    - setuptools

- name: Install requirements package
  pip:
    chdir: "{{ remote_project_dir }}"
    virtualenv: "{{ remote_project_env }}"
    virtualenv_command: virtualenv
    name: "{{ item }}"
  with_items:
     - flask
    - flask-script
    - flask-login
    - flask-sqlalchemy
    - flask-migrate
    - flask-wtf
    - forgerypy
    - flask_whooshalchemyplus
    - jieba
    - flask-debugtoolbar
    - flask-cache
    - redis
    - flask-bootstrap
    - flask-markdown
    - flask-misaka
    - pygments
    - supervisor
    - mysql-python
    - pypinyin
    - flask-mail
    - Pillow

说明: 在 安装 Flask 插件也可以 指定 requirements.txt 文件路径来安装,这里是用插件名来进行安装的

mysql 的安装与配置

这里安装的是 mysql5.7 版本

修改 roles/mysql/tasks/main.yml,添加以下内容:

---
- name: Install the mysql repo
  yum:
    name: http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm
    state: present

- name: Install mysql package
  yum:
    name: "{{ item }}"
    state: installed
  with_items:
    - gcc
    - mysql-devel
    - mysql-community-server
    - mysql-server
    - MySQL-python

- name: Start mysql service
  service:
    name: mysqld
    state: started
    enabled: yes

- name: Create database user
  mysql_user:
    name: "{{ mysql_db_username }}"
    password: "{{ mysql_db_password }}"
    priv: "*.*:ALL"
    state: "present"

- name: Create app database
  mysql_db:
    name: "{{ mysql_db }}"
    login_user: "{{ mysql_db_username }}"
    login_password: "{{ mysql_db_password }}"
    collation: "utf8_general_ci"
    encoding: "utf8"
    state: "present"

- name: Import blog.sql
  mysql_db:
    name: "{{ mysql_db }}"
    login_user: "{{ mysql_db_username }}"
    login_password: "{{ mysql_db_password }}"
    state: import
    target: "{{ remote_project_dir }}/blog.sql"

说明: 这里没有使用 mysql 的配置文件,root 的用户密码也没有修改,就是添加了一个用户,这里还有很多地方需要修改

redis 的安装与配置

修改 roles/redis/tasks/main.yml,添加以下内容:

--
- name: Install redis package
  yum:
    name: redis
    state: present
  register: redis_installed

- name: Start redis
  when: redis_installed|success
  service:
    name: redis
    state: started

说明: 这里可以使用 redis 的配置,禁止外网访问、添加密码验证和禁止一些危险命令等等,来保证 redis 的安全

gunicorn 的配置与安装

修改 roles/gunicorn/tasks/main.yml,添加以下内容:

---
- name: Install gunicorn
  pip:
    chdir: "{{ remote_project_dir }}"
    virtualenv: "{{ remote_project_env }}"
    virtualenv_command: virtualenv
    name: gunicorn
  register: gunicorn_installed

- name: Create gunicorn template
  when: gunicorn_installed|success
  template:
    src: gunicorn.py.j2
    dest: "{{ remote_project_gunicorn }}"
  notify:
    - Start Gunicorn

修改 roles/gunicorn/handlers/main.yml,添加以下内容:

---
- name: Start Gunicorn
  command: "{{ remote_project_dir }}/env/bin/gunicorn -c {{ remote_project_dir }}/gunicorn.py wsgi:app"
  args:
    chdir: "{{ remote_project_dir }}"

修改 roles/gunicorn/templates/gunicorn.py.j2,添加以下内容:

import multiprocessing

bind="127.0.0.1:8000"
workers = multiprocessing.cpu_count() * 2
daemon = True

nginx 的安装与配置

修改 roles/nginx/tasks/main.yml,添加以下内容:

---
- name: Install nginx package
  yum:
    name: nginx
    state: present
  register: nginx_installed

- name: Start nginx
  when: nginx_installed|success
  service:
    name: nginx
    state: started

- name: Copy nginx.conf.j2 template
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    backup: yes
    mode: 0644
  notify:
      - Restart nginx service

修改 roles/nginx/handlers/main.yml,添加以下内容:

---
- name: Restart nginx service
  service:
    name: nginx
    state: restarted

修改 roles/nginx/templates/nginx.conf.j2,添加以下内容:

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        include /etc/nginx/default.d/*.conf;

        location / {
                        proxy_pass http://127.0.0.1:8000;
                        proxy_set_header Host $host;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}

说明: nginx 这里只是简单地反向代理了 gunicorn 的请示

运行并测试

运行 ansible-playbook
ansible-playbook -i hosts playbook.yml -v -o
在浏览器查看效果
http://11.11.11.11

【上一篇】HTTP 基础(下)

【下一篇】Flask大型教程的第十六章:全文搜索【翻译】