本文目录导读:

我来提供一个完整的Ansible自动化部署Java应用的实战案例,涵盖从环境准备到应用部署的全过程。
项目结构
ansible-java-deploy/
├── ansible.cfg
├── inventory/
│ ├── production.ini
│ └── staging.ini
├── playbooks/
│ ├── deploy-java-app.yml
│ ├── setup-java-env.yml
│ └── install-docker.yml
├── roles/
│ ├── java/
│ │ ├── tasks/
│ │ │ └── main.yml
│ │ ├── handlers/
│ │ │ └── main.yml
│ │ └── templates/
│ │ └── application.yml.j2
│ └── tomcat/
│ ├── tasks/
│ │ └── main.yml
│ ├── handlers/
│ │ └── main.yml
│ └── templates/
│ └── server.xml.j2
└── vars/
└── common.yml
配置文件
ansible.cfg
[defaults] inventory = inventory/production.ini remote_user = deploy host_key_checking = False roles_path = roles gathering = smart fact_caching = jsonfile fact_caching_connection = /tmp/ansible_cache fact_caching_timeout = 300 [ssh_connection] pipelining = True control_path = /tmp/ansible-%%h-%%p-%%r
inventory/production.ini
[java-servers] web01 ansible_host=192.168.1.10 web02 ansible_host=192.168.1.11 [tomcat-servers] app01 ansible_host=192.168.1.20 app02 ansible_host=192.168.1.21 [database] db01 ansible_host=192.168.1.30 [all:vars] ansible_python_interpreter=/usr/bin/python3 app_version=1.2.3 DEPLOY_USER=deploy DEPLOY_GROUP=deploy [java-servers:vars] java_version=17 jdk_archive=jdk-17_linux-x64_bin.tar.gz [tomcat-servers:vars] tomcat_version=9.0.85 tomcat_major_version=9
Roles实现
roles/java/tasks/main.yml
---
- name: Create Java installation directory
ansible.builtin.file:
path: "{{ java_install_dir }}"
state: directory
owner: "{{ DEPLOY_USER }}"
group: "{{ DEPLOY_GROUP }}"
mode: '0755'
- name: Download JDK
ansible.builtin.get_url:
url: "{{ java_download_url }}/{{ jdk_archive }}"
dest: "/tmp/{{ jdk_archive }}"
owner: "{{ DEPLOY_USER }}"
group: "{{ DEPLOY_GROUP }}"
mode: '0644'
timeout: 120
register: download_jdk
- name: Extract JDK
ansible.builtin.unarchive:
src: "/tmp/{{ jdk_archive }}"
dest: "{{ java_install_dir }}"
remote_src: yes
owner: "{{ DEPLOY_USER }}"
group: "{{ DEPLOY_GROUP }}"
create: true
when: download_jdk is success
- name: Create symlink for Java
ansible.builtin.file:
src: "{{ java_install_dir }}/jdk-{{ java_version }}"
dest: "{{ java_home }}"
state: link
owner: "{{ DEPLOY_USER }}"
group: "{{ DEPLOY_GROUP }}"
- name: Configure JVM options
ansible.builtin.template:
src: jvm.options.j2
dest: "{{ java_home }}/conf/jvm.options"
owner: "{{ DEPLOY_USER }}"
group: "{{ DEPLOY_GROUP }}"
notify: Restart Java services
- name: Set JAVA_HOME in profile
ansible.builtin.lineinfile:
path: /etc/profile.d/java.sh
line: |
export JAVA_HOME={{ java_home }}
export PATH=$JAVA_HOME/bin:$PATH
create: yes
mode: '0755'
owner: root
group: root
- name: Copy application configuration
ansible.builtin.template:
src: application.yml.j2
dest: "{{ app_home }}/config/application.yml"
owner: "{{ DEPLOY_USER }}"
group: "{{ DEPLOY_GROUP }}"
mode: '0644'
roles/java/templates/application.yml.j2
# Java Application Configuration
server:
port: {{ app_port | default(8080) }}
address: 0.0.0.0
spring:
application:
name: {{ app_name }}
datasource:
url: jdbc:mysql://{{ db_host }}:{{ db_port }}/{{ db_name }}?createDatabaseIfNotExist=true&useSSL=false
username: {{ db_user }}
password: "{{ db_password }}"
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: none
show-sql: false
logging:
level:
com.example: INFO
org.hibernate.SQL: DEBUG
management:
endpoints:
web:
exposure:
include: "*"
roles/tomcat/tasks/main.yml
---
- name: Create Tomcat user
ansible.builtin.user:
name: tomcat
system: yes
shell: /sbin/nologin
home: "{{ tomcat_home }}"
create_home: yes
- name: Download Tomcat
ansible.builtin.get_url:
url: "https://archive.apache.org/dist/tomcat/tomcat-{{ tomcat_major_version }}/v{{ tomcat_version }}/bin/apache-tomcat-{{ tomcat_version }}.tar.gz"
dest: "/tmp/apache-tomcat-{{ tomcat_version }}.tar.gz"
timeout: 120
- name: Extract Tomcat
ansible.builtin.unarchive:
src: "/tmp/apache-tomcat-{{ tomcat_version }}.tar.gz"
dest: "{{ tomcat_home }}/.."
remote_src: yes
creates: "{{ tomcat_home }}"
- name: Set ownership
ansible.builtin.file:
path: "{{ tomcat_home }}"
owner: tomcat
group: tomcat
recurse: yes
- name: Create systemd service file
ansible.builtin.template:
src: tomcat.service.j2
dest: /etc/systemd/system/tomcat.service
mode: '0644'
notify: Reload systemd
- name: Start and enable Tomcat
ansible.builtin.systemd:
name: tomcat
state: started
enabled: yes
daemon_reload: yes
- name: Configure Tomcat server
ansible.builtin.template:
src: server.xml.j2
dest: "{{ tomcat_home }}/conf/server.xml"
owner: tomcat
group: tomcat
mode: '0644'
notify: Restart Tomcat
roles/tomcat/templates/server.xml.j2
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="{{ app_port | default(8080) }}" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200"
minSpareThreads="50"
acceptCount="100" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
Playbook实现
playbooks/setup-java-env.yml
---
- name: Setup Java Environment
hosts: java-servers
become: yes
vars_files:
- ../vars/common.yml
roles:
- role: java
when: ansible_os_family == "RedHat" or ansible_os_family == "Debian"
tasks:
- name: Install MySQL client
ansible.builtin.package:
name: mysql
state: present
when: ansible_os_family == "RedHat"
- name: Install JDBC driver
ansible.builtin.copy:
src: mysql-connector-j-8.0.33.jar
dest: "{{ app_home }}/lib/"
owner: "{{ DEPLOY_USER }}"
group: "{{ DEPLOY_GROUP }}"
mode: '0644'
- name: Setup Tomcat Servers
hosts: tomcat-servers
become: yes
tasks:
- name: Install Tomcat
include_role:
name: tomcat
- name: Deploy application WAR
ansible.builtin.copy:
src: "{{ app_artifact }}"
dest: "{{ tomcat_home }}/webapps/{{ app_name }}.war"
owner: tomcat
group: tomcat
mode: '0644'
when: deploy_type == "war"
notify: Restart Tomcat
playbooks/deploy-java-app.yml
---
- name: Deploy Java Application
hosts: tomcat-servers
become: yes
vars_files:
- ../vars/common.yml
environment:
JAVA_HOME: "{{ java_home }}"
PATH: "{{ java_home }}/bin:{{ ansible_env.PATH }}"
pre_tasks:
- name: Update package cache
ansible.builtin.apt:
update_cache: yes
when: ansible_os_family == "Debian"
- name: Stop Tomcat before deployment
ansible.builtin.systemd:
name: tomcat
state: stopped
when: rolling_update == false
roles:
- java
- tomcat
tasks:
- name: Backup old application
ansible.builtin.command: cp -r {{ tomcat_home }}/webapps/{{ app_name }} /backup/{{ app_name }}-{{ lookup('pipe', 'date +%Y%m%d_%H%M%S') }}
become: yes
- name: Deploy new WAR file
ansible.builtin.copy:
src: "{{ app_artifact }}"
dest: "{{ tomcat_home }}/webapps/{{ app_name }}.war"
backup: yes
- name: Update application configuration
ansible.builtin.template:
src: config.j2
dest: "{{ app_home }}/config/application.properties"
when: update_config
post_tasks:
- name: Start Tomcat if stopped
ansible.builtin.systemd:
name: tomcat
state: started
when: rolling_update == false
- name: Health check
ansible.builtin.uri:
url: "http://{{ inventory_hostname }}:{{ app_port }}/{{ app_name }}/health"
return_content: yes
timeout: 30
register: health_result
until: health_result.status == 200
retries: 10
delay: 5
- name: Report deployment status
ansible.builtin.debug:
msg: "Deployment successful to {{ inventory_hostname }}"
when: health_result.status == 200
playbooks/install-docker.yml (可选容器化部署)
---
- name: Install Docker and Deploy Java App in Container
hosts: docker-hosts
become: yes
tasks:
- name: Install Docker packages
ansible.builtin.package:
name:
- docker
- docker-compose
state: present
- name: Start Docker service
ansible.builtin.systemd:
name: docker
state: started
enabled: yes
- name: Create Dockerfile
ansible.builtin.template:
src: Dockerfile.j2
dest: /opt/{{ app_name }}/Dockerfile
- name: Create docker-compose.yml
ansible.builtin.template:
src: docker-compose.yml.j2
dest: /opt/{{ app_name }}/docker-compose.yml
- name: Build Docker image
ansible.builtin.command:
cmd: docker build -t {{ app_name }}:{{ app_version }} .
chdir: /opt/{{ app_name }}
- name: Deploy container
ansible.builtin.command:
cmd: docker-compose up -d
chdir: /opt/{{ app_name }}
- name: Verify container is running
ansible.builtin.shell: docker ps --filter name=app-{{ app_name }} --format "{{ '{{.Names}}' }} {{ '{{.Status}}' }}"
register: container_status
- name: Show container status
ansible.builtin.debug:
var: container_status.stdout_lines
Variables文件
vars/common.yml
---
# Application settings
app_name: myapp
app_version: 1.2.3
app_port: 8080
app_home: /opt/myapp
deploy_type: war
# Java settings
java_version: 17
java_home: /opt/java/jdk-17
java_install_dir: /opt/java
java_download_url: https://download.java.net/java/GA/jdk17
# Database settings
db_host: db.example.com
db_port: 3306
db_name: myapp
db_user: myapp
db_password: SecurePass123
# Deployment settings
rolling_update: true
update_config: true
artifact_name: myapp-{{ app_version }}.war
app_artifact: /tmp/{{ artifact_name }}
# SMTP settings (if needed)
smtp_host: smtp.example.com
smtp_port: 587
Handler定义
roles/tomcat/handlers/main.yml
---
- name: Restart Tomcat
ansible.builtin.systemd:
name: tomcat
state: restarted
- name: Reload systemd
ansible.builtin.systemd:
daemon_reload: yes
roles/java/handlers/main.yml
---
- name: Restart Java services
ansible.builtin.systemd:
name: "{{ item }}"
state: restarted
loop:
- java-application
- java-service
when: java_services is defined
部署命令
# 检查语法 ansible-playbook playbooks/deploy-java-app.yml --syntax-check # 部署到生产环境 ansible-playbook playbooks/deploy-java-app.yml -i inventory/production.ini # 部署到测试环境 ansible-playbook playbooks/deploy-java-app.yml -i inventory/staging.ini # 只更新配置 ansible-playbook playbooks/deploy-java-app.yml --tags=config # 滚动更新 ansible-playbook playbooks/deploy-java-app.yml -e "rolling_update=true" # 指定特定主机 ansible-playbook playbooks/deploy-java-app.yml --limit web01 # 跳过健康检查 ansible-playbook playbooks/deploy-java-app.yml -e "skip_health_check=true"
高级特性示例
滚动更新策略
- name: Rolling update deployment
hosts: all
serial: 1
strategy: free
tasks:
- name: Deploy to current host
ansible.builtin.include_tasks: deploy.yaml
蓝绿部署
- name: Blue-green deployment
hosts: load_balancer
tasks:
- name: Switch traffic to blue
ansible.builtin.command: ./switch_to_blue.sh
- name: Verify blue deployment
ansible.builtin.uri:
url: "http://blue.example.com/health"
status: 200
这个完整的Ansible Java部署方案包含了:
- 结构化的目录设计 - 便于维护和扩展
- 角色复用 - Java环境和Tomcat配置独立封装
- 环境配置管理 - 通过变量控制不同环境
- 服务管理 - 使用systemd管理服务生命周期
- 健康检查 - 自动验证部署是否成功
- 滚动更新 - 支持零停机部署
- 备份机制 - 部署前自动备份
- Docker容器化 - 支持容器部署方式
你可以根据实际需求调整,比如添加CI/CD集成、监控告警、日志采集等。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播