benmo | 发布于 2019-05-30 16:18:50 | 阅读量 1669 | ? Ansible ? ? Jenkins ?
发布于 2019-05-30 16:18:50 | ? Ansible ? ? Jenkins ?

Author: 本末丶

 

    上一篇中,我们描述了如何借助Ansible来持续发布spring boot/cloud项目,也演示了如何基于jenkins做代码回滚,后面想想还是有不少臃肿和不好管理的地方,又做了一些优化跟备份回滚策略的调整,在这篇文章中,我们可以看到做了优化的一些地方,以及回滚策略的调整,不过本篇将以Tomcat为容器的项目作为演示

 发布流程预览:

 

规范与标准

    下面是规划的一些标准(非强制,根据自己实际情况调整)

  • 应用名称{应用类型}-{端口}-{应用名称} or {类型}-{应用名称}, 例如:web-8080-nc,web-8082-wechat(至于为什么要加端口信息,是因为一台机器可能有N个实例,为了避免端口冲突,将端口描述代入了应用名中)
  • 日志路径/log/web,例如:/log/web/web-8080-gateway
  • 代码路径/data/,例如:/data/web-8080-gateway
  • Tomcat安装路径/usr/local/tomcat
  • 实例路径/usr/local/tomcat/{应用名称}
  • Jenkins job命名: {环境}_{项目分组}_{应用名称},如:TEST_GROUP1_web-8080-nc
  • 应用配置:存放于git中,建立了各个环境相应的目录,环境目录下对应应用名称的同名文件,如:
    git@192.168.1.24:devops-conf/conf.git
    |
    |__UAT
    |      |__web-8080-nc
    |      |__web-8081-wechat
    |
    |__STG
    |      |__web-8080-nc
    |      |__web-8081-wechat
    ... ...

 

部署环境 

1.版本环境

  • Ansible版本:2.6+

  • Tomcat: 7+
  • Jenkins:2.107.1
  • Linux: Cent0S 6+

 

2. Jenkins安装插件


发布任务配置

1. Jenkins Job配置

SVN拉取配置,没啥好说的

 

maven构建配置

Ansible插件配置

 

2. Ansible Role配置

1)代码结构

playbooks
└──test-tomcat-deploy.yml                        # 入口文件
roles
└──tomcat-deploy-test
        ├── defaults
        │   └── main.yml                         # 默认变量
        ├── files
        │   ├── conf                             # 实例配置文件
        │   │   ├── catalina.policy
        │   │   ├── catalina.properties
        │   │   ├── context.xml
        │   │   ├── logging.properties
        │   │   ├── tomcat-users.xml
        │   │   ├── tomcat-users.xsd
        │   │   └── web.xml
        │   └── tomcat.tar.gz                    # tomcat安装文件(没做任何调整,就是改名成tomcat后压缩了一下)
        ├── handlers
        │   └── main.yml                         # handlers任务
        ├── tasks
        │   ├── backup.yml                       # 备份任务
        │   ├── commons.yml                      # 一般任务
        │   ├── deploy.yml                       # 部署任务
        │   ├── init.yml                         # 初始化任务
        │   └── main.yml                         # 主文件
        └── templates
            ├── catalina.sh.j2                   # 启动脚本
            ├── env.j2                           # 对于实例的描述文件,非必要
            ├── server.xml.j2                    # 实例的server.xml配置
            └── systemd.service.j2               # systemd服务脚本


2)Role配置文件说明

  ①.playbooks/test-tomcat-deploy.yml

---
- hosts: target

  roles:
   - { role: tomcat-deploy-test, tags: deploy }

 

    ②.defaults/main.yml

---
# base info
# JOB_NAME等信息直接从环境变量读取,而不是之前那样通过exra vars导入,少了很多不必要的参数填写
JOB_NAME: "{{ lookup('env','JOB_NAME') }}"
TOMCAT_HOME: "/usr/share/tomcat"
# 将JOB_NAME切割出各个信息
PROJECT: "{{ JOB_NAME.split('_')[-1] }}"
CODE_DEPTH_PATH: "{{ code_depth_path | default('') }}"
PROJECT_BASE: "/data/{{ PROJECT }}"
ENV: "{{ JOB_NAME.split('_')[0] }}"

