
1. ✅ansible编写剧本步骤
- 1️⃣创建roles目录结构
- 2️⃣在group_vars/all/main.yml中定义变量列表
- 3️⃣在tasks目录下编写tasks任务
- 4️⃣在files目录下准备部署文件
- 5️⃣在templates目录下创建j2模板文件
- 6️⃣在handlers目录下编写handlers
- 7️⃣在roles目录下编写主playbook
- 8️⃣运行主playbook
- 9️⃣检查验证
2. 🔐部署数据库(db02)
mkdir -p db_server/{files,templates,tasks,handlers}

- 2️⃣在group_vars/all/main.yml中定义变量列表
db_server:ip: "172.16.1.52"basedir: /app/tools/datadir: /app/data/3306/port: 3306root_password: Lidao996user_name: examuser_password: examuser_host: "172.16.1.%"db_name: exam
- name: 1.准备数据库安装目录file:path: "{{ item }}"state: directoryloop:- "{{ db_server.basedir }}"- "{{ db_server.datadir }}"- name: 2.拷贝mysql源码包copy:src: mysql-8.0.28-linux-glibc2.12-x86_64.tar.xzdest: /tmp/backup: yes- name: 3.解压mysql源码包unarchive:src: /tmp/mysql-8.0.28-linux-glibc2.12-x86_64.tar.xzdest: "{{ db_server.basedir }}"remote_src: yescreates: "{{ db_server.basedir }}mysql-8.0.28-linux-glibc2.12-x86_64/LICENSE"- name: 4.创建软链接file:path: "{{ db_server.basedir }}mysql"src: "{{ db_server.basedir }}mysql-8.0.28-linux-glibc2.12-x86_64/"state: link- name: 5.创建mysql用户user:name: mysqlshell: /sbin/nologincreate_home: nostate: present- name: 6.创建my.cnf配置文件template:src: my.cnf.j2dest: /etc/my.cnfowner: mysqlgroup: mysqlbackup: yesnotify:restart_mysqld- name: 7.修为数据库目录所有者file:path: "{{ item }}"owner: mysqlgroup: mysqlloop:- "{{ db_server.basedir }}mysql/"- "{{ db_server.datadir }}"- name: 8.配置环境变量lineinfile:path: /etc/profileline: 'export PATH=/app/tools/mysql/bin:$PATH'insertafter: EOF- name: 9.检查是否已经初始化过数据库stat:path: /tmp/init_dbregister: init_stat- name: 10.初始化数据库script: ./db_server/files/init_mysql.shwhen: not init_stat.stat.exists- name: 11.启动数据库systemd:name: mysqldenabled: yesstate: started- name: 12.安装pipyum:name:- python3-pipstate: present- name: 13.安装pymysql模块pip:name: pymysqlstate: present- name: 14.创建数据库,字符集为 utf8mb4mysql_db:name: "{{ db_server.db_name }}"encoding: utf8mb4collation: utf8mb4_unicode_cistate: presentlogin_user: rootlogin_password: ""when: not init_stat.stat.exists- name: 15.创建用户mysql_user:name: "{{ db_server.user_name }}"host: "{{ db_server.user_host }}"password: "{{ db_server.user_password }}"state: presentwhen: not init_stat.stat.exists- name: 16.授予用户权限mysql_user:name: "{{ db_server.user_name }}"host: "{{ db_server.user_host }}"priv: "{{ db_server.db_name }}.*:ALL"state: presentwhen: not init_stat.stat.exists- name: 17.上传 SQL 文件到目标主机copy:src: xzs-mysql.sqldest: /tmp/xzs-mysql.sqlwhen: not init_stat.stat.exists- name: 18.导入数据库shell: "{{ db_server.basedir }}mysql/bin/mysql -uroot exam </tmp/xzs-mysql.sql"when: not init_stat.stat.exists- name: 19.设置root密码mysql_user:name: rootpassword: "{{ db_server.root_password }}"host: localhostlogin_user: rootlogin_password: ""when: not init_stat.stat.exists- name: 20.创建标记文件表示已初始化file:path: /tmp/init_dbstate: touchmode: '0644'when: not init_stat.stat.exists
#!/bin/bash
##############################################################
# File Name:db_server/files/init_mysql.sh
# Version:V1.0
# Author:zbl
# Organization:zhubaolin.blog.csdn.net
# Desc:
##############################################################
source /etc/profile
#1.初始化数据库
mysqld --initialize-insecure --user=mysql --basedir=/app/tools/mysql/ --datadir=/app/data/3306/#2.拷贝启动管理文件到init.d
if [ -f /app/tools/mysql/support-files/mysql.server ];thencp /app/tools/mysql/support-files/mysql.server /etc/init.d/mysqld
elseecho "file not found"exit 1
fi
#3.修改管理文件权限
chmod +x /etc/init.d/mysqld#4.修改管理文件内容
sed -i '/^basedir=/s#basedir=#basedir=/app/tools/mysql/#g' /etc/init.d/mysqld
sed -i '/^datadir=/s#datadir=#datadir=/app/data/3306/#g' /etc/init.d/mysqld#5.加载自启动服务文件
systemctl daemon-reload
[mysqld]
user=mysql
basedir={{ db_server.basedir }}mysql/
datadir={{ db_server.datadir }}
port={{ db_server.port }}
socket=/tmp/mysql.sock [client]
socket=/tmp/mysql.sock
- 6️⃣在handlers目录下编写handlers
- name: restart_mysqldsystemd:name: mysqldstate: restarted
- hosts: dbroles:- db_server
ansible-playbook top.yml

