当前位置:   article > 正文

Linux红帽认证工程师(RHCE)考试笔记(Ansible学习笔记)_[warning]: provided hosts list is empty, only loca

[warning]: provided hosts list is empty, only localhost is available. note t


写在前面: 

笔记是因为考红帽所以整理的,大都是老师的笔记,主要是常用模块整理,后面有些类似考试的实战题目,不是教程,教程建议大家到下面的学习网站,这篇博客适合温习用,层次有些乱,嘻嘻,生活加油,天天开心。

想学ansible却没有环境的小伙伴可以移步这里:从零搭建Linux+Docker+Ansible+kubernetes 学习环境(1*Master+3*Node)https://blog.csdn.net/sanhewuyang/article/details/120300517https://blog.csdn.net/sanhewuyang/article/details/120300517

建议学习网站:Ansible文档:Ansible Documentation — Ansible Documentation


Ansible是一款简洁、高效的运维自动化工具。只需要将ansible安装在主控机器上,就可以通过SSH协议实现针对大量受管服务器的批量化、剧本化的管理。通过过Ansible实现远程控制,主控机=被控机,通过SSH实现。基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。

ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:

  • (1)、连接插件connection plugins:负责和被监控端实现通信;
  • (2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
  • (3)、各种模块核心模块、command模块、自定义模块;
  • (4)、借助于插件完成记录日志邮件等功能;
  • (5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。

沟通是DevOps的关键。Ansible是第一款可以在整个IT范围读取和编写的自动化语言。它也是唯能够从头至尾自动化应用生命周期和持续交付管道的自动化引擎。
 

一、ANSIBLE概念和架构

Ansible架构中有两种计算机类型,即控制节点和受管主机。 Ansible在控制节点上安装和运行,计算机上也含有Ansible项目文件的副本。控制节点可以是管理员的笔记本电脑、多个管理员共享的系统,或者运行红帽Ansible Tower的服务器。

受管主机列在清单中,清单还可以将这些系统组织到组中,以便于集中管理。清单可以在静态文本文件中定义,或者通过从外部来源获取信息的脚本来动态确定。

Ansible用户无需编写复杂的脚本,而只要创建高级别play即可确保主机或主机组处于特定状态。 Play按该play指定的顺序对主机执行一系列任务。这些play通过采用YAML格式的文本文件来表达。包含一个或多个play的文件称为playbook

每个任务运行一个模块,即(使用Python, Powershell或某种其他语言编写的)一小段代码。各个模块基本上是您的工具包中的一个工具。Ansible随附了数百个实用模块,它们能够执行许多不同的自动化任务。它们可以作用于系统文件,安装软件或者进行AP调用。

在任务中使用时,模块通常确保计算机的某一特定方面处于特定的状态。例如,使用某一模块的任务可以确保某一文件存在且具有特定的权限和内容,而使用另一不同模块的任务可确保已挂载特定的文件系统。如果系统不处于指定的状态,任务应将它置于该状态。如果系统已处于该状态,则不执行任何操作。如果任务失败, Ansible的默认行为是对发生了错误的主机中止playbook的其余部分

QA任务、play和playbook设计为具有幂等性。这意味着,您可以在相同主机上多次安全地运行一个playbooko当您的系统处于正确状态时, playbook在运行时不会进行任何更改。这意味着,您应该能够在相同主机上多次安全地运行一个playbook。当您的系统处于正确状态时, playbook在运行时不应进行任何更改。您可以使用多个模块来运行任意命令。但是,您必须小心使用这些模块,以确保它们以幂等方式运行。

Ansible也使用插件。插件是您可以添加到Ansible中的代码,以对它进行扩展并使它适合新的用途和平台。

Ansible架构是无代理的。通常,当管理员运行Ansible Playbook或临时命令时,控制节点使用SSH (默认)或WinRM连接受管主机。这意味着客户端无需在受管主机上安装特定于Ansible的代理,也不需要允许将特殊的网络流量传输到某一非标准端口。

Ansible概念 

  • 控制机(节点):任何安装了Ansible的计算机。您可以通过从任何控制节点调用ansibleoransible-playbook命令来运行Ansible命令和剧本。您可以将安装了Python的任何计算机用作控制节点-便携式计算机,共享台式机和服务器都可以运行Ansible。但是,不能将Windows计算机用作控制节点。您可以有多个控制节点。
  • 受管机(节点):您使用Ansible管理的网络设备(和/或服务器)。受管节点有时也称为“主机”。未在受管节点上安装Ansible。
  • 主机清单:受管节点的列表。清单文件有时也称为“主机文件”。您的清单可以为每个受管节点指定诸如IP地址之类的信息。库存还可以组织受管节点,创建和嵌套组以便于扩展。
  • 模块:执行代码单元Ansible。从管理特定类型的数据库上的用户到管理特定类型的网络设备上的VLAN接口,每个模块都有特定的用途。您可以通过任务调用单个模块,也可以在剧本中调用多个不同的模块。
  • 任务:Ansible中的行动单位。您可以使用临时命令一次执行一个任务。
  • 剧本:保存任务的有序列表,以便您可以按该顺序重复运行这些任务。剧本可以包含变量以及任务。剧本采用YAML编写,易于阅读,编写,共享和理解。

二、安装和配置ansible环境  

学习环境:

查看yum 安装的文件位置 : rpm -ql  yum包名字

我要用control去控制另外的四台node[1...5]机器,这五台机器都是linux虚拟机。默认我们设置了Ip。做好了主机名映射。

1、ansible安装

软件包:ansible、sshpass、python3-jinja2、python3-pyramiko等

# yum  -y  install  ansible   //装包# ansible --version     //确认版本相关信息

需要的依赖包:

查看版本控制

查看主机清单 

  1. [root@control ~]# ansible 127.0.0.1 --list-hosts
  2. hosts (1):
  3. 127.0.0.1
  4. [root@control ~]# ansible all --list-hosts
  5. [WARNING]: provided hosts list is empty, only localhost is available. Note
  6. implicit localhost does not match 'all'
  7. hosts (0):
  8. [root@control ~]# ansible 127.0.0.1 -m ping
  9. 127.0.0.1 | SUCCESS => {
  10. "changed": false,
  11. "ping": "pong"
  12. }
  13. [root@control ~]# ansible 127.0.0.1 -m command -a 'uname -r'
  14. 127.0.0.1 | CHANGED | rc=0 >>
  15. 4.18.0-193.el8.x86_64
  16. [root@control ~]# ansible 127.0.0.1 -m command -a 'echo "sy"'
  17. 127.0.0.1 | CHANGED | rc=0 >>
  18. sy
  19. [root@control ~]# ansible 127.0.0.1 -m command -a 'echo sy"'
  20. ERROR! failed at splitting arguments, either an unbalanced jinja2 block or quotes: echo sy"
  21. [root@control ~]#

 Command 是默认模块,可以不写。OK。我们先简单尝试一下。

  • 使用 ansible all --list-hosts 命令可以查看主机列表。
  • 使用 ansible 127.0.0.1 -m ping 命令可以查看被控主机是否连接正常,这里使用ping模块
  • 使用 ansible 127.0.0.1 -m command -a 'bash 命令'  命令可以执行bash命令,这里使用command模块,-m command 可以省略。
  1. #查看主机清单
  2. [root@control ~]# ansible 127.0.0.1 --list-hosts
  3. hosts (1):
  4. 127.0.0.1
  5. [root@control ~]# ansible all --list-hosts
  6. [WARNING]: provided hosts list is empty, only localhost is available. Note
  7. implicit localhost does not match 'all'
  8. hosts (0):
  9. [root@control ~]# ansible 127.0.0.1 -m ping
  10. 127.0.0.1 | SUCCESS => {
  11. "changed": false,
  12. "ping": "pong"
  13. }
  14. [root@control ~]# ansible 127.0.0.1 -m command -a 'uname -r'
  15. 127.0.0.1 | CHANGED | rc=0 >>
  16. 4.18.0-193.el8.x86_64
  17. [root@control ~]# ansible 127.0.0.1 -m command -a 'echo "sy"'
  18. 127.0.0.1 | CHANGED | rc=0 >>
  19. sy
  20. [root@control ~]# ansible 127.0.0.1 -m command -a 'echo sy"'
  21. ERROR! failed at splitting arguments, either an unbalanced jinja2 block or quotes: echo sy"
  1. [root@control ~]# ansible 127.0.0.1 -u zhsan -a 'touch /zhanshan.txt'
  2. [WARNING]: Consider using the file module with state=touch rather than running
  3. 'touch'. If you need to use command because file is insufficient you can add
  4. 'warn: false' to this command task or set 'command_warnings=False' in
  5. ansible.cfg to get rid of this message.
  6. 127.0.0.1 | CHANGED | rc=0 >>
  7. [root@control ~]# useradd zhsan
  8. [root@control ~]# echo 123456 | passwd --stdin zhsan
  9. Changing password for user zhsan.
  10. passwd: all authentication tokens updated successfully.
  11. [root@control ~]# ansible 127.0.0.1 -u zhsan -a 'thuch /zhsan.file'
  12. 127.0.0.1 | FAILED | rc=2 >>
  13. [Errno 2] No such file or directory: 'thuch': 'thuch'
  14. [root@control ~]# ansible 127.0.0.1 -u zhsan -a 'tonch /zhsan.file'
  15. 127.0.0.1 | FAILED | rc=2 >>
  16. [Errno 2] No such file or directory: 'tonch': 'tonch'
  17. [root@control ~]# ansible 127.0.0.1 -u zhsan -a 'touch /zhsan.file'
  18. [WARNING]: Consider using the file module with state=touch rather than running
  19. 'touch'. If you need to use command because file is insufficient you can add
  20. 'warn: false' to this command task or set 'command_warnings=False' in
  21. ansible.cfg to get rid of this message.
  22. 127.0.0.1 | CHANGED | rc=0 >>
  23. [root@control ~]# ansible node1 -m ping
  24. [WARNING]: provided hosts list is empty, only localhost is available. Note
  25. that the implicit localhost does not match 'all'
  26. [WARNING]: Could not match supplied host pattern, ignoring: node1
  27. [root@control ~]# vim /etc/ansible/hosts
  28. [root@control ~]# ls
  29. anaconda-ks.cfg
  30. [root@control ~]# ansible node1 -m ping
  31. node1 | SUCCESS => {
  32. "ansible_facts": {
  33. "discovered_interpreter_python": "/usr/libexec/platform-python"
  34. },
  35. "changed": false,
  36. "ping": "pong"
  37. }
  38. [root@control ~]# ssh node1
  39. Last login: Thu Feb 11 01:18:11 2021 from 172.25.254.100
  40. [root@node1 ~]# useradd lisi
  41. [root@node1 ~]# echo 123456 | passwd --stdin lisi
  42. Changing password for user lisi.
  43. passwd: all authentication tokens updated successfully.
  44. [root@node1 ~]# quit
  45. -bash: quit: command not found
  46. [root@node1 ~]# exit
  47. logout
  48. Connection to node1 closed.
  49. [root@control ~]# ansible node1 -u lisi -k -a 'mkdir /tmp/lisidir'
  50. SSH password:
  51. [WARNING]: Consider using the file module with state=directory rather than
  52. running 'mkdir'. If you need to use command because file is insufficient you
  53. can add 'warn: false' to this command task or set 'command_warnings=False' in
  54. ansible.cfg to get rid of this message.
  55. node1 | CHANGED | rc=0 >>
  56. [root@control ~]# ansible node1 -u lisi -k -a 'mkdir /tmp/lisidir'
  57. SSH password:
  58. [WARNING]: Consider using the file module with state=directory rather than
  59. running 'mkdir'. If you need to use command because file is insufficient you
  60. can add 'warn: false' to this command task or set 'command_warnings=False' in
  61. ansible.cfg to get rid of this message.
  62. node1 | FAILED | rc=1 >>
  63. mkdir: cannot create directory ‘/tmp/lisidir’: File existsnon-zero return code

ansible环境配置文件

  • 全局配置:/etc/ansible/ansible.cfg(设置被管机,用户权限)
  • 默认主机清单:/etc/ansible/hosts //存放受管主机列表
  • 默认角色目录:/etc/ansible/roles //存放预设的各种任务角色资料
  • 默认用户身份:root
  • 扩展配置:
    •     ~/.ansible.cfg  //用户配置,会覆盖全局配置
    •     ./ansible.cfg  //工作目录配置(本文采用这种配置方式),会覆盖全局、用户配置

在用户目录下创建配置文件目录。ansible的默认解析配置文件的位置的优先级顺序是,(使用man ansible-config)

  • 目录配置文件,
  • 用户配置文件,
  • 默认配置文件。

在alice的家目录下创建配置文件

在编写配置文件的时候,我们可以参考默认的配置文件编写:

使用 ctrl + z 将当前vim挂到后台,然后打开默认配置文件的 vim /etc/ansible/ansible.cfg  ,copy到需要的之后,ctrl + z 挂到后台,然后使用 fg 1 打开挂到后台的之前的vim。

主配置文件 vim ansible.cfg

  1. [defaults]
  2. # 主机清单文件,就是要控制的主机列表
  3. inventory=inventory
  4. # 连接受管机器的远程的用户名
  5. remote_user=alice
  6. # 角色目录
  7. roles_path=roles
  8. # 设置用户的su 提权
  9. [privilege_escalation]
  10. become=True
  11. become_method=sudo
  12. become_user=root
  13. become_ask_pass=False

主机清单:

被控机列表,可以是 域名,IP,分组([组名]),聚合([组名:children]),也可以主动的设置用户名密码

  1. [test01] # 创建组,名字是test01
  2. node1 # test01组中的成员
  3. node2 # test01组中的成员
  4. [test02] # 再创建组,名字是test02
  5. node[3:4] # test02组中的成员
  6. [web:children] # 创建嵌套组,组名是web,后面:children是关键字,表示该组可以包含其他组
  7. test01 # web组中包含的其他组
  8. test02
  9. node1 ansible_ssh_user-lisi ansible_ssh_password=123456 ansible_ssh_port=2222 #主动设置用户名密码
  1. [alice@control ansible]$ cat ansible.cfg
  2. [defaults]
  3. inventory=invertory
  4. remote_user=alice
  5. roles_path=roles
  6. [privilege_escalation]
  7. become=True
  8. become_method=sudo
  9. become_user=root
  10. become_ask_pass=False
  11. [alice@control ansible]$ vim invertory
  12. [alice@control ansible]$ cat invertory
  13. [test01]
  14. node1
  15. [test02]
  16. node2
  17. [web]
  18. node[3:4]
  19. [test05]
  20. node5
  21. [webtest:children]
  22. web
  23. [alice@control ansible]$ ansible test01 --list-hosts
  24. hosts (1):
  25. node1
  26. [alice@control ansible]$ ansible test02 --list-hosts
  27. hosts (1):
  28. node2
  29. [alice@control ansible]$ ansible web --list-hosts
  30. hosts (2):
  31. node3
  32. node4
  33. [alice@control ansible]$ ansible webtest --list-hosts
  34. hosts (2):
  35. node3
  36. node4
  37. [alice@control ansible]$ ansible test05 --list-hosts
  38. hosts (1):
  39. node5
  40. [alice@control ansible]$
  1. [alice@control ansible]$ ansible localhost -m ping //检测对本机的可控性(应返回pong)
  2. [alice@control ansible]$ ansible all -m ping //检测对所有清单主机的可控性
  3. [alice@control ansible]$ ansible websvrs -m ping //检测对websvrs组内各主机的可控性
  4. [alice@control ansible]$ ansible node1,node5 -m ping //检测node1和node2的可控性
  5. [alice@control ansible]$ ansible node* -m ping //检测node开头的主机的可控性
  6. [alice@control ansible]$ ansible websvrs[0] -m ping //检测websvrs组中第1个主机的可控性

测试一下:

受管机接受控制的方式:

  • a. 受管机提供root用户+密码
  • b. 受管机提供已授sudo特权的普通用户(比如alice)


使用户名密码的方式实现 ansible 远程控制

  1. [root@control ~]# ansible node1 -u lisi -k -b -a 'mkdir /tmp/lisidir1'
  2. SSH password:
  3. node1 | UNREACHABLE! => {
  4. "changed": false,
  5. "msg": "Invalid/incorrect password: Permission denied, please try again.",
  6. "unreachable": true
  7. }
  8. [root@control ~]# ansible node1 -u lisi -k -b -a 'mkdir /tmp/lisidir1'
  9. SSH password:
  10. node1 | FAILED | rc=-1 >>
  11. Missing sudo password
  12. [root@control ~]# ansible localhost -m ping
  13. localhost | SUCCESS => {
  14. "changed": false,
  15. "ping": "pong"
  16. }
  17. [root@control ~]# ansible node1 -m ping
  18. node1 | SUCCESS => {
  19. "ansible_facts": {
  20. "discovered_interpreter_python": "/usr/libexec/platform-python"
  21. },
  22. "changed": false,
  23. "ping": "pong"
  24. }
  25. [root@control ~]# ansible all --list-hosts
  26. hosts (1):
  27. node1
  28. [root@control ~]#

sudo 提权:sudo提权设置

  1. # visudo
  2. alice ALL=(ALL) NOPASSWD:ALL
  1. [zhsan@control /]$ ls
  2. bin cemo etc lib media opt root sbin sys usr zhanshan.txt
  3. boot dev home lib64 mnt proc run srv tmp var zhsan.file
  4. [zhsan@control /]$ mkdir /demo
  5. mkdir: cannot create directory ‘/demo’: Permission denied
  6. [zhsan@control /]$ sudo mkdir /demo
  7. [zhsan@control /]$ ls
  8. bin demo home media proc sbin tmp zhanshan.txt
  9. boot dev lib mnt root srv usr zhsan.file
  10. cemo etc lib64 opt run sys var
  11. [zhsan@control /]$ ls -l demo*
  12. total 0
  13. [zhsan@control /]$ ls -l /demo*
  14. total 0
  15. [zhsan@control /]$ ls -lhd /demo*
  16. drwxr-xr-x. 2 root root 6 Feb 11 08:33 /demo
  17. [zhsan@control /]$ date
  18. Thu Feb 11 08:34:06 CST 2021
  19. [zhsan@control /]$

SSH免密登录

使用ssh-keygen生成密钥,使用特定的用户执行

  1. [root@control ~]# su - alice
  2. Last login: Sat Oct 31 06:02:41 CST 2020 on pts/0
  3. [alice@control ~]$ ssh node1
  4. Last login: Fri Oct 30 14:54:47 2020
  5. [alice@node1 ~]$ exit
  6. logout
  7. Connection to node1 closed.
  8. [alice@control ~]$ ssh node2
  9. Last login: Fri Oct 30 14:55:04 2020
  10. [alice@node2 ~]$ exit
  11. logout
  12. Connection to node2 closed.
  13. [alice@control ~]$

 


三、创建和运行Ansible

ansible管理方式(adhoc、playbook)

adhoc方式(临时命令):

直接使用ansible命令,调用xx模块来完成远程运维任务(类似于手动执行Linux命令)

adhoc方式基本用法:

# ansible 清单主机地址列表 -m 模块名 [-a '任务参数']

 playbook方式:

提前写好任务剧本,需要由ansible-playbook工具加载批量执行(类似于使用Shell脚本)

通过ansible-doc获取模块帮助

等号必须,减号可选。EXAMPLES:  各模块文档都有剧本应用示范

  1. [alice@control ansible]$ ansible-doc -l //列出所有可用模块
  2. [alice@control ansible]$ ansible-doc -l | grep yum //列出名称包含yum的模块
  3. [alice@control ansible]$ ansible-doc yum_repository //查看yum_repository模块的说明文档
  4. .. ..
  5. EXAMPLES: //各模块文档都有剧本应用示范
  6. - name: Add repository
  7. yum_repository:
  8. name: epel
  9. description: EPEL YUM repo
  10. baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
  11. .. ..

 四、Ansible常用模块

使用万能command/shell模块/script模块,推送命令行

  •  command模块:

    • 缺省模块,向受管主机发送简单命令行,不支持管道/重定向/通配符等高级特性
  •  shell模块:

    • 向受管主机发送复杂命令行,支持管道/重定向/通配符等特性
  • script模块:

    • 将本地的脚本拷贝到远程主机执行
  1. [alice@control ansible]$ ansible node1 -a 'ip add list eth0' //查看node1的IP地址
  2. [alice@control ansible]$ ansible -m command node1 -a 'ip add list eth0' //查看node1的IP地址
  3. [alice@control ansible]$ ansible -m shell node1 -a 'echo hello > /root/a.file' //在node1上创建一个文件
  4. [alice@control ansible]$ ansible node1 -a 'cat /root/a.file' //查看node1上的文件内容
  5. [alice@control ansible]$ cat aa.sh
  6. #!/bin/bash
  7. echo "Welcome to $(hostname)"
  8. [alice@control ansible]$ ansible node1 -m script -a './aa.sh' //将./aa.sh文件拷贝到受控机运行
  9. node1 | CHANGED => {
  10. "changed": true,
  11. "rc": 0,
  12. "stderr": "Shared connection to node1 closed.\r\n",
  13. "stderr_lines": [
  14. "Shared connection to node1 closed."
  15. ],
  16. "stdout": "Welcome to node1\r\n",
  17. "stdout_lines": [
  18. "Welcome to node1"
  19. ]
  20. }

使用yum_repository模块,配置软件源

基本用法:等号之间不能有空格。

# ansible  清单主机  -m  yum_repository  [-a  '任务参数']
  •  file="文件名"  //指定新生成的yum源配置文件名(不含 .repo 后缀的部分)
  •  name="源ID" //如果省略file,则文件名使用name的名称
  •  description="源的描述"
  •  baseurl="源的URL访问地址"
  •  gpgcheck="yes|no" //是否开启签名检查
  •  gpgkey="软件签名密钥文件地址" 

编写脚本 /home/alice/ansible/adhoc.sh,用来为所有受管机配置 2 个 yum 仓库。

  1. [alice@control ansible]$ vim yumdoc.sh
  2. #!/bin/bash
  3. ansible node1,node2 -m yum_repository -a 'name=BASH description="sofware base" baseur.lab0.example.com/rhel8/BaseOS gpgcheck=yes gpgkey=http://study.lab0.example.com/rhel8edhat-release enabled=yes'
  4. ansible node1,node2 -m yum_repository -a 'name=STREAM description="sofware stream" //study.lab0.example.com/rhel8/Appstream gpgcheck=yes gpgkey=http://study.lab0.examplM-GPG-KEY-redhat-release enabled=yes'
  5. [alice@control ansible]$ ls
  6. ansible.cfg invertory yumdoc.sh
  7. [alice@control ansible]$ chmod +x yumdoc.sh
  8. [alice@control ansible]$ ./yumdoc.sh

我们开了两台机器node1,node2,所以其他的机器都报错。

软件管理模块(yum/dnf)

  • name:软件名、软件名-版本号、逗号分隔的列表、@组名、*通配符
  • state:present、absent,
  • list:软件名、installed、available

装包:

将 php 和 tftp 软件包安装到 test01、test02 主机组中的主机上

  1. [alice@control ansible]$ ansible test01,test02 -m yum -a 'pkg=php,tftp state=installed'
  2. node1 | CHANGED => {
  3. "ansible_facts": {
  4. "discovered_interpreter_python": "/usr/libexec/platform-python"
  5. },
  6. "changed": true,
  7. "msg": "",
  8. "rc": 0,
  9. "results": [
  10. "Installed: php",
  11. "Installed: tftp",
  12. "Installed: apr-util-openssl-1.6.1-6.el8.x86_64",
  13. "Installed: php-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
  14. "Installed: httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
  15. "Installed: php-cli-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
  16. "Installed: mod_http2-1.11.3-3.module+el8.2.0+4377+dc421495.x86_64",
  17. "Installed: php-common-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
  18. "Installed: httpd-filesystem-2.4.37-21.module+el8.2.0+5008+cca404a3.noarch",
  19. "Installed: mailcap-2.1.48-3.el8.noarch",
  20. "Installed: apr-1.6.3-9.el8.x86_64",
  21. "Installed: php-fpm-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
  22. "Installed: apr-util-1.6.1-6.el8.x86_64",
  23. "Installed: redhat-logos-httpd-81.1-1.el8.noarch",
  24. "Installed: apr-util-bdb-1.6.1-6.el8.x86_64",
  25. "Installed: tftp-5.2-24.el8.x86_64",
  26. "Installed: httpd-tools-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
  27. "Installed: nginx-filesystem-1:1.14.1-9.module+el8.0.0+4108+af250afe.noarch"
  28. ]
  29. }
  30. node2 | CHANGED => {
  31. "ansible_facts": {
  32. "discovered_interpreter_python": "/usr/libexec/platform-python"
  33. },
  34. "changed": true,
  35. "msg": "",
  36. "rc": 0,
  37. "results": [
  38. "Installed: php",
  39. "Installed: tftp",
  40. "Installed: apr-util-openssl-1.6.1-6.el8.x86_64",
  41. "Installed: httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
  42. "Installed: php-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
  43. "Installed: mod_http2-1.11.3-3.module+el8.2.0+4377+dc421495.x86_64",
  44. "Installed: php-cli-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
  45. "Installed: php-common-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
  46. "Installed: httpd-filesystem-2.4.37-21.module+el8.2.0+5008+cca404a3.noarch",
  47. "Installed: php-fpm-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
  48. "Installed: mailcap-2.1.48-3.el8.noarch",
  49. "Installed: apr-1.6.3-9.el8.x86_64",
  50. "Installed: apr-util-1.6.1-6.el8.x86_64",
  51. "Installed: redhat-logos-httpd-81.1-1.el8.noarch",
  52. "Installed: apr-util-bdb-1.6.1-6.el8.x86_64",
  53. "Installed: tftp-5.2-24.el8.x86_64",
  54. "Installed: httpd-tools-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
  55. "Installed: nginx-filesystem-1:1.14.1-9.module+el8.0.0+4108+af250afe.noarch"
  56. ]
  57. }
  58. [alice@control ansible]$ ansible test01,test02 -m yum -a 'pkg=php,tftp state=installed'
  59. node1 | SUCCESS => {
  60. "ansible_facts": {
  61. "discovered_interpreter_python": "/usr/libexec/platform-python"
  62. },
  63. "changed": false,
  64. "msg": "Nothing to do",
  65. "rc": 0,
  66. "results": [
  67. "Installed: php",
  68. "Installed: tftp"
  69. ]
  70. }
  71. node2 | SUCCESS => {
  72. "ansible_facts": {
  73. "discovered_interpreter_python": "/usr/libexec/platform-python"
  74. },
  75. "changed": false,
  76. "msg": "Nothing to do",
  77. "rc": 0,
  78. "results": [
  79. "Installed: php",
  80. "Installed: tftp"
  81. ]
  82. }

装一个包组:

将 RPM Development Tools 软件包组安装到 test01 主机组中的主机上

  1. [alice@control ansible]$ ansible node1 -a 'yum grouplist'
  2. [WARNING]: Consider using the yum module rather than running 'yum'. If you nee
  3. use command because yum is insufficient you can add 'warn: false' to this comman
  4. task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
  5. node1 | CHANGED | rc=0 >>
  6. Updating Subscription Management repositories.
  7. Unable to read consumer identity
  8. This system is not registered to Red Hat Subscription Management. You can use suption-manager to register.
  9. Last metadata expiration check: 0:47:34 ago on Sat 13 Feb 2021 02:10:18 PM CST.
  10. Available Environment Groups:
  11. Server with GUI
  12. Server
  13. Workstation
  14. Custom Operating System
  15. Virtualization Host
  16. Installed Environment Groups:
  17. Minimal Install
  18. Available Groups:
  19. Legacy UNIX Compatibility
  20. Container Management
  21. Development Tools
  22. .NET Core Development
  23. Graphical Administration Tools
  24. Headless Management
  25. Network Servers
  26. RPM Development Tools
  27. Scientific Support
  28. Security Tools
  29. Smart Card Support
  30. System Tools
  31. [alice@control ansible]$ ansible node1 -m yum -a 'pkg=@RPM Development Tools'
  32. ERROR! this task 'yum' has extra params, which is only allowed in the following modules: group_by, include_tasks, include_role, raw, command, shell, import_role, import_tasks, script, win_command, include, meta, include_vars, add_host, win_shell, set_fact
  33. [alice@control ansible]$ ansible node1 -m yum -a 'pkg="@RPM Development Tools" state=installed '
  34. node1 | CHANGED => {
  35. "ansible_facts": {
  36. "discovered_interpreter_python": "/usr/libexec/platform-python"
  37. },
  38. "changed": true,
  39. "msg": "",
  40. "rc": 0,
  41. "results": [
  42. "Group rpm-development-tools installed.",
  43. "Installed: rpm-build-4.14.2-37.el8.x86_64",
  44. "Installed: perl-Net-SSLeay-1.88-1.el8.x86_64",
  45. "Installed: patch-2.7.6-11.el8.x86_64",
  46. "Installed: libatomic_ops-7.6.2-3.el8.x86_64",
  47. "Installed: rpmdevtools-8.10-7.el8.noarch",
  48. "Installed: elfutils-0.178-7.el8.x86_64",
  49. "Installed: bzip2-1.0.6-26.el8.x86_64",
  50. "Installed: libbabeltrace-1.5.4-2.el8.x86_64",
  51. "Installed: perl-srpm-macros-1-25.el8.noarch",
  52. "Installed: python-srpm-macros-3-38.el8.noarch",
  53. "Installed: emacs-filesystem-1:26.1-5.el8.noarch",
  54. "Installed: unzip-6.0-43.el8.x86_64",
  55. "Installed: perl-IO-Socket-SSL-2.066-4.el8.noarch",
  56. "Installed: dwz-0.12-9.el8.x86_64",
  57. "Installed: perl-libnet-3.11-3.el8.noarch",
  58. "Installed: gdb-headless-8.2-11.el8.x86_64",
  59. "Installed: perl-Carp-1.42-396.el8.noarch",
  60. "Installed: efi-srpm-macros-3-2.el8.noarch",
  61. "Installed: perl-Data-Dumper-2.167-399.el8.x86_64",
  62. "Installed: libtool-ltdl-2.4.6-25.el8.x86_64",
  63. "Installed: perl-Encode-4:2.97-3.el8.x86_64",
  64. "Installed: perl-Errno-1.28-416.el8.x86_64",
  65. "Installed: perl-Exporter-5.72-396.el8.noarch",
  66. "Installed: perl-File-Path-2.15-2.el8.noarch",
  67. "Installed: perl-File-Temp-0.230.600-1.el8.noarch",
  68. "Installed: perl-Getopt-Long-1:2.50-4.el8.noarch",
  69. "Installed: perl-HTTP-Tiny-0.074-1.el8.noarch",
  70. "Installed: perl-IO-1.38-416.el8.x86_64",
  71. "Installed: zstd-1.4.2-2.el8.x86_64",
  72. "Installed: perl-MIME-Base64-3.15-396.el8.x86_64",
  73. "Installed: perl-PathTools-3.74-1.el8.x86_64",
  74. "Installed: perl-Pod-Escapes-1:1.07-395.el8.noarch",
  75. "Installed: perl-Pod-Perldoc-3.28-396.el8.noarch",
  76. "Installed: perl-Pod-Simple-1:3.35-395.el8.noarch",
  77. "Installed: perl-Pod-Usage-4:1.69-395.el8.noarch",
  78. "Installed: perl-Scalar-List-Utils-3:1.49-2.el8.x86_64",
  79. "Installed: perl-Socket-4:2.027-3.el8.x86_64",
  80. "Installed: perl-Storable-1:3.11-3.el8.x86_64",
  81. "Installed: zip-3.0-23.el8.x86_64",
  82. "Installed: qt5-srpm-macros-5.12.5-3.el8.noarch",
  83. "Installed: perl-Term-ANSIColor-4.06-396.el8.noarch",
  84. "Installed: perl-Term-Cap-1.17-395.el8.noarch",
  85. "Installed: guile-5:2.0.14-7.el8.x86_64",
  86. "Installed: perl-Text-ParseWords-3.30-395.el8.noarch",
  87. "Installed: perl-Text-Tabs+Wrap-2013.0523-395.el8.noarch",
  88. "Installed: perl-Time-Local-1:1.280-1.el8.noarch",
  89. "Installed: perl-Unicode-Normalize-1.25-396.el8.x86_64",
  90. "Installed: perl-constant-1.33-396.el8.noarch",
  91. "Installed: perl-interpreter-4:5.26.3-416.el8.x86_64",
  92. "Installed: perl-IO-Socket-IP-0.39-5.el8.noarch",
  93. "Installed: perl-libs-4:5.26.3-416.el8.x86_64",
  94. "Installed: perl-macros-4:5.26.3-416.el8.x86_64",
  95. "Installed: perl-parent-1:0.237-1.el8.noarch",
  96. "Installed: perl-podlators-4.11-1.el8.noarch",
  97. "Installed: perl-threads-1:2.21-2.el8.x86_64",
  98. "Installed: perl-threads-shared-1.58-2.el8.x86_64",
  99. "Installed: ghc-srpm-macros-1.4.2-7.el8.noarch",
  100. "Installed: perl-URI-1.73-3.el8.noarch",
  101. "Installed: gc-7.6.4-3.el8.x86_64",
  102. "Installed: go-srpm-macros-2-16.el8.noarch",
  103. "Installed: redhat-rpm-config-122-1.el8.noarch",
  104. "Installed: libipt-1.6.1-8.el8.x86_64",
  105. "Installed: ocaml-srpm-macros-5-4.el8.noarch",
  106. "Installed: tar-2:1.30-4.el8.x86_64",
  107. "Installed: python3-rpm-macros-3-38.el8.noarch",
  108. "Installed: rust-srpm-macros-5-2.el8.noarch",
  109. "Installed: binutils-2.30-73.el8.x86_64",
  110. "Installed: openblas-srpm-macros-2-2.el8.noarch",
  111. "Installed: perl-Digest-1.17-395.el8.noarch",
  112. "Installed: perl-Mozilla-CA-20160104-7.el8.noarch",
  113. "Installed: perl-Digest-MD5-2.55-396.el8.x86_64"
  114. ]
  115. }
  116. [alice@control ansible]$ ansible node1 -m yum -a 'pkg="@RPM Development Tools" state=installed '
  117. node1 | SUCCESS => {
  118. "ansible_facts": {
  119. "discovered_interpreter_python": "/usr/libexec/platform-python"
  120. },
  121. "changed": false,
  122. "msg": "Nothing to do",
  123. "rc": 0,
  124. "results": [
  125. "Group rpm-development-tools installed."
  126. ]
  127. }
  128. [alice@control ansible]$

包升级更新:

将 test01、02 主机组中的主机上所有软件包升级到最新版本 

  1. [alice@control ansible]$ ansible test01,test02 -m yum -a 'pkg=* state=latest'
  2. node1 | SUCCESS => {
  3. "ansible_facts": {
  4. "discovered_interpreter_python": "/usr/libexec/platform-python"
  5. },
  6. "changed": false,
  7. "msg": "Nothing to do",
  8. "rc": 0,
  9. "results": []
  10. }
  11. node2 | SUCCESS => {
  12. "ansible_facts": {
  13. "discovered_interpreter_python": "/usr/libexec/platform-python"
  14. },
  15. "changed": false,
  16. "msg": "Nothing to do",
  17. "rc": 0,
  18. "results": []
  19. }
  20. [alice@control ansible]$

文件管理模块(file/copy/template)

file模块:

创建目录/文件/链接文件(不包括内容)|| ===》path、state、src、owner、group、mode

基本用法:

# ansible  清单主机  -m  file  -a  '任务参数'
  • path="新文件路径"  //指定要创建的新文件路径(必选参数)
  • state="directory|touch|link" //新文件的类型为目录|空文件|链接文件
  • src="被链接的原始文件路径" //如果是创建符号链接文件,需要指定此参数
  • force="yes|no"  //目标文件已存在时是否替换,或者被链接文件不存在时是否仍然创建链接
  • owner=属主 //指定新文件的属主
  • group=属组 //指定新文件的属组
  • mode=权限标记 //指定新文件的权限
  • setype=SELinux类型 //指定新文件的SELinux标签类型

  1. [alice@control ansible]$ ansible node1 -m file -a 'name=/a.txt state=file'
  2. node1 | SUCCESS => {
  3. "ansible_facts": {
  4. "discovered_interpreter_python": "/usr/libexec/platform-python"
  5. },
  6. "changed": false,
  7. "gid": 0,
  8. "group": "root",
  9. "mode": "0644",
  10. "owner": "root",
  11. "path": "/a.txt",
  12. "secontext": "unconfined_u:object_r:etc_runtime_t:s0",
  13. "size": 0,
  14. "state": "file",
  15. "uid": 0
  16. }
  17. [alice@control ansible]$ ansible node1 -m file -a 'src=/ path=/linkroot state=link'
  18. node1 | CHANGED => {
  19. "ansible_facts": {
  20. "discovered_interpreter_python": "/usr/libexec/platform-python"
  21. },
  22. "changed": true,
  23. "dest": "/linkroot",
  24. "gid": 0,
  25. "group": "root",
  26. "mode": "0777",
  27. "owner": "root",
  28. "secontext": "unconfined_u:object_r:root_t:s0",
  29. "size": 1,
  30. "src": "/",
  31. "state": "link",
  32. "uid": 0
  33. }
  34. [alice@control ansible]$
  35. [alice@control ansible]$ ansible node1 -m file -a 'src=/ path=/linkroot state=absent
  36. [WARNING]: The src option requires state to be 'link' or 'hard'. This will become a
  37. error in Ansible 2.10
  38. node1 | CHANGED => {
  39. "ansible_facts": {
  40. "discovered_interpreter_python": "/usr/libexec/platform-python"
  41. },
  42. "changed": true,
  43. "path": "/linkroot",
  44. "state": "absent"
  45. }
  46. [alice@control ansible]$ ansible node1 -m file -a 'path=mulu state=directory mode=0750'
  47. node1 | CHANGED => {
  48. "ansible_facts": {
  49. "discovered_interpreter_python": "/usr/libexec/platform-python"
  50. },
  51. "changed": true,
  52. "gid": 0,
  53. "group": "root",
  54. "mode": "0750",
  55. "owner": "root",
  56. "path": "mulu",
  57. "secontext": "unconfined_u:object_r:user_home_t:s0",
  58. "size": 6,
  59. "state": "directory",
  60. "uid": 0
  61. }
  62. [alice@control ansible]$ ansible node1 -m file -a 'path=mulu state=directory owner=alice'
  63. node1 | CHANGED => {
  64. "ansible_facts": {
  65. "discovered_interpreter_python": "/usr/libexec/platform-python"
  66. },
  67. "changed": true,
  68. "gid": 0,
  69. "group": "root",
  70. "mode": "0750",
  71. "owner": "alice",
  72. "path": "mulu",
  73. "secontext": "unconfined_u:object_r:user_home_t:s0",
  74. "size": 6,
  75. "state": "directory",
  76. "uid": 1000
  77. }
  • 创建目录/webdev,常规权限为 rwxrwxr-x,具有 SetGID 特殊权限

  • 使用符号链接/var/www/html/webdev 链接到/webdev 目录

copy模块:

复制目录/文件、创建指定内容(content 建议少量文本)的文件:|| ===》src、dest、force、owner、group、mode

基本用法:

# ansible  清单主机  -m  copy  -a  '任务参数'
  • dest="目标文件路径"  //指定拷贝到远程后的新文件路径(必选参数)
  • content="文本内容" //指定要拷贝的文本内容
  • src="原始文件路径" //指定要拷贝的本地文件路径
  • force="yes|no"  //目标文件已存在时是否替换
  • owner=属主 //指定新文件的属主
  • group=属组 //指定新文件的属组
  • mode=权限标记 //指定新文件的权限
  • setype=SELinux类型 //指定新文件的SELinux标签类型

 template模块

根据模板文件(适合多行文字)在被控机上生成指定的新文件,使用template模块,从模板上传文件

  • src=模板文件路径  //指定被复制的本地文件(必选参数)
  • dest=目标文件路径  //指定上传到目标主机的新文件(必选参数)
  • force="yes|no"  //目标文件已存在时是否替换
  • owner=属主 //指定新文件的属主
  • group=属组 //指定新文件的属组
  • mode=权限标记 //指定新文件的权限
  •  setype=SELinux类型 //指定新文件的SELinux标签类型
# ansible  清单主机  -m  template  -a  '任务参数'
  1. [alice@control ansible]$ ansible node1 -m template -a 'src=welcome.html dest=/tmp/welcome.html mode=644 force=yes'
  2. .. .. //上传文件到主机node1,强制覆盖
  3. [alice@control ansible]$ ansible node1 -a 'ls -lh /tmp/welcome.html'
  4. node1 | CHANGED | rc=0 >>
  5. -rw-r--r--. 1 root root 23 Apr 17 07:22 /tmp/welcome.html
  6. .. .. //检查结果

用户管理模块(user/group)

user模块:

添加/修改/删除用户账号,设置密码 

参数:name、state、uid、groups、append、remove、password

基本用法:

# ansible  清单主机  -m  user  -a  '任务参数'
  •  name="登录名" //指定用户名(必选参数)
  •  password="加密的密码串" //一般使用 {{'123456'|password_hash('sha512')}} 形式  :|| password={{"明文密码" | password_hash("sha512")}} 
  •  uid="用户ID号" //指定用户的UID
  • group="基本组名" //指定用户的基本组名
  •  groups="附属组名" //将用户添加到xx附属组,结合append=yes
  • append="yes|no"//是否向xx组追加此用户,如果选no用户只属于这个组
  •  state="present|absent" //创建|删除用户(缺省值为present)
  •  force="yes|no"  //是否强制删除用户,即使此用户已经登录
  • remove="yes|no" //删除用户时是否同时删除家目录

  1. [alice@control ansible]$ ansible node1 -m user -a 'name=dongfang uid=1234 groups=users append=yes'
  2. .. .. //添加新用户,加入到users
  3. [alice@control ansible]$ ansible node1 -m user -a "name=bubai password={{' 123456'|password_hash('sha512') }}"
  4. .. .. //添加新用户并设置密码
  5. [alice@control ansible]$ ansible node1 -m user -a 'name=dongfang state=absent remove=yes'
  6. .. .. //删除用户

group模块

添加/修改/删除组账号|| name、state、gid

  • setype="SELinux标签类型" //指定标签类型(必选参数),比如网页内容 httpd_sys_content_t
  • target="目录路径" //指定要设置的目录路径
  • state="present|absent" //添加|取消上下文标记(缺省值为present)

服务控制模块(service)

代替systemctl  指令来控制服务的启动/停止/重启、开机自启动状态的设置

参数: name、state、enabled

  • name=服务名  //指定系统服务名(必选参数)
  • state="started|stoped|restarted|reloaded"   //启动|停止|重启|重载服务
  • enable="yes|no"  //是否开机自启
# ansible  清单主机  -m  service  -a  '任务参数'
  1. [alice@control ansible]$ ansible node1 -m service -a "name=crond state=restarted enabled=yes"
  2. .. .. //重启crond服务,并设置开机自启

安全控制模块(firewalld/sefcontext)

1. firewalld模块

  • Linux防火墙服务 firewalld,默认是开启的
  • 防火墙规则的作用范围:运行时(临时)、永久(重启后仍有效)
  • 默认安全区使用的 public (仅允许ping本机、SSH远程连本机,拒绝其他几乎任何访问)

2.其他常用安全区:

  • trusted 信任区(允许任何访问,办公区域,允许SSH、Samba少数几个服务
  • block 阻塞区(阻止任何访问)
  • drop 丢弃区(丢弃任何来访数据包)

常用参数:permanent(永久开启)、port(端口)、service(服务)、source、state、immediate(立即生效)

2. sefcontext模块

 sefcontext ==》设置文件的SELinux安全上下文/属性

  • 查看文档的安全属性:ls   -Z   /var/www
  • 设置指定目录允许作为网页目录 semanage  fcontext  -a  -t   httpd_sys_content_t   /网页目录的路径  

基本用法:

  1. [alice@control ansible]$ ansible node1 -m sefcontext -a "target='/webdev(/.*)?' setype=httpd_sys_content_t state=present"
  2. .. .. //将node1的/webdev目录设置为网页目录
  1. ansible node2 -m yum -a 'name=policycoreutils-python-utils state=present'
  2. yum provides semanage
  3. ansible node2 -m sefcontext -a 'path="/webdev(/.*)?" setype=httpd sys content t'
  4. ansible node2 -a 'restorecon -R /webdev'

磁盘管理模块(parted/lvg/lvol/filesystem)

parted模块:

规划硬盘的分区,device、number、state、part_start、part_end

基本用法:

# ansible  清单主机  -m  parted  -a  '任务参数'
  • device="磁盘设备"  //指定操作的磁盘设备(必选参数)
  • label="gpt|msdos"  //新磁盘分区表类型
  • number="分区编号" //指定分区编号
  • part_start="起始位置"  //指定新建分区的起始位置
  • part_end="起始位置"  //指定  新建分区的结束位置
  • state="present|absent|info" //创建|删除|查看信息
  1. [alice@control ansible]$ ansible node2 -m parted -a 'device=/dev/vdb state=info'
  2. node2 | SUCCESS => {
  3. "ansible_facts": {
  4. "discovered_interpreter_python": "/usr/libexec/platform-python"
  5. },
  6. "changed": false,
  7. "disk": {
  8. "dev": "/dev/vdb",
  9. "logical_block": 512,
  10. "model": "Virtio Block Device",
  11. "physical_block": 512,
  12. "size": 1048576.0,
  13. "table": "gpt",
  14. "unit": "kib"
  15. },
  16. "partitions": [
  17. {
  18. "begin": 1024.0,
  19. "end": 684032.0,
  20. "flags": [],
  21. "fstype": "",
  22. "name": "primary",
  23. "num": 1,
  24. "size": 683008.0,
  25. "unit": "kib"
  26. }
  27. ],
  28. "script": "unit 'KiB' print"
  29. }
  30. [alice@control ansible]$ ansible node4 -m ping
  31. node4 | SUCCESS => {
  32. "ansible_facts": {
  33. "discovered_interpreter_python": "/usr/libexec/platform-python"
  34. },
  35. "changed": false,
  36. "ping": "pong"
  37. }
  38. [alice@control ansible]$ ansible node4 -m parted -a 'device=/dev/vdb state=info'
  39. node4 | SUCCESS => {
  40. "ansible_facts": {
  41. "discovered_interpreter_python": "/usr/libexec/platform-python"
  42. },
  43. "changed": false,
  44. "disk": {
  45. "dev": "/dev/vdb",
  46. "logical_block": 512,
  47. "model": "Virtio Block Device",
  48. "physical_block": 512,
  49. "size": 2097152.0,
  50. "table": "unknown",
  51. "unit": "kib"
  52. },
  53. "partitions": [],
  54. "script": "unit 'KiB' print"
  55. }
  56. [alice@control ansible]$ ansible node4 -m parted -a 'device=/dev/vdb state=
  57. present number=1 part_start=0% part_end=300MiB'
  58. node4 | CHANGED => {
  59. "ansible_facts": {
  60. "discovered_interpreter_python": "/usr/libexec/platform-python"
  61. },
  62. "changed": true,
  63. "disk": {
  64. "dev": "/dev/vdb",
  65. "logical_block": 512,
  66. "model": "Virtio Block Device",
  67. "physical_block": 512,
  68. "size": 2097152.0,
  69. "table": "msdos",
  70. "unit": "kib"
  71. },
  72. "partitions": [
  73. {
  74. "begin": 1024.0,
  75. "end": 307200.0,
  76. "flags": [],
  77. "fstype": "",
  78. "name": "",
  79. "num": 1,
  80. "size": 306176.0,
  81. "unit": "kib"
  82. }
  83. ],
  84. "script": "unit KiB mklabel msdos mkpart primary 0% 300MiB"
  85. }
  86. [alice@control ansible]$ ansible node4 -m parted -a 'device=/dev/vdb state=info'
  87. node4 | SUCCESS => {
  88. "ansible_facts": {
  89. "discovered_interpreter_python": "/usr/libexec/platform-python"
  90. },
  91. "changed": false,
  92. "disk": {
  93. "dev": "/dev/vdb",
  94. "logical_block": 512,
  95. "model": "Virtio Block Device",
  96. "physical_block": 512,
  97. "size": 2097152.0,
  98. "table": "msdos",
  99. "unit": "kib"
  100. },
  101. "partitions": [
  102. {
  103. "begin": 1024.0,
  104. "end": 307200.0,
  105. "flags": [],
  106. "fstype": "",
  107. "name": "",
  108. "num": 1,
  109. "size": 306176.0,
  110. "unit": "kib"
  111. }
  112. ],
  113. "script": "unit 'KiB' print"
  114. }
  115. [alice@control ansible]$ ansible node4 -a 'lsblk'
  116. node4 | CHANGED | rc=0 >>
  117. NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
  118. sr0 11:0 1 1024M 0 rom
  119. vda 252:0 0 50G 0 disk
  120. ├─vda1 252:1 0 1G 0 part /boot
  121. └─vda2 252:2 0 49G 0 part
  122. ├─rhel-root 253:0 0 46.9G 0 lvm /
  123. └─rhel-swap 253:1 0 2.2G 0 lvm [SWAP]
  124. vdb 252:16 0 2G 0 disk
  125. └─vdb1 252:17 0 299M 0 part
  126. [alice@control ansible]$ ansible node4 -m parted -a 'device=/dev/vdb state=absent'
  127. node4 | FAILED! => {
  128. "ansible_facts": {
  129. "discovered_interpreter_python": "/usr/libexec/platform-python"
  130. },
  131. "changed": false,
  132. "msg": "state is absent but all of the following are missing: number"
  133. }
  134. [alice@control ansible]$ ansible node4 -m parted -a 'device=/dev/vdb number=1 state=absent'
  135. node4 | CHANGED => {
  136. "ansible_facts": {
  137. "discovered_interpreter_python": "/usr/libexec/platform-python"
  138. },
  139. "changed": true,
  140. "disk": {
  141. "dev": "/dev/vdb",
  142. "logical_block": 512,
  143. "model": "Virtio Block Device",
  144. "physical_block": 512,
  145. "size": 2097152.0,
  146. "table": "msdos",
  147. "unit": "kib"
  148. },
  149. "partitions": [],
  150. "script": "rm 1"
  151. }
  152. [alice@control ansible]$ ansible node4 -a 'lsblk'
  153. node4 | CHANGED | rc=0 >>
  154. NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
  155. sr0 11:0 1 1024M 0 rom
  156. vda 252:0 0 50G 0 disk
  157. ├─vda1 252:1 0 1G 0 part /boot
  158. └─vda2 252:2 0 49G 0 part
  159. ├─rhel-root 253:0 0 46.9G 0 lvm /
  160. └─rhel-swap 253:1 0 2.2G 0 lvm [SWAP]
  161. vdb 252:16 0 2G 0 disk
  162. [alice@control ansible]$

lvg模块:

管理卷组,vg、pvs、pesize、state

基本用法:

# ansible  清单主机  -m  lvg  -a  '任务参数'
  •  vg="卷组名"  //指定操作的卷组名(必选参数)
  • state="present|absent"  //创建|删除卷组
  • force="yes|no" //是否强制删除卷组(即使有逻辑卷)
  • pvs="物理卷列表" //新建卷组时,指定由哪些物理设备组成
  • pesize="PE大小" //指定Physical Extent的大小
  1. [alice@control ansible]$ ansible node4 -a 'lsblk'
  2. node4 | CHANGED | rc=0 >>
  3. NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
  4. sr0 11:0 1 1024M 0 rom
  5. vda 252:0 0 50G 0 disk
  6. ├─vda1 252:1 0 1G 0 part /boot
  7. └─vda2 252:2 0 49G 0 part
  8. ├─rhel-root 253:0 0 46.9G 0 lvm /
  9. └─rhel-swap 253:1 0 2.2G 0 lvm [SWAP]
  10. vdb 252:16 0 2G 0 disk
  11. ├─vdb1 252:17 0 299M 0 part
  12. └─vdb2 252:18 0 700M 0 part
  13. [alice@control ansible]$ ansible node4 -m lvg -a 'vg=redhat pvs=/dev/vdb2'
  14. node4 | CHANGED => {
  15. "ansible_facts": {
  16. "discovered_interpreter_python": "/usr/libexec/platform-python"
  17. },
  18. "changed": true
  19. }
  20. [alice@control ansible]$ ansible node4 -a 'lsblk'
  21. node4 | CHANGED | rc=0 >>
  22. NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
  23. sr0 11:0 1 1024M 0 rom
  24. vda 252:0 0 50G 0 disk
  25. ├─vda1 252:1 0 1G 0 part /boot
  26. └─vda2 252:2 0 49G 0 part
  27. ├─rhel-root 253:0 0 46.9G 0 lvm /
  28. └─rhel-swap 253:1 0 2.2G 0 lvm [SWAP]
  29. vdb 252:16 0 2G 0 disk
  30. ├─vdb1 252:17 0 299M 0 part
  31. └─vdb2 252:18 0 700M 0 part
  32. [alice@control ansible]$ ansible node4 -a 'vgscan'
  33. node4 | CHANGED | rc=0 >>
  34. Found volume group "redhat" using metadata type lvm2
  35. Found volume group "rhel" using metadata type lvm2
  36. [alice@control ansible]$ ansible node4 -m lvg -a 'vg=redhat pvs=/dev/vdb2 start=absent'
  37. node4 | FAILED! => {
  38. "ansible_facts": {
  39. "discovered_interpreter_python": "/usr/libexec/platform-python"
  40. },
  41. "changed": false,
  42. "msg": "Unsupported parameters for (lvg) module: start Supported parameters include: force, pesize, pv_options, pvs, state, vg, vg_options"
  43. }
  44. [alice@control ansible]$ ansible node4 -m lvg -a 'vg=redhat pvs=/dev/vdb2 state=absent'
  45. node4 | CHANGED => {
  46. "ansible_facts": {
  47. "discovered_interpreter_python": "/usr/libexec/platform-python"
  48. },
  49. "changed": true
  50. }
  51. [alice@control ansible]$ ansible node4 -a 'vgscan'
  52. node4 | CHANGED | rc=0 >>
  53. Found volume group "rhel" using metadata type lvm2

lvol模块

管理逻辑卷,lv、size、vg、state、force

基本用法:

# ansible  清单主机  -m  lvol  -a  '任务参数'
  • lv="逻辑卷名"  //指定操作的逻辑卷名(必选参数)
  • size="逻辑卷大小" //指定逻辑卷大小
  • vg="卷组名" //指定逻辑卷所在卷组
  • state="present|absent"  //创建|删除逻辑卷
  • force="yes|no" //是否强制删除或调整逻辑卷大小
  1. [alice@control ansible]$ ansible node4 -m lvg -a 'vg=redhat pvs=/dev/vdb2 state=present pesize=300MiB'
  2. node4 | CHANGED => {
  3. "ansible_facts": {
  4. "discovered_interpreter_python": "/usr/libexec/platform-python"
  5. },
  6. "changed": true
  7. }
  8. [alice@control ansible]$ ansible node4 -a 'vgscan'
  9. node4 | CHANGED | rc=0 >>
  10. Found volume group "redhat" using metadata type lvm2
  11. Found volume group "rhel" using metadata type lvm2
  12. [alice@control ansible]$ ansible node4 -m lvol -a 'lv=rhcsa size=200M vg=redhat start=present'
  13. node4 | FAILED! => {
  14. "ansible_facts": {
  15. "discovered_interpreter_python": "/usr/libexec/platform-python"
  16. },
  17. "changed": false,
  18. "msg": "Unsupported parameters for (lvol) module: start Supported parameters include: active, force, lv, opts, pvs, resizefs, shrink, size, snapshot, state, thinpool, vg"
  19. }
  20. [alice@control ansible]$ ansible node4 -m lvol -a 'lv=rhcsa size=200M vg=redhat state=present'
  21. node4 | CHANGED => {
  22. "ansible_facts": {
  23. "discovered_interpreter_python": "/usr/libexec/platform-python"
  24. },
  25. "changed": true,
  26. "msg": ""
  27. }
  28. [alice@control ansible]$ ansible node4 -a 'lvscan'
  29. node4 | CHANGED | rc=0 >>
  30. ACTIVE '/dev/redhat/rhcsa' [300.00 MiB] inherit
  31. ACTIVE '/dev/rhel/swap' [2.16 GiB] inherit
  32. ACTIVE '/dev/rhel/root' [<46.84 GiB] inherit
  33. [alice@control ansible]$

filesystem模块:

格式化,dev、fstype、force

# ansible  清单主机  -m  filesystem  -a  '任务参数'
  • dev="逻辑卷名"  //指定要格式化的设备路径(必选参数)
  • fstype="文件系统类型" //指定格式化类型(xfs、ext4等)
  • force="yes|no" //是否强制格式化(即使已经有文件系统)
  1. [alice@control ansible]$ ansible node4 -a 'blkid /dev/redhat/rhcsa'
  2. node4 | FAILED | rc=2 >>
  3. non-zero return code
  4. [alice@control ansible]$ ansible node4 -m filesystem -a 'dev=/dev/redhat/rhcsa fstype=ext3'
  5. node4 | CHANGED => {
  6. "ansible_facts": {
  7. "discovered_interpreter_python": "/usr/libexec/platform-python"
  8. },
  9. "changed": true
  10. }
  11. [alice@control ansible]$ ansible node4 -a 'blkid /dev/redhat/rhcsa'
  12. node4 | CHANGED | rc=0 >>
  13. /dev/redhat/rhcsa: UUID="a25eff1d-31c8-4568-b01b-4f9fd2da23b5" SEC_TYPE="ext2" TYPE="ext3"
  14. [alice@control ansible]$ ansible node4 -m filesystem -a 'dev=/dev/redhat/rhcsa fstype=xfs force=yes'
  15. node4 | CHANGED => {
  16. "ansible_facts": {
  17. "discovered_interpreter_python": "/usr/libexec/platform-python"
  18. },
  19. "changed": true
  20. }
  21. [alice@control ansible]$ ansible node4 -a 'blkid /dev/redhat/rhcsa'
  22. node4 | CHANGED | rc=0 >>
  23. /dev/redhat/rhcsa: UUID="54cf0807-92cd-4aeb-ba40-47b4e9e30dba" TYPE="xfs"
  24. [alice@control ansible]$

文件修订模块(replace/lineinfile)

replace模块:

使用replace模块,修改文件中的关键词,替换文件内的xx关键词,path、regexp、replace。

基本用法:

# ansible  清单主机  -m  replace  -a  '任务参数'
  • dest="文件路径" //指定要修改的文件路径(必选参数)
  •  regexp="旧字符串" //指定要替换的字符串(必选参数),使用正则表达式
  • replace="新字符串"  //指定要替换的新字符串
  1. [alice@control ansible]$ ansible node2 -m replace -a 'path=/etc/selinux/config regexp="=enforcing" replace=disabled'
  2. node2 | SUCCESS => {
  3. "ansible_facts": {
  4. "discovered_interpreter_python": "/usr/libexec/platform-python"
  5. },
  6. "changed": false,
  7. "msg": ""
  8. }
  9. [alice@control ansible]$ ansible node2 -a 'cat /etc/selinux/config'
  10. node2 | CHANGED | rc=0 >>
  11. # This file controls the state of SELinux on the system.
  12. # SELINUX= can take one of these three values:
  13. # enforcing - SELinux security policy is enforced.
  14. # permissive - SELinux prints warnings instead of enforcing.
  15. # disabled - No SELinux policy is loaded.
  16. # SELINUXTYPE= can take one of these three values:
  17. # targeted - Targeted processes are protected,
  18. # minimum - Modification of targeted policy. Only selected processes are protected.
  19. # mls - Multi Level Security protection.
  20. SELINUXTYPE=targeted

lineinfile模块:

确认文件中存在/不存在/替换 xxxx 行,path、regexp、line、state。

get_url:

从指定的网址下载一个文件,url、dest、force。

基本用法:

# ansible  清单主机  -m  get_url  -a  '任务参数'
  • dest="目标文件路径" //指定下载后存放的新文件路径(必选参数)
  • url="文件的URL网址" //指定要下载的文件的URL地址(必选参数)
  • force="yes|no"  //目标文件已存在时是否替换
  • owner=属主 //指定新文件的属主
  • group=属组 //指定新文件的属组
  • mode=权限标记 //指定新文件的权限
  •  setype=SELinux类型 //指定新文件的SELinux标签类型

docker 模块

1、docker_container模块主要是用于ansible-playbook操作docker容器的一个模块,使用该模块可以实现批量创建docker容器

   Ansible 中部署 docker 镜像主要需要的是 docker_container, docker_image, docker_service 三个模块。其中 docker_container 用于部署 docker 容器,docker_image 用于编译镜像,docker_service 模块用于部署 docker compose。

  一般ansible-playbook的剧本是这样定义的,例如first.yaml所示:

  1. ---
  2. - hosts: all
  3. remote_user: redis
  4. vars:
  5. container_name: "redis"
  6. container_image: "redis:4.0.1"
  7. working_dir: "/data/redis_test"
  8. tasks:
  9. - name: remove container
  10. docker_container:
  11. name: "{{ container_name }}"
  12. state: absent
  13. - name: create working_dir directory
  14. file:
  15. path: "{{ item }}"
  16. state: directory
  17. with_items:
  18. - "{{ working_dir }}"
  19. # docker run -p 6379:6379 --name redis -d redis:4.0.1
  20. - name: create container
  21. docker_container:
  22. name: "{{ container_name }}"
  23. image: "{{ container_image }}"
  24. ports:
  25. - "6379:6379"


五,playbook剧本的作用及语法构成

什么是剧本:

  • 即playbook,因作用类似于拍电影的剧本而得名,也有翻译为“编排”的
  • 指的是包含一系列ansible自动化运维任务操作的特殊文件,一般以 .yml 作为扩展名
  • 剧本代码使用YAML(YAML Ain't a Markup Language)数据标记规则

编剧 ==》 提供 playbook 剧本 ==》 ansible-playbook 执行剧本

剧本的语法构成:

 每一个playbook剧本中可以包括多个play剧情(场景1-小巷子英雄救美、场景2-大教堂美女成婚、……),每一个剧情由以下组件构成:name、hosts、tasks、vars、roles等等

  • 名称(name),此项剧情的描述(非必须,但是建议写上,方便跟踪执行过程)
  • 清单主机(hosts),在哪些主机上(剧情上演场地,小巷子、大教堂等)执行
  • 任务列表(tasks),需要执行的具体的模块操作(美女出场、劫匪出场、英雄出场)
  • 变量列表/文件(vars,vars_files),定义变量或导入变量文件(穿啥衣服、背啥包等等)
  • 角色(roles),加载预设的任务角色(剧本+变量+模板……等资源套餐)

执行playbook剧本

  •  通过ansible-playbook加载剧本,任务按顺序依次执行
  •  添加 --syntax-check 选项时,可以对剧本做语法检查
  • 添加 -C 选项时,只测试剧本,不真正执行
  • 返回结果时,changed表示有更改(橙色)ok表示已经执行过(绿色)failed表示失败(红色)
  1. [alice@control ansible]$ ansible-playbook file.yml
  2. PLAY [configure yum repository] ************************************************
  3. TASK [Gathering Facts] *********************************************************
  4. fatal: [node3]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host node3 port 22: No route to host", "unreachable": true}
  5. fatal: [node4]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host node4 port 22: No route to host", "unreachable": true}
  6. ok: [node2]
  7. ok: [node1]
  8. ok: [node5]
  9. TASK [base] ********************************************************************
  10. ok: [node2]
  11. ok: [node1]
  12. ok: [node5]
  13. TASK [stream] ******************************************************************
  14. ok: [node1]
  15. ok: [node2]
  16. ok: [node5]
  17. PLAY RECAP *********************************************************************
  18. node1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
  19. node2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
  20. node3 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
  21. node4 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
  22. node5 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
  23. [alice@control ansible]$
  1. - hosts: all
  2. tasks:
  3. - yum_repository:
  4. name: abc
  5. description: abcabc
  6. file: test
  7. baseurl: http://study.lab0.example.com/rhel8/BaseOS gpgcheck=yes gpgkey=http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release'
  8. - yum_repository: 'name=abc01 description="abc abc" file=test01 baseurl=http://study.lab0.example.com/rhel8/AppStream gpgcheck=yes gpgkey=http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release'

YAML基本语法:

  •  # 表示注释,起始行标记 --- ,结束行标记 ... ,非必需
  •  以2个或更多空格缩进来确定层次关系,相同层次的代码缩进必须对齐
  •  代码文件以 .yml 或 .yaml 作为扩展名
  •  代码中不能使用Tab标记,建议调整编辑器设置(自动缩进、Tab替换为空格)
  1. [alice@control ansible]$ vim ~/.vimrc //修改vim个性化配置(" 是注释行标记)
  2. #方法一
  3. "autocmd FileType yaml setlocal autoindent shiftwidth=2 tabstop=2 expandtab
  4. # 方法二
  5. au FileType yaml set ai sw=2 ts=2 et
  6. # 方法三
  7. set ai
  8. set ts=2

++ 键值对使用 : 分隔,列表/数组使用 - ,后面必须有空格标记,键值对可以写成一行、缩进的多行

  1. - hosts: node1,node2
  2. tasks:
  3. - yum: name=httpd state=present
  4. - copy: content="RHCE Test" dest=/var/www/html/index.html force=yes
  5. - service: name=httpd state=restarted enabled=yes
  6. - service: name=firewalld state=restarted enabled=yes
  7. - firewalld: service=http state=enabled permanent=yes immediate=yes
  8. ~
  9. ~
  10. ~
  11. ~
  1. [alice@control ansible]$ ansible-playbook -C demo.yml
  2. PLAY [node1,node2] *************************************************************
  3. TASK [Gathering Facts] *********************************************************
  4. ok: [node2]
  5. ok: [node1]
  6. TASK [yum] *********************************************************************
  7. changed: [node2]
  8. changed: [node1]
  9. TASK [copy] ********************************************************************
  10. changed: [node1]
  11. changed: [node2]
  12. TASK [service] *****************************************************************
  13. changed: [node2]
  14. changed: [node1]
  15. TASK [firewalld] ***************************************************************
  16. changed: [node2]
  17. changed: [node1]
  18. PLAY RECAP *********************************************************************
  19. node1 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
  20. node2 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
  21. [alice@control ansible]$

ignore_errors:

ignore_errors忽略错误:在剧本中即使遇到错误,仍然执行后续操作

register接受shell模块输出变量

使用loop循环

  • 通过loop语句可以构造一个值列表(队列)
  • 针对loop队列中的值,可以共享同一个任务操作,从而节省代码量、提高效率
  • 任务要调用队列中的值时,使用固定变量 {{item}},需要时
  1. [alice@control ansible]$ cat lamp.yml
  2. ---
  3. - name: Deploy LAMP Platform
  4. hosts: host1
  5. tasks:
  6. - name: install LAMP packages
  7. yum: name={{item}} state=present //调用循环变量(固定名称item)
  8. loop: //配置列表循环项
  9. - httpd
  10. - mariadb
  11. - mariadb-server
  12. - php
  13. - php-mysqlnd
  14. - name: enable LAMP services
  15. service: name={{item}} state=started enabled=yes
  16. loop:
  17. - httpd
  18. - mariadb

使用when条件(if)

when条件用来判断系统指标,当满足条件时才会执行某个任务

  • 常见条件操作符如下:==、!=、>、>=、<、<=、in、not in、is  defined、is  not  defined
  •  使用and或or可以组合多个条件
  • when表达式中调用变量时,不需要使用 {{  }}
  1. [alice@control ansible]$ cat when.yml
  2. ---
  3. - name: when test
  4. hosts: node1,node3
  5. tasks:
  6. - file: path="/tmp/yes.txt" state=touch //在目录/tmp/下创建文件yes.txt
  7. when: ('web' in group_names) //当主机属于web组时执行
  8. - debug: msg="vg myvg not found" //显示一段文本
  9. when: ('myvg' not in ansible_lvm.vgs) //当卷组myvg不存在时
  10. ...

failed_when中断控制

  • failed_when条件的用法与when类似
  • 但是当满足failed_when的条件时,playbook就认为失败,不再执行后续任务

block语句块的使用(Java的try{}catch(){}finally{})

block语句可以将多个任务操作捆绑到一起,当成一个整体

  • 当满足when条件后要执行多个操作时,就可以使用block把这些操作捆在一块
  • 当然,when条件也不是必需的,可以只是捆绑多个任务
  • rescue抢救机制(非必需),当block任务失败时,可以执行rescue任务
  • always完结机制(非必需),无论block任务是否成功,最后都去执行always任务
  1. block:
  2. - 任务1: .. ..
  3. - 任务2: .. ..
  4. when:条件测试
  5. rescue:
  6. - 任务3: .. ..
  7. - 任务4: .. ..
  8. always:
  9. - 任务5: .. ..

 —— 执行结果是:

  •     当条件测试不成立时,任务1-5都不执行
  •     当条件测试成立时,执行任务1、任务2;如果任务1、2中有失败的,则执行任务3、4
  •     当条件测试成立时,任务5始终都会执行
  1. [alice@control ansible]$ cat block.yml
  2. ---
  3. - name: block test
  4. hosts: node1
  5. tasks:
  6. - block:
  7. - debug: msg="vg myvg not found" //提示卷组没找到
  8. - debug: msg="create vg myvg .. .." //做其他操作(比如创建这个卷组...)
  9. when: ('myvg' not in ansible_lvm.vgs) //当卷组myvg不存在时
  10. rescue:
  11. - debug: msg="creating failed .. .." //block失败时提示创建卷组失败
  12. always:
  13. - shell: vgscan //列出卷组信息
  14. register: list //保存到名为list的变量
  15. - debug: msg={{list.stdout_lines}} //提示卷组扫描结果
  16. ...

handlers任务处理(布雷)、notify通知触发(引爆)

handlers可以设置一个或一块任务,仅当收到某个任务通知时才会执行

  • 每个剧情中handlers任务只会执行一次,即使收到多个任务的触发通知
  • handlers组的每一个任务都要设置名称(name)
  • handlers的层次与tasks平级
  • 其他任务在必要时,使用notify语句通知handlers任务名
  • 仅当发起notify的任务的执行状态为changed时,handlers任务才会被执行
  1. [alice@control ansible]$ cat handlers.yml
  2. ---
  3. - name: handlers test
  4. hosts: node5
  5. tasks:
  6. - lvol: lv=vo001 size=100M vg=search //创建逻辑卷vo001
  7. notify: mkfs //如果changed则通知格式化(否则无需格式化)
  8. handlers:
  9. - name: mkfs //定义格式化操作处理
  10. filesystem: dev=/dev/search/vo001 fstype=xfs force=yes
  11. ...

 


ansible-vault:ansible的vault保险库:

  • 为了方便保护一些敏感文件(如账号的密码)而设置的文件加密机制
  • 加密/解密主要工具 ansible-vault
  •  过ansible-playbook调用保险库文件时,添加 --ask-vault-pass 选项会提示从键盘输入密码
  • 需要验证密码的地方,都可以添加 --vault-password-file= 来指定密码文件以免除交互
  • 在重设密码时,可以添加 --new-vault-password-file 来指定存放新密码的文件

ansible-vault基本操作(以下为手动验密):

  1. [alice@control ansible]$ ansible-vault create new.txt //直接创建新加密文件
  2. .. .. //根据提示设置密码
  3. [alice@control ansible]$ ansible-vault view new.txt //查看已加密的文件
  4. .. .. //根据提示输入正确的密码验证
  5. [alice@control ansible]$ ansible-vault decrypt new.txt //将文件解密(恢复成明文数据)
  6. .. .. //根据提示输入正确的密码验证
  7. [alice@control ansible]$ ansible-vault encrypt new.txt //将现有文件加密(变成密文)
  8. .. .. //根据提示设置密码
  9. [alice@control ansible]$ ansible-vault rekey new.txt //修改已加密文件的密码
  10. .. .. //根据提示验证旧密码
  11. .. .. //再设置新密码
  12. [alice@control ansible]$ ansible-vault view new.txt --vault-password-file=key.txt //通过密码文件输入密码

 


主机信息搜集(gather_facts: yes)

    Ansible每次执行playbook剧本时,默认第一个任务就是Gathering Facts搜集主机信息。所有收集到的系统信息都被保存在ansible_facts指标变量中,可以通过setup模块查看,或者在playbook剧本中调用。当添加参数 gather_facts:no 时,不会采集

playbook变量的作用及定义、调用方法

什么是变量:

  • 通过固定的名称来调用可能变化的值,方便ansible重复调用以提高管理效率
  • 采用 key=value,或者 key: value 的方式定义
  • 调用时一般采用 {{key}} 方式

变量的领域:

  •      清单变量:在inventory清单主机中定义,作用于某个主机或某个主机组  主机名后面
node1 ansible_ssh_user-lisi ansible_ssh_password=123456 ansible_ssh_port=2222 #主动设置用户名密码
  •     剧本变量:在playbook剧本中定义,只在当前剧本中有效,patam那个

  • 系统变量:通过剧本的gather_facts=yes自动搜集(默认调用setup模块),对任务主机有效,系统指标
  • 魔法变量:由ansible预设,用来获取清单组、清单主机名等管理信息


 


setup模块

使用setup模块,过滤出清单主机的系统指标

基本用法:

# ansible  清单主机  -m  setup  [-a  'filter=系统指标名']

filter参数用来过滤出特定名称的系统指标,未知指标名部分可以使用 * 通配符

  1. [alice@control ansible]$ ansible node1 -m setup //查看node1的所有系统指标
  2. node1 | SUCCESS => {
  3. "ansible_facts": {
  4. "ansible_all_ipv4_addresses": [
  5. "172.25.254.101"
  6. ],
  7. "ansible_all_ipv6_addresses": [
  8. "fe80::6a52:a669:ccc3:13cc"
  9. ],
  10. "ansible_apparmor": {
  11. "status": "disabled"
  12. },
  13. .. ..
  14. [alice@control ansible]$ ansible node1 -m setup -a "filter=ansible_all_ipv4_addresses"
  15. .. .. //查看指定名称的系统指标
  16. [alice@control ansible]$ ansible node1 -m setup -a "filter=*_ipv4_addresses"
  17. .. .. //指定系统指标时,名称中允许使用通配符 *

debug模块

使用debug模块,通过msg参数显示变量的内容、自定义文本

  • 需要在playbook剧本中测试(adhoc方式未搜集信息,会提示变量未定义)
  • 使用msg显示变量时,变量名需要加 {{ }} 括起来
  • 使用var显示变量时,变量名无需 {{ }} 标记;var与msg不能同时使用

常用系统指标:

  • ansible_eth0 //网卡eth0的配置信息
  • ansible_fqdn //完整的主机名
  • ansible_hostname //主机名
  • ansible_all_ipv4_addresses//系统IPv4地址列表
  • ansible_bios_version //主机BIOS版本
  • ansible_date_time //系统日期时间信息
  • ansible_devices //硬件设备信息
  • ansible_distribution //操作系统版本
  • ansible_env //用户环境变量列表
  • ansible_kernel //内核版本信息
  • ansible_lvm //逻辑卷存储相关信息
  • ansible_memtotal_mb //总的内存大小
  • ansible_memfree_mb //空闲内存大小
  • ansible_mounts //已挂载的文件系统信息
  • ansible_interfaces //网络接口列表
  • ansible_distribution  //当前系统的发行版名称

ansible魔法变量

  • 指的是ansible为管理目的而预设的特殊变量
  • 通过adhoc方式或者playbook方式,都可以调用/或者msg查看
  1. [alice@control ansible]$ ansible node1 -m debug -a 'msg={{hostvars}}' |grep playbook_*
  2. "ansible_playbook_python": "/usr/libexec/platform-python",
  3. "playbook_dir": "/ansible"
  4. "ansible_playbook_python": "/usr/libexec/platform-python",
  5. "playbook_dir": "/ansible"
  6. "ansible_playbook_python": "/usr/libexec/platform-python",
  7. "playbook_dir": "/ansible"
  8. "ansible_playbook_python": "/usr/libexec/platform-python",
  9. "playbook_dir": "/ansible"
  10. "ansible_playbook_python": "/usr/libexec/platform-python",
  11. "playbook_dir": "/ansible"

常用魔法变量:

  • hostvars  //包含所有可控清单主机的魔法变量
  • hostvars.node1  //主机node1的魔法变量
  • hostvars.node1.group_names //主机node1在清单中所在的组名
  • group_names //当前主机所在的清单组名
  • hostvars.node1.inventory_hostname//主机node1在清单中的主机名
  • inventory_hostname //当前主机的清单主机名
  • groups//主控机清单中的所有主机组及成员主机信息
  • groups.all //主控机清单中的所有主机
  • groups.web //主控机清单中web组的所有主机

playbook中使用变量:

使用vars列表项定义

  1. [alice@control ansible]$ cat var.yml //定义v1、v2两个变量
  2. ---
  3. - name: vars test
  4. hosts: node1
  5. vars: //直接定义变量
  6. - yonghu: zhsan
  7. - mima: ab1234
  8. tasks:
  9. - debug:
  10. msg: msg="username:{{yonghu}}, password:{{mima}}"
  11. ...
  12. [alice@control ansible]$ ansible-playbook var.yml //测试剧本
  13. .. ..
  14. TASK [debug] ***************************************************************************************
  15. ok: [node1] => {
  16. "msg": "username:zhsan, password:ab1234"
  17. }
  18. .. ..

使用vars_files列表项定义,从外部变量文件加载变量

  1. [alice@control ansible]$ cat vars_files.yml
  2. ---
  3. - name: vars_files test
  4. hosts: node1
  5. vars_files: //调用变量文件
  6. - v3v4.txt
  7. tasks:
  8. - debug: msg="username:{{yonghu}}, password:{{mima}}"
  9. ...
  10. [alice@control ansible]$ ansible-playbook vars_files.yml
  11. .. ..
  12. TASK [debug] ***************************************************************************************
  13. ok: [node1] => {
  14. "msg": "username:lisi, password:cd5678"
  15. }
  16. .. ..

使用vars_prompt从键盘输入变量值

  1. [alice@control ansible]$ cat vars_prompt.yml
  2. ---
  3. - name: vars_prompt test
  4. hosts: node1
  5. vars_prompt: //人机交互为变量赋值
  6. - name: ilogin
  7. prompt: "login"
  8. private: no //回显
  9. - name: ipass
  10. prompt: "password"
  11. private: yes //不回显(缺省)
  12. tasks:
  13. - name: create an user
  14. user: name="{{ilogin}}" password="{{ ipass | password_hash('sha512') }}"
  15. ...
  16. [alice@control ansible]$ ansible-playbook vars_prompt.yml //执行剧本
  17. login: wangwu //输入用户名
  18. password: //输入密码(不显示)
  19. .. ..
  20. [alice@control ansible]$ ansible node1 -a 'id wangwu' //检查结果
  21. node1 | CHANGED | rc=0 >>
  22. uid=1002(wangwu) gid=1004(wangwu) groups=1004(wangwu)

通过register模块保存命令结果(类似于Shell的重定向)

  1. [alice@control ansible]$ cat register.yml
  2. ---
  3. - name: register test
  4. hosts: node1
  5. ignore_errors: yes //即使遇到错误,仍然执行后续操作
  6. tasks:
  7. - shell: ls -lh /etc/hosts /etc/null
  8. register: result //将屏幕输出保存到result变量
  9. - debug: msg="{{result.stdout}}" //提取标准输出
  10. - debug: msg="{{result.stderr}}" //提权标准错误
  11. - debug: msg="{{result}}" //提取变量result的所有内容
  12. ...
  13. [alice@control ansible]$ ansible-playbook register.yml //执行剧本
  14. .. ..
  15. TASK [debug] ***************************************************************************************
  16. ok: [node1] => {
  17. "msg": "-rw-r--r--. 1 root root 617 Mar 27 19:10 /etc/hosts"
  18. }
  19. TASK [debug] ***************************************************************************************
  20. ok: [node1] => {
  21. "msg": "ls: cannot access '/etc/null': No such file or directory"
  22. }
  23. .. ..

模板中的for循环应用

  • 通过魔法变量 groups.all 取得所有清单主机名
  •  通过魔法变量 hostvars["node1"] 取得node1的魔法变量和系统变量信息(如果使用目标主机的系统变量,需要在剧本中提前搜集)
  1. [alice@control ansible]$ vim newhosts.j2
  2. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  3. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
  4. {% for id in groups.all %}
  5. {{hostvars[id].ansible_eth0.ipv4.address}} {{hostvars[id].ansible_fqdn}}
  6. {{hostvars[id].ansible_hostname}}
  7. {% endfor %}
  1. [alice@control ansible]$ vim newhosts.yml
  2. - hosts: all //搜集所有主机的信息
  3. - hosts: test01 //为 xx 组部署
  4. tasks:
  5. - template: src=newhosts.j2 dest=/etc/newhosts force=yes //通过模板部署文件

模板文件中的if分支应用

  1. [alice@control ansible]$ vim newissue.yml
  2. - name: deploy /etc/issue
  3. hosts: all
  4. tasks:
  5. - copy:
  6. content: | //准备文本内容
  7. {% if "test01" in group_names %} //如果所在组包括 dev
  8. test01
  9. {% elif "test02" in group_names %} //如果所在组包括 test
  10. test02
  11. {% elif "web" in group_names %} //如果所在组包括 prod
  12. Webserver
  13. {% endif %}
  14. dest: /etc/issue //复制到指定目标文件
  15. [alice@control ansible]$ ansible-playbook newissue.yml

六、ansible角色

什么是角色:

  • role指的是,为了方便复杂任务(包含大批量任务操作、模板、变量等资源)的重复使用,降低playbook剧本编写难度,而预先定义好的一套目录结构。
  • 针对每一个角色,ansible会到固定的目录去调取特定的数据
  • 角色内不指定“hosts: 清单主机列表”,而是交给调用此角色的剧本来指定

名为 nginx角色 的角色目录构成:

  • nginx/ //角色根目录
  • nginx/tasks/main.yml //任务入口,最主要的文件
  • nginx/defualts/main.yml //定义变量的缺省值,优先级较低
  • nginx/files/ //存放静态文件
  • nginx/handlers/main.yml //定义handlers处理任务
  • nginx/meta/main.yml //定义作者、版本等描述信息
  • nginx/README.md //整个角色的描述信息
  • nginx/templates/ //存放模板文件
  • nginx/vars/main.yml //定义角色变量,优先级高

rhel-system-roles软件包:

  • 安装后会提供一组由红帽预先设置好的角色,方便用来管理RHEL系统
  • 比如 timesync、kdump、network、postfix、……等等
  • 默认位置 /usr/share/ansible/roles/*,可以按需复制到用户的roles目录下使用

设置角色变量:

  • 通过修改角色目录下的 vars/main.yml 文件,可以定义角色变量
  1. [alice@control ansible]$ cp -r /usr/share/ansible/roles/rhel-system-roles.timesync roles/
  2. [alice@control ansible]$ vim roles/rhel-system-roles.timesync/vars/main.yml
  3. .. ..
  4. timesync_ntp_servers:
  5. - hostname: 172.25.254.250
  6. iburst: yes

通过playbook剧本调用xx系统角色:

  • 使用roles语句,指定角色名称即可调用角色任务、变量等批量数据
  1. [alice@control ansible]$ cat timesync.yml
  2. ---
  3. - name: timesync
  4. hosts: all
  5. roles:
  6. - rhel-system-roles.timesync //调用xx角色
  7. ...

ansible-galaxy工具:

  • galaxy的本意为“银河系”,ansible-galaxy工具可以用来统一管理大量角色
  • 联网情况下,可以通过ansible-galaxy工具访问ansible官网的公共仓库 https://galaxy.ansible.com/api/
  1. [alice@control ansible]$ ansible-galaxy list
  2. .. .. //列出已经安装的角色
  3. [alice@control ansible]$ ansible-galaxy init roles/myrole
  4. .. .. //创建名为myrole的自定义角色(目录结构)
  5. [alice@control ansible]$ ansible-galaxy remove myrole
  6. .. .. //删除名为myrole的角色
  7. [alice@control ansible]$ ansible-galaxy search nginx
  8. .. .. //从ansible官网搜索可用的角色(需联网)
  9. [alice@control ansible]$ ansible-galaxy info haproxy --offline
  10. .. .. //查询已安装的haproxy角色的描述信息
  11. [alice@control ansible]$ ansible-galaxy install -r 角色列表文件
  12. .. .. //根据角色列表文件的定义,下载并安装新的角色
  1. [alice@control ansible]$ vim roles/down.yml //配置角色导入信息
  2. - name: haproxy //指定角色1的新名称
  3. src: http://study.lab0.example.com/roles/haproxy.tar //指定角色tar包的下载地址
  4. - name: myphp //指定角色2的新名称
  5. src: acandid.httpd //通过名称直接从ansible官网下载(需联网)

七、实战题目:

1.安装和配置ansible环境 

1) 安装所需软件包 
2) 在/home/alice/ansible/inventory文件中设置主机清单,要求: node1属于test01主机组 node2属于test02主机组 node3和node4属于web主机组 node5属于test05主机组 web组属于webtest主机组 
3) 在/home/alice/ansible目录中创建ansible.cfg,满足以下需求:主机清单文件为 /home/alice/ansible/inventory playbook中角色位置为 /home/alice/ansible/roles 

  1. [root@control ~]# yum  -y  install  ansible      //安装ansible软件包 
  2. [root@control ~]# su - alice           //切换为指定用户 
  3. [alice@control ~]$ mkdir  -p  ~/ansible/roles ; cd  ~/ansible/  //进入工作目录 
  4. [alice@control ansible]$ vim  ansible.cfg 
  5. [defaults] 
  6. inventory = inventory             //主机清单文件
  7. remote_user = alice            //连接受管机的远程用户名
  8. roles_path = roles             //角色目录
  9. [privilege_escalation]            //设置用户sudo提权
  10. become=True
  11. become_method=sudo
  12. become_user=root
  13. become_ask_pass=False 
  14.  
  15. [alice@control ansible]$ vim inventory   
  16. [test01]
  17. node1
  18. [test02]
  19. node2
  20. [web]
  21. node3
  22. node4
  23. [test05]
  24. node5 
  25. [webtest:children] web           //配置主机清单  

2.创建和运行Ansible临时命令

编写脚本 /home/alice/ansible/adhoc.sh,用来为所有受管机配置2个yum仓库。
仓库1: 
名称为BASE,描述为software base 
URL为http://study.lab0.example.com/rhel8/BaseOS 
GPG签名启用,GPG秘钥URL为http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release 仓库为启用状态 
仓库2: 
名称为STREAM,描述为software stream 
URL为http://study.lab0.example.com/rhel8/AppStream 
GPG签名启用,GPG秘钥URL为http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release 仓库为启用状态 
 

  1. [alice@control ansible]$ vim  adhoc.sh 
  2. #!/bin/bash 
  3. ansible all -m yum_repository -a 'name=BASE description="software base" baseurl=http://study.lab0.example.com/rhel8/BaseOS gpgcheck=yes gpgkey=http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release enabled=yes'
  4. ansible all -m yum_repository -a 'name=STREAM description="software stream" baseurl=http://study.lab0.example.com/rhel8/AppStream gpgcheck=yes  gpgkey=http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release enabled=yes'  
  5. [alice@control ansible]$ chmod  +x  adhoc.sh 
  6. [alice@control ansible]$ ./adhoc.sh  

3.编写剧本远程安装软件 

创建名为/home/alice/ansible/tools.yml的playbook,能够实现以下目的: 
  1) 将php和tftp软件包安装到test01、test02和web主机组中的主机上 
  2) 将RPM Development Tools软件包组安装到test01主机组中的主机上
       3)将test01主机组中的主机上所有软件包升级到最新版

  1.  [alice@control ansible]$ vim  tools.yml 
  2. - name: 1. install php and mariadb on test01, test02, web  
  3. hosts: test01, test02, web  
  4. tasks: 
  5. - yum: pkg=php state=present           //安装php软件包    
  6. - yum: pkg=tftp state=present           //安装mariadb软件包
  7. - name: 2. install @RPM Development Tools on test01    
  8. hosts: test01  
  9. tasks: 
  10. - yum: name="@RPM Development Tools" state=present     //安装xx包组
  11. - name: 3. update all packages  
  12. hosts: test01  
  13. tasks:  
  14. - yum: name="*" state="latest"  //升级所有包       
  15. [alice@control ansible]$ ansible-playbook tools.yml  

  1. - hosts: test01,test02,web
  2. tasks:
  3. - yum: name="php,tftp" state=present
  4. - hosts: test01
  5. tasks:
  6. - yum: name="@RPM Development Tools" state=present
  7. - yum: name="*" state=latest

 4.安装并使用系统角色 


安装RHEL角色软件包,并创建剧本 /home/alice/ansible/timesync.yml,满足以下要求: 
  1) 在所有受管理节点运行 
  2) 使用timesync角色 
  3) 配置该角色,使用时间服务器172.25.254.250,并启用iburst参数 

  1. [root@control ~]# yum  -y install rhel-system-roles     //安装rhel系统角色 
  2. [root@control ~]# su  -  alice 
  3. [alice@control ~]$ cd  ansible/ 
  4. [alice@control ansible]$ cp -r /usr/share/ansible/roles/rhel-system-roles.timesync  roles/ 
  5.                  //复制角色目录 
  6. [alice@control ansible]$ vim  timesync.yml 
  7. - name: timesync  
  8. hosts: all  
  9. vars: 
  10. - timesync_ntp_servers:          //设置NTD服务器变量 
  11. - hostname: 172.25.254.250          
  12. iburst: yes  
  13. roles: 
  14. - rhel-system-roles.timesync         //调用角色 
  15. [alice@control ansible]$ ansible-playbook timesync.yml 

5.通过galaxy安装角色 

创建剧本 /home/alice/ansible/roles/down.yml,用来从以下 URL 下载角色,并安装到
/home/alice/ansible/roles目录下: http://study.lab0.example.com/roles/haproxy.tar 此角色名为haproxy http://study.lab0.example.com/roles/myphp.tar 此角色名为myphp 

  1. [alice@control ansible]$ vim  /home/alice/ansible/roles/down.yml   
  2. - name: haproxy 
  3.   src: http://study.lab0.example.com/roles/haproxy.tar
  4. - name: myphp //配置角色导入信息
  5.   src: http://study.lab0.example.com/roles/myphp.tar 
  6. [alice@control ansible]$ ansible-galaxy  install  -r  roles/down.yml   //导入角色

6.创建及使用自定义角色

 根据下列要求,在/home/alice/ansible/roles中创建名为httpd的角色: 
  1) 安装httpd软件,并能够开机自动运行 
  2) 开启防火墙,并允许httpd通过 
  3) 使用模板index.html.j2,用来创建/var/www/html/index.html网页,内容如下(其中,HOSTNAME是受管理节点的完全域名,IPADDRESS是IP地址): 
Welcome to HOSTNAME on IPADDRESS 
然后创建剧本 /home/alice/ansible/myrole.yml,为webtest主机组启用httpd角色。 

  1. [alice@control roles]$ cd ~/ansible/roles 
  2. [alice@control roles]$ ansible-galaxy  init  httpd    //在roles/目录下初始化角色 
  3. [alice@control roles]$ vim  httpd/templates/index.html.j2  //编写角色模板(网页) 
  4. Welcome to {{ ansible_facts.fqdn }} on {{ ansible_facts.eth0.ipv4.address }}  
  5. [alice@control roles]$ vim  httpd/tasks/main.yml    //配置角色主任务 
  6. - name: 1. install httpd          //装包  
  7. yum: pkg=httpd state=present 
  8. - name: 2. deploy index.html         //配置网页资源 
  9.   template: src=index.html.j2 dest=/var/www/html/index.html 
  10. - name: 3. httpd               //起服务 
  11.   service: name=httpd state=restarted enabled=yes 
  12. - name: 4. firewalld           //起服务 
  13.   service: name=firewalld state=restarted enabled=yes 
  14. - name: 5. configure firewall rules       //配置防火墙规则 
  15.   firewalld: service=http state=enabled permanent=yes immediate=yes  
  16. [alice@control roles]$ cd ~/ansible/ 
  17. [alice@control ansible]$ vim  myrole.yml      //编写启动脚本 
  18. - name: use role  
  19. hosts: webtest  
  20. roles: 
  21. - httpd 
  22. [alice@control ansible]$ ansible-playbook myrole.yml 

7.使用之前通过galaxy下载的角色 

创建剧本 /home/alice/ansible/web.yml,满足下列需求: 
  1) 该剧本中包含一个play,可以在test05主机组运行haproxy角色(此角色已经配置好网站的负载均衡服务) 
  2) 多次访问http://node5.net0.example.com可以输出不同主机的欢迎页面 
  3) 该剧本中包含另一个play,可以在webtest主机组运行myphp角色(此角色已经配置好网站的php页面) 
  4) 多次访问http://node5.net0.example.com/index.php也输出不同主机的欢迎页面 

  1. [alice@control ansible]$ vim  web.yml 
  2.   - name: use role B             //先部署web节点  
  3. hosts: webtest  
  4. roles: 
  5.    - myphp 
  6.   - name: use role A 
  7.   hosts: test05             //再配置负载均衡器  
  8. roles: 
  9.    - haproxy  
  10. tasks: 
  11.    - firewalld: service=http state=enabled permanent=yes immediate=yes [alice@control ansible]$ ansible-playbook web.yml

08. 编写剧本远程管理逻辑卷 

创建剧本 /home/alice/ansible/lvm.yml,用来为所有受管机完成以下部署: 
  1) 在卷组search中创建名为mylv的逻辑卷,大小为1000MiB 
  2) 使用ext4文件系统格式化该逻辑卷 
  3) 如果无法创建要求的大小,应显示错误信息insufficient free space,并改为500MiB 
  4) 如果卷组search不存在,应显示错误信息 VG not found 5)不需要挂载逻辑卷

  1. [alice@control ansible]$ vim  lvm.yml 
  2. - name: manager volume  
  3. hosts: all  
  4. tasks: 
  5. - name: 1. failed when VG not found      
  6. debug: msg="VG not found" 
  7.       when: "'search' not in ansible_facts.lvm.vgs"     //目标VG不存在时报错      
  8. failed_when: "'search' not in ansible_facts.lvm.vgs"   //停止后续任务    
  9. - name: 2. lvcreate      
  10. block:               //配置指令块        
  11. - lvol: lv=mylv size=1000M vg=search 
  12.           notify: mkfs             //lv建成功后通知mkfs      
  13. rescue:               //若块操作失败,则执行补救
  14. - debug: msg="insufficient free space" 
  15. - lvol: lv=mylv size=500M vg=search 
  16.       notify: mkfs             //lv建成功后通知mkfs  
  17. handlers:               //收到通知后执行    
  18. - name: mkfs                  
  19. filesystem: dev=/dev/search/mylv fstype=ext4 force=yes
  20.  
  21. [alice@control ansible]$ ansible-playbook lvm.yml //定义通知接口名mkfs 
  1. - hosts: all
  2. tasks:
  3. - fail: msg="VG not found"
  4. when: ( 'search' not in ansible_facts.lvm.vgs)
  5. - block:
  6. - lvol: lv=mylv szie=1000M vg=search
  7. rescue:
  8. - debug: msg="insufficient free space"
  9. - lvol: lv=mylv size=500M vg=search
  10. - filesystem: dev=/dev/search/mylv fstype=ext4 force=yes
  11. ~

09. 根据模板部署主机文件 

1) 从http://study.lab0.example.com/materials/newhosts.j2 下载模板文件 
2) 完成该模板,用来生成新主机清单(主机的显示顺序没有要求),结构如下 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6  172.25.254.101 node1.lab0.example.com node1 
172.25.254.102 node2.lab0.example.com node2 
172.25.254.103 node3.lab0.example.com node3 
172.25.254.104 node4.lab0.example.com node4 
172.25.254.105 node5.lab0.example.com node5 
3) 创建剧本 /home/alice/ansible/newhosts.yml,它将使用上述模板在test01主机组的主机上生成文件/etc/newhosts 

  1. [alice@control ansible]$ sudo yum -y  install   wget 
  2. [alice@control ansible]$ wget http://study.lab0.example.com/materials/newhosts.j2 
  3. [alice@control ansible]$ vim  newhosts.j2       //制作J2动态模板文件 
  4. 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6  
  5. {% for id in groups.all %} 
  6. {{hostvars[id].ansible_facts.eth0.ipv4.address}}     {{hostvars[id].ansible_facts.fqdn}}   
  7. {{hostvars[id].ansible_facts.hostname}} 
  8. {% endfor %} 
  9.  
  10. [alice@control ansible]$ vim  newhosts.yml 
  11. - name: gather groups facts 
  12.   hosts: all              //搜集所有主机的信息 
  13. - name: deploy /etc/newhosts 
  14.   hosts: test01             //只为xx组部署  
  15. tasks: 
  16. - template: src=newhosts.j2 dest=/etc/newhosts     //通过模板部署文件 
  17.  
  18. [alice@control ansible]$ ansible-playbook newhosts.yml 

10. 编写剧本修改远程文件内容 

创建剧本 /home/alice/ansible/newissue.yml,满足下列要求: 
1) 在所有清单主机上运行,替换/etc/issue的内容 
2) 对于test01主机组中的主机,/etc/issue文件内容为test01 
3) 对于test02主机组中的主机,/etc/issue文件内容为test02 
4) 对于web主机组中的主机,/etc/issue文件内容为Webserver 

  1. [alice@control ansible]$ vim  newissue.yml 
  2. - name: deploy /etc/issue  
  3. hosts: all  
  4. tasks:
  5. - copy: content: |                 //准备文本内容          
  6. {% if "test01" in group_names %}           //如果所在组包括dev  
  7. test01 
  8.   {% elif "test02" in group_names %}           //如果所在组包括test          
  9. test02 
  10.   {% elif "web" in group_names %}   
  11.   Webserver 
  12.   {% endif %}         //如果所在组包括prod  
  13. dest: /etc/issue          
  14. [alice@control ansible]$ ansible-playbook newissue.yml   //复制到指定目标文件 


11.编写剧本部署远程Web目录 

创建剧本 /home/alice/ansible/webdev.yml,满足下列要求: 
1) 在test01主机组运行 
2) 创建目录/webdev,属于webdev组,常规权限为rwxrwxr-x,具有SetGID特殊权限 3)使用符号链接/var/www/html/webdev链接到/webdev目录 4)创建文件/webdev/index.html,内容是It's works! 
5)查看test01主机组的web页面  http://node1/webdev/ 将显示It's works! 

  1. [alice@control ansible]$ vim  webdev.yml  
  2. - name: Prepare Web Directory  
  3. hosts: test01  
  4. tasks: 
  5. - group: name=webdev state=present 
  6. - file: name=/webdev group=webdev mode=2775 state=directory    //建目录 
  7. - file: src=/webdev name=/var/www/html/webdev state=link force=yes  //建链接 
  8. - copy: content="It's works!" dest=/webdev/index.html force=yes   //部署网页 
  9. - yum: name=policycoreutils-python-utils.noarch state=present  //安装semanage工具    
  10. - sefcontext: target='/webdev(/.*)?' setype=httpd_sys_content_t  //设置目录安全上下文  
  11. - command: restorecon -iR /webdev         //应用上下文策略 
  12. - firewalld: service=http state=enabled permanent=yes immediate=yes    
  13. - service: name=httpd state=restarted enabled=yes  
  14. [alice@control ansible]$ ansible-playbook webdev.yml 

 

  1. [alice@control ansible]$ ansible test01 -a 'cat /etc/selinux/config'
  2. node1 | CHANGED | rc=0 >>
  3. # This file controls the state of SELinux on the system.
  4. # SELINUX= can take one of these three values:
  5. # enforcing - SELinux security policy is enforced.
  6. # permissive - SELinux prints warnings instead of enforcing.
  7. # disabled - No SELinux policy is loaded.
  8. # SELINUXTYPE= can take one of these three values:
  9. # targeted - Targeted processes are protected,
  10. # minimum - Modification of targeted policy. Only selected processes are protected.
  11. # mls - Multi Level Security protection.
  12. SELINUXTYPE=targeted
  13. SELINUX=enforcing
  14. [alice@control ansible]$ ansible-playbook webde.yml
  15. PLAY [test01] ******************************************************************
  16. TASK [Gathering Facts] *********************************************************
  17. ok: [node1]
  18. TASK [group] *******************************************************************
  19. changed: [node1]
  20. TASK [file] ********************************************************************
  21. changed: [node1]
  22. TASK [file] ********************************************************************
  23. [WARNING]: Cannot set fs attributes on a non-existent symlink target. follow
  24. should be set to False to avoid this.
  25. changed: [node1]
  26. TASK [copy] ********************************************************************
  27. changed: [node1]
  28. TASK [lineinfile] **************************************************************
  29. changed: [node1]
  30. TASK [service] *****************************************************************
  31. changed: [node1]
  32. TASK [command] *****************************************************************
  33. changed: [node1]
  34. TASK [firewalld] ***************************************************************
  35. ok: [node1]
  36. PLAY RECAP *********************************************************************
  37. node1 : ok=9 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
  38. [alice@control ansible]$ ansible test01 -a 'cat /etc/selinux/config'
  39. node1 | CHANGED | rc=0 >>
  40. # This file controls the state of SELinux on the system.
  41. # SELINUX= can take one of these three values:
  42. # enforcing - SELinux security policy is enforced.
  43. # permissive - SELinux prints warnings instead of enforcing.
  44. # disabled - No SELinux policy is loaded.
  45. # SELINUXTYPE= can take one of these three values:
  46. # targeted - Targeted processes are protected,
  47. # minimum - Modification of targeted policy. Only selected processes are protected.
  48. # mls - Multi Level Security protection.
  49. SELINUXTYPE=targeted
  50. SELINUX=disabled
  51. [alice@control ansible]$

12.编写剧本为受管机生成硬件报告

 
创建名为/home/alice/ansible/hardware.yml的playbook,满足下列要求: 
1) 使所有受管理节点从以下URL下载文件: 
http://study.lab0.example.com/materials/hardware.empty   
2) 并用来生成以下硬件报告信息,存储在各自的/root/hardware.txt文件中 

  • 清单主机名称
  • 以MB表示的总内存大小 
  • BIOS版本
  • 硬盘vda的大小
  • 硬盘vdb的大小 

其中,文件的每一行含有一个key=value对,如果项目不存在,则显示NONE。 

  1. [alice@control ansible]$ vim  hardware.yml 
  2. - name: hardware report  
  3. hosts: all 
  4.   ignore_errors: yes        //忽略个别错误  
  5. vars:               //提取硬件检测结果 
  6.   - sfile: /root/hardware.txt         //硬件报告文件路径 
  7.   - host: "{{inventory_hostname}}"        //提取清单主机名 
  8.   - mem: "{{ansible_facts.memtotal_mb}}"       //提取总内存大小(MB) 
  9.   - bios: "{{ansible_facts.bios_version}}"      //提取BIOS版本 
  10.   - vdasize: "{{ansible_facts.devices.vda.size}}"    //提取磁盘vda大小 
  11.   - vdbsize: "{{ansible_facts.devices.vdb.size if ansible_facts.devices.vdb.size is defined  else 'NONE' }}"              //提取磁盘vdb大小,或NONE  
  12. tasks:            //修改报告(根据模板内容查找替换) 
  13.   - get_url: url=http://study.lab0.example.com/materials/hardware.empty dest={{sfile}} force=yes 
  14.   - replace: name={{sfile}} regexp=inventoryhostname replace={{host}}   
  15.   - replace: name={{sfile}} regexp=memory_in_MB replace={{mem}} 
  16.   - replace: name={{sfile}} regexp=BIOS_version replace={{bios}} 
  17.   - replace: name={{sfile}} regexp=disk_vda_size replace={{vdasize}} 
  18.   - replace: name={{sfile}} regexp=disk_vdb_size replace={{vdbsize}} [alice@control ansible]$ ansible-playbook hardware.yml 

13.编写脚步创建保险库文件   

1)创建ansible保险库 /home/alice/ansible/passdb.yml,其中有2个变量: 
pw_dev,值为ab1234

pw_man,值为cd5678 
2) 加密和解密该库的密码是pwd@1234 ,密码存在/home/alice/ansible/secret.txt中 

  1. [alice@control ansible]$ echo 'pwd@1234' > secret.txt //创建保险库钥匙文件
  2. [alice@control ansible]$ ansible-vault create passdb.yml --vault-password-file=secret.txt  //创建保险库文件
  3. pw_dev: ab1234
  4. pw_man: cd5678

14.编写剧本为受管机批量创建用户,要求使用保险库中的密码

从以下URL下载用户列表,保存到/home/alice/ansible目录下: http://study.lab0.example.com/materials/name_list.yml  
创建剧本 /home/alice/ansible/users.yml的playbook,满足下列要求: 
  1) 使用之前题目中的passdb.yml保险库文件 
  2) 职位描述为dev的用户应在test01、test02主机组的受管机上创建,从pw_dev变量分配密码,是补充组devops的成员 
  3) 职位描述为man的用户应在web主机组的受管机上创建,从pw_man变量分配密码,是补充组opsmgr的成员 
  4) 该playbook可以使用之前题目创建的secret.txt密码文件运行 
解题参考: 

 

  1. [alice@control ansible]$ wget http://study.lab0.example.com/materials/name_list.yml  
  2.                //获取用户列表文件
  3. [alice@control ansible]$ cat  name_list.yml      //确认列表内容  
  4. users:  
  5. - name: tom 
  6.   job: dev              //用户岗位a
  7. - name: jerry 
  8.   job: man             //用户岗位b 
  9.  
  10. [alice@control ansible]$ vim  users.yml  
  11. - name: batch users  
  12. hosts: test01, test02, web  
  13. vars_files: 
  14. - passdb.yml             //加载密码变量    
  15. - name_list.yml           //加载用户名变量  
  16. tasks: 
  17. - group: name=devops         //确保补充组1在指定主机已存在      
  18. when: ('test01' in group_names or 'test02' in group_names) 
  19. - group: name=opsmgr          //确保补充组2在指定主机已存在      
  20. when: ('web' in group_names) 
  21. - user: name={{item.name}} password={{pw_dev|password_hash('sha512')}} groups=devops append=yes 
  22.       when: (item.job == 'dev') and ('test01' in group_names or 'test02' in group_names) 
  23.       loop: "{{users}}"           //按条件添加a岗用户 
  24. - user: name={{item.name}} password={{pw_man|password_hash('sha512')}} groups=opsmgr append=yes 
  25.       when: (item.job == 'man') and ('web' in group_names) 
  26.       loop: "{{users}}"             //按条件添加b岗用户 
  27.  
  28. [alice@control  ansible]$     ansible-playbook     users.yml     --vaultid=/home/alice/ansible/secret.txt         //测试效果 

15.重设保险库密码

  • 1) 从以下URL下载保险库文件到/home/alice/ansible目录: http://study.lab0.example.com/materials/topsec.yml  
  • 2) 当前的库密码是banana,新密码是big_banana,请更新该库密码 
  1. [alice@control ansible]$ wget http://study.lab0.example.com/materials/topsec.yml
  2. //下载指定保险库文件
  3. [alice@control ansible]$ ansible-vault rekey topsec.yml //为保险库设置新的密码
  4. Vault password: 输入当前的库密码
  5. New Vault password: 输入新的库密码
  6. confirm New Vault password: 再次输入新的库密码确认
  7. Rekey successful

16.从control把node2远程部署一个支持PHP网页的Web服务器

  • 1)为主机node2安装httpd、php这两个包
  • 2)为主机node2准备网页 /var/www/html/index.php,内容如下:LIRUILONG。。。
  • 3)为主机node2启动httpd服务、关闭firewalld服务
  • 4)从server1上浏览器访问 http://node2.net0.example.com
  1. [alice@control ansible]$ ansible node2 -m yum -a 'name=httpd state=installed'
  2. node2 | SUCCESS => {
  3. "ansible_facts": {
  4. "discovered_interpreter_python": "/usr/libexec/platform-python"
  5. },
  6. "changed": false,
  7. "msg": "Nothing to do",
  8. "rc": 0,
  9. "results": [
  10. "Installed: httpd"
  11. ]
  12. }
  13. [alice@control ansible]$ ansible node2 -m copy -a 'content="LIRUILONG I LOVE .." dest=/var/www/html/index.php'
  14. node2 | CHANGED => {
  15. "ansible_facts": {
  16. "discovered_interpreter_python": "/usr/libexec/platform-python"
  17. },
  18. "changed": true,
  19. "checksum": "fc99d7c0185aef310990bb4c4e153c353921f25c",
  20. "dest": "/var/www/html/index.php",
  21. "gid": 0,
  22. "group": "root",
  23. "md5sum": "8ac9bcd94020e2284a3522af4a13d1a3",
  24. "mode": "0644",
  25. "owner": "root",
  26. "secontext": "system_u:object_r:httpd_sys_content_t:s0",
  27. "size": 19,
  28. "src": "/home/alice/.ansible/tmp/ansible-tmp-1613309455.7519739-91578945277811/source",
  29. "state": "file",
  30. "uid": 0
  31. }
  32. [alice@control ansible]$ ansible node2 -m service -a 'name=httpd state=started enabled=yes'
  33. node2 | CHANGED => {
  34. "ansible_facts": {
  35. "discovered_interpreter_python": "/usr/libexec/platform-python"
  36. },
  37. "changed": true,
  38. "enabled": true,
  39. "name": "httpd",
  40. "state": "started",
  41. "status": {
  42. "ActiveEnterTimestampMonotonic": "0",
  43. "ActiveExitTimestampMonotonic": "0",
  44. "ActiveState": "inactive",
  45. "After": "remote-fs.target -.mount network.target nss-lookup.target systemd-journald.socket tmp.mount systemd-tmpfiles-setup.service system.slice basic.target httpd-init.service sysinit.target",
  46. "AllowIsolate": "no",
  47. ...
  48. }
  49. }
  50. [alice@control ansible]$ curl http://node2/
  51. curl: (7) Failed to connect to node2 port 80: No route to host
  52. [alice@control ansible]$ ansible node2 -m service -a 'name=firewalld state=stopped enabled=no'
  53. node2 | CHANGED => {
  54. "ansible_facts": {
  55. "discovered_interpreter_python": "/usr/libexec/platform-python"
  56. },
  57. "changed": true,
  58. "enabled": false,
  59. "name": "firewalld",
  60. "state": "stopped",
  61. "status": {
  62. "ActiveEnterTimestamp": "Sun 2021-02-14 20:59:54 CST",
  63. "ActiveEnterTimestampMonotonic": "99056499",
  64. "ActiveExitTimestampMonotonic": "0",
  65. "ActiveState": "active",
  66. "After": "basic.target sysinit.target polkit.service system.slice dbus.socket dbus.service",
  67. "AllowIsolate": "no",
  68. }
  69. }
  70. [alice@control ansible]$ curl http://node2/
  71. LIRUILONG I LOVE ..[alice@control ansible]$

17.逻辑卷管理

  • 1)为node4的/dev/vdb建立2个分区,分别300M、700M。
  • 2)使用node4的/dev/vdb2创建一个名为redhat的卷组。
  • 3)在node4上的redhat卷组中创建一个200M、名为rhcsa的逻辑卷。
  • 4)将node4上的逻辑卷/dev/redhat/rhcsa格式为xfs文件系统。

  1. ansible node4 -m parted -a 'device=/dev/vdb state=present number=1 part_start=0% part_end=300MiB'
  2. ansible node4 -m parted -a 'device=/dev/vdb state=present number=2 part_start=300MiB part_ end=1000MiB'
  3. ansible node4 -m lvg -a 'vg=redhat pvs=/dev/vdb2'
  4. ansible node4 -m lvol -a 'lv=rhcsa size=200M vg=redhat state=present force=yes'
  5. ansible node4 -m filesystem -a 'dev=/dev/redhat/rhcsa fstype=xfs force=yes'

18.编写play部署远程Web目录 

  • 1)为node2创建新目录 /webdev
  • 2)确认node2上 /webdev目录的安全属性
  • 3) 通过sefcontext去修改node2主机上 /webdev 目录的安全属性(结合restorecon命令)
  • 4)确认node2上 /webdev目录的安全属性
  • 5)为node2部署网页 /webdev/index.html,内容为"SELinux Test"
  • 6)访问 http://node2/webdev/ 时能看到上述网页内容

方法一:直接关闭SELinux属性

  1. [alice@control ansible]$ ansible node2 -m file -a 'name=/webdev state=directory'
  2. node2 | CHANGED => {
  3. "ansible_facts": {
  4. "discovered_interpreter_python": "/usr/libexec/platform-python"
  5. },
  6. "changed": true,
  7. "gid": 0,
  8. "group": "root",
  9. "mode": "0755",
  10. "owner": "root",
  11. "path": "/webdev",
  12. "secontext": "unconfined_u:object_r:default_t:s0",
  13. "size": 6,
  14. "state": "directory",
  15. "uid": 0
  16. }
  17. [alice@control ansible]$ ansible node2 -m file -a 'name=/webdev state=directory'
  18. node2 | SUCCESS => {
  19. "ansible_facts": {
  20. "discovered_interpreter_python": "/usr/libexec/platform-python"
  21. },
  22. "changed": false,
  23. "gid": 0,
  24. "group": "root",
  25. "mode": "0755",
  26. "owner": "root",
  27. "path": "/webdev",
  28. "secontext": "unconfined_u:object_r:default_t:s0",
  29. "size": 6,
  30. "state": "directory",
  31. "uid": 0
  32. }
  33. [alice@control ansible]$ ansible node2 -a 'ls -lZd /webdev /var/www/html'
  34. node2 | CHANGED | rc=0 >>
  35. drwxr-xr-x. 2 root root system_u:object_r:httpd_sys_content_t:s0 23 Feb 14 21:30 /var/www/html
  36. drwxr-xr-x. 2 root root unconfined_u:object_r:default_t:s0 6 Feb 15 10:15 /webdev
  37. [alice@control ansible]$ ansible node2 -a 'setenforce 0'
  38. node2 | CHANGED | rc=0 >>
  39. [alice@control ansible]$ curl http://node2/webdev/
  40. SElinux Love[alice@controansible node2 -a 'cat /var/www/html/webdev/index.html'
  41. node2 | CHANGED | rc=0 >>
  42. SElinux Love
  43. [alice@control ansible]$ curl http://node2/webdev/
  44. SElinux Love[alice@control ansible]$

方法二,通过sefcontext修改SElinux权限设置。

  1. ansible node2 -m yum -a 'name=policycoreutils-python-utils state=present'
  2. yum provides semanage
  3. ansible node2 -m sefcontext -a 'path="/webdev(/.*)?" setype=httpd sys content t'
  4. ansible node2 -a 'restorecon -R /webdev'
  5. [alice@control ansible]$ ansible node2 -m yum -a 'name=policycoreutils-python-utils state=present'
  6. node2 | CHANGED => {
  7. "ansible_facts": {
  8. "discovered_interpreter_python": "/usr/libexec/platform-python"
  9. },
  10. "changed": true,
  11. "msg": "",
  12. "rc": 0,
  13. "results": [
  14. "Installed: policycoreutils-python-utils",
  15. "Installed: python3-setools-4.2.2-2.el8.x86_64",
  16. "Installed: policycoreutils-python-utils-2.9-9.el8.noarch",
  17. "Installed: python3-libsemanage-2.9-2.el8.x86_64",
  18. "Installed: python3-policycoreutils-2.9-9.el8.noarch",
  19. "Installed: checkpolicy-2.9-1.el8.x86_64",
  20. "Installed: python3-audit-3.0-0.17.20191104git1c2f876.el8.x86_64"
  21. ]
  22. }
  23. [alice@control ansible]$ ansible node2 -m sefcontext -a 'path="/webdev(/.*)?" setype=httpd_sys_content_t'
  24. node2 | CHANGED => {
  25. "ansible_facts": {
  26. "discovered_interpreter_python": "/usr/libexec/platform-python"
  27. },
  28. "changed": true,
  29. "ftype": "a",
  30. "serange": "s0",
  31. "setype": "httpd_sys_content_t",
  32. "seuser": "system_u",
  33. "state": "present",
  34. "target": "/webdev(/.*)?"
  35. }
  36. [alice@control ansible]$ ansible node2 -a 'restorecon -R /webdev'
  37. node2 | CHANGED | rc=0 >>
  38. [alice@control ansible]$ curl http://node2/webdev/
  39. SElinux Love[alice@control ansible]$

19.play方式文件修改

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/409022
推荐阅读
相关标签
  

闽ICP备14008679号