# project info
project:
  public:
    JAVA_HOME: "{{ java_home | default('') }}"
    GIT_CONF_REPO: "git@192.168.1.24:devops/conf.git"
    JAVA_OPTS: "{{ lookup('env','JAVA_OPTS') | default('-server -Xms2048M -Xmx2048M') }}"

  local:
    # 备份信息日志路径
    deploy_release_log: "/data/deploy_release_log/{{ ENV }}/{{ PROJECT }}"
    # 构建后的代码路径
    CODE_PATH: "{{ local_code_path | default('') }}"

  target:
    # 实例相关配置
    CATALINA_HOME: "{{ TOMCAT_HOME }}"
    CATALINA_BASE: "/usr/local/tomcat/{{ PROJECT }}"
    CATALINA_LOGBASE: "/usr/local/tomcat/{{ PROJECT }}/logs"
    #tomcat虚拟路径,默认为空
    TOMCAT_VIRTUAL_PATH: "{{ lookup('env','tomcat_virtual_path') }}"
    CODE_PATH: "{{ PROJECT_BASE }}/{{ CODE_DEPTH_PATH }}"
    TOMCAT_USER: "{{ tomcat_user | default('tomcat') }}"
    TOMCAT_PORT: "{{ PROJECT.split('-')[1] }}"
    # 备份目录
    HISTORY_ARCHIVR_DIR: "/data/deploy_release_library/{{ PROJECT }}"
    # 应用日志(不是必须的)
    LOGPATH: "/log/{{ PROJECT.split('-')[0] }}/{{ PROJECT }}"

 

    ③files/conf(直接从tomcat二进制包里的conf原样复制过来即可)

 

    ④tasks/main.yml

---
# 打印变量信息
- name: show project info
  debug: var=project
  failed_when: (project is not defined)

# 初始化实例
- include_tasks: "init.yml"

# 一般任务
- include_tasks: "commons.yml"

# 备份任务,存在代码才备份
- include_tasks: "backup.yml"
  when: (code_status.rc == 0)

# 发布任务
- include_tasks: "deploy.yml"

 

    ⑤ tasks/init.yml

---
# 创建运行账户
- name: Create {{ project.target.TOMCAT_USER }} user
  user: name={{ project.target.TOMCAT_USER }}

# 检查tomcat是否安装
- name: Verify that tomcat installed
  command: "{{ TOMCAT_HOME }}/bin/catalina.sh version"
  environment:
    JAVA_HOME: "{{ project.public.JAVA_HOME }}"
  register: check_install
  failed_when: false

# 没装就直接解压过去
- name: Install tomcat
  unarchive:
    src: tomcat.tar.gz
    dest: /usr/share
    owner: "{{ project.target.TOMCAT_USER }}"
    group: "{{ project.target.TOMCAT_USER }}"
  when: check_install.rc != 0

# 创建实例目录接口(file循环我嫌慢,shell来的快)
- name: Create {{ PROJECT }} directory
  shell: |
    mkdir -p {{ project.target.CATALINA_BASE }}/{conf,work,bin,webapps,temp,logs,lib} {{ project.target.LOGPATH }} {{ project.target.CODE_PATH }} &>/dev/null
    chown {{ project.target.TOMCAT_USER }}. -R {{ project.target.CATALINA_BASE }} {{ project.target.LOGPATH }} {{ project.target.CODE_PATH }}

# 推送实例模板文件
- name: Push {{ PROJECT }} templates
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
    mode: "{{ item.mode }}"
    owner: "{{ project.target.TOMCAT_USER }}"
    group: "{{ project.target.TOMCAT_USER }}"
  loop:
  - { src: server.xml.j2, dest: "{{ project.target.CATALINA_BASE }}/conf/server.xml", mode: 644 }
  - { src: catalina.sh.j2, dest: "{{ project.target.CATALINA_BASE }}/bin/catalina.sh", mode: 'u=rwx,g=rx,o=r' }
  - { src: env.j2, dest: "{{ project.target.CATALINA_BASE }}/env", mode: 644 }