ansible db -m shell -a 'ps -ef | grep mysql'

3. 🚀启动jar项目(web03/web04)
mkdir -p backend_web/{files,templates,tasks,handlers}

- 2️⃣在group_vars/all/main.yml中定义变量列表
backend_web:ip:- "10.0.0.9"- "10.0.0.10"port: 8000site_dir: /app/code/exam/backend/host: exam
- name: 1.安装jdkyum:name:- java-11-openjdk- java-11-openjdk-develstate: present- name: 2.拷贝项目文件到后端web服务器上copy:src: xzs-3.9.0.jardest: "{{ backend_web.site_dir }}"backup: yes- name: 3.拷贝配置文件到后端web服务器上template:src: application-prod.yml.j2dest: "{{ backend_web.site_dir }}application-prod.yml"backup: yes- name: 4.拷贝自启动脚本到后端web服务器上template:src: "{{ backend_web.host }}.sh.j2"dest: /server/scripts/{{ backend_web.host }}.shbackup: yes- name: 5.拷贝service服务管理文件到web服务器上template:src: "{{ backend_web.host }}.service.j2"dest: /usr/lib/systemd/system/{{ backend_web.host }}.servicebackup: yes- name: 6.重新加载systemd配置systemd:daemon_reload: yes- name: 7.启动服务,并设置下次开机启动systemd:name: "{{ backend_web.host }}"enabled: yesstate: started
xzs-3.9.0.jar
- 5️⃣在templates目录下创建j2模板文件
- exam.sh.j2
#!/bin/bash
##############################################################
# File Name:exam.sh
# Version:V1.0
# Author:zbl
# Organization:zhubaolin.blog.csdn.net
# Desc:
###############################################################1.vars
service=xzs-3.9.0.jar
dir={{ backend_web.site_dir }}
choose=$1
time=`date +%F_%T`
jar_file=${dir}${service}#2.function
function srv_start() {pid=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}'`pidcount=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}' | wc -l`if [ -f ${jar_file} ];thenif [ -z ${pid} ];thencd ${dir}nohup java -Duser.timezone=Asia/Shanghai -jar -Dspring.profiles.active=prod xzs-3.9.0.jar >/dev/null 2>&1 &fielseexitfireturn $?
}function srv_stop() {pid=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}'`pidcount=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}' | wc -l`if [ ${pidcount} -gt 0 ];thenkill ${pid}fireturn $?
}function srv_restart() {srv_stopsleep 1srv_start
}function srv_status() {pid=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}'`pidcount=`ps -ef | grep -w xzs-3.9.0 | grep -v grep | awk '{print $2}' | wc -l`if [ ${pidcount} -ge 1 ];thenecho -e "\E[1;32mrunning pid:[${pid}] ${service}\E[0m"elseecho -e "\E[1;31mstoped ${service}\E[0m"fireturn $?
}#3.case
case "${choose}" instart) srv_start ;;stop) srv_stop ;;restart) srv_restart ;;status) srv_status ;;*) echo input error
esac
#server后端服务的配置
server:port: {{ backend_web.port }}undertow:io-threads: 16worker-threads: 4000buffer-size: 1024direct-buffers: truecompression:enabled: truemin-response-size: 1
#日志
logging:path: {{ backend_web.site_dir }}#数据库,redis等等配置
spring:datasource:#mysql://数据库地址:端口号/库名字?url: jdbc:mysql://{{ db_server.ip }}:{{ db_server.port }}/{{ db_server.db_name }}?useSSL=false&useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true&allowMultiQueries=trueusername: {{ db_server.user_name }}password: {{ db_server.user_password }}driver-class-name: com.mysql.cj.jdbc.Driver
[Unit]
Description={{ backend_web.host }}
After=network.target
[Service]
Type=forking
#EnvironmentFile=/etc/sysconfig/tomcat
ExecStart=bash /server/scripts/{{ backend_web.host }}.sh start
ExecStop=bash /server/scripts/{{ backend_web.host }}.sh stop
[Install]
WantedBy=multi-user.target
- 6️⃣在handlers目录下编写handlers
- 7️⃣在roles目录下编写主playbook
- hosts: backend_webroles:- backend_web
ansible-playbook top.yml

