jenkins 自动化部署实战

  jenkins 做为一个自动化的集成工具,已是必不可少的了。它里面提供各类插件,以及完备的基础流程设施,为你们的自动化集成之路提供了不少的方便。因此,咱们有必要完整的实践一回。以切身体会到它的好处!前端

1、 操做步骤说明陈列

  1. 下载jenkins包,并安装;(两种方案,基于物理机和基于docker,视状况而定建议使用docker)java

  2. 安装后,初始化jenkins,基本都是下一步下一步搞定,保持默认是比较稳妥的选择;node

  3. 订立目标,须要完成什么的场景下的打包功能? git ?  subversion? 或者其余 ?git

  4. 选择此场景须要的必要插件安装,并进行简单调试;github

  5. 新建一个任务,尝试使用工具完成一次简单的打包操做;web

  6. 完善一个任务,使其能够支持一些简单的参数定制,如分支的选择;docker

  7. 打包完成后,编写部署脚本,使其能够一键部署;shell

  8. 设置权限管理,使不一样环境的包由不一样级别的同窗进行操做;npm

  9. 进行反复功能验证,及权限验证;安全

  10. 备注全部的操做流程,以便在进行下次从新安装时,可以随时搞定;

 

 2、具体实践操做

  简单的安装和初始化,我们就很少说了,网上一大堆的信息,随便找一个就能搞定,不找也能搞定,请参考官网: https://wiki.jenkins.io/display/JENKINS/Use+Jenkins

打包场景一: 如何打包 maven 管理的java项目 ?

  其实要打包这种项目比较简单,只要安装一个 maven integeration 的插件便可!以下:

  安装好后,新建一个 maven 任务便可!

  其实maven任务和其余任务不太同样的地方是,它会出现一个 pom.xml 的字样,其实就是本身去加载这个配置文件,而后自行调用 maven 进行打包。而若是想要更灵活,也是能够的,只须要使用 系统的命令进行自由构建便可!

 

  goal 里可写: clean install | package

   通过上面的操做后,你可能会发现,其实并不会打包成功,为何呢?由于咱们尚未安装 maven 的工具到系统上,或者说没有向 jenkins 解释 maven 在哪里,因此须要到全局工具配置一下!

  另外,若是你是须要打包 git 类的代码的话,通常只须要进行简单受权就能够了!

  到此,一个 简单的 maven java 项目打包就成功了!

 

可是,其实,打包到这个程度,其实对咱们的环境部署一点更多的意义都没有,因此咱们须要更深的定制化!我们稍后再说!

 

先来讲说,另外一种项目的打包方式, h5 代码的打包。 更具体的讲,就是 基于 nodejs 的打包实现!

 

  首先,咱们固然须要安装 node js 的插件了!

  一样,该插件安装好后,还要安装  nodejs 的软件!能够直接选择自动 安装 ! 注意要求的版本!

  安装好后,新建一个自由风格的任务!

  进入,把 node 的环境支持勾选上!而后定稿node 的打包命令!

  一样,git 相关的操做同样!

  至此,简单的 node 版本的代码打包功能也作好了。 

  一样,只是进行打包,没法定制化的东西,对咱们毫无心义,因此,咱们须要更高级的定制 jenkins !

  例外:若是有依赖一些私有的包,那么,你能够选择安装私服,或者用以下方式解决:

# for local repository dependency...
ln -sf /var/lib/jenkins/pkg-bak/testmodule/ $WORKSPACE/node_modules/testmodule
npm install
npm run prod

 

 

3、 定制你的 jenkins 功能!

场景一: 我须要为一个git 仓库的多个分支打包?

  这个,简单, jenkins 中一添加定制化参数的功能,只须要添加一个文本参数就能够 了!

  在 git 分支一栏,写入 $branch 替换便可!

 

   如此,一个简单的支持 git 多分支打包的功能就作好了!

可是:每次都让我本身输入分支,好烦啊! 并且,我本身也不必定知道有什么样的分支,这可怎么办?

  借助 groovy 脚本,能够动态拉取 分支列表,进行显示了!

  简单来讲就是,执行一些shell脚本 , 从 git 远端列举出分支,给到列表选项! groovy 脚本以下:

