目录
在《DevOps(十)Jenkins实战之发布Django开发Web应用》的博文中,我们学习了创建一个简单的Jenkins脚本用来发布Django开发Web应用,在Jenkins任务执行的时候会有一个问题,就是git拉取代码以后,启动django应用以后会卡住,不会执行后面的步骤了,jenkins一直在等待django应用执行的结果,导致后面的任务无法执行。怎么解决这个问题呢?我们需要引进一个工具Supervisor,这个工具是用来管理进程,一般和Python应用一起配合使用,可以确保django应用在服务器后台运行。本篇博文当中我们首先介绍Supervisor,然后用给大家演示修改Jenkins脚本,优化这个发布任务。
一、Supervisor详解
Supervisor是一个用Python编写的客户端/服务器系统,用于监控和控制UNIX-like操作系统上的多个进程。它主要用于管理长时间运行的后台进程,并且广泛应用于Python web应用程序(如Django、Flask等)的生产环境中。
主要特性
- 自动重启: 如果被监控的进程意外崩溃,Supervisor可以自动重启它们。
- 日志记录: 自动管理每个管理的进程的标准输入、输出和错误日志。
- 进程分组: 将相关的进程组合为一个组,可以同时管理。
- Web界面: 提供一个可选的web界面,用于查看进程状态和发送控制命令。
- 事件监听: 可以配置事件监听器,响应进程状态的改变。
- 易于配置: 使用INI风格的配置文件进行进程管理。
安装 Supervisor
Supervisor 可以通过 Python 的包管理工具 pip 安装。首先确保你的系统中安装了 Python 和 pip。
sudo apt-get install python-pip # Debian/Ubuntu
然后使用 pip 安装 Supervisor:
sudo pip install supervisor
配置 Supervisor
安装完成后,你需要创建一个配置文件。Supervisor 提供了一个工具 echo_supervisord_conf
,用于生成默认的配置文件:
echo_supervisord_conf > /etc/supervisord.conf
你可以将此文件放在任何地方,但通常放在 /etc/supervisord.conf
。
修改配置文件
打开 /etc/supervisord.conf
,进行以下基本配置:
-
[unix_http_server]: 配置http服务器,用于内部通信。
;http://localhost:9001 file=/tmp/supervisor.sock ; (the path to the socket file)
-
[supervisord]: 主进程的日志配置。
logfile=/var/log/supervisor/supervisord.log ; (main log file path) logfile_maxbytes=50MB ; (max log file bytes b4 rotation) logfile_backups=10 ; (num of main logfile rotation backups) loglevel=info ; (logging level) pidfile=/var/run/supervisord.pid ; (pidfile path)
-
[supervisorctl]: 控制工具的配置。
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
-
[program:x]: 定义要管理的程序。
[program:yourprogramname] command=/path/to/command ; the program (relative uses PATH, can take args) autostart=true ; start at supervisord start (default: true) autorestart=true ; retstart at unexpected quit (default: true) stderr_logfile=/var/log/yourprogramname/err.log stdout_logfile=/var/log/yourprogramname/out.log
启动 Supervisor
配置文件设置完成后,可以使用以下命令启动 Supervisor:
supervisord -c /etc/supervisord.conf
使用 supervisorctl 管理进程
supervisorctl
是一个命令行客户端工具,用于与 Supervisord 交互。一些基本的命令包括:
supervisorctl status # 查看所有程序的状态
supervisorctl stop all # 停止所有程序
supervisorctl start all # 启动所有程序
supervisorctl restart all # 重启所有程序
supervisorctl update # 重新载入配置文件并添加/删除管理的程序
二、修改和优化发布过程
我们这次在源码增加一个Supervisor的配置django.conf文件,然后git将所有源码拉下来以后,将源码拷到一个python应用发布的目录比如/opt/HelloWorld,然后将django.conf复制到/etc/supervisor/conf.d/目录,然后重新载入配置文件,重启django应用。具体步骤如下:
1、创建django.conf
在源码根目录新建一个配置文件django.conf,内容如下:
[program:django]
command=python manage.py runserver 0.0.0.0:8081
directory=/opt/HelloWorld
user=jenkins
autostart=true
autorestart=true
stderr_logfile=/var/log/django/django.err.log
stdout_logfile=/var/log/django/django.out.log
这个配置是在 Supervisor 配置文件中定义的,用于管理一个名为 "django" 的程序。这里,配置指定了如何启动、运行、监控和记录 Django 应用的日志。下面是每个配置项的详细解释:
-
[program:django]: 这一行定义了一个新的程序部分,名为 "django"。在 Supervisor 中,每个被管理的程序都需要在配置文件中以
[program:name]
的形式独立设置。 -
command: 指定启动程序的命令。在这个例子中,命令是
python manage.py runserver 0.0.0.0:8000
,这是启动 Django 开发服务器的标准方式,监听所有可用 IP 的 8000 端口。注意,实际生产环境中不推荐使用 Django 自带的开发服务器,而应该使用像 Gunicorn 或 uWSGI 这样的生产级应用服务器。 -
directory: 设置程序执行时的工作目录。对于这个 Django 应用,工作目录被设置为
/opt/HelloWorld
。Supervisor 会在启动程序前切换到这个目录。 -
user: 指定运行该程序的用户。这里配置为
jenkins
,意味着 Django 应用将以jenkins
用户的权限运行。这有助于限制程序的权限,增加系统的安全性。 -
autostart: 表示 Supervisor 会在启动时自动启动这个程序。设置为
true
,确保每次 Supervisor 启动时,Django 应用也会自动启动。 -
autorestart: 配置程序在退出时是否自动重启。设置为
true
,意味着如果 Django 应用意外停止或崩溃,Supervisor 会自动重新启动它。 -
stderr_logfile: 指定标准错误流的日志文件路径。在这个配置中,所有标准错误输出将被重定向到
/var/log/django/django.err.log
。这对于调试和记录错误非常有用。 -
stdout_logfile: 指定标准输出流的日志文件路径。在这个配置中,所有标准输出将被记录在
/var/log/django/django.out.log
。这可以帮助您审查程序的运行输出。
这个配置是一个典型的例子,展示了如何使用 Supervisor 来管理一个 Django 应用。通过这种方式,您可以确保应用的持续运行,并且能够在出现问题时迅速响应。在设置完这些配置后,您需要确保相应的日志目录存在,并且 jenkins
用户有权写入这些目录。
注意:需要在jenkins服务器创建/var/log/django目录,并给这个目录jenkin所有权。完成脚本以后,提交发布到gitlab。
2、优化Jenkins脚本
打开jenkins管理界面,选择前面我们创建的jenkins任务HelloWorld。
点击配置按钮,进入配置界面。
编写jenkins脚本,然后保存。
Jenkins脚本代码如下:
pipeline {
agent any
stages {
stage('Checkout') {
steps {
git branch: 'main', credentialsId: 'sean', url: 'http://gitlab.povison-pro.com/Sean/helloworld.git'
}
}
stage('Stop Application') {
steps {
script {
// 检查 Django 服务是否存在
def serviceStatus = sh(script: "sudo supervisorctl status django || true", returnStdout: true).trim()
if (serviceStatus.contains("RUNNING")) {
// 如果服务正在运行,尝试停止它
sh 'sudo supervisorctl stop django'
} else {
echo "Django process not running or does not exist."
}
}
}
}
stage('Prepare Deployment') {
steps {
// 清理旧代码并复制新代码到 /opt/HelloWorld
sh 'sudo rm -rf /opt/HelloWorld/*'
sh 'sudo cp -R . /opt/HelloWorld'
}
}
stage('Configure Supervisor') {
steps {
// 假设 django.conf 已经准备好,在源码根目录
sh 'sudo cp /opt/HelloWorld/django.conf /etc/supervisor/conf.d/django.conf'
sh 'sudo supervisorctl reread'
sh 'sudo supervisorctl update'
}
}
stage('Restart Application') {
steps {
sh 'sudo supervisorctl restart django'
}
}
}
post {
always {
// 清理工作,可选
echo 'Build completed.'
}
}
}
3、示例代码详解
上面 Jenkins Pipeline 脚本的详细解析:
声明和代理
-
pipeline
: 声明这是一个 Jenkins Pipeline 脚本。 -
agent any
: 指定 Pipeline 可以在任何可用的 Jenkins Agent 上运行。
阶段定义
- Pipeline 包含五个阶段:Checkout、Stop Application、Prepare Deployment、Configure Supervisor 和 Restart Application。
Checkout 阶段
- 使用 Git 插件从指定的 Git 仓库克隆代码到 Jenkins 工作空间。
-
branch
: 指定要克隆的分支名称。 -
credentialsId
: 指定用于访问 Git 仓库的凭证 ID。 -
url
: 指定 Git 仓库的 URL。
Stop Application 阶段
- 使用
script
块执行 Groovy 代码:-
serviceStatus
: 运行supervisorctl status django
命令检查 Django 服务状态,并使用|| true
忽略可能的错误。 - 如果
serviceStatus
包含 "RUNNING",则使用supervisorctl stop django
命令停止 Django 服务。 - 否则,输出信息表示 Django 进程未运行或不存在。
-
Prepare Deployment 阶段
- 使用
sh
步骤执行 shell 命令:-
sudo rm -rf /opt/HelloWorld/*
: 删除/opt/HelloWorld/
目录中的所有文件。 -
sudo cp -R . /opt/HelloWorld
: 将 Jenkins 工作空间中的所有文件复制到/opt/HelloWorld/
目录。
-
Configure Supervisor 阶段
- 使用
sh
步骤执行 shell 命令:-
sudo cp /opt/HelloWorld/django.conf /etc/supervisor/conf.d/django.conf
: 将django.conf
文件复制到 supervisord 配置目录。 -
sudo supervisorctl reread
: 重新读取 supervisord 配置文件。 -
sudo supervisorctl update
: 更新 supervisord 进程。
-
Restart Application 阶段
- 使用
sh
步骤执行 shell 命令:-
sudo supervisorctl restart django
: 重启django
进程。
-
后处理 (Post)
-
always
: 无论 Pipeline 执行成功或失败,都会执行此块中的步骤。 -
echo 'Build completed.'
: 输出信息表示构建已完成。
这个 Jenkins Pipeline 脚本实现了以下功能:
- 从 Git 仓库克隆代码。
- 停止正在运行的 Django 服务。
- 将新代码部署到
/opt/HelloWorld/
目录。 - 配置 supervisord 以管理 Django 进程。
- 重启 Django 服务。
请根据您的实际环境和需求调整脚本,例如文件路径、Git 仓库 URL、凭证 ID 和 supervisord 配置。
4、执行任务,并看结果
执行这个修改保存后的jenkins任务,我们看到任务执行成功了。
然后在浏览器访问一下这个页面,http://192.168.110.170:8081/hello/就能看到我们想要的页面了。