ansible backend_web -m shell -a 'ps -ef | grep java'

4. 🍀接入4层负载均衡(lb01/lb02)
mkdir -p backend_lb/{files,templates,tasks,handlers}

- 2️⃣在group_vars/all/main.yml中定义变量列表
backend_lb:ip:- "10.0.0.5"- "10.0.0.6"port: 8000
- name: 1.分发nginx源copy:src: nginx.repodest: /etc/yum.repos.d/backup: yes- name: 2.安装nginx软件yum:name: nginxstate: present- name: 3.分发nginx配置文件template:src: nginx.conf.j2dest: /etc/nginx/nginx.confbackup: yesnotify:reload_nginx- name: 4.启动nginx并设置下次开机启动systemd:name: nginxenabled: yesstate: started
vim backend_lb/files/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
- 5️⃣在templates目录下创建j2模板文件
- backend_lb/templates/nginx.conf.j2
user nginx;
worker_processes auto;error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;events {worker_connections 1024;
}stream {upstream exam_pools {
{% for i in backend_web.ip %}server {{ i }}:{{ backend_web.port }};
{% endfor %}hash $remote_addr consistent;}log_format basic '$remote_addr [$time_local] ''$protocol $status $bytes_sent $bytes_received ''$session_time';access_log /var/log/nginx-l4.log basic;server {listen {{ backend_lb.port }};proxy_pass exam_pools;}
}http {include /etc/nginx/mime.types;default_type application/octet-stream;log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log /var/log/nginx/access.log main;sendfile on;#tcp_nopush on;keepalive_timeout 65;#gzip on;include /etc/nginx/conf.d/*.conf;
}
- 6️⃣在handlers目录下编写handlers
- name: reload_nginxsystemd:name: nginxstate: reloaded
- hosts: lbroles:- backend_lb
ansible-playbook top.yml

ansible lb -m shell -a 'ss -lntup | grep 8000'

5. 🌏部署前端web(web01/web02)
mkdir -p front_web/{files,templates,tasks,handlers}