# 推送实例一般配置文件
- name: Push Tomcat config
  synchronize:
    src: conf/
    dest: "{{ project.target.CATALINA_BASE }}/conf"

# CentOS7使用systemd管理服务
- name: Copy Systemd script
  template:
    src: systemd.service.j2
    dest: /etc/systemd/system/{{ PROJECT }}.service
    mode: 0644
  when: ansible_distribution_major_version|int >= 7

# CentOS6使用SysV脚本
- block:
  - name: Link to Sysvinit
    file:
      src: "{{ project.target.CATALINA_BASE }}/bin/catalina.sh"
      dest: "/etc/init.d/{{ PROJECT }}"
      state: link
      force: yes

  - name: Add to chkconfig
    shell: chkconfig --add {{ PROJECT }}
  when: ansible_distribution_major_version|int < 7

 

    ⑥tasks/commons.yml

---
# 设置变量,time相关的不要放入defaults里,因为include是动态取的,会有变化
- set_fact:
    deploy_time: "{{ lookup('pipe','date +%Y%m%d%H') }}"
    # 这里使用lookup获取本地时间,而不是strftime去取,因为客户端时间可能不一致
    git_conf_tmp_path: "/tmp/.config/{{ lookup('pipe', 'date +%s') }}"

# 拉取git里存放的配置到临时目录
- name: Git conf
  git:
    repo: "{{ project.public.GIT_CONF_REPO }}"
    dest: "{{ git_conf_tmp_path }}"
    ssh_opts: '-o StrictHostKeyChecking=no'
  delegate_to: localhost
  run_once: true
  
