2019独角兽企业重金招聘Python工程师标准>>>
开源地址:https://github.com/leebingbin/Python3.WebAPP.Blog
一、何为 DevOps
DevOps(英文Development和Operations的组合)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。它的出现是由于软件行业日益清晰地认识到:为了按时交付软件产品和服务,开发和运营工作必须紧密合作。简单地说,可以把DevOps看作开发(软件工程)、技术运营和质量保障(QA)三者的交集。
可以把DevOps看作开发(软件工程)、技术运营和质量保障(QA)三者的交集。使用现代化的DevOps工具,如Chef、Docker、Ansible、Packer、Troposphere、Consul、Jenkins、SonarQube、AWS等,并不代表你就在正确的应用DevOps的原则。DevOps是一种思维方式。我们所有人都是该系统流程的一部分,我们一起分享共同的时光和交付价值。每个参加到这个软件交付流程上来的成员都能够加速或减缓整个系统的运作速度。系统出现的一个缺陷,以及错误配置的团队之间的“防火墙”,都可能会使得整个系统瘫痪,所有的人都是DevOps的一部分,一旦你的组织明白了这一点,能够帮你管理好这些的工具和技术栈就自然而然的会出现在你眼前了。
就是说,开发和运维要变成一个整体。其次,运维的难度,其实跟开发质量有很大的关系。代码写得垃圾,运维再好也架不住天天挂掉。最后,DevOps理念需要把运维、监控等功能融入到开发中。你想服务器升级时不中断用户服务?那就得在开发时考虑到这一点。
二、部署 Web App 项目
利用 Python 自带的 asyncio ,已经编写了一个异步高性能服务器。但是,还需要一个高性能的Web服务器(这里选择Nginx),它可以处理静态资源,同时作为反向代理把动态请求交给 Python 代码处理。
Nginx负责分发请求,在服务器端,我们需要定义好部署的目录结构:
/
+- srv/+- blog-python3-webapp/ <-- Web App根目录+- www/ <-- 存放Python源码| +- static/ <-- 存放静态资源文件+- log/ <-- 存放log
在服务器上部署,要考虑到新版本如果运行不正常,需要回退到旧版本时怎么办。每次用新的代码覆盖掉旧的文件是不行的,需要一个类似版本控制的机制。由于Linux系统提供了软链接功能,所以,我们把 www 作为一个软链接,它指向哪个目录,哪个目录就是当前运行的版本,而Nginx和python代码的配置文件只需要指向 www 目录即可。
Nginx可以作为服务进程直接启动,但 app.py 还不行,所以,可以使用 Supervisor !Supervisor 是一个管理进程的工具,可以随系统启动而启动服务,它还时刻监控服务进程,如果服务进程意外退出,Supervisor可以自动重启服务。
总结一下我们需要用到的服务有:
· Nginx:高性能Web服务器+负责反向代理;
· Supervisor:监控服务进程的工具;
· MySQL:数据库服务。
自动化部署
用FTP还是SCP还是rsync复制文件?如果手动复制,用一次两次还行,一天如果部署100次不但慢、效率低,而且容易出错。
正确的部署方式是使用工具配合脚本完成自动化部署。Fabric就是一个自动化部署工具。由于Fabric是用Python 2.x开发的,所以,部署脚本要用Python 2.7来编写,本机还必须安装Python 2.7版本。
要用Fabric部署,需要在本机(是开发机器,不是Linux服务器)安装Fabric:
$ easy_install fabric
Linux服务器上不需要安装Fabric,Fabric使用SSH直接登录服务器并执行部署命令。
编写部署脚本。Fabric的部署脚本叫autoblog.py,我们把它放到 blog-python3-webapp 的目录下,与 www 目录平级:
blog-python3-webapp/
+- autoblog.py
+- www/
+- ...
Fabric 的脚本编写很简单,首先导入 Fabric 的API,设置部署时的变量:
# fabfile.py
import os, re
from datetime import datetime# 导入Fabric API:
from fabric.api import *# 服务器登录用户名:
env.user = 'redhat'
# sudo用户为root:
env.sudo_user = 'root'
# 服务器地址,可以有多个,依次部署:
env.hosts = ['192.168.1.66']# 服务器MySQL用户名和口令:
db_user = 'root'
db_password = 'root'
然后,每个 Python 函数都是一个任务。我们先编写一个打包的任务:
_TAR_FILE = 'blog-python3-webapp.tar.gz'def build():includes = ['static', 'templates', 'transwarp', 'favicon.ico', '*.py']excludes = ['test', '.*', '*.pyc', '*.pyo']local('rm -f dist/%s' % _TAR_FILE)with lcd(os.path.join(os.path.abspath('.'), 'www')):cmd = ['tar', '--dereference', '-czvf', '../dist/%s' % _TAR_FILE]cmd.extend(['--exclude=\'%s\'' % ex for ex in excludes])cmd.extend(includes)local(' '.join(cmd))
Fabric提供local('...')来运行本地命令,with lcd(path)可以把当前命令的目录设定为lcd()指定的目录,注意Fabric只能运行命令行命令,Windows 下可能需要 Cgywin 环境。
在 blog-python3-webapp 目录下运行:
$ fab build
看看是否在 dist 目录下创建了 blog-python3-webapp.tar.gz 的文件。
打包后,我们就可以继续编写 deploy 任务,把打包文件上传至服务器,解压,重置 www 软链接,重启相关服务:
_REMOTE_TMP_TAR = '/tmp/%s' % _TAR_FILE
_REMOTE_BASE_DIR = '/srv/blog-python3-webapp'def deploy():newdir = 'www-%s' % datetime.now().strftime('%y-%m-%d_%H.%M.%S')# 删除已有的tar文件:run('rm -f %s' % _REMOTE_TMP_TAR)# 上传新的tar文件:put('dist/%s' % _TAR_FILE, _REMOTE_TMP_TAR)# 创建新目录:with cd(_REMOTE_BASE_DIR):sudo('mkdir %s' % newdir)# 解压到新目录:with cd('%s/%s' % (_REMOTE_BASE_DIR, newdir)):sudo('tar -xzvf %s' % _REMOTE_TMP_TAR)# 重置软链接:with cd(_REMOTE_BASE_DIR):sudo('rm -f www')sudo('ln -s %s www' % newdir)sudo('chown www-data:www-data www')sudo('chown -R www-data:www-data %s' % newdir)# 重启Python服务和nginx服务器:with settings(warn_only=True):sudo('supervisorctl stop blog-python3-webapp')sudo('supervisorctl start blog-python3-webapp')sudo('/etc/init.d/nginx reload')
注意 run() 函数执行的命令是在服务器上运行,with cd(path) 和 with lcd(path) 类似,
把当前目录在服务器端设置为 cd() 指定的目录。如果一个命令需要 sudo 权限,就不能用 run() ,而是用sudo() 来执行。
配置Supervisor
上面让 Supervisor 重启 blog-python3-webapp 的命令会失败,因为我们还没有配置 Supervisor 呢。
编写一个 Supervisor 的配置文件 blog-python3-webapp.conf,存放到/etc/supervisor/conf.d/目录下:
[program:blog-python3-webapp]command = /srv/blog-python3-webapp/www/app.py
directory = /srv/blog-python3-webapp/www
user = www-data
startsecs = 3redirect_stderr = true
stdout_logfile_maxbytes = 50MB
stdout_logfile_backups = 10
stdout_logfile = /srv/blog-python3-webapp/log/app.log
配置文件通过[program:blog-python3-webapp]指定服务名为 blog-python3-webapp ,command 指定启动 app.py。
然后重启 Supervisor 后,就可以随时启动和停止 Supervisor 管理的服务了:
$ sudo supervisorctl reload
$ sudo supervisorctl start blog-python3-webapp
$ sudo supervisorctl status
blog-python3-webapp RUNNING pid 1501, uptime 6:05:34
配置Nginx
Supervisor 只负责运行 app.py,我们还需要配置Nginx。把配置文件 blog-python3-webapp 放到/etc/nginx/html/目录下:
server {listen 80; # 监听80端口root /srv/blog-python3-webapp/www;access_log /srv/blog-python3-webapp/log/access_log;error_log /srv/blog-python3-webapp/log/error_log;# server_name www.baidu.com; # 配置域名# 处理静态文件/favicon.ico:location /favicon.ico {root /srv/blog-python3-webapp/www;}# 处理静态资源:location ~ ^\/static\/.*$ {root /srv/blog-python3-webapp/www;}# 动态请求转发到9000端口:location / {proxy_pass http://127.0.0.1:9000;proxy_set_header X-Real-IP $remote_addr;proxy_set_header Host $host;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;}
}
然后在 /etc/nginx/html/ 目录下创建软链接:
$ pwd
/etc/nginx/sites-enabled
$ sudo ln -s /etc/nginx/html/blog-python3-webapp.
让Nginx重新加载配置文件,不出意外,我们的项目应该正常运行:
$ sudo /etc/init.d/nginx reload
如果Supervisor启动时报错,可以 /var/log/supervisor 下查看Supervisor的log。
如果在开发环境更新了代码,只需要在命令行执行:
$ fab build
$ fab deploy
自动部署完成!刷新浏览器就可以看到服务器代码更新后的效果。
本文为博主原创文章,转载请注明出处!
https://my.oschina.net/u/3375733/blog/