- 2️⃣在group_vars/all/main.yml中定义变量列表
front_web:ip:- "10.0.0.7"- "10.0.0.8"port: 80site_dir: /app/code/exam/front/front_host: studentbackend_host: admin
- name: 1.分发nginx源copy:src: nginx.repodest: /etc/yum.repos.d/nginx.repobackup: yes- name: 2.安装nginx软件yum:name: nginxstate: present- name: 3.分发nginx配置文件template:src: exam.conf.j2dest: /etc/nginx/conf.d/exam.confbackup: yesnotify:reload_nginx- name: 4.创建站点目录file:path: "{{ front_web.site_dir }}"state: directory- name: 5.分发前端代码到前端web服务器上copy:src: exam-web.tar.gzdest: /tmp/backup: yes- name: 6.解压代码到站点目录下unarchive:src: /tmp/exam-web.tar.gzdest: "{{ front_web.site_dir }}"remote_src: yes- name: 7.启动nginx并设置开机自启动systemd:name: nginxenabled: yesstate: started
vim front_web/files/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
- 5️⃣在templates目录下创建j2模板文件
- front_web/templates/exam.conf.j2
server {listen {{ front_web.port }};server_name {{ front_web.front_host }}.zhubl.xyz;root {{ front_web.site_dir }}{{ front_web.front_host }}/;location / {index index.html;}location /api/ {proxy_pass http://{{ backend_lb.vip }}:{{ backend_lb.port }};}
}server {listen 80;server_name {{ front_web.backend_host }}.zhubl.xyz;root {{ front_web.site_dir }}{{ front_web.backend_host }}/;location / {index index.html;}location /api/ {proxy_pass http://{{ backend_lb.vip }}:{{ backend_lb.port }};}
}
- 6️⃣在handlers目录下编写handlers
- name: reload_nginxsystemd:name: nginxstate: reloaded
- hosts: front_webroles:- front_web
ansible-playbook top.yml

ansible front_web -m shell -a 'ss -lntup | grep 80'

6. 🍀接入7层负载(lb01/lb02)
mkdir -p front_lb/{files,templates,tasks,handlers}

- 2️⃣在group_vars/all/main.yml中定义变量列表
front_lb:ip:- "10.0.0.5"- "10.0.0.6"port: 80vip: "10.0.0.3"
- name: 1.分发nginx源copy:src: nginx.repodest: /etc/yum.repos.d/backup: yes- name: 2.安装nginx软件yum:name: nginxstate: present- name: 3.分发nginx配置文件template:src: exam.conf.j2dest: /etc/nginx/conf.d/exam.confbackup: yesnotify:reload_nginx- name: 4.启动nginx并设置下次开机自启动systemd:name: nginxenabled: yesstate: started
vim front_lb/files/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
- 5️⃣在templates目录下创建j2模板文件
- front_lb/templates/exam.conf.j2
upstream l7_pools {
{% for i in front_web.ip %}server {{ i }}:{{ front_web.port }};
{% endfor %}hash $remote_addr consistent;
}
server {listen {{ front_lb.port }};server_name {{ front_web.front_host }}.zhubl.xyz;location / {proxy_pass http://l7_pools;proxy_set_header Host $http_host;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Real-Ip $remote_addr;}
}
server {listen {{ front_lb.port }};server_name {{ front_web.backend_host }}.zhubl.xyz;location / {proxy_pass http://l7_pools;proxy_set_header Host $http_host;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Real-Ip $remote_addr;}
}
- 6️⃣在handlers目录下编写handlers
- name: reload_nginxsystemd:name: nginxstate: reloaded
- hosts: lbroles:- front_lb
ansible-playbook top.yml

ansible lb -m shell -a 'ss -lntup | grep 80'

7. 🚀接入高可用(lb01/lb02)
mkdir -p front_keepalived/{files,templates,tasks,handlers}
- 2️⃣在group_vars/all/main.yml中定义变量列表
- 3️⃣在tasks目录下编写tasks任务
- name: 1.安装keepalived软件yum:name: keepalivedstate: present- name: 2.获取主机名shell: hostnameregister: hostname- name: 3.分发lb01配置文件template:src: lb01.keepalived.conf.j2dest: /etc/keepalived/keepalived.confbackup: yeswhen: hostname.stdout is match("lb01")notify:restart_keepalived- name: 4.分发lb02配置文件template:src: lb02.keepalived.conf.j2dest: /etc/keepalived/keepalived.confbackup: yeswhen: hostname.stdout is match("lb02")notify:restart_keepalived- name: 5.分发监控nginx进程脚本到负载均衡copy:src: check_lb.shdest: /server/scripts/check_lb.shmode: '0755'backup: yes- name: 6.启动keepalived并设置下次开机自启动systemd:name: keepalivedenabled: yesstate: started
#!/bin/bash
##############################################################
# File Name:/server/scripts/check_lb.sh
# Version:V1.0
# Author:zbl
# Organization:zhubaolin.blog.csdn.net
# Desc:
##############################################################
#1.vars
count=`ps -ef | grep nginx | wc -l`#2.stop keepalived
if [ ${count} -eq 1 ];thensystemctl stop keepalived
fi
- 5️⃣在templates目录下创建j2模板文件
- front_keepalived/templates/lb01.keepalived.conf.j2
global_defs {router_id lb01
}
vrrp_script check_lb.sh { script /server/scripts/check_lb.shinterval 2weight 1user root
}vrrp_instance vip_3 { state MASTER interface ens33virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASSauth_pass 1111
}
virtual_ipaddress { {{ front_lb.vip }} dev ens33 label ens33:1
}
track_script {check_lb.sh
}
}vrrp_instance vip_4 {state BACKUPinterface ens33virtual_router_id 52priority 50advert_int 1authentication {auth_type PASSauth_pass 1111
}
virtual_ipaddress {{{ backend_lb.vip }} dev ens33 label ens33:2
}
}
- front_keepalived/templates/lb02.keepalived.conf.j2
global_defs {router_id lb02
}
vrrp_script check_lb.sh {script /server/scripts/check_lb.shinterval 2weight 1user root
}vrrp_instance vip_3 {state BACKUPinterface ens33virtual_router_id 51priority 50advert_int 1authentication {auth_type PASSauth_pass 1111
}
virtual_ipaddress {{{ front_lb.vip }} dev ens33 label ens33:1
}
}vrrp_instance vip_4 {state MASTERinterface ens33virtual_router_id 52priority 100advert_int 1authentication {auth_type PASSauth_pass 1111
}
virtual_ipaddress {{{ backend_lb.vip }} dev ens33 label ens33:2
}
track_script {check_lb.sh
}
}
- 6️⃣在handlers目录下编写handlers
- name: restart_keepalivedsystemd:name: keepalivedstate: restarted
- hosts: lbroles:- keepalived
ansible-playbook top.yml
8. 🌏浏览器访问


9. ✅总结
9.1. 🌟总变量
db_server:ip: "172.16.1.52"basedir: /app/tools/datadir: /app/data/3306/port: 3306root_password: Lidao996user_name: examuser_password: examuser_host: "172.16.1.%"db_name: examfront_web:ip:- "10.0.0.7"- "10.0.0.8"port: 80site_dir: /app/code/exam/front/front_host: studentbackend_host: adminbackend_web:ip:- "10.0.0.9"- "10.0.0.10"port: 8000site_dir: /app/code/exam/backend/host: exambackend_lb:ip:- "10.0.0.5"- "10.0.0.6"port: 8000vip: "10.0.0.4"front_lb:ip:- "10.0.0.5"- "10.0.0.6"port: 80vip: "10.0.0.3"
9.2. 🌟总roles
[root@m02 /server/ansible/roles]# tree -F
.
├── ansible.cfg
├── backend_lb/
│ ├── files/
│ │ └── nginx.repo
│ ├── handlers/
│ │ └── main.yml
│ ├── tasks/
│ │ └── main.yml
│ └── templates/
│ └── nginx.conf.j2
├── backend_web/
│ ├── files/
│ │ └── xzs-3.9.0.jar
│ ├── handlers/
│ ├── tasks/
│ │ └── main.yml
│ └── templates/
│ ├── application-prod.yml.j2
│ ├── exam.service.j2
│ └── exam.sh.j2
├── db_server/
│ ├── files/
│ │ ├── init_mysql.sh*
│ │ ├── mysql-8.0.28-linux-glibc2.12-x86_64.tar.xz
│ │ └── xzs-mysql.sql
│ ├── handlers/
│ │ └── main.yml
│ ├── tasks/
│ │ └── main.yml
│ └── templates/
│ └── my.cnf.j2
├── front_lb/
│ ├── files/
│ │ └── nginx.repo
│ ├── handlers/
│ │ └── main.yml
│ ├── tasks/
│ │ └── main.yml
│ └── templates/
│ └── exam.conf.j2
├── front_web/
│ ├── files/
│ │ ├── exam-web.tar.gz
│ │ └── nginx.repo
│ ├── handlers/
│ │ └── main.yml
│ ├── tasks/
│ │ └── main.yml
│ └── templates/
│ └── exam.conf.j2
├── group_vars/
│ └── all/
│ └── main.yml
├── hosts
├── keepalived/
│ ├── files/
│ │ └── check_lb.sh
│ ├── handlers/
│ │ └── main.yml
│ ├── tasks/
│ │ └── main.yml
│ └── templates/
│ ├── lb01.keepalived.conf.j2
│ └── lb02.keepalived.conf.j2
└── top.yml32 directories, 33 files
9.3. 🌟总剧本
- hosts: dbroles:- db_server- hosts: backend_webroles:- backend_web- hosts: lbroles:- backend_lb- hosts: front_webroles:- front_web- hosts: lbroles:- front_lb- keepalived
