颜色说明
绿色: 代表被管理主机没有被修改
黄色: 代表被管理主机发生变更
红色: 代表出现故障
参数
--version # ansible 版本信息
-v # 显示详细信息
-i # 主机清单文件路径,默认在/etc/ansible/hosts
-m # 使用的模块名称,默认使用command模块
-a # 使用的模块参数,模块的具体动作
-k # 提示输入ssh密码,而不使用基于ssh的密钥认证
-C # 模拟执行测试,但不会真的执行
-T # 执行命令的超时
example
hosts
[web]
192.168.101.28 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='111111'
192.168.101.15 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass='111111'
执行
[root@localhost ~]# ansible web -m ping -i ./hosts
192.168.101.28 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.101.15 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
可能会出现问题 host_key_checking
免密登录
# 生成公钥和私钥
ssh-keygen
# 把公钥匙拷贝到指定机器中
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.101.15
# 那么就可以免密登录15这台服务器了
# 此时 15 这台服务器的 /root/.ssh目录中的authorized_keys便会添加一条公钥
[root@localhost .ssh]# cat /root/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDK7KpTXRal9YQ5VlN8Hwav11ggYd6DEwEH2V3uWWJLb9F9xuwzIOpehapHmDgO7vRIzy8+5392mPdBkF+qsa3OOA7GK6gGPg6CDa0dUcfumo7QSkE+M8YfxefvIZGQXHSEDOHJnc2m/KPizus7K5bV0M3D9w0HxGGDbKaWBGQH2lt8gWAznvYaqV5wiHN6KCVd74Lz3DqHYLG74JRA5x3kVwDgGjEDH/0KNexQQsmQ9nG4suWp2JkDQBCaoEU3wtGQ1wf27QNmnrL5postrsbzzBX2zN7hHPIqh6XUBTzMEBJtyUtt5qrM/MlZFIO3pkcVz2g8yA3tUgRSOLyd+z6T root@localhost.localdomain
为主机命名
hosts
[web]
测试服务器 ansible_ssh_host=192.168.101.15
测试服务器2 ansible_ssh_host=192.168.101.28
[root@localhost ~]# ansible web -m ping -i ./hosts
测试服务器 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
测试服务器2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
ad-hoc
ansible-doc-l # 查看所有模块说明
ansible-doc copy # 查看指定模块方法
ansible-dock -s copy # 查看指定模块参数
常用模块
command # 执行shell命令(不支持管道符等特殊字符)
shell # 执行shell命令
script # 执行shell脚本
yum_repository # 配置yum仓库
yum # 安装软件
copy # 变更配置文件
file # 创建文件或目录
service # 启动与停止服务
mount # 挂载设备
cron # 定时任务
get_url # 下载软件
firewalld # 防火墙
selinux # selinux
Example
Command模块
不能使用管道符等特殊字符
[root@zhangsan ~]# ansible web -m command -a 'df -h' -i ./hosts
192.168.101.15 | CHANGED | rc=0 >>
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root 50G 3.2G 47G 7% /
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 18M 1.9G 1% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/mapper/centos-home 46G 33M 46G 1% /home
/dev/sda1 1014M 145M 870M 15% /boot
tmpfs 379M 0 379M 0% /run/user/0
overlay 50G 3.2G 47G 7% /var/lib/docker/overlay2/bef255a75bec68c23cdc64b4ab841d45cee96266edd4607e6eea6ffc644639eb/merged
shm 64M 0 64M 0% /var/lib/docker/containers/0195f9ca948a6689b4467b75d01ef014ce1db6f9c5835c24ee5de85670b1639b/mounts/shm
overlay 50G 3.2G 47G 7% /var/lib/docker/overlay2/36db0f3cbe48e6cfda85a7ac485ec76b9c5abf673657e2dbd8511d13ec1f0cbe/merged
shm 64M 0 64M 0% /var/lib/docker/containers/76ed696b5f68f18fde74590b308c6ff44f34e630ccb54372dd513cf47ee58d87/mounts/shm
[root@zhangsan ~]# ansible web -m command -a 'free -h' -i ./hosts
192.168.101.15 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 3.7G 764M 1.1G 17M 1.8G 2.6G
Swap: 0B 0B 0B
Shell模块
用来执行shell命令,可以使用管道符等特殊字符
[root@zhangsan ~]# ansible web -m shell -a 'ps aux | grep nginx' -i hosts
192.168.101.15 | CHANGED | rc=0 >>
root 757 0.0 0.0 20556 1560 ? Ss 10月25 0:00 nginx: master process /usr/local/nginx/sbin/nginx -g daemon off;
nobody 792 0.0 0.0 21004 1560 ? S 10月25 0:00 nginx: worker process
root 11535 0.0 0.1 123780 5956 ? Ss 10月24 0:00 nginx: master process nginx
nginx 11865 0.0 0.1 124252 4444 ? S 10月24 0:00 nginx: worker process
root 12705 0.0 0.0 113280 1208 pts/0 S+ 13:55 0:00 /bin/sh -c ps aux | grep nginx
root 12707 0.0 0.0 112832 956 pts/0 S+ 13:55 0:00 grep nginx
script模块
用来执行shell脚本
test.sh
#!/bin/bash
yum -y install vsftpd
[root@zhangsan ~]# ansible web -m script -a './test.sh' -i hosts
192.168.101.15 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.101.15 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.101.15 closed."
],
"stdout": "已加载插件:fastestmirror\r\nDetermining fastest mirrors\r\n * base: mirrors.aliyun.com\r\n * extras: mirrors.aliyun.com\r\n * updates: mirrors.aliyun.com\r\n\rbase | 3.6 kB 00:00 \r\n\rdocker-ce-stable | 3.5 kB 00:00 \r\n\repel | 4.7 kB 00:00 \r\n\rextras | 2.9 kB 00:00 \r\n\rkubernetes/signature | 454 B 00:00 \r\n\rkubernetes/signature | 1.4 kB 00:00 !!! \r\n\rupdates | 2.9 kB 00:00 \r\n正在解决依赖关系\r\n--> 正在检查事务\r\n---> 软件包 vsftpd.x86_64.0.3.0.2-27.el7 将被 安装\r\n--> 解决依赖关系完成\r\n\r\n依赖关系解决\r\n\r\n================================================================================\r\n Package 架构 版本 源 大小\r\n================================================================================\r\n正在安装:\r\n vsftpd x86_64 3.0.2-27.el7 base 172 k\r\n\r\n事务概要\r\n================================================================================\r\n安装 1 软件包\r\n\r\n总下载量:172 k\r\n安装大小:353 k\r\nDownloading packages:\r\n\rvsftpd-3.0.2-27.el7.x86_64.rpm | 172 kB 00:00 \r\nRunning transaction check\r\nRunning transaction test\r\nTransaction test succeeded\r\nRunning transaction\r\n\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [ ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [###### ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [########### ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [############## ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [############### ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [################ ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [##################### ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [###################### ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [####################### ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [######################## ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [######################### ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [########################## ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [########################### ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [############################ ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [############################# ] 1/1\r 正在安装 : vsftpd-3.0.2-27.el7.x86_64 1/1 \r\n\r 验证中 : vsftpd-3.0.2-27.el7.x86_64 1/1 \r\n\r\n已安装:\r\n vsftpd.x86_64 0:3.0.2-27.el7 \r\n\r\n完毕!\r\n",
"stdout_lines": [
"已加载插件:fastestmirror",
"Determining fastest mirrors",
" * base: mirrors.aliyun.com",
" * extras: mirrors.aliyun.com",
" * updates: mirrors.aliyun.com",
"",
"base | 3.6 kB 00:00 ",
"",
"docker-ce-stable | 3.5 kB 00:00 ",
"",
"epel | 4.7 kB 00:00 ",
"",
"extras | 2.9 kB 00:00 ",
"",
"kubernetes/signature | 454 B 00:00 ",
"",
"kubernetes/signature | 1.4 kB 00:00 !!! ",
"",
"updates | 2.9 kB 00:00 ",
"正在解决依赖关系",
"--> 正在检查事务",
"---> 软件包 vsftpd.x86_64.0.3.0.2-27.el7 将被 安装",
"--> 解决依赖关系完成",
"",
"依赖关系解决",
"",
"================================================================================",
" Package 架构 版本 源 大小",
"================================================================================",
"正在安装:",
" vsftpd x86_64 3.0.2-27.el7 base 172 k",
"",
"事务概要",
"================================================================================",
"安装 1 软件包",
"",
"总下载量:172 k",
"安装大小:353 k",
"Downloading packages:",
"",
"vsftpd-3.0.2-27.el7.x86_64.rpm | 172 kB 00:00 ",
"Running transaction check",
"Running transaction test",
"Transaction test succeeded",
"Running transaction",
"",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [ ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [###### ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [########### ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [############## ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [############### ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [################ ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [##################### ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [###################### ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [####################### ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [######################## ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [######################### ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [########################## ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [########################### ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [############################ ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 [############################# ] 1/1",
" 正在安装 : vsftpd-3.0.2-27.el7.x86_64 1/1 ",
"",
" 验证中 : vsftpd-3.0.2-27.el7.x86_64 1/1 ",
"",
"已安装:",
" vsftpd.x86_64 0:3.0.2-27.el7 ",
"",
"完毕!"
]
}
Yum模块
name
httpd # 指定要安装的软件包名称
file:// # 指定本地安装路径(yum localinstall 本地rpm包)
http:// # 指定yum源(从远程仓库获取)
state # 指定使用yun的方法动作
installed, present # 安装软件包
removed, absent # 移除软件
latest # 安装最新软件包
安装
[root@zhangsan ~]# ansible web -m yum -a 'name=httpd state=present' -i ./hosts
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"installed": [
"httpd"
]
},
"msg": "",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.aliyun.com\n * extras: mirrors.aliyun.com\n * updates: mirrors.aliyun.com\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-93.el7.centos will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n httpd x86_64 2.4.6-93.el7.centos base 2.7 M\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 2.7 M\nInstalled size: 9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : httpd-2.4.6-93.el7.centos.x86_64 1/1 \n Verifying : httpd-2.4.6-93.el7.centos.x86_64 1/1 \n\nInstalled:\n httpd.x86_64 0:2.4.6-93.el7.centos \n\nComplete!\n"
]
}
卸载
[root@zhangsan ~]# ansible web -m yum -a 'name=httpd state=absent' -i ./hosts
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"removed": [
"httpd"
]
},
"msg": "",
"rc": 0,
"results": [
"已加载插件:fastestmirror\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 httpd.x86_64.0.2.4.6-93.el7.centos 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package 架构 版本 源 大小\n================================================================================\n正在删除:\n httpd x86_64 2.4.6-93.el7.centos @base 9.4 M\n\n事务概要\n================================================================================\n移除 1 软件包\n\n安装大小:9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n 正在删除 : httpd-2.4.6-93.el7.centos.x86_64 1/1 \n 验证中 : httpd-2.4.6-93.el7.centos.x86_64 1/1 \n\n删除:\n httpd.x86_64 0:2.4.6-93.el7.centos \n\n完毕!\n"
]
}
Copy模块
src # 源文件
dest # 目标路径
backup # 传输过去的文件进行备份
content # 直接批量在被管理端文件中添加内容
group # 指定文件属组信息
owner # 指定文件属主信息
mode # 文件权限
拷贝文件
[root@zhangsan ~]# ansible web -m copy -a 'src=/etc/passwd dest=/tmp/passwd_copy' -i ./hosts
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "8256a0b27707bf2ac7aef8c45335eee24854152e",
"dest": "/tmp/passwd_copy",
"gid": 0,
"group": "root",
"md5sum": "160858c4b4ac90155f7da05d396db308",
"mode": "0644",
"owner": "root",
"size": 1007,
"src": "/root/.ansible/tmp/ansible-tmp-1603190747.93-9270-39814859258206/source",
"state": "file",
"uid": 0
}
修改内容
内容会被替换
[root@zhangsan ~]# ansible web -m copy -a 'content="hello world" dest=/tmp/passwd_copy' -i ./hosts
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
"dest": "/tmp/passwd_copy",
"gid": 0,
"group": "root",
"md5sum": "5eb63bbbe01eeed093cb22bb8f5acdc3",
"mode": "0755",
"owner": "root",
"size": 11,
"src": "/root/.ansible/tmp/ansible-tmp-1603191296.79-9342-270551071927816/source",
"state": "file",
"uid": 0
}
File模块
path # 远程主机目录或文件信息
recurse # 递归授权
state
directory # 在被管理端创建目录
touch # 在远端创建文件
link # link或hand表示创建链接文件
absent # 删除文件或目录
mode # 设置文件或目录权限
owner # 设置文件或目录属主
group # 设置文件或目录属组
创建目录
[root@zhangsan ~]# ansible web -m file -a 'path=/tmp/test state=directory' -i ./hosts
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/tmp/test",
"size": 6,
"state": "directory",
"uid": 0
}
删除目录
[root@zhangsan ~]# ansible web -m file -a 'path=/tmp/test state=absent' -i ./hosts
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"path": "/tmp/test",
"state": "absent"
}
group模块
name # 指定创建的组名
gid # 指定组的gid
state
absent # 移除被管理端的组
present # 创建被管理段的组
创建组
[root@zhangsan ~]# ansible web -m group -a 'name=t1 state=present' -i ./hosts
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 1000,
"name": "t1",
"state": "present",
"system": false
}
删除组
[root@zhangsan ~]# ansible web -m group -a 'name=t1 state=absent' -i ./hosts
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "t1",
"state": "absent"
}
user模块
uid # 指定用户的uid
group # 指定用户的组
groups # 指定附加组
password # 给用户添加密码(单引号)
shell # 指定用户登录的shell
create_home # 是否创建家目录
创建普通用户
[root@zhangsan ~]# ansible web -m user -a 'name=testuser shell=/bin/bash create_home=true' -i ./hosts
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1000,
"home": "/home/testuser",
"name": "testuser",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1000
}
创建不能登录的用户
[root@zhangsan ~]# ansible web -m user -a 'name=testuser2 shell=/sbin/nologin create_home=false' -i ./hosts
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": false,
"group": 1001,
"home": "/home/testuser2",
"name": "testuser2",
"shell": "/sbin/nologin",
"state": "present",
"system": false,
"uid": 1001
}
Selinux
关闭selinux
查看selinux状态
[root@zhangsan ~]# ansible web -m shell -a 'getenforce' -i ./hosts
192.168.101.15 | CHANGED | rc=0 >>
Enforcing
重启后生效
[root@zhangsan ~]# ansible web -m selinux -a 'state=disabled' -i ./hosts
[WARNING]: SELinux state temporarily changed from 'enforcing' to 'permissive'. State change will take effect next reboot.
192.168.101.15 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"configfile": "/etc/selinux/config",
"msg": "Config SELinux state changed from 'enforcing' to 'disabled'",
"policy": "targeted",
"reboot_required": true,
"state": "disabled"
}
[root@zhangsan ~]# ansible web -m shell -a 'getenforce' -i ./hosts
192.168.101.15 | CHANGED | rc=0 >>
Permissive
临时关闭
[root@zhangsan ~]# ansible web -m shell -a 'setenforce 0' -i ./hosts
192.168.101.15 | CHANGED | rc=0 >>
Setup模块
查看所有详细信息
[root@zhangsan ~]# ansible web -m setup -i ./hosts
192.168.101.15 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.101.15"
],
"ansible_all_ipv6_addresses": [
"fe80::30f3:dfc2:af2d:658a"
],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "12/12/2018",
"ansible_bios_version": "6.00",
"ansible_cmdline": {
"BOOT_IMAGE": "/vmlinuz-3.10.0-957.el7.x86_64",
"LANG": "en_US.UTF-8",
"crashkernel": "auto",
"quiet": true,
"rd.lvm.lv": "centos/swap",
"rhgb": true,
"ro": true,
"root": "/dev/mapper/centos-root"
},
"ansible_date_time": {
"date": "2020-11-03",
"day": "03",
"epoch": "1604408353",
"hour": "07",
"iso8601": "2020-11-03T12:59:13Z",
"iso8601_basic": "20201103T075913324409",
"iso8601_basic_short": "20201103T075913",
"iso8601_micro": "2020-11-03T12:59:13.324409Z",
"minute": "59",
"month": "11",
"second": "13",
"time": "07:59:13",
"tz": "EST",
"tz_offset": "-0500",
"weekday": "星期二",
"weekday_number": "2",
"weeknumber": "44",
"year": "2020"
},
"ansible_default_ipv4": {
"address": "192.168.101.15",
"alias": "ens192",
"broadcast": "192.168.101.255",
"gateway": "192.168.101.1",
"interface": "ens192",
"macaddress": "00:0c:29:c3:a7:8e",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "192.168.101.0",
"type": "ether"
},
......
获取IP地址
[root@zhangsan ~]# ansible web -m setup -a 'filter=ansible_default_ipv4' -i ./hosts
192.168.101.15 | SUCCESS => {
"ansible_facts": {
"ansible_default_ipv4": {
"address": "192.168.101.15",
"alias": "ens192",
"broadcast": "192.168.101.255",
"gateway": "192.168.101.1",
"interface": "ens192",
"macaddress": "00:0c:29:c3:a7:8e",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "192.168.101.0",
"type": "ether"
},
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
Playbook
example.yml
- hosts: web
tasks:
- name: touch a file
file: name=/tmp/hello state=touch
检查语法
[root@zhangsan ~]# ansible-playbook --syntax-check example.yml -i ./hosts
playbook: example.yml
模拟执行(不是真的执行)
[root@zhangsan ~]# ansible-playbook -C example.yml -i ./hosts
PLAY [web] **********************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************
ok: [192.168.101.15]
TASK [touch a file] *************************************************************************************************************************
ok: [192.168.101.15]
PLAY RECAP **********************************************************************************************************************************
192.168.101.15 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
执行playbook
[root@zhangsan ~]# ansible-playbook example.yml -i ./hosts
PLAY [web] **********************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************
ok: [192.168.101.15]
TASK [touch a file] *************************************************************************************************************************
changed: [192.168.101.15]
PLAY RECAP **********************************************************************************************************************************
192.168.101.15 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Playbook定义变量
example.yml
- hosts: web
vars:
filename: t1 # 定义变量
tasks:
- name: touch a file
file: name=/tmp/{{filename}} state=touch
使用变量
[root@zhangsan ~]# ansible-playbook example.yml -i ./hosts
PLAY [web] **********************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************
ok: [192.168.101.15]
TASK [touch a file] *************************************************************************************************************************
changed: [192.168.101.15]
PLAY RECAP **********************************************************************************************************************************
192.168.101.15 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
传参
example.yml
- hosts: web
tasks:
- name: touch a file
file: name=/tmp/{{filename}} state=touch
--extra-vars filename=t2
[root@zhangsan ~]# ansible-playbook -C example.yml --extra-vars 'filename=t2' -i ./hosts
PLAY [web] **********************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************
ok: [192.168.101.15]
TASK [touch a file] *************************************************************************************************************************
ok: [192.168.101.15]
PLAY RECAP **********************************************************************************************************************************
192.168.101.15 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
主机组中定义变量
hosts
[web]
192.168.101.15
[web:vars]
filename=t3
example.yml
- hosts: all
tasks:
- name: touch a file
file: name=/tmp/{{filename}} state=touch
[root@zhangsan ~]# ansible-playbook example.yml -i ./hosts
PLAY [all] **********************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************
ok: [192.168.101.15]
TASK [touch a file] *************************************************************************************************************************
changed: [192.168.101.15]
PLAY RECAP **********************************************************************************************************************************
192.168.101.15 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
变量传参优先级
extra-vars外置传参的优先级最高 [所有执行主机都生效]- 定义在yml文件中的优先级第二 [所有主机都生效]
hosts文件中定义的变量优先级最低 [当前主机组定义会生效]
Playbook注册变量
注册变量: register关键字可以存储指定命令的输出结果到一个自定义变量中
example.yml
- hosts: web
tasks:
- name:
shell: netstat -luntp
register: test
- name: get listen port
debug: msg={{test.stdout_lines}}
[root@zhangsan ~]# ansible-playbook example.yml -i ./hosts
PLAY [web] **********************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************
ok: [192.168.101.15]
TASK [shell] ********************************************************************************************************************************
changed: [192.168.101.15]
TASK [get listen port] **********************************************************************************************************************
ok: [192.168.101.15] => {
"msg": [
"Active Internet connections (only servers)",
"Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name ",
"tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 6088/sshd ",
"tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 6400/master ",
"tcp6 0 0 :::22 :::* LISTEN 6088/sshd ",
"tcp6 0 0 ::1:25 :::* LISTEN 6400/master ",
"udp 0 0 0.0.0.0:68 0.0.0.0:* 5896/dhclient ",
"udp 0 0 127.0.0.1:323 0.0.0.0:* 5552/chronyd ",
"udp6 0 0 ::1:323 :::* 5552/chronyd "
]
}
PLAY RECAP **********************************************************************************************************************************
192.168.101.15 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
facts变量
facts是ansible中一个非常重要的元素, facts中包含了被采集主机的一些基本信息,包括:被采集端的主机名,CPU,磁盘等一些基本信息。有时候我们需要通过对不同主机设置不同的主机名,此时我们就可以使用facts变量。这些变量是setup模块中的。
如果开启facts会导致采集速度变慢(可以通过 gather_facts: no 关闭facts采集)
- hosts: web
tasks:
- name: Installed Memcached
yum: name=memcached state=present
- name: Configure Memcached
template: src=./memcached.j2 dest=/etc/sysconfig/memcached
- name: Start Memcached
service: name=memcached state=started enabled=yes
[root@zhangsan ~]# ansible-playbook example.yml -C -i ./hosts
PLAY [web] *********************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.101.15]
TASK [Installed Memcached] *****************************************************************************************************
changed: [192.168.101.15]
TASK [Configure Memcached] *****************************************************************************************************
changed: [192.168.101.15]
TASK [Start Memcached] *********************************************************************************************************
changed: [192.168.101.15]
PLAY RECAP *********************************************************************************************************************
192.168.101.15 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
条件语句
我们可能会有这样的需求,需要根据不同的操作系统安装相同的软件包。但是不同的系统软件包的名称可能是不一样的,比如apache在ubuntu系统上的软件包名是httpd2, 在centos操作系统上的软件包名称是httpd,因此我们需要的playbook中引入条件判断语句
example.yml
- hosts: web
tasks:
- name: Installed httpd Server
yum: name=httpd state=present
when: ansible_distribution == "CentOS"
- name: Installed httpd Server
apt: name=httpd2 state=present
when: ansible_distribution == "Ubuntu"
[root@zhangsan ~]# ansible-playbook example.yml -C -i ./hosts
PLAY [web] *********************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.101.15]
TASK [Installed httpd Server] **************************************************************************************************
changed: [192.168.101.15]
TASK [Installed httpd Server] **************************************************************************************************
skipping: [192.168.101.15]
PLAY RECAP *********************************************************************************************************************
192.168.101.15 : ok=2 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
实例: 给 web 开头的主机名添加仓库地址
- hosts: web
tasks:
- name: Add Nginx Repository
yum_repository:
name: nginx
description: Nginx Yum Repository
baseurl: http://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
when: (ansible_hostname is match ("web*")) or (ansible_hostname is match ("lb*"))
[root@zhangsan ~]# ansible-playbook example.yml -C -i ./hosts
PLAY [web] *********************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.101.15]
TASK [Add Nginx Repository] ****************************************************************************************************
changed: [192.168.101.15]
PLAY RECAP *********************************************************************************************************************
192.168.101.15 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
循环语句
有时候我们需要对多台服务器安装多个不一样的服务,比如说
mysql,httpd等, 如果安装之前的方法,我们需要写很多次安装,效率差,因此我们可以使用playbook中的循环语句来进行添加
循环启动多个服务
example.yml
- hosts: all
tasks:
- name: start httpd firewalld
systemd: name={{ item }} state=started
with_items:
- httpd
- firewalld
[root@zhangsan ~]# ansible-playbook example.yml -C -i ./hosts
PLAY [all] *********************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.101.15]
TASK [start httpd firewalld] ***************************************************************************************************
changed: [192.168.101.15] => (item=httpd)
ok: [192.168.101.15] => (item=firewalld)
PLAY RECAP *********************************************************************************************************************
192.168.101.15 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
使用定义变量方式循环安装软件包
[root@zhangsan ~]# cat example.yml
- hosts: web
tasks:
- name: ensure a list of packages installed
yum: name={{ packages }} state=present
vars:
packages:
- httpd
- httpd-tools
[root@zhangsan ~]# ansible-playbook example.yml -C -i ./hosts
PLAY [web] *********************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.101.15]
TASK [ensure a list of packages installed] *************************************************************************************
changed: [192.168.101.15]
PLAY RECAP *********************************************************************************************************************
192.168.101.15 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Handlers触发器
当我们安装好一个服务,并且将配置文件推到被控制端的服务器之后,被控端服务并不会重启被控端的服务,因此我们需要一个策略,在我们安装以及配置好服务后,通过这个策略重启服务
[root@zhangsan ~]# cat example.yml
- hosts: web
vars:
- http_port: 8060
tasks:
- name: install http server
yum: name=httpd state=present
- name: configure httpd server
template: src=./httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- Restart Httpd Server
- Restart PHP Server
- name: start httpd server
service: name=httpd state=started enabled=yes
handlers:
- name: Restart Httpd Server
systemd: name=httpd state=restarted
- name: Restart PHP Server
systemd: name=php-fpm state=restarted
[root@zhangsan ~]# ansible-playbook example.yml -C -i ./hosts
PLAY [web] *********************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.101.15]
TASK [install http server] *****************************************************************************************************
ok: [192.168.101.15]
TASK [configure httpd server] **************************************************************************************************
changed: [192.168.101.15]
TASK [start httpd server] ******************************************************************************************************
changed: [192.168.101.15]
RUNNING HANDLER [Restart Httpd Server] *****************************************************************************************
changed: [192.168.101.15]
RUNNING HANDLER [Restart PHP Server] *******************************************************************************************
changed: [192.168.101.15]
PLAY RECAP *********************************************************************************************************************
192.168.101.15 : ok=6 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Tags
tags主要是用来调试的,因为我们在写playbook的时候,可能会有很多个 task任务,因此我们可以给一些tasks任务打上一些标记,执行的时候,可以根据tag标记来执行对应的任务。
example.yml
- hosts: all
tasks:
- name: restart httpd server
service: name=httpd state=restarted enabled=yes
tags:
- restart_httpd
- name: restart firewalld server
service: name=firewalld state=restarted enabled=yes
tags:
- restart_firewalld
列出所有tag
[root@zhangsan ~]# ansible-playbook example.yml --list-tags -i ./hosts
playbook: example.yml
play #1 (all): all TAGS: []
TASK TAGS: [restart_firewalld, restart_httpd]
运行指定tag
[root@zhangsan ~]# ansible-playbook example.yml -t restart_httpd -i ./hosts
PLAY [all] *********************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.101.15]
TASK [restart httpd server] ****************************************************************************************************
changed: [192.168.101.15]
PLAY RECAP *********************************************************************************************************************
192.168.101.15 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
忽略错误
有时候由于上一个Playbook可能执行出错,导致整个程序不能执行下去,如果我们还想继续执行下去的话,可以使用忽略错误这个选项
- hosts: web
tasks:
- name: Ignore Error
command: /bin/false
ignore_errors: yes
# 上面如果不忽略错误就会因为报错而退出执行
- name: touch new file
file: path=/tmp/test_ignore state=touch
[root@zhangsan ~]# ansible-playbook example.yml -i ./hosts
PLAY [web] *********************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.101.15]
TASK [Ignore Error] ************************************************************************************************************
fatal: [192.168.101.15]: FAILED! => {"changed": true, "cmd": ["/bin/false"], "delta": "0:00:00.006053", "end": "2020-11-03 10:32:41.946471", "msg": "non-zero return code", "rc": 1, "start": "2020-11-03 10:32:41.940418", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring
TASK [touch new file] **********************************************************************************************************
changed: [192.168.101.15]
PLAY RECAP *********************************************************************************************************************
192.168.101.15 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
Jinja2模板引擎
[root@zhangsan ~]# cat ./database.conf
host=127.0.0.1
port=3306
username=root
password={{ password }}
example.yml
- hosts: web
tasks:
- name: copy config file
template: src=./database.conf dest=/tmp/database.conf
[root@zhangsan ~]# ansible-playbook example.yml --extra-vars 'password=111111' -i ./hosts
PLAY [web] *********************************************************************************************************************
TASK [Gathering Facts] *********************************************************************************************************
ok: [192.168.101.15]
TASK [copy config file] ********************************************************************************************************
changed: [192.168.101.15]
PLAY RECAP *********************************************************************************************************************
192.168.101.15 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
目标主机
[root@localhost tmp]# cat /tmp/database.conf
host=127.0.0.1
port=3306
username=root
password=111111