持续集成部署

Posted by xiezg247 on December 20, 2017

一. 背景

自动化部署就是为了解放生产力。

二. CI部署

Jenkins与Github集成

Github Hooks

配置Github项目仓库,Github项目仓库在处理这些动作的同时会发送信号至Jenkins触发自动构建操作。

生成Personal Access Token
  • 登录Github,在头像上点击settings settings
  • 点击Developer settings下的Personal access tokens tokens
  • 点击Generate new token,在Token description中填一个描述名称,下面的复选框是这个token需要的权限,按照需要的权限勾上。 new_token
  • token可复制使用 authority
配置Github项目仓库

上面的Token是属于账户级的东西,Webhooks是项目级别的。当项目发生了某个事件,Github会给一个指定的url发Post请求。

  • 点击项目仓库的settings settings
  • 在Webhooks选项卡中,点击Add webhook add webhooks
  • 将在Jenkins生成的Hook URL填入至Payload URL中,选择自主事件,当Github收到了客户端有Push/Pull Request动作时,会触发一个Hook jenkins
  • 保存WebHook jenkins

Jenkins安装

Jenkins全局配置

systerm config

Jenkins项目配置

project config

Jenkins执行脚本分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env bash

set -e

source /home/xiezhigang/deploy_pluto/bin/activate

./runtest.sh

version=$(date +%Y%m%d_%H%M)
registry=bu6.io
image_name=pluto

docker build -f Dockerfile -t $registry/$image_name:$version .

docker push ${registry}/${image_name}:$version

docker rmi ${registry}/${image_name}:$version

ansible-playbook deploy_prod.yml --extra-vars "version=$version"

从执行命令可以知道几点:

  • 需要安装了ansible的python虚拟环境(一般在jenkins服务器上面配置)
  • 需要安装了docker的环境
  • 需要docker registry镜像服务器
  • 需要在项目中写好了dockerfile/deploy_prod.yml配置文件

三. 项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
.
├── alembic  // alembic环境
│   ├── env.py
│   ├── env.pyc
│   ├── README
│   ├── script.py.mako
│   └── versions
├── alembic.ini  // alembic配置
├── ansible.cfg  // ansible配置
├── celerybeat-schedule
├── common  // 共用模块
│   ├── __init__.py
│   ├── README.md
│   ├── rpc
│   └── tingyun
├── config  // 环境变量
│   ├── dev
│   ├── prod
│   ├── stage
│   └── test
├── deploy_prod.yml  // ansible playbook正式环境配置
├── deploy_test.yml  // ansible playbook测试环境配置
├── Dockerfile  // dockerfile配置
├── docs  // 文档
│   ├── about.md
│   └── index.md
├── gunicorn_config.py  // gunicorn配置
├── hosts.ansible.cfg  // ansible的主机配置
├── manage.py
├── migrations  // alembic脚本
│   ├── alembic.ini
│   ├── env.py
│   ├── env.pyc
│   ├── README
│   ├── script.py.mako
│   └── versions
├── mkdocs.yml  // mkdocs配置
├── pluto  // 项目主体
│   ├── app.py
│   ├── app.pyc
│   ├── config.py
│   ├── config.pyc
│   ├── corelibs
│   ├── exc
│   ├── forms
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── models
│   ├── static
│   ├── tasks
│   ├── templates
│   ├── utils
│   ├── views
│   ├── wsgi.py
│   └── wsgi.pyc
├── Procfile  // honcho配置
├── README.md
├── requirements.txt
├── runserver.sh
├── runtest.sh
├── scripts
│   ├── cron
│   ├── __init__.py
│   └── once
├── setup.cfg
├── site
│   ├── about
│   ├── css
│   ├── fonts
│   ├── img
│   ├── index.html
│   ├── js
│   ├── mkdocs
│   ├── search.html
│   └── sitemap.xml
└── tests
    └── __init__.py

四. 部署脚本

Docker

Docker File

项目的Dockerfile如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
FROM bu6.io/python2.7
MAINTAINER  xiezhigang "xiezg02@vanke.com"
LABEL version="1.0"
LABEL description="优惠券中心测试环境"

# 重要:设置image的时区
ENV TZ=Asia/Shanghai
ENV PYTHONPATH="${PYTHONPATH}:/usr/src/app"
ENV prometheus_multiproc_dir="/tmp/prometheus-metrics"
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

WORKDIR /usr/src/app

COPY requirements.txt /usr/src/app/
RUN mkdir /tmp/prometheus-metrics
RUN pip install -i https://mirrors.ustc.edu.cn/pypi/web/simple --no-cache-dir -r requirements.txt
COPY . /usr/src/app

Docker Registry

Docker Compose

待补充

Ansible

Ansible

1
2
3
4
5
6
7
8
9
10
11
12
2. hosts.ansible.cfg
```yaml
[pluto.test]
192.168.0.92

[pluto.migrate]
192.168.0.169

[pluto.prod]
192.168.0.169
192.168.0.208

  1. deploy_prod.yml ```yaml
    • hosts: pluto.migrate remote_user: deploy tasks:
    • name: run migration shell: docker run –name run_migraion –rm bu6.io/pluto:’’ honcho -e config/prod/env run python manage.py db upgrade head
  • hosts: pluto.prod remote_user: deploy tasks:
    • name: stop container shell: docker stop pluto_prod_worker || true

    • name: stop container shell: docker stop pluto_prod_beat || true

    • name: stop container shell: docker stop pluto_prod_web || true

    • name: remove images shell: docker rmi $(docker images -f reference=’bu6.io/pluto’) || true

    • name: run celery worker shell: docker run –log-driver fluentd –log-opt fluentd-address=192.168.0.24:24224 –log-opt tag=pluto_prod_worker –log-opt fluentd-async-connect=true –name pluto_prod_worker -ti -d –rm bu6.io/pluto:’’ honcho -e config/prod/env run celery worker -A pluto.corelibs.async.celery_worker –loglevel=INFO -c 20 -P gevent -Q pluto,celery

    • name: run celery beat shell: docker run –log-driver fluentd –log-opt fluentd-address=192.168.0.24:24224 –log-opt tag=pluto_prod_beat –log-opt fluentd-async-connect=true –name pluto_prod_beat -ti -d –rm bu6.io/pluto:’’ honcho -e config/prod/env run celery beat -A pluto.corelibs.async.celery_worker –loglevel=INFO

    • name: run pluto shell: docker run –log-driver fluentd –log-opt fluentd-address=192.168.0.24:24224 –log-opt tag=pluto_prod_web –log-opt fluentd-async-connect=true –name pluto_prod_web -ti -d –rm -p 0.0.0.0:8089:8080 bu6.io/pluto:’’ honcho -e config/prod/env run gunicorn -c gunicorn_config.py -k gevent -t 10 -w 10 -b “0.0.0.0:8080” pluto.wsgi:application

    • name: check url get_url: url=http://localhost:8089/_internal/ping timeout=30 dest=/dev/null

```

五. 优化

待补充

六. 总结

待补充

七. 参考