# 检查应用代码是否为空  
- name: Verify remote code exists
  shell: ls {{ project.target.CODE_PATH }}/* &> /dev/null
  register: code_status
  failed_when: false

 

    ⑦tasks/backup.yml

---
# 创建备份目录
- name: Create Histroy Archive Directory
  file:
    dest: "{{ project.target.HISTORY_ARCHIVR_DIR }}/{{ deploy_time }}"
    state: directory
    owner: "{{ project.target.TOMCAT_USER }}"
    group: "{{ project.target.TOMCAT_USER }}"
    recurse: yes

# 压缩文件到备份目录下
- block:
  - name: Compress and backup files
    archive:
      path:
       - "{{ PROJECT_BASE }}/*"
      dest: "{{ HISTORY_ARCHIVR_DIR }}/{{ deploy_time }}/{{ PROJECT }}.zip"
      exclude_path:
      - "{{ PROJECT_BASE }}/log"
      - "{{ PROJECT_BASE }}/logs"
      format: zip
      owner: "{{ RUN_USER }}"
      group: "{{ RUN_USER }}"

  - name: Write Deploy release log
    blockinfile:
      path: "{{ project.local.deploy_release_log }}/{{ deploy_time }}"
      block: |-
        {{ release_log | to_nice_json(indent=2) }}
      create: yes
    delegate_to: localhost
    run_once: true
    vars:
      release_log:
        target: "{{ ansible_play_hosts | join(':') }}"
        project: "{{ PROJECT }}"
        run_user: "{{ RUN_USER }}"
        backup_dir: "{{ HISTORY_ARCHIVR_DIR }}/{{ deploy_time }}"
        backup_file: "{{ HISTORY_ARCHIVR_DIR }}/{{ deploy_time }}/{{ PROJECT }}.zip"
        project_dir: "{{ PROJECT_BASE }}"
        backup_time: "{{ deploy_time }}"
        env: "{{ ENV }}"

  # 备份该时间段的第一次,一小时内的不重复备份,防止破坏备份文件稳定性
  when: not lookup('pipe','ls ' + project.local.deploy_release_log + '/' + deploy_time + ' &> /dev/null', errors='ignore')

 

    ⑧tasks/deploy.yml

---
# 同步构建后的代码
- name: "Sync {{ project.local.CODE_PATH }} >> {{ project.target.CODE_PATH }}"
  synchronize:
    src: "{{ project.local.CODE_PATH }}/"
    dest: "{{ project.target.CODE_PATH }}"
    delete: yes

# 同步git拉取到临时目录的配置文件,同事触发handler,不同系统触发不同的hander任务重启
- name: "Sync {{ git_conf_tmp_path }}/{{ ENV }}/{{ PROJECT }}/ >> {{ PROJECT_BASE }}"
  synchronize:
    src: "{{ git_conf_tmp_path }}/{{ ENV }}/{{ PROJECT }}/"
    dest: "{{ PROJECT_BASE }}"
  notify:
  - "{{ ansible_distribution_major_version }} Restart Tomcat"

# 设置属主
- name: Set owner >> "{{ project.target.TOMCAT_USER }}"
  file:
    path: "{{ PROJECT_BASE }}"
    recurse: yes
    state: directory
    owner: "{{ project.target.TOMCAT_USER }}"
    group: "{{ project.target.TOMCAT_USER }}"

# 删除临时文件
- name: Remove local config
  file:
    path: "{{ git_conf_tmp_path }}"
    state: absent
  delegate_to: localhost
  run_once: true

 

    ⑨handlers/main.yml

---
- name: 7 Restart Tomcat
  systemd: name={{ PROJECT }} state=restarted enabled=yes daemon_reload=yes

# 因为我们是root过去的,6指定下become到运行账户启动
- name: 6 Restart Tomcat
  service: name={{ PROJECT }} pattern=/etc/init.d/{{ PROJECT }} state=restarted sleep=5 enabled=yes
  become_user: "{{ project.target.TOMCAT_USER }}"
  become: yes

 

    ⑩templates/server.xml.j2

<?xml version='1.0' encoding='utf-8'?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!-- Note:  A "Server" is not itself a "Container", so you may not
     define subcomponents such as "Valves" at this level.
     Documentation at /docs/config/server.html
 -->
<Server port="{{ project.target.TOMCAT_PORT|int + 1000 }}" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="off" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <!-- Global JNDI resources
       Documentation at /docs/jndi-resources-howto.html
  -->
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <!-- A "Service" is a collection of one or more "Connectors" that share
       a single "Container" Note:  A "Service" is not itself a "Container",
       so you may not define subcomponents such as "Valves" at this level.
       Documentation at /docs/config/service.html
   -->
  <Service name="Catalina">

    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <!--
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>
    -->


    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
    -->
    <Connector port="{{ project.target.TOMCAT_PORT }}"
	       protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="3000" minSpareThreads="500" 
               acceptCount="1000" maxKeepAliveRequests="1" 
               connectionTimeout="20000" enableLookups="false" 
               URIEncoding="UTF-8" redirectPort="8443" />

    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    -->
    <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443
         This connector uses the NIO implementation that requires the JSSE
         style configuration. When using the APR/native implementation, the
         OpenSSL style configuration is required as described in the APR/native
         documentation -->
    <!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />
    -->

    <!-- Define an AJP 1.3 Connector on port 8009
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->


    <!-- An Engine represents the entry point (within Catalina) that processes
         every request.  The Engine implementation for Tomcat stand alone
         analyzes the HTTP headers included with the request, and passes them
         on to the appropriate Host (virtual host).
         Documentation at /docs/config/engine.html -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie :
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
    -->
    <Engine name="Catalina" defaultHost="localhost">

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->

      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase="{{ PROJECT_BASE }}"
            unpackWARs="true" autoDeploy="true">

        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->

        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t "%r" %s %b" />
               
{#-
这是是虚拟路径的配置,只有指定了tomcat_virtual_path才生效,
默认TOMCAT_VIRTUAL_PATH为空,tomcat_vittual_path做为jenkins参数化构建传递,
格式为: /path:/docBase,比如,
项目名称为web-8080-static,代码路径为/data/web-8080-nc/static,那么格式如下:
/static:/static
多个路径格式为:
/static:/static,/nc:/nc
-#}
{% if project.target.TOMCAT_VIRTUAL_PATH != "" %}
  {% for vpath in project.target.TOMCAT_VIRTUAL_PATH.split(',') %}
       <Context path="{{ vpath.split(':')[0] }}" docBase="{{ PROJECT_BASE }}{{ vpath.split(':')[1] }}" reloadable="true"  crossContext="true"></Context>
  {% endfor %}
{% endif %}

	<!--<Context path="" docBase="{{ PROJECT_BASE }}" reloadable="true"  crossContext="true"></Context>-->

      </Host>
    </Engine>
  </Service>
</Server>

 

    ⑫templates/catalina.sh.j2

#!/bin/bash
# Provides:          {{ PROJECT }}
# chkconfig:         - 55 25
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start Tomcat.
# Description:       Start the Tomcat servlet engine.
# Author:            本末丶
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

program="{{ PROJECT }}"
export TOMCAT_USER="{{ project.target.TOMCAT_USER }}"
export CATALINA_PID="{{ project.target.CATALINA_BASE }}/bin/$program.pid"
export TOMCAT_HOME={{ TOMCAT_HOME }}
export CATALINA_HOME=$TOMCAT_HOME
export CATALINA_BASE={{ project.target.CATALINA_BASE }}
export CATALINA_LOGBASE={{ project.target.CATALINA_LOGBASE }}

export JAVA_OPTS="{{ project.public.JAVA_OPTS }} -Dcatalina.logbase=$CATALINA_LOGBASE -Djava.security.egd=file:/dev/./urandom"

{% if project.public.JAVA_HOME != '' %}
export JAVA_HOME={{ project.public.JAVA_HOME }}
{% else %}
source /etc/profile
{% endif %}
# Set Tomcat environment.
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$CATALINA_HOME
export CATALINA_OUT=$CATALINA_LOGBASE/catalina.out
export PATH=$PATH:$JAVA_HOME/bin:/usr/bin:/usr/lib/bin

# locale环境,防止中文写日志乱码问题
export LANG=en_US.UTF-8
export LC_CTYPE="en_US.UTF-8"
export LC_NUMERIC="en_US.UTF-8"
export LC_TIME="en_US.UTF-8"
export LC_COLLATE="en_US.UTF-8"
export LC_MONETARY="en_US.UTF-8"
export LC_MESSAGES="en_US.UTF-8"
export LC_PAPER="en_US.UTF-8"
export LC_NAME="en_US.UTF-8"
export LC_ADDRESS="en_US.UTF-8"
export LC_TELEPHONE="en_US.UTF-8"
export LC_MEASUREMENT="en_US.UTF-8"
export LC_IDENTIFICATION="en_US.UTF-8"
export LC_ALL=

# cache
cache_dir="${CATALINA_BASE}/work"

# check --no-daemonize option
args=$2

# sctipt
catalinaScript="${TOMCAT_HOME}/bin/catalina.sh"

get_pid() {
     ps -eo pid,cmd | grep java | grep "${CATALINA_BASE}" | grep -Pv "grep|python" | awk '{print $1}'
}

run_program() {
    if [[ "${args}"x == "--no-daemonize"x ]];then
        ${catalinaScript} start 2>&1 | tee -a $CATALINA_OUT
        tailf $CATALINA_OUT
    else
        nohup ${catalinaScript} start &>> $CATALINA_OUT
        return $?
    fi
}

run_or_not() {
    pid=$(get_pid)
    if [[ ! ${pid} ]];then
        return 1
    else
	return 0
    fi
}

start() {
    run_or_not
    if [[ $? -eq 0 ]];then
        pid=$(get_pid)
        success;echo -e "[\e[0;32m${pid}\e[0m] Tomcat ${program} is running..."
    else
        echo -n 'Start Tomcat.'
        run_program
        if [[ $? -eq 0 ]];then
            sleep 5
            pid=$(get_pid)
            if [[ "$pid"x != x ]];then
                flag=success
            else
                flag=failure
                $flag;echo -e "Success Start Tomcat ${program}, but it exists.!"
                return 1
            fi
        else
            flag=failure
        fi
        $flag;echo -e "[\e[0;32m$pid\e[0m] Start Tomcat ${program}"
    fi
}

stop() {
    run_or_not
    if [[ $? -eq 0 ]];then
        ${catalinaScript} stop |& tee -a $CATALINA_OUT
        sleep 5
        run_or_not
        if [[ $? -eq 0 ]];then
            pid=$(get_pid)
	    kill -9 $pid
            echo -e "Stop Failed...Killing Process [\e[0;32m$pid\e[0m]..."
        fi
	success;echo -e "Stop Tomcat $program"
    else
        failure;echo -e "Tomcat $program is not running."
    fi
}

status() {
    run_or_not
    if [[ $? -eq 0 ]];then
	    pid=$(get_pid)
	    success;echo -e "[\e[0;32m${pid}\e[0m] Tomcat $program is running..."
	    return 0
    else
	    failure;echo -e "Tomcat $program not running."
	    return 1
    fi
}

case $1 in
    start)
	    start
	    ;;
    stop)
	    stop
	    ;;
    status)
	    status
	    ;;
    restart)
	    stop
	    start
	    ;;
    *)
        echo "Usage: $0 {start [--no-daemonize]|stop|status|restart}"
        return 1
esac

 

    ⑬templates/systemd.service.j2

[Unit]
Description={{ PROJECT }}
After=network.target

[Service]
ExecStart={{ project.target.CATALINA_BASE }}/bin/catalina.sh start --no-daemonize
ExecStop={{ project.target.CATALINA_BASE }}/bin/catalina.sh stop
#WorkingDirectory={{ project.target.CATALINA_BASE }}
#Restart=on-failure
#RestartSec=30
User={{ project.target.TOMCAT_USER }}
Group={{ project.target.TOMCAT_USER }}

[Install]
WantedBy=multi-user.target

 

    ⑮templates/env.j2(描述信息而已)

project_name="{{ PROJECT }}"
tomcat_port="{{ project.target.TOMCAT_PORT }}"
control_port="{{ project.target.TOMCAT_PORT|int + 1000 }}"
project_base="{{ PROJECT_BASE }}"
log_base="{{ project.target.CATALINA_LOGBASE }}"
last_update="{{ '%Y-%m-%d %H:%M' | strftime }}"

 

3) 发布演示。

大部分的工作都OK了,由于我们没有沿用之前jenins中账号密码的方式去验证,所以我们需要先做ssh key的信任,这里提供一个playbooks

ssh_keys.yml

---
- hosts: "{{ target }}"
  gather_facts: false

  tasks:

  - name: Create user if not exists
    user: name={{ luser }} shell=/bin/bash generate_ssh_key=yes
    register: local
    delegate_to: localhost

  - name: Ensure remote user exists
    user: name={{ ruser }} shell=/bin/bash

  - name: Write key to authorized_keys
    authorized_key:
      user: "{{ ruser }}"
      state: present
      key: "{{ local.ssh_public_key }}"
      manage_dir: yes

运行方式:

ansible-playbook ssh_keys.yml -e 'target=你远程的服务器 luser=jenkins ruser=root' -u root -k
# 其中target是你远程服务器的地址,luser是你jenkins运行账户,ruser是远程账户

 

发布预览(动图,PDF不会动,要动的自己看blog):

 

查看服务:

 

查看备份日志;

 

查看备份文件:


OK.发布相关的任务到此结束,后面会说说怎么做回滚。

 

未完待续...


内容更新于: 2019-07-23 15:10:21
链接地址: http://blog.leanote.com/post/benmo/Tomcat%E5%9F%BA%E4%BA%8EJenkins-Ansible%E7%9A%84%E8%87%AA%E5%8A%A8%E5%8F%91%E5%B8%83%E3%80%81%E5%9B%9E%E6%BB%9A

上一篇: Tomcat基于Jenkins+Ansible的自动发布(2)

下一篇: Nginx -- 模拟接口返回

1669 人读过
立即登录, 发表评论.
没有帐号? 立即注册
0 条评论
文档导航