×

使用deployer部署工具配合阿里云RDC完成部署,持续交付

96
never615
2017.10.27 19:22* 字数 1033

首先需要了解一下,开发应用的四层环境

  1. 开发环境(Development)
    这个环境可以是一个独立开发者使用,也可以是较少的几个人一起使用.这个环境中对
    代码的任何改动都不会影响其他人,所以可以随便改.
  2. 集成环境(Integration)
    各个开发者开发的不同功能代码都会提交到这个环境进行整合,进行测试,以保证进入预发布环境没有问题.根据实际开发情况,集成环境和开发环境也可以使用同一个环境,具体会在下文的实践中介绍.
  3. 预演环境(Staging)
    预发布环境需要尽可能的和生产环境一样.连接测试数据库,这个环境也可作为演示和培训.
  4. 生产环境(Production)
    就是正式上线的环境了,项目可能部署在服务器集群上.

我实际使用的环境是:production/staging/testing/integration

  • production:上线的正式环境(多服务器部署)
  • staging:连接着正式数据库(多服务器部署,因为当时刚开始弄多服务器* 部署/负载/redis等,所以这个也是为了测试)
  • testing:连接测试数据库
  • integration:日常的开发环境,可以直接上传修改的文件到服务器.其他三个环境需要走部署流程.

如果你也打算像我一下用这四个环境时,记得这几个关键字最好也和我一样,因为我后来使用阿里云的RDC发现定义的几个关键字是这个,分别是日常环境:testing/预发环境:staging/生产环境:production.这在写同一个部署命令到不同环境的时候很有用.


正式开始

在阿里云RDC中创建项目之后,创建应用,分支选择自由模式.

创建应用的时候需要关联分支,会自动在master分支下给你创建好发布配置文件,名字是[应用名].release.如下:

# 请参考 https://help.aliyun.com/document_detail/59293.html 了解更多关于release文件的编写方式 

# 构建源码语言类型
code.language=php7.0

# 应用部署脚本
deploy.appctl.path=deploy.sh

deploy.appctl.path=deploy.sh是你源码中的部署脚本,详见在代码库中存储部署脚本.
我之前用RDC的时候还没这个东西,所以我项目release的配置都是:

# 构建源码语言类型
code.language=scripts
# 要部署到服务器上的文件,我在里面放了deployer脚本
build.output=deploy/
Screen Shot 2017-10-27 at 7.01.11 PM.png

然后配置应用的环境:

Screen Shot 2017-10-27 at 6.47.16 PM.png

你需要配置的地方有:资源管理/部署策略/部署配置

资源管理:配置要部署的机器.我是日常环境配置一台.预发和正式配置多台.因为当时刚开始使用多服务器运行项目,我怕出问题,所以需要有一个给我测试多服务运行状态的环境.
部署策略:我都选的是分批发布不暂停
部署配置:

Screen Shot 2017-10-27 at 7.02.08 PM.png

下载路径中的文件就是发布配置文件中设置的build.output参数.

这个RDC脚本部署执行起来的流程就是:

  1. 将源码中的build.output设置的文件打包传到服务器的下载路径
  2. 执行stop命令,我用它创建了部署文件的目录..很奇葩,因为当时还没有deploy.sh文件,我需要解压目录保证存在,不然部署会失败(我假设部署的是一台之后基本软件环境的新系统,没有创建该目录).我没写应该有的stop命令,因为我项目目前的情况用不到.
  3. 解压步骤1中的包到指定目录

如果你现在写配置话,建议把命令放在deploy.appctl.path=deploy.sh,我没有改我之前的配置,因为RDC想在还经常升级迭代...我不着急弄...

配置流水线

我是develop分支对应一条流水线:对应环境日常环境和预发环境;
master分支对应一条流水线:对应正式环境

Screen Shot 2017-10-27 at 7.19.32 PM.png
Screen Shot 2017-10-27 at 7.20.03 PM.png
Screen Shot 2017-10-27 at 7.20.18 PM.png

我的一个deploy.php,测试环境用的部署文件:
deployer

<?php
namespace Deployer;

require 'recipe/laravel.php';

use Symfony\Component\Console\Input\InputOption;


//dep -vv deploy --first true  --branch develop -- test


option('first', null, InputOption::VALUE_OPTIONAL, 'If first deploy.');

// Configuration
set('repository', 'git@code.aliyun.com:mall-to/easy-admin.git');
set('allow_anonymous_stats', false);
set('default_timeout', 600);

localhost()
    ->stage('test')
    ->set("branch", "develop")
    ->set('deploy_path', '/app/back_end/easy_admin/test');


// Tasks

desc('first deploy');
task('deploy:first', function () {
    if (input()->hasOption('first')) {
        $first = input()->getOption('first');
        if ($first) {
            run('{{bin/php}} {{release_path}}/artisan tool:install');
            run('{{bin/php}} {{release_path}}/artisan admin:install');
            run('{{bin/php}} {{release_path}}/artisan user:install');
            run('{{bin/php}} {{release_path}}/artisan mall:install');
            run('{{bin/php}} {{release_path}}/artisan activity:install');
            //生成的key需要各个地方一样
//            run('{{bin/php}} {{release_path}}/artisan passport:install');
//            run('{{bin/php}} {{release_path}}/artisan passport:keys');
            run('{{bin/php}} {{release_path}}/artisan passport:client --personal');
        }
    }
});

desc('update');
task('deploy:update',function(){
    run('yes|{{bin/php}} {{release_path}}/artisan tool:update');
    run('yes|{{bin/php}} {{release_path}}/artisan admin:update');
    run('yes|{{bin/php}} {{release_path}}/artisan user:update');
    run('yes|{{bin/php}} {{release_path}}/artisan mall:update');
    run('yes|{{bin/php}} {{release_path}}/artisan activity:update');
});

desc('copy env');
task('deploy:cp_env', 'cp .env.{{stage}} .env');

desc('copy composer');
task('deploy:cp_composer', 'cp composer.json.circle composer.json');

desc('Restart PHP-FPM service');
task('php-fpm:restart', function () {
    // The user must have rights for restart service
    // /etc/sudoers: username ALL=NOPASSWD:/bin/systemctl restart php-fpm.service
    run('sudo systemctl restart php-fpm.service');
});

task("artisan:vendor", '
        php artisan queue:restart;
    ');

after('deploy:symlink', 'php-fpm:restart');
after('deploy:update_code', 'deploy:cp_env');
after('deploy:update_code', 'deploy:cp_composer');


// [Optional] if deploy fails automatically unlock.
after('deploy:failed', 'deploy:unlock');

// first deploy run
after('artisan:vendor', 'deploy:first');
// plugin install
after('artisan:vendor', 'deploy:update');
// publish vendor
before('deploy:symlink', 'artisan:vendor');

// Migrate database before symlink new release.
before('deploy:symlink', 'artisan:migrate');

参考链接

deployer
阿里云RDC/云效
Traditional Development/Integration/Staging/Production Practice for Software Development
Amazon为何能做到持续交付
谈谈持续集成,持续交付,持续部署之间的区别

部署&上线
Web note ad 1