2. Ansible-playbook实现Apache批量部署,并创建以各自IP地址为内容的index.html

任务内容:Ansible-playbook实现apache批量部署,并对不同主机提供以各自IP地址为内容的index.html

2.1 架构及主机

Ansible-playbook实现Apache(httpd)编译安装及批量部署_Apache编译安装

五台服务器
1 Ansible主控端:
节点1:(只设一个节点)
主机名:Ansible-PRI
CentOS 8.4
IP: 192.168.250.8/24
ansible 2.9.27

2 Ansible被控端--CentOS7组:
节点1:
主机名:Ansible-IP17
CentOS 7.9
IP: 192.168.250.17/24

节点2:
主机名:Ansible-IP27
CentOS 7.9
IP: 192.168.250.27/24

3. Ansible被控端--CentOS8组:
节点1:
主机名:Ansible-IP18
CentOS 8.4
IP: 192.168.250.18/24

节点2:
主机名:Ansible-IP28
CentOS 8.4
IP: 192.168.250.28/24

4. Ansible被控端--DBS组:
节点1:
主机名:Ansible-IP58
CentOS 8.4
IP: 192.168.250.58/24

节点2:
主机名:Ansible-IP68
CentOS 8.4
IP: 192.168.250.68/24

# 说明:按照上面的架构图,准备好五台不同组别和操作系统的主机,将以此为基础环境完成ansible的参数等学习和案例实践

2.2 Ansible 主控端准备

2.2.1 主控端环境准备及软件包安装

基本任务:同步时钟;安装ansible;查看版本并了解文件格式和基本语法等

# 主控端服务器CentOS8.4 上基本配置
[root@CentOS84 ]#hostnamectl set-hostname Ansible-PRI
[root@CentOS84 ]#exit
[root@Ansible-PRI ]#
[root@Ansible-PRI ]#hostname -I
192.168.250.8
[root@Ansible-PRI ]#systemctl enable --now chronyd.service

# Ansible 走的是EPEL源,如果没配置的话需要配置或者启用
[root@Ansible-PRI ]#yum repolist
repo id repo name
AppStream AppStream
BaseOS BaseOS
EPEL EPEL
centosplus centosplus
extras extras
[root@Ansible-PRI ]#

# 查看默认ansible的版本
[root@Ansible-PRI ]#yum info ansible
BaseOS 4.6 kB/s | 3.9 kB 00:00
AppStream 6.8 kB/s | 4.3 kB 00:00
EPEL 30 kB/s | 4.7 kB 00:00
EPEL 326 kB/s | 11 MB 00:35
extras 11 kB/s | 1.5 kB 00:00
centosplus 1.7 kB/s | 1.5 kB 00:00
Available Packages
Name : ansible
Version : 2.9.27
Release : 1.el8
Architecture : noarch
Size : 17 M
Source : ansible-2.9.27-1.el8.src.rpm
Repository : EPEL
Summary : SSH-based configuration management, deployment, and task execution system
URL : http://ansible.com
License : GPLv3+
Description : Ansible is a radically simple model-driven configuration management,
: multi-node deployment, and remote task execution system. Ansible works
: over SSH and does not require any software or daemons to be installed
: on remote nodes. Extension modules can be written in any language and
: are transferred to managed machines automatically.

[root@Ansible-PRI ]#

# 安装ansible
[root@Ansible-PRI ]#yum -y install ansible

# 验证安装及查看版本
[root@Ansible-PRI ]#ansible --version
ansible 2.9.27
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 3.6.8 (default, Mar 19 2021, 05:13:41) [GCC 8.4.1 20200928 (Red Hat 8.4.1-1)]
[root@Ansible-PRI ]#whereis ansible
ansible: /usr/bin/ansible /etc/ansible /usr/share/ansible /usr/share/man/man1/ansible.1.gz
[root@Ansible-PRI ]#file /usr/bin/ansible
/usr/bin/ansible: Python script, ASCII text executable
# ansible是Python script

[root@Ansible-PRI ]#cat /usr/bin/ansible
........................
#!/usr/bin/python3.6
# 从文件内容可以考到是python3.6开发的
........................

[root@Ansible-PRI ]#

2.1.2 主控端与被控端基于key验证

基本任务:利用编写好的脚本实现与主控端相同网段内的所有主机之间基于key的SSH免密通信

# 修改SSH的配置文件
[root@Ansible-PRI ]#vim /etc/ssh/ssh_config
...............................
StrictHostKeyChecking no
...............................
"/etc/ssh/ssh_config" 53L, 1795C written

[root@Ansible-PRI ]#cat /etc/ssh/ssh_config | grep StrictHostKeyChecking
# StrictHostKeyChecking ask
StrictHostKeyChecking no

# 编写脚本实现Ansible 主控端与被控端的基于key的绵密SSH登录
[root@Ansible-PRI ]#vim ssh_key_iplist.sh
[root@Ansible-PRI ]#cat ssh_key_iplist.sh
#!/bin/bash
#
#********************************************************************************************<strong>
#Author: WuDongWuXia
#QQ: 1050572574@qq.com
#Date: 2022-03-02
#FileName: ssh_key_iplist.sh
#URL: www.shoneinfo.cn
#Description: The Test Script
#Copyright (C):2022 All rights reserved
#</strong>*******************************************************************************************

IPLIST="
192.168.250.17
192.168.250.27
192.168.250.8
192.168.250.18
192.168.250.28
192.168.250.58
192.168.250.68"

rpm -q sshpass &> /dev/null || yum -y install sshpass
[ -f /root/.ssh/id_rsa ] || ssh-keygen -f /root/.ssh/id_rsa -P ''
export SSHPASS=2XXXX8
for IP in $IPLIST;do
sshpass -e ssh-copy-id -o StrictHostKeyChecking=no $IP
done
[root@Ansible-PRI ]#
# 运行脚本
[root@Ansible-PRI ]#bash ssh_key_iplist.sh

# 查看SSH KEY认证的主机信息
[root@Ansible-PRI ]#cat /root/.ssh/known_hosts

2.1.3 主控端 ansbile 基础配置

基本任务:配置好ansible的主机信息;并测通方可进入下一步骤。

# 配置ansible的主机组等,这样为整个ansible 的实验统一准备好环境,本次仅针对 [dbs] 组实践数据库的安装
[root@Ansible-PRI ]#cat /etc/ansible/hosts
........................
[local]
192.168.250.8 ansible_connection=local

[centos7]
192.168.250.17
192.168.250.27

[centos8]
192.168.250.18
192.168.250.28

# 本次数据库安装仅针对[dbs]组
[dbs]
192.168.250.58
192.168.250.68
........................

[root@Ansible-PRI ]#ansible all --list-hosts
hosts (7):
192.168.250.8
192.168.250.17
192.168.250.27
192.168.250.18
192.168.250.28
192.168.250.58
192.168.250.68
[root@Ansible-PRI ]#ansible dbs --list-hosts
hosts (2):
192.168.250.58
192.168.250.68

# ansible 的主控端和被控端之间通信检测,确保pong
[root@Ansible-PRI ]#ansible all -m ping
192.168.250.8 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.250.27 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.250.17 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.250.28 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.250.18 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.250.58 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.250.68 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[root@Ansible-PRI ]#
[root@Ansible-PRI ]#
[root@Ansible-PRI ]#ll
total 1168604
-rw-r--r-- 1 root root 1196633756 Mar 2 18:42 mysql-8.0.27-linux-glibc2.12-x86_64.tar.xz
-rw-r--r-- 1 root root 781 Mar 2 17:57 ssh_key_iplist.sh
[root@Ansible-PRI ]#

2.3 准备httpd源码包、依赖包及httpd运行文件

# 创建目录
[root@Ansible-PRI ]#
[root@Ansible-PRI ]#pwd
/data/ansible
[root@Ansible-PRI ]#mkdir -p /apps/httpd/
[root@Ansible-PRI ]#tree /apps/
/apps/
└── httpd

1 directory, 0 files
[root@Ansible-PRI ]#pwd
/data/ansible
[root@Ansible-PRI ]#cd /apps/httpd/
[root@Ansible-PRI ]#wget https://mirrors.tuna.tsinghua.edu.cn/apache/httpd/httpd-2.4.52.tar.bz2
[root@Ansible-PRI ]#
[root@Ansible-PRI ]#wget https://mirrors.tuna.tsinghua.edu.cn/apache/apr/apr-1.7.0.tar.bz2
[root@Ansible-PRI ]#
[root@Ansible-PRI ]#wget https://mirrors.tuna.tsinghua.edu.cn/apache/apr/apr-util-1.6.1.tar.bz2
[root@Ansible-PRI ]#
[root@Ansible-PRI ]#vim /apps/httpd/httpd.service
[root@Ansible-PRI ]#cat /apps/httpd/httpd.service

[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd(8)
Documentation=man:apachectl(8)

[Service]
Type=forking
#EnvironmentFile=/etc/sysconfig/httpd
ExecStart=/apps/httpd/bin/apachectl start
#ExecStart={{ install_dir }}/bin/httpd $OPTIONS -k start
ExecReload=/apps/httpd/bin/apachectl graceful
#ExecReload={{ install_dir }}/bin/httpd $OPTIONS -k graceful
ExecStop=/apps/httpd/bin/apachectl stop
# We want systemd to give httpd some time to finish gracefully, but still want
# it to kill httpd after TimeoutStopSec if something went wrong during the
# graceful stop. Normally, Systemd sends SIGTERM signal right after the
# ExecStop, which would kill httpd. We are sending useless SIGCONT here to give
# httpd time to finish.
KillSignal=SIGCONT
PrivateTmp=true
[Install]
WantedBy=multi-user.target

[root@Ansible-PRI ]#

# 下面是需要准备的几个文件
[root@Ansible-PRI ]#tree /apps
/apps
└── httpd
├── apr-1.7.0.tar.bz2
├── apr-util-1.6.1.tar.bz2
├── httpd-2.4.52.tar.bz2
└── httpd.service

1 directory, 4 files

2.4 利用Ansible-playbook实现批量编译安装部署 httpd

# 编写Ansible-playbook的yaml文件
[root@Ansible-PRI ]#cd /data/ansible/
[root@Ansible-PRI ]#vim install_httpd_v01.yml
[root@Ansible-PRI ]#cat install_httpd_v01.yml
---
# install httpd

- hosts: dbs
remote_user: root
gather_facts: no
vars:
data_dir: /usr/local/src
base_dir : /apps/httpd
install_dir: /apps/httpd
httpd_version: httpd-2.4.52
apr_version: apr-1.7.0
apr_util_version: apr-util-1.6.1
httpd_url: https://mirrors.tuna.tsinghua.edu.cn/apache/httpd
apr_url: https://mirrors.tuna.tsinghua.edu.cn/apache/apr
tasks :
- name : install packages
yum : name=gcc,make,pcre-devel,openssl-devel,expat-devel,bzip2 state=installed
- name : download httpd file
unarchive :
src: "{{ base_dir }}/{{ httpd_version }}.tar.bz2"
dest: "{{ data_dir }}"
owner: root
copy: yes
- name : download apr file
unarchive :
src: "{{ base_dir }}/{{ apr_version }}.tar.bz2"
dest: "{{ data_dir }}"
owner: root
copy: yes
- name : download apr_util file
unarchive :
src: "{{ base_dir }}/{{ apr_util_version }}.tar.bz2"
dest: "{{ data_dir }}"
owner: root
copy: yes
- name : prepare apr dir
shell: mv {{ apr_version }} {{ httpd_version }}/srclib/apr
args:
chdir: "{{ data_dir }}"
- name : prepare apr_util dir
shell : mv {{ apr_util_version }} {{ httpd_version }}/srclib/apr-util
args:
chdir: "{{ data_dir }}"
- name : build httpd
shell : ./configure --prefix={{ install_dir }} --enable-so --enable-ssl --enable-cgi --enable-rewrite --with-zlib --with-pcre --with-included-apr --enable-modules=most --enable-enablempms-shared=all --with-mpm=prefork && make -j && make install
args:
chdir: "{{ data_dir }}/{{ httpd_version }}"
- name : create group
group : name=apache gid=80 system=yes
- name : create user
user : name=apache uid=80 group=apache shell=/sbin/nologin system=yes create_home=no home={{ install_dir }}/conf/httpd
- name : set httpd user
lineinfile : path={{ install_dir }}/conf/httpd.conf regexp='^User' line='User apache'
- name : set httpd group
lineinfile : path={{ install_dir }}/conf/httpd.conf regexp='^Group' line='Group apache'
- name : set variable PATH
shell : echo PATH={{ install_dir }}/bin:$PATH >> /etc/profile.d/httpd.sh
- name : copy service file to remote
copy:
src: "{{ base_dir }}/httpd.service"
dest: /usr/lib/systemd/system/httpd.service
- name: config index.html
shell: echo `hostname -I` > /apps/httpd/htdocs/index.html
- name : start service
service : name=httpd state=started enabled=yes

[root@Ansible-PRI ]#
[root@Ansible-PRI ]#tree /data/ansible
/data/ansible
├── files
│ ├── mysql-8.0.27-linux-glibc2.12-x86_64.tar.xz
│ └── mysql8.cnf
├── install_httpd_v01.yml
├── install-mysql8.0.27-v01.yml
└── install-mysql8.0.27-v02.yml

1 directory, 5 files
[root@Ansible-PRI ]#

# 语法检查
[root@Ansible-PRI ]#ansible-playbook --syntax-check install_httpd_v01.yml
[WARNING]: Could not match supplied host pattern, ignoring: webserver

playbook: install_httpd_v01.yml

[root@Ansible-PRI ]#ansible-playbook install_httpd_v01.yml

PLAY [dbs] **********************************************************************************************************************************<strong>

TASK [install packages] </strong>*******************************************************************************************************************<strong>
changed: [192.168.250.58]
changed: [192.168.250.68]

TASK [download httpd file] </strong>****************************************************************************************************************<strong>
changed: [192.168.250.68]
changed: [192.168.250.58]

TASK [download apr file] </strong>******************************************************************************************************************<strong>
changed: [192.168.250.68]
changed: [192.168.250.58]

TASK [download apr_util file] </strong>*************************************************************************************************************<strong>
changed: [192.168.250.58]
changed: [192.168.250.68]

TASK [prepare apr dir] </strong>********************************************************************************************************************<strong>
changed: [192.168.250.68]
changed: [192.168.250.58]

TASK [prepare apr_util dir] </strong>***************************************************************************************************************<strong>
changed: [192.168.250.68]
changed: [192.168.250.58]

TASK [build httpd] </strong>************************************************************************************************************************<strong>
changed: [192.168.250.58]
changed: [192.168.250.68]

TASK [create group] </strong>***********************************************************************************************************************<strong>
changed: [192.168.250.58]
changed: [192.168.250.68]

TASK [create user] </strong>************************************************************************************************************************<strong>
changed: [192.168.250.68]
changed: [192.168.250.58]

TASK [set httpd user] </strong>*********************************************************************************************************************<strong>
changed: [192.168.250.68]
changed: [192.168.250.58]

TASK [set httpd group] </strong>********************************************************************************************************************<strong>
changed: [192.168.250.58]
changed: [192.168.250.68]

TASK [set variable PATH] </strong>******************************************************************************************************************<strong>
changed: [192.168.250.58]
changed: [192.168.250.68]

TASK [copy service file to remote] </strong>********************************************************************************************************<strong>
changed: [192.168.250.68]
changed: [192.168.250.58]

TASK [config index.html] </strong>******************************************************************************************************************<strong>
changed: [192.168.250.68]
changed: [192.168.250.58]

TASK [start service] </strong>**********************************************************************************************************************<strong>
changed: [192.168.250.58]
changed: [192.168.250.68]

PLAY RECAP </strong>**********************************************************************************************************************************
192.168.250.58 : ok=15 changed=15 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.250.68 : ok=15 changed=15 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

[root@Ansible-PRI ]#
[root@Ansible-PRI ]#curl 192.168.250.58
192.168.250.58
[root@Ansible-PRI ]#curl 192.168.250.68
192.168.250.68
[root@Ansible-PRI ]#

2.5 验证安装

# 被控端服务器上验证httpd的安装
[root@Ansible-IP58 ]#ss -tlnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 *:80 *:* users:(("httpd",pid=49236,fd=4),
[root@Ansible-IP58 ]#
[root@Ansible-IP58 ]#curl localhost
192.168.250.58
[root@Ansible-IP58 ]#
[root@Ansible-IP58 ]#curl 192.168.250.58
192.168.250.58
[root@Ansible-IP58 ]#