def git_url = "https://github.com/yougewe/elastic-job-lite"
def git_cmd = "/usr/local/git/bin/git ls-remote -h $git_url  | grep -oP '(?<=refs/heads/).*' "
branch = ['bash', '-c', git_cmd].execute().text.readLines()

  好了,分支的选择,看起来咱们已经解决得差很少了!

  可是,前端有个点,就是这分支的触发问题,其实咱们能够更动态方式实现!

场景二: 我须要支持多个仓库进行切换打包,固然这里的仓库将必然影响到上面分支列表的选择!

  可使用 Active Choice 这个插件,可让咱们在须要的时候触发一次分支的选择,好比支持 分支快速过滤!达到数据联动的效果;

  而后,也可使分支依赖于动态的仓库进行变动分支列表等等!总之, Active Choice 插件真是很方便发挥!

 

  最终的效果就是,咱们能够选择,多仓库,动态列表多分支,进行打包!

      总之,经过这个联动支持,以及简单groovy知识,你能够有很大的发挥空间;

 

场景三: 我须要将打好的包部署到指定服务器上?

      这是个关键的问题,就是咱们打包来的包,应该处理的问题!

      这里有两个核心问题: 1. 我如何找到打包后的东西? 2. 如何将找到的东西部署到线上?

  若是不能很好的处理这些包,咱们将很无奈!因此  shell 就出场了!

  jenkins 支持在打包后进行一些自定义的操做! 好比 上传包到另外的服务器,或者部署到另外的地方等等!总之,就是任你发挥!

      通常地说,查找打包后的东西,要依赖于你的代码实现,因此具体问题具体分析;固然了,你能够经过mvn等命令直接订制打包的各类配置,从而活动查找的麻烦;

      另外,对于部署到服务器,至少有两个解决方案:1. 直接经过scp等服务器拷贝技术,将包放到目标服务器便可; 2. 将包打包成可执行的安装包,上传yum源服务器,在使用端直接拉取镜像便可;

  好比以下的脚本 ,咱们能够将它部署到咱们指定服务器的 docker 容器中!

  参考脚本以下:

echo "hello, build over ??? would you scp or deploy apps ??? work dir: $WORKSPACE , repository: $spec_repository;"
# specify dev environment or product environment
deploy_env_server="root@172.10.11.16"
deploy_path_prefix="/opt/docker/webapps/test"
docker_app_startup_script="/etc/init.d/startup restart";
case "$spec_repository" in
    richCash)
        docker_container_name="test_container";
        docker_app_startup_script="/etc/init.d/startup restart";
        deploy_path_prefix="/opt/docker/webapps/";
        deploy_sub_path="$deploy_environment"
        case "$deploy_environment" in
            "test-p8081")
                docker_container_name="test_p8081_container"
                ;;
                docker_container_name="test_p8083_container"
                ;;
            *)
                # default container
                ;;
        esac
        deploy_path_prefix="/opt/docker/webapps/$deploy_sub_path";
        ;;
    test2-01)
        deploy_path_prefix="/opt/docker/webapps/test2-01";
        docker_container_name="test2_01_container";
        docker_app_startup_script="/etc/init.d/startup restart";
        ;;
    *)
        echo "not find special configures in $spec_repository, do the default thing";
    ;;
esac
# deploy script
deploy_script_path="ssh $deploy_env_server \"docker exec $docker_container_name bash -c '$docker_app_startup_script'\"";

pom_file="$WORKSPACE/pom.xml";
pom_file_tmp="$pom_file\.tmp";
cd $WORKSPACE;
cat $pom_file | awk '{if($0 ~ /<parent>/){parent_begin++; print "no dump parent"} else if(parent_begin > 0){ if($0 ~ /<\/parent>/){parent_begin = 0; print "match the parent end.";} else {print "hit parent dump"; }} else { print $0;}}' > $pom_file_tmp
package_artifactId=`grep "<artifactId>" $pom_file_tmp | head -n 1 | sed -e 's/\(\s*<artifactId>\|<\/artifactId>\s*\)//g'`;
package_version=`grep "<version>" $pom_file_tmp | head -n 1 | sed -e 's/\(\s*<version>\|<\/version>\s*\)//g'`;
package_full_name="$package_artifactId-$package_version.jar"    # 定义为jar包写死
package_full_path="$WORKSPACE/target/$package_full_name";
echo "packaged file is: $package_full_name";
scp $package_full_path $deploy_env_server:"$deploy_path_prefix/$package_full_name";
# restart the server...
eval $deploy_script_path;

  如上,是对 jar 包的部署方式,咱们再来看下 h5 包的部署方式:

