关于如何使用Ansible实现Windows环境下的Tomcat自动安装部署。
为了在部门内部推进这DEVOPS,笔者感觉现在自学的新增知识里,运维性的内容占比是越来越大了,最近被列入书单目录的居然多了两本关于Ansible知识系统的,而且还把搁置了好几年的Powershell和BAT语法全部又捡回来了(笔者上一次接触Powershell还是在这篇2017年的博客【效率】Windows之QuickStart-续)。
好了,玩笑话到此结束,接下来让我们步入正文,本文延续之前的风格,尝试提供一站式解决方案,你找到这就算是到家了。当然也是非常欢迎读者提出各自的问题和困惑,笔者将保持文章的更新。
笔者是最近才开始沉下心研究Ansible,所以以下实现并没有完全遵从Ansible的最佳实践,目前阶段还是以实现功能为主,后期将在足够熟悉之后再回头进行相应的优化。
首先来看看目录结构:
# /etc/ansible/
ansible.cfg
batscript/ # 存放将要在目标Windows服务器上被执行的bat或ps1脚本, 这些脚本将被
# ansbile playbook拷贝到目标Windows服务器上. 至于为什么会有ps1脚本,
# 原因其实很简单, 因为笔者以.NET研发人员身份进入地这个行业, 并且时至
# 今日都非常喜欢这个身份。
hosts # 配置远程服务的链接地址和登录信息等
playbooks/ # playbook的集中地, 用yaml形式声明操作, 实现操作的持久化和配置化.
var-XXXX.json
windows_deploy_war.yaml
windows_destory_tomcat.yaml
windows_install_tomcat.yaml
roles/ # 使用Role组织任务,可以将复杂的Playbook剧本进行拆分,达到缩小文件,任务重用的作用。本文中我们不会用到这个特性。
software/ # 存放一些常用的安装包和软件, 降低网络带宽限制, 例如本次将要进行演示的tomcat。
介绍完整体的目录结构,接下来让我们看看主要的配置项:
# 配置将要被远程控制的Windows远程服务器地址
vi /etc/ansible/hosts
[windows_80]
xxx.16.3.80 ansible_ssh_user="Administrator" ansible_ssh_pass="xxxx@80" ansible_ssh_port=5985 ansible_connection="winrm" ansible_winrm_server_cert_validation=ignore
# 配置由多个playbook公用的全局变量参数配置文件.
vi /etc/ansible/playbooks/var-XXXX.json
{
"ANSIBLE_HOME":"/etc/ansible",
"tomcat_version":"7.0.72",
"tomcat_install_dir_local":"/opt/",
"tomcat_install_win_dir": "E:/_applications/XXXX/",
"tomcat_server_name":"tomcat7XXXX",
"project_name":"xxxx-shell"
}
对于能够找到本文,并阅读到这里的读者而言,playbook内容应该才是他们所作为关心的,所以这里我们将其作为单独的章节进行统一的描述。
本次示例中,一共有三个playbook。
windows_install_tomcat.yaml
本playbook作用是进行tomcat的安装,毕竟相较于应用的部署,tomcat的安装和配置频率并不高,所以这里进行单独处理。
- hosts: windows_80
vars:
vars_files:
- var-XXXX.json
tasks:
- name: copy tomcat software to remote host
win_copy: src={
{
ANSIBLE_HOME}}/software/apache-tomcat-{
{
tomcat_version}}-windows-x64.zip dest={
{
tomcat_install_win_dir}}
- name: unzip tomcat zip
win_unzip: creates=yes src="{
{
tomcat_install_win_dir}}/apache-tomcat-{
{
tomcat_version}}-windows-x64.zip" dest="{
{
tomcat_install_win_dir}}" delete_archive=yes
- name: copy bat script for install tomcat server to dest windows server
win_copy: src={
{
ANSIBLE_HOME}}/batscript/tomcatWindowsService4Install.bat dest={
{
tomcat_install_win_dir}}
- name: copy bat script for remove tomcat server to dest windows server
win_copy: src={
{
ANSIBLE_HOME}}/batscript/tomcatWindowsService4Remove.bat dest={
{
tomcat_install_win_dir}}
- name: copy ps1 for modify tomcat port to dest windows server
win_copy: src={
{
ANSIBLE_HOME}}/batscript/tomcatWindows4ModifyPort.ps1 dest={
{
tomcat_install_win_dir}}
- name: modify tomcat http/ajp port
win_command: "powershell.exe -ExecutionPolicy ByPass -File {
{tomcat_install_win_dir}}/tomcatWindows4ModifyPort.ps1 1888 1999 >> {
{tomcat_install_win_dir}}/modifyTomcatPort.log"
- name: install tomcat as windows server
win_command: "cmd.exe /c {
{tomcat_install_win_dir}}/tomcatWindowsService4Install.bat >> {
{tomcat_install_win_dir}}/installTomcatServer.log"
register: installtomcatserver_out
windows_destory_tomcat.yaml
本playbook负责tomcat服务的停止以及其他的清理工作。
---
- hosts: windows_80
vars_files:
- var-XXXX.json
tasks:
- name: stop tomcat server
win_service:
name: tomcat7XXXX
state: stopped
- name: remove tomcat windows server
win_command: "cmd.exe /c {
{tomcat_install_win_dir}}/tomcatWindowsService4Remove.bat >> {
{tomcat_install_win_dir}}/removeTomcatServer.log"
register: removetomcatserver_out
- name: remove tomcat directory
win_file: path={
{
tomcat_install_win_dir}}/ state=absent
windows_deploy_war.yaml
本playbook负责WAR的发布。这个playbook是需要注意细节最多的,是最需要投入精力的。读者可以在本样例的基础上进行迭代。
---
- hosts: windows_80
vars_files:
- var-XXXX.json
tasks:
- name: stop tomcat server
win_service:
name: tomcat7XXXX
state: stopped
- name: rm current project in tomcat/webapps/
win_file: path={
{
tomcat_install_win_dir}}/apache-tomcat-{
{
tomcat_version}}/webapps/{
{
project_name}} state=absent
- name: download war form nexus
win_get_url: url="http://xxx.xx.xxx.xx:xxx/nexus/service/local/repositories/snapshots/content/com/xx.war" dest="{
{
tomcat_install_win_dir}}/apache-tomcat-{
{
tomcat_version}}/webapps/"
- name: rename war file name
win_shell: |
cd {
{tomcat_install_win_dir}}/apache-tomcat-{
{tomcat_version}}/webapps
mv xx.war yy.war
- name: Start tomcat server in windows server
win_service:
name: "{
{tomcat_server_name}}"
state: restarted
秉承送佛送到西的原则,这里一并提供所有相关的bat和ps1脚本。
#### tomcatWindowsService4Remove.bat
cd %~dp0\apache-tomcat-7.0.72\bin
set CATALINA_HOME=%~dp0\apache-tomcat-7.0.72
rem 这里的服务名推荐以参数传入
%~dp0/apache-tomcat-7.0.72/bin/service.bat remove tomcat7XXXX
#### tomcatWindowsService4Install.bat
cd %~dp0\apache-tomcat-7.0.72\bin
set CATALINA_HOME=%~dp0\apache-tomcat-7.0.72
rem 这里的服务名推荐以参数传入
%~dp0/apache-tomcat-7.0.72/bin/service.bat install tomcat7XXXX
### modifyTomcatPort.ps1 (作废,此功能可以使用ansible自带的 win_lineinfile 模块来实现。具体实现可以参见下方的参考链接)
<#
modifyTomcatPort.ps1 newHttpPort newAjpPort
#>
Function getParentDirPath($sFilePath){
# https://blog.csdn.net/Q215046120/article/details/100123294
$file = [io.fileinfo]$sFilePath;
return $file.DirectoryName;
}
if($args.Length -lt 2){
Write-Error "pass [newHttpPort], [newAjpPort]"
return
}
$newHttpPort=$args[0] # 18080
$newAjpPort=$args[1] #18009
#$newAjpRedirectPort=19443
$filePath = "$PSScriptRoot/apache-tomcat-7.0.72/conf/server.xml"
$newFilePath = ($filePath -replace "server.xml", "server-tmp.xml")
$allLines = Get-Content $filePath
foreach($line in $allLines){
# HTTP port
if($line -match '){
Write-Host "================当前行匹配" + $line
($line -replace $Matches.num, $newHttpPort) | Out-File -Encoding utf8 -Append $newFilePath
continue;
}
# AJP port
if($line -match '){
Write-Host "================当前行匹配AJP: " + $line
($line -replace $Matches.num2, $newAjpPort) | Out-File -Encoding utf8 -Append $newFilePath
continue;
}
# TODO更多的替换
Write-Host "当前行不匹配" + $line
# Write-Output $line >> $newFilePath
$line | Out-File -Encoding utf8 -Append $newFilePath
}
cd (getParentDirPath $filePath)
copy "server.xml" "server-bak.xml"
mv $newFilePath $filePath -Force