技术

简易CI-CD (2)

背景

前文我们设置了jenkins 的pipeline,并且接受调用方传过来的参数,现在我们实现具体的CD操作,也就是把产物传到目标机器,并且停止老应用,启动新应用。 一般而言CD会包含以下的步骤

  • 登录目标机器
  • 备份原有文件
  • 下载目标文件
  • 停止原有进程
  • 启动新的进程

而具体每一步,根据公司自己的要求,又会有所不同,例如有些公司会做一些健康检查,检查目标应用有没有成功启动。或者是在停止应用之前,做一些优雅上下线的操作。 由于我们公司使用的是阿里云的oss来存储产物的,所以就会涉及到含有AK的配置文件的发送,为了安全起见,配置文件是不能留在机器上面的,所以会有配置文件的复制以及删除。 启动命令根据各公司要求而异吧

由于打包的动作不频繁,所以打包跟分发的pipeline进行了区分

分发


def TARGET_HOST = params.TARGET_HOST
def WORKER_URL = params.WORKER_URL
def WORK_SPACE = "/tmp/workspace/pangu-agent/"+currentBuild.number
node{
    stage("创建文件夹"){
         sh "mkdir -p "+ WORK_SPACE
    }
    ws(WORK_SPACE){

        stage("生成临时host文件"){         //因为后面ansible执行的时候,需要传入host,并且需要host是已知的。因此需要临时生成一个inventory文件,并且调用ansible的时候传入
            tmpHost = ""
            tmpHost += "[tmp]\n"
            String[] hosts = TARGET_HOST.split(",")
            for(String host:hosts){
                tmpHost += host
                tmpHost += "\n"
            }
            writeFile file:WORK_SPACE+'/tmpInventory',text:tmpHost
        }


        stage("安装探针"){
        ansiblePlaybook colorized: true, installation: "Ansible", playbook: "/sharedata/pangu-agent.yml",
                dynamicInventory:true,
                inventory:WORK_SPACE+'/tmpInventory',
                extraVars: [
				hosts: TARGET_HOST,
                worker_url: WORKER_URL,
                oss_config: "/opt/platform/myConfig",
                source_url: "oss://ggj-private/pangu-agent/pangu-agent.jar",
                dest_path: "pangu-agent.jar"
                ]
    }
    }
    
}

ansible的执行playbook

---
- hosts: "{{hosts}}"        //目标机器信息
  remote_user: "root"       //ansible执行任务时候的角色
  gather_facts: False       //不收集fact信息
  vars:                     //一些下面会用到的参数,因人而异
    worker_url: "{{worker_url}}"
    oss_config: "{{oss_config}}"
    source_url: "{{source_url}}"
    dest_path: "{{dest_path}}"
    jvm_params: " -Xss256K -Xmx100M -XX:MaxRAM=128M -Xint -XX:ParallelGCThreads=1 -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+StartAttachListener "
  tasks:
    - name: copy oss config             //从jenkins机器上面复制oss配置文件过去
      copy: src={{ oss_config }} dest=/tmp/oss_config owner=root group=root mode=0644              //设置文件的属性

    - name: check agent_exist
      stat: 'path=/opt/platform/pangu-agent.jar'
      register: exist_result            //检查机器上面是否已经有老的产物存在,如果存在,下面就会进行备份

    - name: back previous version
      copy:
        src: /opt/platform/pangu-agent.jar
        dest: /opt/platform/pangu-agent.bak.jar
        follow: yes                     //该选项为覆盖的意思
        remote_src: yes                 //设置操作为远程的地址,如果不设置,则会任务从jenkins的机器复制文件到目标机器
      when: exist_result.stat.exists    //只有老的产物存在的时候,才会执行

    - name: oss get file
      shell: /opt/platform/ossutil64 --config-file /tmp/oss_config cp -f {{source_url}}  /tmp/{{dest_path}}      //oss下载文件,本地如果存在,强行覆盖


    - name: copy agent file             //将产物移动到目标位置
      copy:
        src: /tmp/{{dest_path}}
        dest: /opt/platform/pangu-agent.jar
        follow: yes
        remote_src: yes

    - name: remove oss config           //删除配置文件
      file: path=/tmp/oss_config state=absent     //ansible的file模块,absent表示删除文件

    - name: get previous thread
      shell: source /etc/profile; jps -l|grep pangu-agent|awk '{print $1}'
      register: pid           //查找当前存在的进程,如果存在,后面再进行kill操作,这里需要由source /etc/profile来让环境变量生效,不然的话会导致jps等命令找不到,因为这些属于后续设置的环境变量

    - debug: var=pid.stdout_lines[0]    //打印一下,看看当前有没有存在进行

    - name: kill previous thread
      shell: kill -9 {{pid.stdout_lines[0]}}
      when: pid.stdout_lines|length !=0     //如果pid.stdout_lines的length为0,说明没有进程,反之则说明有进程存在
 
    - name: start agent
      shell: source /etc/profile; nohup java -jar {{jvm_params}} -Dregister.target-url={{worker_url}} /opt/platform/pangu-agent.jar > /logs/agent.log 2>&1 &