• PHP 基于 Jenkins ansible 动态选择版本进行自动化部署与回滚(第二版)


    PHP 基于 Jenkins ansible 动态选择版本进行自动化部署与回滚(第二版)

    先看流程图:

    流程图

    大概介绍一下:

    • 版本选择使用jenkins 中的 git parameter 插件实现
    • 回滚方式比较low,直接使用代码库目录方式实现

    其中gitlab、ansible、jenkins安装不在本文讨论范围之内。

    效果

    先看下效果图:
    jpg

    jenkins 发布配置

    PHP 代码不需要 Ant 或者 meaven 编译,所以可以直接使用。

    新建一个项目,比较重要的是:选择参数化构建

    1. 选择git parameter,需要给参数定义个变量名称。部署发布作用区
    2. 选择dynamic chocie parameter , 选择回滚版本号,默认 none 的话就是部署发布

    下图为配置详情:

    jpg1

    dynamic 参数配置代码:

    def ver_keys = ['bash', '-c','cd /home/www/Repositories/HaifaxOnline/rollback  ;  echo none; ls | sort -rn ' ]
    ver_keys.execute().text.tokenize('
    ')
    

    git 库配置

    然后选择git仓库的配置,网上很多。

    回滚和发布配置

    然后在构建时选择插件:excute shell,执行shell 命令:

    jp

    具体代码在这:

    echo $branch_and_tags
    echo "build_id:"$BUILD_NUMBER
    echo "项目名称:" $JOB_NAME
    echo "work_sapce" $JENKINS_HOME
    echo "choice:" $choice
    id
    
    echo "==============================="
    if [ $choice = "none" ];then
       echo "choice:部署"
       
       python3 /home/www/deploy.py -build_id=$BUILD_NUMBER -jenkins_home=$JENKINS_HOME -job_name=$JOB_NAME -repo_path=/home/www/Repositories
    
       sudo ansible-playbook /etc/ansible/$JOB_NAME.yml -e "job_name=$JOB_NAME code_src=/home/www/Repositories/$JOB_NAME/code/ code_dest=/alidata/www/"
       
    else
       echo "choice:回滚"
       HIS_ID=$choice
       echo "回滚版本:$HIS_ID"
       sudo ansible-playbook /etc/ansible/$JOB_NAME.yml -e "job_name=$JOB_NAME code_src=/home/www/Repositories/$JOB_NAME/rollback/$HIS_ID/ code_dest=/alidata/www/"
    fi
    
    

    需要注意的是,如果ansible需要使用root用户执行时,需要对jenkins的帐号授权sodu权限处理。

    一些参数的解释:

    • code_dest: 线上服务器的代码目录位置,需要手动配置
    • code_src: jenkins本地服务器的代码存储位置,需手动配置
    • job_name: 这个参数为了好套用,所以设计成job_name的方式,传递给ansible,ansible的yml文件一定要使用job_name.yml命名,否则会报错

    代码库存储目录处理:

    deploy.py中代码如下,主要是对jenkins服务器中的本地代码库,进行目录处理:

    #!/usr/bin/env python
    # -*-coding=utf-8-*-
    # __author__ = 'ccorz'
    
    import argparse, os, shutil
    
    
    class Deploye:
        def __init__(self):
            parse = argparse.ArgumentParser()
            parse.add_argument('-job_name', type=str, required=True)
            parse.add_argument('-build_id', type=str)
            parse.add_argument('-repo_path', type=str)
            parse.add_argument('-jenkins_home', type=str)
            self.args = parse.parse_args()
            self.job_repo = '%s/%s' % (self.args.repo_path, self.args.job_name)
            self.job_git = '%s/workspace/%s/' % (self.args.jenkins_home, self.args.job_name)
            self.job_code = '%s/code' % self.job_repo
            self.job_rollback = '%s/rollback' % self.job_repo
    
        def path_handler(self):
            """判断代码库目录是否存在,不存在则创建"""
            # print(self.args.repo_path)
            if not os.path.exists(self.args.repo_path):
                os.mkdir(self.args.repo_path)
            if not os.path.exists(self.job_repo):
                os.makedirs(self.job_rollback,exist_ok=True)
            else:
                shutil.rmtree(self.job_code)
    
        def copy_code(self):
            shutil.copytree(self.job_git, self.job_code,symlinks=False,ignore=shutil.ignore_patterns('.git'))
            os.system('find %s -ctime +2 -exec rm -rf {} ;' % self.job_rollback)
            shutil.copytree(self.job_git, "%s/%s"%(self.job_rollback,self.args.build_id),
                            symlinks=False,ignore=shutil.ignore_patterns('.git'))
    
    if __name__ == '__main__':
        obj = Deploye()
        obj.path_handler()
        obj.copy_code()
    

    ansbile中的设置

    这一部分其实实现方式很多,为了方便套用,基本实现了参数化方式,先看下目录结构:

    chengchendeiMac:ansible shane$ tree
    .
    |____.DS_Store
    |____ansible.cfg
    |____google.yml
    |____XXXXXnline.yml
    |____hosts
    |____mysqlbak.yml
    |____roles
    | |____google
    | | |____tasks
    | | | |____main.yml
    | | |____templates
    | | | |____common.inc.php.j2
    | | | |____config.common.inc.php.j2
    | | |____vars
    | | | |____main.yml
    | |____XXXXXnline
    | | |____tasks
    | | | |____main.yml
    | | |____templates
    | | | |____common.inc.php.j2
    | | | |____config.common.inc.php.j2
    | | |____vars
    | | | |____main.yml
    | |____test_job
    | | |____tasks
    | | | |____main.yml
    | | |____templates
    | | | |____common.inc.php.j2
    | | | |____config.common.inc.php.j2
    | | |____vars
    | | | |____main.yml
    

    再看下ansible的入口yml文件:

    chengchendeiMac:ansible shane$ cat google.yml 
    ---
    
    - hosts: google
      user: root
      gather_facts: no
      roles:
        - "{{job_name}}"
    

    然后在看下角色配置:

    chengchendeiMac:ansible shane$ cat roles/google/tasks/main.yml   
    ---
    
    - name: sync "{{job_name}}" statics code
      synchronize:
        src: "{{code_src}}/statics/"
        dest: "{{code_dest}}/statics/"
        delete: yes
        rsync_opts: --exclude=upload
    
    - name: sync "{{job_name}}" web code
      synchronize:
        src: "{{code_src}}/web/"
        dest: "{{code_dest}}/p2p/"
        delete: yes
        rsync_opts: '--exclude=data/pay_cache/* --exclude=data/*'
    
    - name: "configure conf files: common.inc.php"
      template:
        src: common.inc.php.j2
        dest: "{{code_dest}}/xxx/common.inc.php"
    
    - name: "configure conf files: config.common.inc.php"
      template:
        src: config.common.inc.php.j2
        dest: "{{code_dest}}/xxx/config.common.inc.php"
    

    因为我这边的代码中有两个目录,做了动静分离,写了两个,这一块自由发挥吧。然后使用模板的方式,将固定的配置文件覆盖即可。

  • 相关阅读:
    【转】Java并发编程:深入剖析ThreadLocal
    【转】关于Java的Daemon线程的理解
    【转】详细分析Java中断机制
    【转】Java并发编程注意事项
    【转】Java并发编程:volatile关键字解析
    【转】Java并发编程:Lock
    【转】JVM运行原理及JVM中的Stack和Heap的实现过程
    【转】Linux常用命令大全
    Linux 命令学习
    js中的prototype和__proto__
  • 原文地址:https://www.cnblogs.com/ccorz/p/6699757.html
Copyright © 2020-2023  润新知