echo "hello, build over ??? work dir: $WORKSPACE , repository: $spec_repository; branch: $branch ;"
# specify dev environment or product environment
deploy_env_server="root@172.11.1.12"
docker_container_name="web_container";
deploy_path_prefix="/opt/docker/webapps/";
deploy_sub_path="$deploy_environment"
deploy_path_prefix="$deploy_path_prefix""$deploy_sub_path"
deploy_package_bak_path="/opt/docker/webapps/bak/"
docker_app_startup_script="ls "
case "$deploy_environment" in
    "web-p81")
        docker_container_name="web_81_container"
    ;;
    *)
        # default container
    ;;
esac
datetime=`date '+%Y%m%d%H%M'`;
package_full_name="$spec_repository-$branch-$datetime.tar.gz"
package_full_origin_path_prefix="/var/lib/jenkins/tmppackages/h5"
package_full_origin_path="$package_full_origin_path_prefix/$package_full_name";
deploy_package_bak_path="$deploy_package_bak_path""$package_full_name"
# deploy script
deploy_script_path="ssh $deploy_env_server \"rm -rf $deploy_path_prefix/*; if [ ! -d $deploy_path_prefix ]; then mkdir -p $deploy_path_prefix; fi; tar -xzf $deploy_package_bak_path -C $deploy_path_prefix\"";

package_dist_origin_path="$WORKSPACE/dist";
cd $package_dist_origin_path;
tar -czf $package_full_origin_path -C $package_dist_origin_path .;
echo "packaged file is: $package_full_origin_path";
scp $package_full_origin_path $deploy_env_server:"$deploy_package_bak_path";
# restart the server...
eval $deploy_script_path;

  如上,h5 的打包方式,区别在于须要手动打包一为 gz 包,而后到目标机器进行解压缩便是安装!

  
  如上,就能够进行一键部署测试环境了!
  剩下的,就是本身自由发挥了!
  同理于 h5 的部署方式!

4、重难点提示

       其实,准确来讲,上面的操做都比较常规,由于都是最终的结果步骤展现!可是其实这其中有不少的坑,指望提示对你有帮助!

       1. 使用groovy 进行分支获取时, 须要对 git 命令进行免密受权操做,不然将永远拉不到分支;

       2. 使用scp, scp 这些命令调用远程,须要免密登陆,不然受权失败;

       3. 使用 ssh xx@1.2.2.4 "ls ." 运行远程命令如同本地命令;

       4. 真正的部署脚本能够远程服务器上,也能够写在部署机器上;

       5. 出于安全考虑,默认状况下运行jenkins的用户都不是root,因此通常不要觉得在terminal操做正常的命令,在jenkins上也能正常;

 5、jenkins带来的切实好处

       为何必定要用jenkins?难道就由于其名声大燥吗?实际上是是由于它真的能带来这些好处:

       1. 部署速度指数级提高,之前按照我的的操做速度,要10分钟左右的操做且要记忆多种复杂关联命令,如今可能只要2分钟一键搞定,爽不爽?

       2. 部署信息有迹可查,若是按照以前的部署,谁部署出了问题,彻底不知道,可是jenkins上有操做记录,更易发现问题;

       3. 解决了系统兼容性问题引起的不适,以前各自部署来源不一致,可能致使各类难查问题,而用jenkins则保证彻底一致;

       4. 拒毫不可靠错误代码的上线,借助于jenkins的单元测试功能,能够发如今一些简单代码的问题,避免以前的误操做上线;

       5. 由于收口部署方式,对于后续新的部署方案,有了更加有利的支持,好比想加入sonar代码扫描,只需修改下部署部署脚本便可;

 

一句话总结:有时知道问题比解决问题更重要!

相关文章
相关标签/搜索