您的位置:新葡亰496net > 奥门新萄京娱乐场 > 新葡亰496net自动化铺排深度实践,是时候换种更

新葡亰496net自动化铺排深度实践,是时候换种更

发布时间:2019-11-04 02:57编辑:奥门新萄京娱乐场浏览(152)

    让我们来回忆下上次你是怎么发布你的代码的:

    1.1 早期手动部署代码

    方式

    • 纯手动scp上传代码。
    • 纯手动登陆,git pull 或者svn update。
    • 纯手动xftp上传代码。
    • 开发发送压缩包,rz上传,解压部署代码。

    缺点:

    • 全程运维参与,占用大量时间。
    • 如果节点多,上线速度慢。
    • 人为失误多,目录管理混乱。
    • 回滚不及时,或者难以回退。

    在centos部署yii2 advanced框架

    手头闲置了一个阿里云的云服务器,干脆拿来部署一个yii2 advance框架,之后也可以在上面搭建自己的个人博客。话不多说,撸起袖子开干。

    本次部署需要达到的目标:

    a、可访问的网站正式环境端口10080(因域名还没准备,就先用ip地址 端口访问)。

    b、可访问的网站测试环境端口10081。

    c、可通过Git进行版本管理与迭代。git推入到远端时,代码即时更新至测试环境。

    PHP运行环境提前备好,安装apache、php、MySQL,composer、git等, 此类的教程很多可以尽情百度,保证php能正常在网页中执行,就可以开始安装yii2了,开工!

    1、首先从yii2官网获取yii2_advanced的框架文件,解压至特定文件夹:

    新葡亰496net 1

    解压后的目录如上图。

    2、创建空的git仓库,为承载框架内容做准备。

    a、进入到准备存放git的仓库:cd /mnt/git

    b、初始化git仓库:git init --bare yzz.git

    c、建立可以使用git的用户:useradd gituser ; passwd gituser

    d、之后赋予git用户访问git仓库的权限:chown -R gituser:gituseryzz.git/

    3、创建测试环境:

    a、进入测试环境的目录:cd /mnt/test

    b、clone刚刚创建的空git仓库:git clone /mnt/git/yzz.git

    c、将正式环境目录下的文件拷贝至测试环境目录:cp -a /www/project/. project/ #注意这里的/www/project/后有一个点号,代表连同隐藏文件一并复制,-a则可以连同文件权限属性一并复制。

    4、以上即填充好了测试环境的数据,但此时git仓库还是空的,我们将测试目录下的文件提交至git。

    a、进入测试环境的目录:cd /mnt/test

    b、提交当前所有文件:

    git add .

    git commit -m "first init"

    git push

    c、等提交完成之后用git log看看日志,已经提交成功:

    新葡亰496net 2

    d、另外,为了让本地推入到远程的代码能自动同步至测试服,这里将test/project目录更改为git用户所有,以让git的hooks脚本可以更新此目录下的文件,执行:chown -R gituser:gituser /mnt/test/project

    4、以上即完成了正式环境数据、测试环境数据及git环境的初始化。现在尝试在本地检出代码。在Windows的G:/xmapp/htdocs/执行git命令:

    git clone gituser:xxx.xxx.xxx.xx:/mntgit/project.git project/

    新葡亰496net 3

    等待clone完成,本地的文件即同步完成。

    5、现在所有的基础数据都准备好了。离目标还有三件事:1、让正式服和测试服目录可以通过浏览器访问。2、正式服或测试服的yii框架初始化。3、当本地更改代码并通过git 完成push之后,代码需要自动同步至测试服。先来让正式服和测试服可访问:

    a、修改服务器apache的http.conf,增加对10080及10081端口的监听。目前只需要yii2的前台部分可访问,将网站根目录定至frontend/web。如下为测试环境的apache配置,具体情况根据个人服务器环境进行配置:

    新葡亰496net 4

    b、同时更改fpm的配置,在php_admin_value[open_basedir后面加上正式环境及测试环境的目录。

    c、完成以上工作,重启apache和fpm,理论上就可以通过外部访问正式服和测试服。这时访问xxx.xxx.xxx.xx:10080就可以看到yii2输出的网页了,但因为yii框架并没有初始化,此时会提示错误。

    6、初始化正式服和测试服的数据。如有必要,本地也可以初始化,方法都是一样,非常简单,此处以初始化正式服为例。进入正式服的project目录,执行:php init ,之后选择1(测试环境可选择0,便于开发过程中定位问题),二次确认“yes”,之后输入“all”,初始化即完成。此时访问正式环境的10080端口,就可以看到正常的yii2框架了:

    新葡亰496net 5

    测试环境或本地的初始化也是一样,1个“php init”命令搞定初始化。

    最后一个任务,git自动提交。当本地提交并push代码后,要可以在测试服立刻看到效果:

    a、在/mnt/git/project.git/hooks中,新建post-receive文件:执行“cp -a post-update.sample post-receive“,打开post-receive,删除已有的所有内容,并写入以下3行命令:

    git --work-tree=/mnt/test/project checkout -f

    cd /mnt/test/project

    composer dump-autoload

    新葡亰496net 6

    保存后退出文件就ok了。之后只需在本地修改文件,用git推入远端即可在测试服看到效果,待测试服稳定,再发布至正式服。

    后续需要使用数据库,则还要在project/common/config/main-local.php里填写数据库相关信息,可参考yii2的官方文档进行。

    以上,作为本次操作的记录,希望对大家有所帮助

    advanced框架 手头闲置了一个阿里云的云服务器,干脆拿来部署一个yii2 advance框架,之后也可以在上面搭建自己的个人博客。...

    通过shell脚本实现代码自动化部署

    1. 先把线上的代码用ftp备份下来

    2. 上传修改了的文件

    3. 测试一下功能是否正常

    4. 网站500了,赶紧用备份替换回去

    5. 替换错了/替换漏了

    6. 一台服务器发布成功

    7. 登录每一台执行一遍发布操作

    8. 加班搞定

    9. 老板发飙

    1.2 设计自动部署代码

    流程设计,确定目标

    一、传统部署方式及优缺点

    ...

    1.2.1 自动部署环境

    1.开发环境

    开发者本地有自己的环境,运维配置公共开发环境,大家可共用的服务。例如:开发数据库MySQL,redis,Memcached等

    2.测试环境

    功能测试以及性能测试。

    3.预生产环境

    生产环境集群中的某一个节点,并且连接生产库。(不对外,不做破坏性操作。)

    4.灰度环境

    根据不同的区域进行划分。(生产环境)

    5.生产环境

    对用户提供服务的环境。

    预生产环境由来:

    1.数据库不一致,测试环境和生产环境数据库是不一样的。
    2.使用生产环境的联调接口;例如:支付接口。(电商业务)

    新葡亰496net自动化铺排深度实践,是时候换种更文雅的艺术布署你的php代码了。1.传统部署方式

    (1)纯手工scp

    (2)纯手工登录git pull、svn update

    (3)纯手工xftp往上拉

    (4)开发给打一个压缩包,rz上去;解压

    尤其现在的互联网行业,讲究快速迭代,小步快跑。像bug修复或者小功能的修改几乎每天都发版本,大功能的版本迭代每周也差不多会有一次。相信不少同行们像我上面说的这样发布自己的代码吧。或者可能先进一点,直接去服务器上执行一条类似git pull的命令拖下仓库中的代码,但是如果你的代码运行在集群中呢?每台机器登录一次执行一次git pull吗?如果发现代码有问题需要回滚呢?

    1.2.2 自动部署规划

    • 已经有一个可以上线的代码在git仓库。
    • 我们现在要做10个集群节点的一键部署,秒级回滚。
    • 所有的web服务,都应该使用普通用户。(强烈建议)
    • 所有的web服务都不应该监听80端口,除了负载均衡。
    • 那我们如何设计一套生产自动化部署系统。

    1.规划。
    2.实现。
    3.总结和扩展。(PDCA方法论)
    4.生产环境应用。

    实现思路:

    1.代码放置位置

    Git(优先)、Svn

    2.获取最新代码

    • git pull获取最新分支(更新非常频繁,没有特别严格的项目管理团队。)
    • git tag 获取指定标签版本(更新没有那么频繁,有一定的项目管理的团队。)
    • git commit获取指定版本号

    3.差异解决

    • 各个节点之间差异
    • 代码仓库和实际的差异。配置文件是否放在代码仓库中。(配置单独进行存放,config.example )短信接口,支付,等敏感信息不让所有开发知道
    • 统一的.集群有10个节点。(Job节点 crontab.xml 配置文件不一样)

    4.项目名称如何设计

    项目名称_环境名称_版本_分支_时间_某开发提交
    测试: rainbow_test_v1.1.1_dev_2016-08-11_12:12_wanyongzhen
    生产: rainbow_pro_v1.1.1_master_2016-08-11_11:11_wanyongzhen

    5.如何更新

    php,tomcat需要重启,重新软链接。

    6.如何测试

    测试(关键的页面,API,后台等)
    测试一个预生产环境,通过则继续部署,如果失败,退出部署操作。

    7.记录日志

    可以部署统计。
    成功多少次。
    失败多少次。
    回滚多少次。

    8.多人同时执行脚本

    防止多人操作导致重复上线失败。通过lock锁对文件进行控制。

    9.串行,并行

    机器少的情况串行感觉不出什么。如果机器过多则会很慢。
    分组部署并行部署,以及分组测试。
    测试一个预生产环境,通过则继续部署,如果失败,退出部署操作。

    10.如何执行

    1.shell执行
    2.web界面点击(自定义或jenkins)

    11.如何实现正常回退,以及紧急回退(回滚的必要性)

    通过软链接的方式来实现代码秒级别回退。

    2.缺点

    (1)全程运维参与,占用大量时间

    (2)上线速度慢

    (3)人为失误多,管理混乱

    (4)回滚慢,不及时

    如果你还在像我上面说的这种方式部署自己的代码的话,那么我希望你能耐心看完这篇文章,从此摆脱代码部署之痛。

    1.2.3 自动部署难点

    在大公司推进自动化部署上线,是有许多的难点,根据个人公司的不同,来选择不同的方法来进行推进。

    自动化推进难点:

    • 能力(个人能力,团队能力)
    • 责任(责任能否承担,敢于承担责任)
    • 公司流程、人员、组织架构。

    可通过如下方法推进:

    • 目标化沟通。
    • 责任划分
    • ITIL
    • 项目管理:PMBOOK

    二、环境规划

    1、开发环境--开发者本地有自己的环境。

    运维需要设置的开发环境,大家共用的服务。

    2、测试环境:功能测试环境和性能测试环境。

    3、预生产环境:生产环境集群中的某一个节点。

    4、生产环境:直接对用户提供服务的环境。

    测试环境与生产环境的数据库不一致时,可能会导致测试的功能不全面,在测试环境测无问题,放在线上可能出现问题

     

    1.3 自动部署实践

    整个集群自动化部署流程设计如下:
    可根据如下思路,结合公司实际业务来编写shell脚本或者Python。

    • 获取最新代码
    • 编译(可选)
    • 配置文件(软连接或者拷贝)。
    • 打包(tar,加速传输)
    • 文件分发(Scp Rsync Salt)(不需要密码验证)
    • 将目标服务器移除集群(注释配置文件)
    • 解压
    • 防止webroot站点目录
    • scp差异文件(可能有一个节点配置文件不一样)
    • 重启Web服务
    • 测试

    三、需求分析

    其实绕了这么一圈今天是想向大家介绍一下用php写的代码发布工具:deployer。

    1.4 正常回退实践

    • 列出回滚版本
    • 目标服务器移除集群
    • 执行回滚
    • 重启并测试
    • 加入集群

    一、功能需求需求

    一个集群有十个节点

    1.实现 一键部署10个节点

    2.一键回滚到任意版本

    3.一键回滚到上个版本

    deployer具有以下吸引人的特性:

    1.5 紧急回退实践

    • 列出回滚版本(ls -l或find查出对应的历史版本)。
    • 执行回滚操作(删除软链接,重建软链接)。
    • 重启对应服务。

    二、部署需求

    部署:

    1.代码在哪里:svn、git

    2.获取什么版本代码?

    svn/git:直接拉去某个分支

    svn:指定版本号

    git:指定tag

    3.差异解决:

    (1)各个节点直接差异:配置文件未必一致(crontab.xml)。预生产节点。

    (2)代码仓库和实际的差异。配置文件是否放在代码仓库中。

    4.如何更新

    更新时需要考虑是否重启。例如java代码,需要考虑重启tomcat。重启过程中,用户就不能访问了。

    5.测试

    部署多个节点,某个节点由于配置问题导致部署不成功。如何测试。

    6.串行和并行

    部署多个节点,串行部署还是并行部署,视具体业务需求决定。

    7.如何执行

    1.shell脚本,直接执行

    2.web界面

    - 快速      采用了比如并发发布、ssh通道复用、缓存可用情况下使用缓存等技术加速代码部署

    1.6 自动部署采坑

    自动化部署php环境或者java环境的过程中,那么你一定遇到了如下的问题。

    • 如何应用到你的生产环境。
    • 回退到“上一个”“正常”版本。
    • 自动部署软连接的坑。
      • PHP如果开启Opcache,需要重启PHP,或者清理opcache
      • Java Tomcat是必须要重启,最好每次清理work,tmp缓存目录。

    三、部署流程

    1.获取代码(直接拉取)----》 2.编译(可选)----》 3.配置文件放进去----》 4.打包 ----》 

     

    5.SCP到目标服务器----》 6.将目标服务器移除集群----》 7.解压 ----》 8.放置到webroot ----》

     

    9.SCP差异文件 ----》 10.重启(可选) ----》 11.测试 ----》 12.加入集群

    - 原子部署   在新发布的版本内执行所有定义的操作,诸如下载依赖、设置文件访问权限等都不会直接影响线上,只有全部成功后,最后一步设置软链才会真正替换线上代码

    1.7 自动化系统构建实践-运维体系

    四、代码实现

    - 快速回滚   由于采用了原子部署,所以回滚也只是重新设置一下软链指向

    1.7.1 环境准备

    首先在执行脚本前,先做好初始化环境,最好是通过saltstack来完成。我这里没有那么多机器,就先用两台演示。

    • linux-node1 192.168.90.201
    • linux-node2 192.168.90.202

    1.创建普通用户

    useradd wanyuetian
    passwd wanyuetian
    

    2.配置密钥

    [root@linux-node1 ~]# su - wanyuetian #切换至普通用户
    [wanyongzhen@Linux-node1 ~]$ ssh-keygen -t dsa #生成密钥    
    Generating public/private dsa key pair.
    Enter file in which to save the key (/home/wanyuetian/.ssh/id_dsa):  #默认回车一路
    /home/wanyuetian/.ssh/id_dsa already exists.
    Overwrite (y/n)? y
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /home/wanyuetian/.ssh/id_dsa. #这是钥匙
    Your public key has been saved in /home/wanyuetian/.ssh/id_dsa.pub. #这是锁
    The key fingerprint is:
    39:6f:d8:42:61:d7:c3:f9:4b:e7:fb:b0:af:52:cd:59 wanyuetian@nfs-server
    The key's randomart image is:
     --[ DSA 1024]---- 
    |                 |
    |           o .   |
    |        o . =    |
    |       .     o  E|
    |        S     oo |
    |       . =   ..=o|
    |        o    .o .|
    |         o  .  o.|
    |             .o  |
     ----------------- 
    [wanyuetian@nfs-server ~]$ ssh-copy-id -i ~/.ssh/id_dsa.pub wanyuetian@192.168.90.202  #公钥分发给其他服务器
    wanyuetian@192.168.90.202's password: 
    Now try logging into the machine, with "ssh 'wanyuetian@192.168.90.202'", and check in:
      .ssh/authorized_keys
    to make sure we haven't added extra keys that you weren't expecting.
    [wanyuetian@nfs-server ~]$ ssh -p22 wanyuetian@192.168.90.202       #使用wanyuetian用户登录node2节点服务器
    Last login: Wed Aug 10 17:59:02 2016 from 192.168.90.201
    [wanyuetian@linux-node2 ~]$ #成功登录
    

    3.创建相关目录

    mkdir /deploy/
    mkdir -p /deploy/code/rainbow_pro
    mkdir -p /deploy/source/rainbow_pro
    mkdir -p /deploy/config/rainbow_pro/config
    mkdir -p /deploy/config/rainbow_pro/admin_config
    mkdir -p /deploy/tmp
    mkdir -p /home/wanyuetian/webroot
    chown -R www:www /deploy
    chown -R www:www /home/wanyuetian/webroot
    

    4.配置Nginx

    user wanyuetian;  #指定用户
    root  /home/wanyuetian/webroot/rainbow_pro; #指定项目路径
    

    5.配置好git环境

    • centos7部署gitlab
    • 克隆项目可参考 git远程仓库创建与建立

    最终效果如下:

    [wanyuetian@linux-node1 ~]$ ll /deploy/source/rainbow_pro/
    总用量 4
    -rw-rw-r-- 1 wanyuetian wanyuetian   34 8月  12 18:05 index.html
    

    1、设置无交互访问

    通过ssh-keygen将部署机的公钥发送给应用服务器。

    注意,这里通常是用普通用户登陆部署机,生成公钥后,再把公钥发给应用服务器

     

    ssh-keygen -t rsa

     

    切换到.ssh目录下

    [www@linux-node1 ~/.ssh]$ ll

    total 16

    -rwx------ 1 www www  397 Jul 31 22:45 authorized_keys

    -rwx------ 1 www www 1679 Jul 31 22:44 id_rsa

    -rwx------ 1 www www  397 Jul 31 22:44 id_rsa.pub

     

    将id_rsa.pub中的内容复制粘贴到应用服务器的www用户的.ssh目录下,

    文件名称为authorized_keys

     

    [www@linux-node2 .ssh]$ cat authorized_keys 

    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqT3VwY9Wo7tKsXa4Ce1zXGLT/Iygy30tDBKnV4HW4g5BdUS48urTvYljL9cwJ/HWvoqbtJ5mc7PMmhDMOAjIh1CRZtGxKEkQFB/Xp5cLeAsE7iH WfkNqavFHD75 YuM2mbNBvisDXO /pJ/QfbmYwWJ6CW6uLpQKpitdJwrLpQDJGQv5H3aV0kHKZdoA twdXm0LmQcWWJt7zruPq19CAXG5b93KTdgyt/1x4BfcT5/ PCaEd9suYwEneI2Io8CX9oTAe3MRyRPtlN0szT89qP/q Q4sktVjc1nkxHhdP2mahqeiBLUGULfkgUBtEjaGAFSWb ejFV0fRDHk6bSJ www@linux-node1

     

    注意,修改authorized_keys的权限

    chmod 600 authorized_keys

     

    另外,将.ssh目录的权限设置成700

    chmod 700 .ssh

    - 并发部署   集群环境下,并发在所有机器上执行相同的部署流程

    1.7.2 剖析脚本

    查看脚本,具体配和自动化运维之自动化部署系统构建及演变文章来解读

    [wanyuetian@linux-node1 ~]$ cat deploy.sh
    #!/bin/bash
    # useradd wanyuetian  && sshkey需认证
    # Nginx 权限必须让wanyuetian用户可访问
    # Dir List
    # mkdir -p /deploy/code/rainbow_pro  # web code的仓库
    # mkdir -p /deploy/source/rainbow_pro #存放git源码仓库
    # mkdir -p /deploy/config/rainbow_pro/config  #存放config信息
    # mkdir -p /deploy/config/rainbow_pro/admin_config  #存放后台config信息
    # mkdir -p /deploy/tmp
    # Web Root Dir
    # mkdir -p /home/wanyuetian/webroot
    # chown web
    # chown -R www:www /deploy
    # chown -R www:www /home/wanyuetian/webroot
    # Code Env
    PRO_NAME="rainbow_pro"
    CODE_DIR="/deploy/code/$PRO_NAME"
    SOURCE_DIR="/deploy/source/$PRO_NAME"
    CONFIG_DIR="/deploy/config/$PRO_NAME"
    WEB_DIR="/home/wanyuetian/webroot"
    TMP_DIR="/deploy/tmp"
    # Node List
    PRE_LIST="192.168.90.201"
    GROUP1_LIST="192.168.90.202"
    ROLLBACK_LIST="192.168.90.201 192.168.90.202"
    # Date/Time Veriables
    CTIME=$(date " %F-%H-%M")
    # Shell Env
    SHELL_NAME="deploy.sh"
    SHELL_DIR="/home/wanyuetian/webroot"
    # Log
    LOG_FILE="${SHELL_DIR}/${SHELL_NAME}".log
    LOCK_FILE="/tmp/deploy.lock"
    # Lock
    shell_lock(){
        touch ${LOCK_FILE}
    }
    shell_unlock(){
        rm -f ${LOCK_FILE}
    }
    # URL Test
    url_test(){
        URL=$1
        curl -s --head $URL |egrep '200|301|302'
        if [ $? -ne 0 ];then
            shell_unlock;
            echo  "test error" && exit;
        fi
    }
    # log 
    writelog(){
        LOGINFO=$1
        echo "${CTIME}: ${SHELL_NAME} : ${LOGINFO}" >> ${LOG_FILE}
    }
    code_get(){
        writelog "code_get"
        cd $SOURCE_DIR && git pull
        GIT_CID=$(git log|awk 'NR==1{print $2}'|cut -c 1-6)
        PKG_VER="${CTIME}_${GIT_CID}"
        PKG_NAME="${PRO_NAME}_${PKG_VER}"
        cp -r ${SOURCE_DIR} ${TMP_DIR}/${PKG_NAME}
    }
    code_bulid(){
        echo code_bulid #由于php没有编译过程
    }
    code_config(){
        writelog "code_config"
        /bin/cp -r ${CONFIG_DIR}/config.php ${TMP_DIR}/${PKG_NAME}/config.php
    }
    code_tar(){
        writelog "code_tar"
        cd ${TMP_DIR} && tar czf ${PKG_NAME}_tar.gz ${PKG_NAME} --exclude=.git --exclude=.gitignore
        writelog "${PKG_NAME}_tar.gz"
    }
    code_scp(){
        writelog "code_scp"
        for node in $PRE_LIST;do
            scp ${TMP_DIR}/${PKG_NAME}_tar.gz $node:${TMP_DIR}/
        done
        for node in $GROUP1_LIST;do
            scp ${TMP_DIR}/${PKG_NAME}_tar.gz $node:${TMP_DIR}/
        done
    }
    pre_deploy(){
        writelog "remove from cluster"
        ssh $PRE_LIST "cd ${TMP_DIR} && tar xf ${PKG_NAME}_tar.gz -C ${CODE_DIR}/"
        ssh $PRE_LIST "rm -f $WEB_DIR/${PRO_NAME} && ln -s ${CODE_DIR}/${PKG_NAME} $WEB_DIR/${PRO_NAME}"
    }
    pre_test(){
        url_test "http://${PRE_LIST}/index.html"
        echo "Rre add to cluster"
    }
    group1_deploy(){
            writelog "remove from cluster"
        for node in $GROUP1_LIST;do
                ssh $node "cd ${TMP_DIR} && tar xf ${PKG_NAME}_tar.gz -C ${CODE_DIR}/"
                ssh $node "rm -f $WEB_DIR/${PRO_NAME} && ln -s ${CODE_DIR}/${PKG_NAME} $WEB_DIR/${PRO_NAME}"
        done
       #scp ${CONFIG_DIR}/other/192.168.90.201.crontab.xml 192.168.90.201:/$WEB_DIR/${PRO_NAME}/crontab.xml 额外不一样的配置可能需要用到
    }
    group1_test(){
            url_test "http://${GROUP1_LIST}/index.html"
            echo "group1_node add to cluster"
    }
    code_reload(){
        systemctl restart php-fpm  #重启php清楚opcode缓存
    }
    rollback_list(){
      for node in $GROUP1_LIST;do
            ssh $node ls -l "$WEB_DIR" &&
            ssh $node find "$CODE_DIR/" -maxdepth 1 -mtime -2|sed 1d|awk -F '/' '{print $5}'
            #find "$CODE_DIR" -type d -name "$PRO_NAME*" -mtime  30|xargs rm -fr
      done
    }
    rollback_fun(){
      if [ -z $ROOLBACK ];then
        shell_unlock;
        echo "Please input rollback version" && exit;
    else
        for node in $ROLLBACK_LIST;do
        ssh $node rm -f $WEB_DIR/${PRO_NAME} && 
        ssh $node ln -s ${CODE_DIR}/$ROOLBACK $WEB_DIR/${PRO_NAME}
        done
    fi
    }
    main(){
      if [ -f "$LOCK_FILE" ];then
        echo "Deploy is Running" && exit;
      fi
      DEPLOY_METHOD="$1"
      ROOLBACK="$2"
      case $DEPLOY_METHOD in
        deploy)
            shell_lock;
            code_get;
            code_bulid;
            code_config;
            code_tar;
            code_scp;
            pre_deploy;
            pre_test;
            group1_deploy;
            group1_test;
        #   group2_deploy;
        #   group2_test;
            shell_unlock;
            ;;
        list)
        rollback_list;
            ;;
        rollback)
            shell_lock;
            rollback_fun $ROLLBACK;
            shell_unlock;
            ;;
        *)
            echo "$Usage:$0 [ deploy | list | rollback ]"
        esac
    }
    main $1 $2
    

    执行上线:

    [wanyuetian@linux-node1 ~]$ sh deploy.sh deploy
    Already up-to-date.
    code_bulid
    rainbow_pro_2016-08-12-21-16_46236b_tar.gz                                     100% 6016KB   5.9MB/s   00:00
    rainbow_pro_2016-08-12-21-16_46236b_tar.gz                                     100% 6016KB   5.9MB/s   00:00
    rainbow_pro_2016-08-12-21-16_46236b_tar.gz                                     100% 6016KB   5.9MB/s   00:00
    HTTP/1.1 200 OK
    Rre add to cluster
    HTTP/1.1 200 OK
    HTTP/1.1 200 OK
    group1_node add to cluster
    php-fpm restart
    

    查看当前版本

    [wanyuetian@linux-node1 ~]$ sh deploy.sh list
    总用量 16
    lrwxrwxrwx 1 wanyuetian wanyuetian    60 8月  12 21:16 rainbow_pro -> /deploy/code/rainbow_pro/rainbow_pro_2016-08-12-21-16_46236b
    rainbow_pro_2016-08-12-19-24_46236b
    rainbow_pro_2016-08-12-21-16_46236b
    总用量 0
    lrwxrwxrwx 1 wanyuetian wanyuetian 60 8月  12 21:16 rainbow_pro -> /deploy/code/rainbow_pro/rainbow_pro_2016-08-12-21-16_46236b
    rainbow_pro_2016-08-12-19-24_46236b
    rainbow_pro_2016-08-12-21-16_46236b
    

    执行回滚操作

    [wanyuetian@linux-node1 ~]$ sh deploy.sh rollback #直接执行是不允许的
    Please input rollback version
    [wanyuetian@linux-node1 ~]$ sh deploy.sh rollback rainbow_pro_2016-08-12-19-24_46236b #这个操作一定要配合list来做。
    

    查看已经回退到19点的版本

    [wanyuetian@linux-node1 ~]$ sh deploy.sh list
    总用量 16
    -rw-rw-r-- 1 wanyuetian wanyuetian 14224 8月  12 21:16 deploy.sh.log
    lrwxrwxrwx 1 wanyuetian wanyuetian    60 8月  12 21:18 rainbow_pro -> /deploy/code/rainbow_pro/rainbow_pro_2016-08-12-19-24_46236b
    rainbow_pro_2016-08-12-19-24_46236b
    rainbow_pro_2016-08-12-21-16_46236b
    总用量 0
    lrwxrwxrwx 1 wanyuetian wanyuetian 60 8月  12 21:18 rainbow_pro -> /deploy/code/rainbow_pro/rainbow_pro_2016-08-12-19-24_46236b
    rainbow_pro_2016-08-12-19-24_46236b
    rainbow_pro_2016-08-12-21-16_46236b
    

    查看日志:

    [wanyuetian@linux-node1 ~]$ cat webroot/deploy.sh.log
    2016-08-12-21-35: deploy.sh : code_get
    2016-08-12-21-35: deploy.sh : code_config
    2016-08-12-21-35: deploy.sh : code_tar
    2016-08-12-21-35: deploy.sh : rainbow_pro_2016-08-12-21-35_46236b_tar.gz
    2016-08-12-21-35: deploy.sh : code_scp
    2016-08-12-21-35: deploy.sh : remove from cluster
    2016-08-12-21-35: deploy.sh : remove from cluster
    

    2、详细代码

     

    新葡亰496net 7新葡亰496net 8

      1 #!/bin/bash
      2 
      3 #Node List
      4 
      5 PRE_LIST="192.168.56.11"
      6 
      7 GROUP1_LIST="192.168.56.12"
      8 
      9 ROLLBACK_LIST="192.168.56.11 192.168.56.12"
     10 
     11 #Date/Time Variable
     12 
     13 LOG_DATE='date " %Y-%m-%d"'
     14 
     15 LOG_TIME='date " %H-%M-%S"'
     16 
     17 CDATE=$(date " %Y-%m-%d")
     18 
     19 CTIME=$(date " %H-%M-%S")
     20 
     21 #Shell env
     22 
     23 SHELL_NAME="/deploy1.sh"
     24 
     25 SHELL_DIR="/home/www/"
     26 
     27 SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}.log"
     28 
     29 #Code ENV
     30 
     31 PRO_NAME="web-demo"
     32 
     33 CODE_DIR="/deploy/code/web-demo"
     34 
     35 CONFIG_DIR="/deploy/config/web-demo"
     36 
     37 TMP_DIR="/deploy/tmp"
     38 
     39 TAR_DIR="/deploy/tar"
     40 
     41 LOCK_FILE="/tmp/deploy.lock"
     42 
     43  
     44 
     45 usage(){
     46 
     47          echo $"Usage: $0 {deploy | rollback [ list | version ]} "
     48 
     49 }
     50 
     51  
     52 
     53 writelog(){
     54 
     55          LOGINFO=$1
     56 
     57          echo "${CDATE}${CTIME}: ${SHELL_NAME}: ${LOGINFO} " >> ${SHELL_LOG}
     58 
     59 }
     60 
     61  
     62 
     63  
     64 
     65 shell_lock(){
     66 
     67          touch ${LOCK_FILE}
     68 
     69 }
     70 
     71  
     72 
     73 shell_unlock(){
     74 
     75          rm -f ${LOCK_FILE} 
     76 
     77 }
     78 
     79  
     80 
     81 code_get(){
     82 
     83          writelog "code_get";
     84 
     85          cd $CODE_DIR && echo "git pull";
     86 
     87         cp -r ${CODE_DIR} ${TMP_DIR}/
     88 
     89          API_VER="456"       
     90 
     91 }
     92 
     93  
     94 
     95 code_build(){
     96 
     97          echo code_build
     98 
     99 }
    100 
    101  
    102 
    103 code_config(){
    104 
    105          writelog "code_config"
    106 
    107          /bin/cp -r ${CONFIG_DIR}/base/* ${TMP_DIR}/"${PRO_NAME}"
    108 
    109          PKG_NAME="${PRO_NAME}"_"$API_VER"_"${CDATE}-${CTIME}"
    110 
    111          cd ${TMP_DIR} && mv ${PRO_NAME} ${PKG_NAME}       
    112 
    113 }
    114 
    115  
    116 
    117 code_tar(){
    118 
    119          writelog "code_tar"
    120 
    121          cd ${TMP_DIR} && tar czf ${PKG_NAME}.tar.gz $PKG_NAME
    122 
    123          writelog "${PKG_NAME}.tar.gz"
    124 
    125 }
    126 
    127  
    128 
    129 code_scp(){
    130 
    131          writelog "code_scp"
    132 
    133          for node in $PRE_LIST;do
    134 
    135                  scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot
    136 
    137          done
    138 
    139          for node in $GROUP1_LIST;do
    140 
    141                  scp ${TMP_DIR}/${PKG_NAME}.tar.gz $node:/opt/webroot
    142 
    143          done
    144 
    145 }
    146 
    147  
    148 
    149 cluster_node_remove(){
    150 
    151          writelog  "cluster_node_remove"
    152 
    153 }
    154 
    155  
    156 
    157 pre_deploy(){
    158 
    159          writelog "remove from cluster"  
    160 
    161         ssh $PRE_LIST "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz"
    162 
    163         ssh $PRE_LIST "rm -rf /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo"
    164 
    165 }
    166 
    167 url_test(){
    168 
    169          URL=$1
    170 
    171          curl -s --head $URL|grep "200 OK"
    172 
    173          if [ $? -ne 0 ];then
    174 
    175                  shell_unlock;
    176 
    177                  writelog "test error" && exit;
    178 
    179          fi
    180 
    181 }
    182 
    183 pre_test(){
    184 
    185          url_test "http://${PRE_LIST}/index.html"
    186 
    187          echo "add to cluster"
    188 
    189 }
    190 
    191  
    192 
    193 group1_deploy(){
    194 
    195          writelog "remove from cluster"
    196 
    197         
    198 
    199          for node in $GROUP1_LIST;do
    200 
    201                 ssh $node "cd /opt/webroot && tar zxf ${PKG_NAME}.tar.gz"
    202 
    203                  ssh $node "rm -rf /webroot/web-demo && ln -s /opt/webroot/${PKG_NAME} /webroot/web-demo"
    204 
    205         done    
    206 
    207          scp ${CONFIG_DIR}/other/192.168.56.12.crontab.xml 192.168.56.12:/webroot/web-demo/crontab.xml
    208 
    209 }
    210 
    211  
    212 
    213 group1_test(){
    214 
    215          url_test "http://192.168.56.12/index.html"
    216 
    217          echo "add to cluster"
    218 
    219 }
    220 
    221 rollback_fun(){
    222 
    223          for node in $ROLLBACK_LIST;do
    224 
    225                 ssh $node "rm -rf /webroot/web-demo && ln -s /opt/webroot/$1 /webroot/web-demo"
    226 
    227         done 
    228 
    229 }
    230 
    231 rollback(){
    232 
    233 if [ -z $1 ];then
    234 
    235          shell_unlock; 
    236 
    237          echo "please input rollback version" && exit;
    238 
    239 fi
    240 
    241          case $1 in
    242 
    243              list)
    244 
    245                  ls -l /opt/webroot/*.tar.gz
    246 
    247                  ;;
    248 
    249              *)
    250 
    251                  rollback_fun $1
    252 
    253          esac        
    254 
    255 }
    256 
    257  
    258 
    259 main(){
    260 
    261     if [ -f $LOCK_FILE ];then
    262 
    263          echo "Deploy is running" && exit;
    264 
    265     fi
    266 
    267     DEPLOY_METHON=$1
    268 
    269     ROLLBACK_VER=$2
    270 
    271     case $DEPLOY_METHON in
    272 
    273         deploy)
    274 
    275              shell_lock;
    276 
    277              code_get;
    278 
    279              code_build;
    280 
    281              code_config;
    282 
    283              code_tar;
    284 
    285              code_scp;
    286 
    287              pre_deploy;
    288 
    289              pre_test;
    290 
    291              group1_deploy;
    292 
    293              group1_test;
    294 
    295              shell_unlock;
    296 
    297              ;;
    298 
    299          rollback)
    300 
    301              shell_lock;
    302 
    303              rollback $ROLLBACK_VER;
    304 
    305              shell_unlock;
    306 
    307              ;;
    308 
    309          *)
    310 
    311              usage;
    312 
    313          esac 
    314 
    315 }
    316 
    317 main $1 $2
    

    View Code

    测试方式

    [www@linux-node1 ~]$ curl --head 

    HTTP/1.1 200 OK

    Date: Mon, 01 Aug 2016 09:42:23 GMT

    Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips PHP/5.4.16 mod_wsgi/3.4 Python/2.7.5

    Last-Modified: Mon, 01 Aug 2016 09:39:52 GMT

    ETag: "17-538ff61ca0a00"

    Accept-Ranges: bytes

    Content-Length: 23

    Content-Type: text/html; charset=UTF-8

     

    [www@linux-node1 ~]$ curl -s --head  "200 OK"

    HTTP/1.1 200 OK

    上面脚本远程执行命令或者拷贝 是使用ssh/scp完成的。当服务器稍多的时候,效率并不高。

    我在生产环境中是使用 ansible 替代的,个人感觉对于这个脚本来说,就是个并行、串行的区别。

    进一步的发展,还可以开发一些WEB界面去结合这个脚本,做到WEB化自动部署,当然也可以使用开源的jenkis。

    - 一致性     集群环境下,只有所有机器都执行成功才算成功,一台失败则全部失败

    1.7.3 脚本其他功能

    当然此脚本功能不仅仅如此,可以通过git分支,git tag包等方式来上线,这些根据贵公司的具体业务来进行调整,也可以自己开发一个web界面来调用此脚本,这样就可以将上线工作交给开发,当然也可以使用开源jenkins来实现。

    3、回滚

    1.列出回滚版本

    2.目标服务器移除集群

    3.执行回滚

    4.重启和测试

    5.加入集群

    ===========

    如果是遇到重大bug

    1.列出回滚版本

    2.执行回滚(重启)

    ==========

    非常紧急

    1.直接回滚到上个版本(重启)

    自动化部署的核心是创建软链接,同样在回滚的时候也能实现秒级回滚。

    但是在生产环境中,使用软连接可能会造成WEB打开页面空白,这点需要注意。

     

    来自为知笔记(Wiz)

    - 内置多个框架发布模板   比如Laravel、Yii、Symfony、CodeIgniter、Zend Framework等

    1.7.4 后期更新

    (如上脚本) gitlab jenkins Sonar 构建自动化部署代码,并代码发布前质量管理

    - 易扩展     很容易可以依据自己的项目用Common模板编写发布流程

    安装: 

    composer global require deployer/deployer
    

    安装完成后,切换到自己的项目目录,执行dep init,按照自己项目使用的框架选择生成的部署模板:

    ➜  tb dep init
    Please select your project type (defaults to common):
      [0] Common
      [1] Laravel
      [2] Symfony
      [3] Yii
      [4] Zend Framework
      [5] CakePHP
      [6] CodeIgniter
      [7] Drupal
     > 0
    

    如果你的框架未使用上面列出的任何一个框架,则选择0,然后回车,就会生成通用的发布模板。

    执行完这一步应该会在你的项目根目录生成一个deploy.php文件,你所需要的做的一切就是编辑这个脚本,填写一些自己的服务器和项目配置,然后定制一些task。

    下面我将用一个具体的配置文件来介绍deployer的使用,配置文件如下:

     

    <?php
    namespace Deployer;
    
    use SymfonyComponentConsoleInputInputOption;
    
    require 'recipe/common.php';
    
    option('tag', null, InputOption::VALUE_OPTIONAL, '发布的tag');
    
    // 全局配置文件   
    set('ssh_type', 'native');    // 登录远程主机使用的方式,有三种:phpseclib(默认方式)、native、ext-ssh2
    set('ssh_multiplexing', true);  // 是否开启ssh通道复用技术(开启可以降低服务器和本地负载,并提升速度)
    set('keep_releases', 10); //    报错10个之前版本,设置为-1表示一直保存历史版本
    set('repository', 'git@xxxxxxx.com:loc/loc-api.git');    // 代码仓库的地址,只支持git
    set('branch', 'master');    // 发布代码时候默认使用的分支
    set('shared_files', []);    // 共享文件列表   这里面列出的文件会被移动到项目根目录的shared目录下,并做软链
    set('shared_dirs', []);     // 共享目录    同上
    set('writable_mode', 'chmod');  // 采用哪种方式控制可写权限,有4中:chown、chgrp、chmod、acl(默认方式)
    set('writable_chmod_mode', '0755'); // 当使用chmod控制可写权限的时候,赋予的可写权限值
    set('writable_dirs', []);   // 可写目录   规定那些目录是需要可以被web server写入的
    set('clear_path', []);  // 设置在代码发布的时候需要被删除的目录
    set('http_user', 'nginx');  // web server的用户,一般不用设置,deployer会自动判断
    set('release_name', function () {   // 设置发布版名称,这里优先使用tag作为名称,不传的话会使用日期 时间表示发布时间
        if (input()->hasOption('tag')) {
            return input()->getOption('tag');
        }
        return date('Ymd-H:i');
    });
    
    // 可以设置多个服务器,发布的时候根据设置会同步发往多个服务器
    // 针对每个服务器可以单独设置参数,设置的参数会覆盖全局的参数
    server('prod_1', 'xxx.xxx.xxx.xxx')
        ->user('root')
        ->password('xxxxx')
        ->set('deploy_path', '/var/www/tb')   // 代码部署目录,注意:你的webserver,比如nginx,设置的root目录应该是/var/www/tb/current,
                                              // 因为current是一个指向当前线上实际使用的版本的软链
        ->stage('prod');  // 标识该服务器类型,用于服务器分组
    
    server('prod_2', 'xxx.xxx.xxx.xxx')
        ->user('root')
        ->password('xxxxx')
        ->set('deploy_path', '/var/www/tb')
        ->set('branch', 'master')   // 指定发往这个服务器的分支,会覆盖全局设置的branch参数
        ->set('extra_stuff', '...') // 随意指定其他什么参数
        ->stage('prod');
    
    server('beta', 'xxx.xxx.xxx.xxx')
        ->user('root')
        ->password('xxxxx')
        ->set('deploy_path', '/var/www/test')
        ->set('branch', 'beta')   // 测试环境使用beta分支
        ->stage('beta');    // 放在beta分组
    
    
    // 配置的任务
    task('success', function () {
        Deployer::setDefault('terminate_message', '<info>发布成功!</info>');
    })->once()->setPrivate();   // 增加once调用那么这个任务将会在本地执行,而非远端服务器,并且只执行一次
    
    desc('重启php-fpm');    // 可以给任务增加一个描述,在执行dep list的时候将能看到这个描述
    task('php-fpm:restart', function () {
        run('systemctl restart php-fpm.service');  // run函数定义在服务器执行的操作,通常是一个shell命令,可以有返回值,返回命令打印
    });     // 聪明如你一定发现了,可以用run函数制作一些批量管理服务器的任务,比如批量重载所有的nginx配置文件、批量执行服务器上的脚本等
    
    after('deploy:symlink', 'php-fpm:restart'); // 钩子函数,表示执行完设置软链任务之后执行php-fpm重启任务
    
    desc('发布项目');
    task('deploy', [    // 可以设置复合任务,第二个参数是这个复合任务包括的所有子任务,将会依次执行
        'deploy:prepare',   // 发布前准备,检查一些需要的目录是否存在,不存在将会自动创建
        'deploy:lock',  // 生成锁文件,避免同时在一台服务器上执行两个发布流程,造成状态混乱
        'deploy:release',   // 创建代码存放目录
        'deploy:update_code',   // 更新代码,通常是git,你也可以重写这个task,使用upload方法,采用sftp方式上传
        'deploy:shared',    // 处理共享文件或目录
        'deploy:writable',  // 设置目录可写权限
        'deploy:vendors',   // 根据composer配置,安装依赖
        'deploy:clear_paths',   // 根据设置的clear_path参数,执行删除操作
        'deploy:symlink',   // 设置符号连接到最新更新的代码,线上此时访问的就是本次发布的代码了
        'deploy:unlock',     // 删除锁文件,以便下次发布
        'cleanup',  // 根据keep_releases参数,清楚过老的版本,释放服务器磁盘空间
        'success'   // 执行成功任务,上面自己定义的,一般用来做提示
    ]);
    
    
    after('deploy:failed', 'deploy:unlock');    // 如果发布失败,则删除锁文件,以便下次重试
    

     

    上面就是一个比较完整的自动化部署脚本配置了,是不是感觉到很简单? 因为大部分配置工作在你执行dep init的时候就已经帮你做了!

    在接下来还需要做的一件事情就是把你要部署的服务器的ssh-key加入到你的git帐号的认证库里面,你也可以创建一个账户,只拥有仓库的git pull和git clone权限,保持最小权限原则。需要注意的是,加完key之后,首次在服务器上执行git clone可能会需要让你输入yes,所以最稳妥的办法是,去每台要部署的服务器上去执行一遍git clone,把仓库代码拖一份到其他目录。

    做完上面的事情之后,所有的准备工作就算完成了。接下来就可以进行部署测试了。

    首先检查下配置有没问题:

     

    dep config:dump beta    // 打印beta环境的配置
    dep config:dump prod    // 打印生产环境的配置
    

    打印出来的配置没有问题的话,接着执行发布任务:

    dep deploy beta // 发布当前beta分支到beta环境
    dep --tag=v1.1 deploy prod // 发布v1.1这个tag的代码到生产环境,可以增加-p选项,并发发往所有服务器
    

    一次成功的部署应该会有类似如下输出:

     

    ➜  tb git:(master) ✗ dep --tag=v1.1 deploy prod_1
    ✔ Executing task deploy:prepare
    ✔ Executing task deploy:lock
    ✔ Executing task deploy:release
    ✔ Executing task deploy:update_code
    ✔ Executing task deploy:shared
    ✔ Executing task deploy:writable
    ✔ Executing task deploy:vendors
    ✔ Executing task deploy:clear_paths
    ✔ Executing task deploy:symlink
    ✔ Executing task php-fpm:restart
    ✔ Executing task deploy:unlock
    ✔ Executing task cleanup
    ✔ Executing task success
    发布成功!
    

    查看当前生产环境使用的哪个版本

    dep current prod  //这里应该会输出v1.1 
    

    查看当前生产环境使用的哪个版本:

     

    dep current prod  //这里应该会输出v1.1 
    

    如果发布到线上之前之后发现有问题,需要回滚,只需要执行:

    dep rollback prod   // 实际上只是修改软链指向,所以很快就能执行完成且基本不可能失败
    

    再次用dep current prod应该就可以看到回滚到之前版本了

    再比如之前执行出了问题,被中断,再次执行可能会提示:Deploy locked,那么只用执行:

     

    dep deploy:unlock prod // 删除锁文件
    

    如果线上磁盘空间吃紧了的话(一般不会),可以执行如下命令删除掉太早以前的版本:

    dep cleanup
    

     

    到了这里关于deployer所有你应该都掌握了。虽然第一次配置的确需要花点时间,可能半个小时也可能半天。  不过换来的却是接下来更优雅、快速、安全、易回滚的发布流程,这么想一下是不是还有点小激动呢?

    如果在安装使用过程中有什么问题的话可以加群:632109190进行讨论。对php、java、运维感兴趣的同学都可以加进来,我在这等你们 :)

    本文由新葡亰496net发布于奥门新萄京娱乐场,转载请注明出处:新葡亰496net自动化铺排深度实践,是时候换种更

    关键词: