Ansible PlayBook初识
什么是PlayBook
PlayBook,意为“剧本”或“兵书”,由以下部分组成:
- play:定义主机的角色(主角还是配角,找哪个明星)
- task:定义具体执行的任务(角色的台词和动作)
- playbook:由一个或多个play(角色)组成,一个play(角色)可以包含多个task(台词,动作)
简单理解为:使用不同的模块完成一件事情。
文件格式:
- Ansible中的“剧本文件”以
.yml
结尾。 - SaltStack中的“剧本文件”以
.sls
结尾。 - 两者都使用YAML语法。
- ansible-playbook –syntax-check wget.yml检查文件内容语法
PlayBook与ad-hoc
- PlayBook语法展现更直观。
- PlayBook可以持久使用,而ad-hoc无法持久使用。
PlayBook—《孙子兵法》编写
- host:对哪些主机进行操作(演员)
- remote_user:使用什么用户执行(通行证)
- tasks:具体执行任务(台词和动作)
YAML语法
- 缩进:YAML使用固定的缩进风格表示层级结构,每个缩进由两个空格组成,不能使用TAB。
- 冒号:以冒号结尾的除外,其他所有冒号后面所有必须有空格。
- 短横线:表示列表项,使用一个短横线加一个空格,多个项使用同样的缩进级别作为同一列表。
示例:
yum:
name: vsftpd
state: present
yum:
name:
- httpd
- nginx
- php-fpm
state: present
示例2:
playbook安装wget
1#编写yml
[root@ansible ansible]# cat wget.yml
- hosts: backup
tasks:
- name: Install wget
yum:
name: wget
state: present
2#检查playbook的语法
[root@ansible ansible]# ansible-playbook --syntax-check wget.yml
playbook: wget.yml
3#执行playbook
[root@ansible ansible]# ansible-playbook wget.yml
客户端信息获取 setup变量
[root@Ansible /etc/ansible]# ansible web01 -m setup
/usr/local/lib/python3.7/site-packages/ansible/parsing/vault/__init__.py:44: CryptographyDeprecationWarning: Python 3.7 is no longer supported by the Python core team and support for it is deprecated in cryptography. A future release of cryptography will remove support for Python 3.7.
from cryptography.exceptions import InvalidSignature
web01 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"10.0.0.7",
"172.16.1.7"
],
"ansible_all_ipv6_addresses": [
"fe80::20c:29ff:fe6d:9e0c",
"fe80::20c:29ff:fe6d:9e16"
],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "11/12/2020",
"ansible_bios_vendor": "Phoenix Technologies LTD",
"ansible_bios_version": "6.00",
"ansible_board_asset_tag": "NA",
"ansible_board_name": "440BX Desktop Reference Platform",
"ansible_board_serial": "None",
"ansible_board_vendor": "Intel Corporation",
"ansible_board_version": "None",
"ansible_chassis_asset_tag": "No Asset Tag",
"ansible_chassis_serial": "None",
"ansible_chassis_vendor": "No Enclosure",
"ansible_chassis_version": "N/A",
"ansible_cmdline": {
"BOOT_IMAGE": "/vmlinuz-4.19.90-52.22.v2207.ky10.x86_64",
"audit": "0",
"crashkernel": "1024M,high",
"quiet": true,
"resume": "UUID=fbeb99c6-031d-417c-8c36-d0471127b5d2",
playbook重构backup
定义主机清单
[root@ansible ansible]# cat /etc/ansible/hosts
nfs ansible_ssh_host=10.0.0.31
backup ansible_ssh_host=10.0.0.41
编写Playbook
backup-rsync.yml
[root@Ansible ~]# cat /etc/ansible/backup-rsync.yml
- hosts: backup
tasks:
- name: 01-Install rsync
yum:
name: rsync
state: present
- name: 02-Create group www
group:
name: www
gid: 666
state: present
- name: 03-Create user www
user:
name: www
uid: 666
group: www
shell: /sbin/nologin
create_home: false
state: present
- name: 04-Create user and pass
copy:
content: rsync_backup:123456
dest: /etc/rsync.user.password
mode: 0600
- name: 05-Create password
copy:
content: 123456
dest: /etc/rsync.password
mode: 0600
- name: 06-Create share directory
file:
path: /backup/
state: directory
owner: www
group: www
- name: 07-Copy rsyncd.conf to backup
copy:
src: rsyncd.conf
dest: /etc/
- name: 08-Systemd rsyncd
systemd:
name: rsyncd
state: started
enabled: yes
检查Playbook语法
[root@ansible ansible]# ansible-playbook --syntax-check backup-rsync.yml
or
[root@ansible ansible]# ansible-playbook -C backup-rsync.yml #模拟运行
执行Playbook
[root@ansible ansible]# ansible-playbook backup-rsync.yml
测试,其他主机推
[root@Ansible ~]# rsync -av /etc/hosts rsync_backup@10.0.0.41::data
playbook重构nfs和lsync
定义主机清单
[root@ansible ansible]# cat /etc/ansible/hosts
nfs ansible_ssh_host=10.0.0.31
backup ansible_ssh_host=10.0.0.41
编写Playbook
nfs-lsync.yml
[root@Ansible ~]# cat /etc/ansible/nfs-lsync.yml
- hosts: nfs
tasks:
- name: 01-Install nfs-utils
yum:
name: nfs-utils
state: present
- name: 02-Create exports
copy:
src: exports
dest: /etc/
- name: 03-Create group www
group:
name: www
gid: 666
state: present
- name: 04-Create user www
user:
name: www
uid: 666
group: www
shell: /sbin/nologin
create_home: false
state: present
- name: 05-Create dir /date
file:
path: /data
state: directory
owner: www
group: www
- name: 06-Copy tar static data
unarchive:
src: data.tar.gz
dest: /
#creates: /data
- name: 07-systemd nfs
systemd:
name: nfs
state: started
enabled: yes
- name: 08-Install lsyncd
yum:
name: lsyncd
state: present
- name: 09-Create lsyncd.conf
copy:
src: lsyncd.conf
dest: /etc/
- name: 10-Create rsync.passwd
copy:
content: 123456
dest: /etc/rsync.passwd
mode: 0600
- name: 11-systemd lsyncd
systemd:
name: lsyncd
state: started
enabled: yes
检查Playbook语法
执行Playbook
测试,其他主机推
nfs测试:别的主机挂载创建文件,nfs服务器查看
lsync测试:在监控目录创建文件,在backup模块服务器查看
playbook重构db01
- 重构mariadb
- 两种方法,一种从新单台搭建,mysqldump出来使用。另一种用旧的all.sql数据库数据
定义主机清单
[root@ansible ansible]# cat /etc/ansible/hosts
web01 ansible_ssh_host=10.0.0.7
web02 ansible_ssh_host=10.0.0.8
nfs ansible_ssh_host=10.0.0.31
backup ansible_ssh_host=10.0.0.41
db01 ansible_ssh_host=10.0.0.51
编写Playbook
/etc/ansible/db01.yml
[root@Ansible ~]# cat /etc/ansible/db01.yml
- hosts: db01
tasks:
- name: 01-install mariadb,pyt3
yum:
name: mariadb-server,python3-mysqlclient
state: present
- name: 02-start mariadb
systemd:
name: mariadb
state: started
enabled: yes
- name: 03-copy all.sql to db01
copy:
src: all.sql
dest: /root/
- name: 04-configure maridb
mysql_db:
login_user: root
login_host: localhost
login_port: 3306
name: all
target: /root/all.sql
state: import
- name: 05-restart mariadb
systemd:
name: mariadb
state: restarted
检查Playbook语法
执行Playbook
测试,其他主机推
远程连接数据库:mysql -h 10.0.0.51 -uhsc -p
查看数据库:show databases;
playbook重构web01
- 重构nginx、php、mariadb
定义主机清单
[root@ansible ansible]# cat /etc/ansible/hosts
web01 ansible_ssh_host=10.0.0.7
web02 ansible_ssh_host=10.0.0.8
nfs ansible_ssh_host=10.0.0.31
backup ansible_ssh_host=10.0.0.41
编写Playbook
/etc/ansible/webs.yml
[root@Ansible ~]# cat /etc/ansible/webs.yml
- hosts: web01
tasks:
- name: 01-create nginx.repo
yum_repository:
name: nginx
description: cnetos7 nginx.repo
baseurl: http://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
enabled: yes
- name: 02-install nginx-php-mariadb
yum:
name: nginx,php,php-bcmath,php-cli,php-common,php-devel,php-embedded,php-fpm,php-gd,php-intl,php-mbstring,php-mysqlnd,php-opcache,php-pdo,php-process,php-xml,php-json,mariadb-server
state: present
- name: 03-Create php/www.conf
copy:
src: www.conf
dest: /etc/php-fpm.d/
- name: 04-Create nginx.conf
copy:
src: www.conf
dest: /etc/nginx/
- name: 05-Create conf.d/wp.conf
copy:
src: wp.conf
dest: /etc/nginx/conf.d
- name: 06-Create rmove de
file:
path: /etc/nginx/conf.d/default.conf
state: absent
- name: 07-Create group www
group:
name: www
gid: 666
state: present
- name: 08-Create user www
user:
name: www
uid: 666
group: www
shell: /sbin/nologin
create_home: false
state: present
- name: 09-Create dir /code
file:
path: /code
state: directory
owner: www
group: www
- name: 10-systemd mariadb
systemd:
name: mariadb
state: stopped
enabled: no
- name: 11-systemd nginx
systemd:
name: nginx
state: started
enabled: yes
- name: 12-systemd php-fpm
systemd:
name: php-fpm
state: started
enabled: yes
- name: 13-mount nfs
mount:
path: /code
src: 172.16.1.31:/data
state: mounted
fstype: nfs
检查Playbook语法
执行Playbook
测试,其他主机推
访问网站测试
playbook一键重构集群
- 重构web01、nfs、backup、db01
- 两种方法,一种写到一个yml里执行,另一种写到一个脚本里执行脚本
脚本集合:
vim refactoring-all.sh
#!/bin/bash
sshpass -p 'haoshuaicong123.com' ssh-copy-id 10.0.0.31
sshpass -p 'haoshuaicong123.com' ssh-copy-id 10.0.0.41
sshpass -p 'haoshuaicong123.com' ssh-copy-id 10.0.0.51
sshpass -p 'haoshuaicong123.com' ssh-copy-id 10.0.0.7
ansible-playbook /etc/ansible/backup-rsync.yml
ansible-playbook /etc/ansible/nfs-lsync.yml
ansible-playbook /etc/ansible/db01.yml
ansible-playbook /etc/ansible/web01.yml
增加执行权限,执行
chmod +x refactoring-all.sh
sh -x refactoring-all.sh
测试,其他主机推
解析10.0.0.7
www.wp.com
访问网站测试
playbook模块使用说明:
各模块使用方法
- yum:用于在基于 Yum 的系统中管理软件包的安装、删除等操作。
- group:用于管理用户组的创建、删除等。
- user:用于管理用户的创建、删除等属性设置。
- copy:用于将文件从一处复制到另一处,也可直接创建包含指定内容的文件。
- file:用于管理文件和目录的状态,如创建、删除、设置权限等。
- systemd:用于管理系统服务,如启动、停止、重启服务以及设置服务开机自启状态。
- mysql_db:用于管理 MySQL 数据库相关操作,如导入数据库等。
- yum_repository:用于管理 Yum 仓库的配置。
- mount:用于管理文件系统的挂载操作。
- unarchive:用于解压归档文件。
1.yum 模块
- 语法:
yum:
name: <软件包名或软件包列表,逗号分隔>
state: <present|absent|latest等>
- 说明
name
:指定要操作的软件包名称。可以是单个软件包,也可以是多个软件包组成的列表。state
:present
表示安装软件包;absent
表示删除软件包;latest
表示安装最新版本的软件包。- 示例:
- name: 安装rsync
yum:
name: rsync
state: present
2.group 模块
- 语法:
group:
name: <用户组名>
gid: <组ID(可选)>
state: <present|absent>
- 说明
name
:指定要操作的用户组名称。gid
:指定用户组的组 ID,若不指定则系统自动分配。state
:present
表示创建用户组;absent
表示删除用户组。- 示例:
- name: 创建组www
group:
name: www
gid: 666
state: present
3.user 模块
- 语法:
user:
name: <用户名>
uid: <用户ID(可选)>
group: <所属组名>
shell: <用户默认shell(可选)>
create_home: <true|false(可选)>
state: <present|absent>
- 说明
name
:指定要操作的用户名。uid
:指定用户的用户 ID,若不指定则系统自动分配。group
:指定用户所属的用户组。shell
:指定用户的默认 shell,默认通常为/bin/bash
。create_home
:指定是否为用户创建家目录,默认true
。state
:present
表示创建用户;absent
表示删除用户。- 示例:
- name: 创建用户www
user:
name: www
uid: 666
group: www
shell: /sbin/nologin
create_home: false
state: present
4.copy 模块
- 语法:
copy:
src: <源文件路径(可选)>
dest: <目标文件路径>
mode: <文件权限(可选)>
content: <文件内容(可选)>
- 说明
src
:指定源文件的路径,若使用content
则可不填。dest
:指定目标文件的路径。mode
:指定目标文件的权限,格式如0600
。content
:用于直接指定文件内容,而不通过复制源文件。- 示例 1(复制文件):
- name: 复制rsyncd.conf到/etc/
copy:
src: rsyncd.conf
dest: /etc/
- 示例 2(创建含指定内容的文件):
- name: 创建用户和密码文件
copy:
content: rsync_backup:123456
dest: /etc/rsync.user.password
mode: 0600
5.file 模块
- 语法:
file:
path: <文件或目录路径>
state: <directory|file|link软连接|absent|touch等>
owner: <所有者(可选)>
group: <所属组(可选)>
- 说明
path
:指定要操作的文件或目录的路径。state
:directory
表示创建目录;file
表示创建文件;link
表示创建链接;absent
表示删除文件或目录;touch
表示创建或更新文件时间戳。owner
:指定文件或目录的所有者。group
:指定文件或目录的所属组。- 示例:
- name: 创建共享目录/backup
file:
path: /backup/
state: directory
owner: www
group: www
6.systemd 模块
- 语法:
systemd:
name: <服务名>
state: <started|stopped|restarted|reloaded|enabled|disabled等>
- 说明
name
:指定要操作的系统服务名称。state
:started
表示启动服务;stopped
表示停止服务;restarted
表示重启服务;reloaded
表示重新加载服务配置;enabled
表示设置服务开机自启;disabled
表示设置服务开机不自启。- 示例:
- name: 启动并设置开机自启rsyncd服务
systemd:
name: rsyncd
state: started
enabled: yes
7.mysql_db 模块
- 语法:
mysql_db:
login_user: <登录用户名>
login_host: <登录主机(可选)>
login_port: <登录端口(可选)>
name: <数据库名>
target: <导入文件路径(可选)>
state: <import等>
- 说明
login_user
:指定登录 MySQL 数据库的用户名。login_host
:指定登录的主机,默认localhost
。login_port
:指定登录的端口,默认3306
。name
:指定要操作的数据库名称。target
:指定要导入的 SQL 文件路径。state
:import
表示导入数据库。- 示例:
- name: 导入数据库
mysql_db:
login_user: root
login_host: localhost
login_port: 3306
name: all
target: /root/all.sql
state: import
8.yum_repository 模块
- 语法:
yum_repository:
name: <仓库名>
description: <仓库描述(可选)>
baseurl: <仓库地址>
gpgcheck: <yes|no(可选)>
enabled: <yes|no(可选)>
- 说明
name
:指定 Yum 仓库的名称。description
:对仓库的描述信息。baseurl
:指定仓库的 URL 地址。gpgcheck
:指定是否检查 GPG 签名,yes
表示检查,no
表示不检查。enabled
:指定该仓库是否启用,yes
表示启用,no
表示禁用。- 示例:
- name: 创建nginx.repo
yum_repository:
name: nginx
description: cnetos7 nginx.repo
baseurl: http://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
enabled: yes
9.mount 模块
- 功能:
通过 mount 命令进行挂载操作,可修改 /etc/fstab 实现永久挂载。 - mount 命令选项:
src
:原地址(nfs 服务端共享目录,例如 172.16.1.31/data)。path
:挂载点(指定源挂载到哪里)。fstype
:文件系统类型(指定文件系统,如 xfs、ext4、iso9660 等)。state
:参考如下值。- mount 模块的 state 参数可用值:
absent
:卸载并删除 /etc/fstab里的这条挂载。unmounted
:卸载不删除 /etc/fstab里的这条挂载。present
:仅修改 /etc/fstab添加开机挂载,不立即挂载。mounted
:立即挂载,并 /etc/fstab 添加开机自动挂载。remounted
:重新挂载设备,用于强制刷新挂载本身。- 语法:
mount:
path: <挂载点路径>
src: <源设备或远程共享路径>
state: <mounted|unmounted等>
fstype: <文件系统类型(可选)>
- 说明:
path
:指定要挂载的目标路径。src
:指定源设备或远程共享的路径。state
:mounted
表示挂载;unmounted
表示卸载。fstype
:指定文件系统类型,如nfs
、ext4
等。- 示例:
- name: 挂载NFS共享
mount:
path: /code
src: 172.16.1.31:/data
state: mounted
fstype: nfs
10.unarchive 模块
- 语法:
unarchive:
src: <归档文件路径>
dest: <解压目标目录>
creates: <文件或目录(可选)>
- 说明
src
:指定要解压的归档文件路径。dest
:指定解压后的目标目录。creates
:指定一个文件或目录,如果该文件或目录已存在,则不执行解压操作。- 示例:
- name: 解压静态数据
unarchive:
src: data.tar.gz
dest: /
11.debug 模块
- 语法:
debug:
msg: <要打印的消息内容>
- 说明
msg
:使用 Jinja2 模板语法来指定要打印的消息内容。可以是变量、表达式等。- 示例:
- name: print ng_re env
debug:
msg: "{{ ng_re }}"
这个示例的作用是打印ng_re
变量的值。通过debug
模块,在 Ansible 执行过程中可以输出调试信息,帮助排查问题。
12.notify 模块与 handlers
notify
并非一个独立的模块,而是 Ansible 中用于触发handlers
的一种机制。
handlers
是 Ansible 中一组任务的集合,只有在被notify
通知或者手动调用时才会执行。
- name: Configure Nginx Server
copy:
src: nginx.conf
dest: /etc/nginx/
notify: Restart Nginx Server
handlers:
- name: Restart Nginx Server
systemd:
name: nginx
state: restarted
when: ng_re.stderr_lines is search "ok"
此例中,若文件内容有变动,就会通知并触发名为Restart Nginx Server
的handler
。
13.mysql_user模块
tasks:
- name: Grant all privileges to hsc user
mysql_user:
name: hsc
host: '%'
password: 'hsc123.com'
priv: '*.*:ALL'
state: present
login_user: root # 用于登录MySQL的用户名
login_password: your_root_password # root用户的当前密码
解释:
模块:用于管理 MySQL 用户。
name
:要授予权限的 MySQL 用户名。host
:用户允许登录的主机,%
表示允许从任何主机登录。password
:用户的密码。priv
:授予的权限,*.*:ALL
表示对所有数据库的所有表授予所有权限。state: present
:确保用户存在并具有指定的权限。login_user
:用于登录 MySQL 的用户名,这里使用root
用户。login_password
:root
用户的当前密码。
14.mysql_db模块
mysql_db:
login_user: root # 用于登录MySQL的用户名
login_host: localhost # MySQL服务器的主机地址
login_port: 3306 # 连接MySQL服务器的端口号
login_password: hsc123.com # 登录MySQL的密码
name: wordpress # 要操作的数据库名称
state: present # 数据库的期望状态,present表示若不存在则创建
解释:
- 模块:用于管理 MySQL 数据库。
- login_user:指定登录 MySQL 数据库的用户名,此处为 root。
- login_host:指定 MySQL 服务器所在的主机地址,localhost表示本地。
- login_port:指定连接 MySQL 服务器的端口,默认是 3306。
- login_password:用于登录 MySQL 的密码,这里是hsc123.com。
- name:要进行操作(创建或检查是否存在)的数据库名字,这里是 wordpress。
- state:期望数据库所处的状态,present 表示如果数据库不存在就创建它。
15.loop循环
1. 基本概念
loop
允许你对一个列表、字典或其他可迭代对象中的每个元素执行相同的任务。它取代了早期 Ansible 版本中的with_*
系列的循环语句。
2. 使用示例
简单列表循环
- name: Install multiple packages
yum:
name: "{{ item }}"
state: present
loop:
- httpd
- mysql
- php
在这个例子中,yum
模块会对loop
中的每个软件包进行安装操作。item
是一个特殊的变量,它在每次循环时代表列表中的一个元素。
字典循环
- name: Create multiple users with specific UIDs
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
state: present
loop:
- { name: 'user1', uid: 1000 }
- { name: 'user2', uid: 1001 }
这里loop
是一个字典列表,item
在每次循环时会代表一个字典,通过item.name
和item.uid
可以访问字典中的键值。
3. 进阶用法
与条件语句结合
- name: Process items based on condition
debug:
msg: "Processing item: {{ item }}"
loop:
- a
- b
- c
when: item!= "b"
在这个例子中,when
条件语句用于筛选出item
不等于b
的元素进行处理。
嵌套循环
- name: Nested loops
debug:
msg: "Outer item: {{ outer_item }}, Inner item: {{ inner_item }}"
loop:
- outer1
- outer2
with_nested:
- [1, 2]
- [3, 4]
这里展示了一个嵌套循环的示例,外层循环遍历loop
中的元素,内层循环遍历with_nested
中的元素。
4. 注意事项
- 变量作用域:在循环内部定义的变量(如
item
)只在循环内部有效。 - 性能考虑:如果循环处理的数据量非常大,可能会影响执行效率,需要合理设计任务。
loop
模块极大地增强了 Ansible 在批量处理和自动化操作方面的能力,通过合理利用它,可以更高效地管理系统和部署应用。