寫在前面:
筆記是因為考紅帽所以整理的,主要是常用模塊整理,后面有些類似考試的實戰題目,還在完善中.. 額,不是教程,教程建議大家到下面的學習網站,適合溫習用,
建議學習網站:Ansible檔案:https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html
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:劇本執行多個任務時,非必需可以讓節點一次性運行多個任務,
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 //確認版本相關資訊

需要的依賴包:

查看版本控制

查看主機清單

[root@control ~]# ansible 127.0.0.1 --list-hosts
hosts (1):
127.0.0.1
[root@control ~]# ansible all --list-hosts
[WARNING]: provided hosts list is empty, only localhost is available. Note
implicit localhost does not match 'all'
hosts (0):
[root@control ~]# ansible 127.0.0.1 -m ping
127.0.0.1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
[root@control ~]# ansible 127.0.0.1 -m command -a 'uname -r'
127.0.0.1 | CHANGED | rc=0 >>
4.18.0-193.el8.x86_64
[root@control ~]# ansible 127.0.0.1 -m command -a 'echo "sy"'
127.0.0.1 | CHANGED | rc=0 >>
sy
[root@control ~]# ansible 127.0.0.1 -m command -a 'echo sy"'
ERROR! failed at splitting arguments, either an unbalanced jinja2 block or quotes: echo sy"
[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 可以省略,
#查看主機清單
[root@control ~]# ansible 127.0.0.1 --list-hosts
hosts (1):
127.0.0.1
[root@control ~]# ansible all --list-hosts
[WARNING]: provided hosts list is empty, only localhost is available. Note
implicit localhost does not match 'all'
hosts (0):
[root@control ~]# ansible 127.0.0.1 -m ping
127.0.0.1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
[root@control ~]# ansible 127.0.0.1 -m command -a 'uname -r'
127.0.0.1 | CHANGED | rc=0 >>
4.18.0-193.el8.x86_64
[root@control ~]# ansible 127.0.0.1 -m command -a 'echo "sy"'
127.0.0.1 | CHANGED | rc=0 >>
sy
[root@control ~]# ansible 127.0.0.1 -m command -a 'echo sy"'
ERROR! failed at splitting arguments, either an unbalanced jinja2 block or quotes: echo sy"
[root@control ~]# ansible 127.0.0.1 -u zhsan -a 'touch /zhanshan.txt'
[WARNING]: Consider using the file module with state=touch rather than running
'touch'. If you need to use command because file is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in
ansible.cfg to get rid of this message.
127.0.0.1 | CHANGED | rc=0 >>
[root@control ~]# useradd zhsan
[root@control ~]# echo 123456 | passwd --stdin zhsan
Changing password for user zhsan.
passwd: all authentication tokens updated successfully.
[root@control ~]# ansible 127.0.0.1 -u zhsan -a 'thuch /zhsan.file'
127.0.0.1 | FAILED | rc=2 >>
[Errno 2] No such file or directory: 'thuch': 'thuch'
[root@control ~]# ansible 127.0.0.1 -u zhsan -a 'tonch /zhsan.file'
127.0.0.1 | FAILED | rc=2 >>
[Errno 2] No such file or directory: 'tonch': 'tonch'
[root@control ~]# ansible 127.0.0.1 -u zhsan -a 'touch /zhsan.file'
[WARNING]: Consider using the file module with state=touch rather than running
'touch'. If you need to use command because file is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in
ansible.cfg to get rid of this message.
127.0.0.1 | CHANGED | rc=0 >>
[root@control ~]# ansible node1 -m ping
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'
[WARNING]: Could not match supplied host pattern, ignoring: node1
[root@control ~]# vim /etc/ansible/hosts
[root@control ~]# ls
anaconda-ks.cfg
[root@control ~]# ansible node1 -m ping
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[root@control ~]# ssh node1
Last login: Thu Feb 11 01:18:11 2021 from 172.25.254.100
[root@node1 ~]# useradd lisi
[root@node1 ~]# echo 123456 | passwd --stdin lisi
Changing password for user lisi.
passwd: all authentication tokens updated successfully.
[root@node1 ~]# quit
-bash: quit: command not found
[root@node1 ~]# exit
logout
Connection to node1 closed.
[root@control ~]# ansible node1 -u lisi -k -a 'mkdir /tmp/lisidir'
SSH password:
[WARNING]: Consider using the file module with state=directory rather than
running 'mkdir'. If you need to use command because file is insufficient you
can add 'warn: false' to this command task or set 'command_warnings=False' in
ansible.cfg to get rid of this message.
node1 | CHANGED | rc=0 >>
[root@control ~]# ansible node1 -u lisi -k -a 'mkdir /tmp/lisidir'
SSH password:
[WARNING]: Consider using the file module with state=directory rather than
running 'mkdir'. If you need to use command because file is insufficient you
can add 'warn: false' to this command task or set 'command_warnings=False' in
ansible.cfg to get rid of this message.
node1 | FAILED | rc=1 >>
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
[defaults]
# 主機清單檔案,就是要控制的主機串列
inventory=inventory
# 連接受管機器的遠程的用戶名
remote_user=alice
# 角色目錄
roles_path=roles
# 設定用戶的su 提權
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False

主機清單:
被控機串列,可以是 域名,IP,分組([組名]),聚合([組名:children]),也可以主動的設定用戶名密碼
[test01] # 創建組,名字是test01
node1 # test01組中的成員
node2 # test01組中的成員
[test02] # 再創建組,名字是test02
node[3:4] # test02組中的成員
[web:children] # 創建嵌套組,組名是web,后面:children是關鍵字,表示該組可以包含其他組
test01 # web組中包含的其他組
test02
node1 ansible_ssh_user-lisi ansible_ssh_password=123456 ansible_ssh_port=2222 #主動設定用戶名密碼
[alice@control ansible]$ cat ansible.cfg
[defaults]
inventory=invertory
remote_user=alice
roles_path=roles
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
[alice@control ansible]$ vim invertory
[alice@control ansible]$ cat invertory
[test01]
node1
[test02]
node2
[web]
node[3:4]
[test05]
node5
[webtest:children]
web
[alice@control ansible]$ ansible test01 --list-hosts
hosts (1):
node1
[alice@control ansible]$ ansible test02 --list-hosts
hosts (1):
node2
[alice@control ansible]$ ansible web --list-hosts
hosts (2):
node3
node4
[alice@control ansible]$ ansible webtest --list-hosts
hosts (2):
node3
node4
[alice@control ansible]$ ansible test05 --list-hosts
hosts (1):
node5
[alice@control ansible]$
[alice@control ansible]$ ansible localhost -m ping //檢測對本機的可控性(應回傳pong)
[alice@control ansible]$ ansible all -m ping //檢測對所有清單主機的可控性
[alice@control ansible]$ ansible websvrs -m ping //檢測對websvrs組內各主機的可控性
[alice@control ansible]$ ansible node1,node5 -m ping //檢測node1和node2的可控性
[alice@control ansible]$ ansible node* -m ping //檢測node開頭的主機的可控性
[alice@control ansible]$ ansible websvrs[0] -m ping //檢測websvrs組中第1個主機的可控性
測驗一下:

受管機接受控制的方式:
- a. 受管機提供root用戶+密碼
- b. 受管機提供已授sudo特權的普通用戶(比如alice)
使用用戶名密碼的方式實作 ansible 遠程控制
[root@control ~]# ansible node1 -u lisi -k -b -a 'mkdir /tmp/lisidir1'
SSH password:
node1 | UNREACHABLE! => {
"changed": false,
"msg": "Invalid/incorrect password: Permission denied, please try again.",
"unreachable": true
}
[root@control ~]# ansible node1 -u lisi -k -b -a 'mkdir /tmp/lisidir1'
SSH password:
node1 | FAILED | rc=-1 >>
Missing sudo password
[root@control ~]# ansible localhost -m ping
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
[root@control ~]# ansible node1 -m ping
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[root@control ~]# ansible all --list-hosts
hosts (1):
node1
[root@control ~]#
sudo 提權:sudo提權設定
受管機接受控制的方式:
- a. 受管機提供root用戶+密碼
- b. 受管機提供已授sudo特權的普通用戶(比如alice)
# visudo
alice ALL=(ALL) NOPASSWD:ALL
[zhsan@control /]$ ls
bin cemo etc lib media opt root sbin sys usr zhanshan.txt
boot dev home lib64 mnt proc run srv tmp var zhsan.file
[zhsan@control /]$ mkdir /demo
mkdir: cannot create directory ‘/demo’: Permission denied
[zhsan@control /]$ sudo mkdir /demo
[zhsan@control /]$ ls
bin demo home media proc sbin tmp zhanshan.txt
boot dev lib mnt root srv usr zhsan.file
cemo etc lib64 opt run sys var
[zhsan@control /]$ ls -l demo*
total 0
[zhsan@control /]$ ls -l /demo*
total 0
[zhsan@control /]$ ls -lhd /demo*
drwxr-xr-x. 2 root root 6 Feb 11 08:33 /demo
[zhsan@control /]$ date
Thu Feb 11 08:34:06 CST 2021
[zhsan@control /]$
SSH免密登錄


使用ssh-keygen生成密鑰,使用特定的用戶執行
[root@control ~]# su - alice
Last login: Sat Oct 31 06:02:41 CST 2020 on pts/0
[alice@control ~]$ ssh node1
Last login: Fri Oct 30 14:54:47 2020
[alice@node1 ~]$ exit
logout
Connection to node1 closed.
[alice@control ~]$ ssh node2
Last login: Fri Oct 30 14:55:04 2020
[alice@node2 ~]$ exit
logout
Connection to node2 closed.
[alice@control ~]$
創建和運行Ansible
ansible管理方式(adhoc、playbook)
adhoc方式(臨時命令):
直接使用ansible命令,呼叫xx模塊來完成遠程運維任務(類似于手動執行Linux命令)
adhoc方式基本用法:
# ansible 清單主機地址串列 -m 模塊名 [-a '任務引數']
playbook方式:
提前寫好任務劇本,需要由ansible-playbook工具加載批量執行(類似于使用Shell腳本)
通過ansible-doc獲取模塊幫助
等號必須,減號可選,EXAMPLES: 各模塊檔案都有劇本應用示范
[alice@control ansible]$ ansible-doc -l //列出所有可用模塊
[alice@control ansible]$ ansible-doc -l | grep yum //列出名稱包含yum的模塊
[alice@control ansible]$ ansible-doc yum_repository //查看yum_repository模塊的說明檔案
.. ..
EXAMPLES: //各模塊檔案都有劇本應用示范
- name: Add repository
yum_repository:
name: epel
description: EPEL YUM repo
baseurl: https://download.fedoraproject.org/pub/epel/$releasever/$basearch/
.. ..
ansible常用模塊
使用萬能command/shell模塊/script模塊,推送命令列
command模塊:
預設模塊,向受管主機發送簡單命令列,不支持管道/重定向/通配符等高級特性
shell模塊:
向受管主機發送復雜命令列,支持管道/重定向/通配符等特性
script模塊:
將本地的腳本拷貝到遠程主機執行
[alice@control ansible]$ ansible node1 -a 'ip add list eth0' //查看node1的IP地址
[alice@control ansible]$ ansible -m command node1 -a 'ip add list eth0' //查看node1的IP地址
[alice@control ansible]$ ansible -m shell node1 -a 'echo hello > /root/a.file' //在node1上創建一個檔案
[alice@control ansible]$ ansible node1 -a 'cat /root/a.file' //查看node1上的檔案內容
[alice@control ansible]$ cat aa.sh
#!/bin/bash
echo "Welcome to $(hostname)"
[alice@control ansible]$ ansible node1 -m script -a './aa.sh' //將./aa.sh檔案拷貝到受控機運行
node1 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to node1 closed.\r\n",
"stderr_lines": [
"Shared connection to node1 closed."
],
"stdout": "Welcome to node1\r\n",
"stdout_lines": [
"Welcome to node1"
]
}

使用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 倉庫,
[alice@control ansible]$ vim yumdoc.sh
#!/bin/bash
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'
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'
[alice@control ansible]$ ls
ansible.cfg invertory yumdoc.sh
[alice@control ansible]$ chmod +x yumdoc.sh
[alice@control ansible]$ ./yumdoc.sh
我們開了兩臺機器node1,node2,所以其他的機器都報錯,

軟體管理模塊(yum/dnf)
- ++ name:軟體名、軟體名-版本號、逗號分隔的串列、@組名、*通配符
- ++ state:present、absent,
- ++ list:軟體名、installed、available



裝包:
將 php 和 tftp 軟體包安裝到 test01、test02 主機組中的主機上
[alice@control ansible]$ ansible test01,test02 -m yum -a 'pkg=php,tftp state=installed'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"msg": "",
"rc": 0,
"results": [
"Installed: php",
"Installed: tftp",
"Installed: apr-util-openssl-1.6.1-6.el8.x86_64",
"Installed: php-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
"Installed: httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
"Installed: php-cli-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
"Installed: mod_http2-1.11.3-3.module+el8.2.0+4377+dc421495.x86_64",
"Installed: php-common-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
"Installed: httpd-filesystem-2.4.37-21.module+el8.2.0+5008+cca404a3.noarch",
"Installed: mailcap-2.1.48-3.el8.noarch",
"Installed: apr-1.6.3-9.el8.x86_64",
"Installed: php-fpm-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
"Installed: apr-util-1.6.1-6.el8.x86_64",
"Installed: redhat-logos-httpd-81.1-1.el8.noarch",
"Installed: apr-util-bdb-1.6.1-6.el8.x86_64",
"Installed: tftp-5.2-24.el8.x86_64",
"Installed: httpd-tools-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
"Installed: nginx-filesystem-1:1.14.1-9.module+el8.0.0+4108+af250afe.noarch"
]
}
node2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"msg": "",
"rc": 0,
"results": [
"Installed: php",
"Installed: tftp",
"Installed: apr-util-openssl-1.6.1-6.el8.x86_64",
"Installed: httpd-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
"Installed: php-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
"Installed: mod_http2-1.11.3-3.module+el8.2.0+4377+dc421495.x86_64",
"Installed: php-cli-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
"Installed: php-common-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
"Installed: httpd-filesystem-2.4.37-21.module+el8.2.0+5008+cca404a3.noarch",
"Installed: php-fpm-7.2.24-1.module+el8.2.0+4601+7c76a223.x86_64",
"Installed: mailcap-2.1.48-3.el8.noarch",
"Installed: apr-1.6.3-9.el8.x86_64",
"Installed: apr-util-1.6.1-6.el8.x86_64",
"Installed: redhat-logos-httpd-81.1-1.el8.noarch",
"Installed: apr-util-bdb-1.6.1-6.el8.x86_64",
"Installed: tftp-5.2-24.el8.x86_64",
"Installed: httpd-tools-2.4.37-21.module+el8.2.0+5008+cca404a3.x86_64",
"Installed: nginx-filesystem-1:1.14.1-9.module+el8.0.0+4108+af250afe.noarch"
]
}
[alice@control ansible]$ ansible test01,test02 -m yum -a 'pkg=php,tftp state=installed'
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": "Nothing to do",
"rc": 0,
"results": [
"Installed: php",
"Installed: tftp"
]
}
node2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": "Nothing to do",
"rc": 0,
"results": [
"Installed: php",
"Installed: tftp"
]
}
裝一個包組:
將 RPM Development Tools 軟體包組安裝到 test01 主機組中的主機上
[alice@control ansible]$ ansible node1 -a 'yum grouplist'
[WARNING]: Consider using the yum module rather than running 'yum'. If you nee
use command because yum is insufficient you can add 'warn: false' to this comman
task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
node1 | CHANGED | rc=0 >>
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered to Red Hat Subscription Management. You can use suption-manager to register.
Last metadata expiration check: 0:47:34 ago on Sat 13 Feb 2021 02:10:18 PM CST.
Available Environment Groups:
Server with GUI
Server
Workstation
Custom Operating System
Virtualization Host
Installed Environment Groups:
Minimal Install
Available Groups:
Legacy UNIX Compatibility
Container Management
Development Tools
.NET Core Development
Graphical Administration Tools
Headless Management
Network Servers
RPM Development Tools
Scientific Support
Security Tools
Smart Card Support
System Tools
[alice@control ansible]$ ansible node1 -m yum -a 'pkg=@RPM Development Tools'
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
[alice@control ansible]$ ansible node1 -m yum -a 'pkg="@RPM Development Tools" state=installed '
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"msg": "",
"rc": 0,
"results": [
"Group rpm-development-tools installed.",
"Installed: rpm-build-4.14.2-37.el8.x86_64",
"Installed: perl-Net-SSLeay-1.88-1.el8.x86_64",
"Installed: patch-2.7.6-11.el8.x86_64",
"Installed: libatomic_ops-7.6.2-3.el8.x86_64",
"Installed: rpmdevtools-8.10-7.el8.noarch",
"Installed: elfutils-0.178-7.el8.x86_64",
"Installed: bzip2-1.0.6-26.el8.x86_64",
"Installed: libbabeltrace-1.5.4-2.el8.x86_64",
"Installed: perl-srpm-macros-1-25.el8.noarch",
"Installed: python-srpm-macros-3-38.el8.noarch",
"Installed: emacs-filesystem-1:26.1-5.el8.noarch",
"Installed: unzip-6.0-43.el8.x86_64",
"Installed: perl-IO-Socket-SSL-2.066-4.el8.noarch",
"Installed: dwz-0.12-9.el8.x86_64",
"Installed: perl-libnet-3.11-3.el8.noarch",
"Installed: gdb-headless-8.2-11.el8.x86_64",
"Installed: perl-Carp-1.42-396.el8.noarch",
"Installed: efi-srpm-macros-3-2.el8.noarch",
"Installed: perl-Data-Dumper-2.167-399.el8.x86_64",
"Installed: libtool-ltdl-2.4.6-25.el8.x86_64",
"Installed: perl-Encode-4:2.97-3.el8.x86_64",
"Installed: perl-Errno-1.28-416.el8.x86_64",
"Installed: perl-Exporter-5.72-396.el8.noarch",
"Installed: perl-File-Path-2.15-2.el8.noarch",
"Installed: perl-File-Temp-0.230.600-1.el8.noarch",
"Installed: perl-Getopt-Long-1:2.50-4.el8.noarch",
"Installed: perl-HTTP-Tiny-0.074-1.el8.noarch",
"Installed: perl-IO-1.38-416.el8.x86_64",
"Installed: zstd-1.4.2-2.el8.x86_64",
"Installed: perl-MIME-Base64-3.15-396.el8.x86_64",
"Installed: perl-PathTools-3.74-1.el8.x86_64",
"Installed: perl-Pod-Escapes-1:1.07-395.el8.noarch",
"Installed: perl-Pod-Perldoc-3.28-396.el8.noarch",
"Installed: perl-Pod-Simple-1:3.35-395.el8.noarch",
"Installed: perl-Pod-Usage-4:1.69-395.el8.noarch",
"Installed: perl-Scalar-List-Utils-3:1.49-2.el8.x86_64",
"Installed: perl-Socket-4:2.027-3.el8.x86_64",
"Installed: perl-Storable-1:3.11-3.el8.x86_64",
"Installed: zip-3.0-23.el8.x86_64",
"Installed: qt5-srpm-macros-5.12.5-3.el8.noarch",
"Installed: perl-Term-ANSIColor-4.06-396.el8.noarch",
"Installed: perl-Term-Cap-1.17-395.el8.noarch",
"Installed: guile-5:2.0.14-7.el8.x86_64",
"Installed: perl-Text-ParseWords-3.30-395.el8.noarch",
"Installed: perl-Text-Tabs+Wrap-2013.0523-395.el8.noarch",
"Installed: perl-Time-Local-1:1.280-1.el8.noarch",
"Installed: perl-Unicode-Normalize-1.25-396.el8.x86_64",
"Installed: perl-constant-1.33-396.el8.noarch",
"Installed: perl-interpreter-4:5.26.3-416.el8.x86_64",
"Installed: perl-IO-Socket-IP-0.39-5.el8.noarch",
"Installed: perl-libs-4:5.26.3-416.el8.x86_64",
"Installed: perl-macros-4:5.26.3-416.el8.x86_64",
"Installed: perl-parent-1:0.237-1.el8.noarch",
"Installed: perl-podlators-4.11-1.el8.noarch",
"Installed: perl-threads-1:2.21-2.el8.x86_64",
"Installed: perl-threads-shared-1.58-2.el8.x86_64",
"Installed: ghc-srpm-macros-1.4.2-7.el8.noarch",
"Installed: perl-URI-1.73-3.el8.noarch",
"Installed: gc-7.6.4-3.el8.x86_64",
"Installed: go-srpm-macros-2-16.el8.noarch",
"Installed: redhat-rpm-config-122-1.el8.noarch",
"Installed: libipt-1.6.1-8.el8.x86_64",
"Installed: ocaml-srpm-macros-5-4.el8.noarch",
"Installed: tar-2:1.30-4.el8.x86_64",
"Installed: python3-rpm-macros-3-38.el8.noarch",
"Installed: rust-srpm-macros-5-2.el8.noarch",
"Installed: binutils-2.30-73.el8.x86_64",
"Installed: openblas-srpm-macros-2-2.el8.noarch",
"Installed: perl-Digest-1.17-395.el8.noarch",
"Installed: perl-Mozilla-CA-20160104-7.el8.noarch",
"Installed: perl-Digest-MD5-2.55-396.el8.x86_64"
]
}
[alice@control ansible]$ ansible node1 -m yum -a 'pkg="@RPM Development Tools" state=installed '
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": "Nothing to do",
"rc": 0,
"results": [
"Group rpm-development-tools installed."
]
}
[alice@control ansible]$
包升級更新:
將 test01、02 主機組中的主機上所有軟體包升級到最新版本
[alice@control ansible]$ ansible test01,test02 -m yum -a 'pkg=* state=latest'
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": "Nothing to do",
"rc": 0,
"results": []
}
node2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": "Nothing to do",
"rc": 0,
"results": []
}
[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標簽型別

[alice@control ansible]$ ansible node1 -m file -a 'name=/a.txt state=file'
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"path": "/a.txt",
"secontext": "unconfined_u:object_r:etc_runtime_t:s0",
"size": 0,
"state": "file",
"uid": 0
}
[alice@control ansible]$ ansible node1 -m file -a 'src=/ path=/linkroot state=link'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"dest": "/linkroot",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"secontext": "unconfined_u:object_r:root_t:s0",
"size": 1,
"src": "/",
"state": "link",
"uid": 0
}
[alice@control ansible]$
[alice@control ansible]$ ansible node1 -m file -a 'src=/ path=/linkroot state=absent
[WARNING]: The src option requires state to be 'link' or 'hard'. This will become a
error in Ansible 2.10
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"path": "/linkroot",
"state": "absent"
}
[alice@control ansible]$ ansible node1 -m file -a 'path=mulu state=directory mode=0750'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0750",
"owner": "root",
"path": "mulu",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
[alice@control ansible]$ ansible node1 -m file -a 'path=mulu state=directory owner=alice'
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0750",
"owner": "alice",
"path": "mulu",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 6,
"state": "directory",
"uid": 1000
}
- 創建目錄/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 '任務引數'
[alice@control ansible]$ ansible node1 -m template -a 'src=welcome.html dest=/tmp/welcome.html mode=644 force=yes'
.. .. //上傳檔案到主機node1,強制覆寫
[alice@control ansible]$ ansible node1 -a 'ls -lh /tmp/welcome.html'
node1 | CHANGED | rc=0 >>
-rw-r--r--. 1 root root 23 Apr 17 07:22 /tmp/welcome.html
.. .. //檢查結果

- 創建檔案/webdev/index.html,內容是 It's works!

用戶管理模塊(user/group)
user模塊:
添加/修改/洗掉用戶賬號,設定密碼
引數:name、state、uid、groups、append、remove、password
基本用法:
# ansible 清單主機 -m user -a '任務引數'
- name="登錄名" //指定用戶名(必選引數)
- password="加密的密碼串" //一般使用 {{'123456'|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" //洗掉用戶時是否同時洗掉家目錄

|| password={{"明文密碼" | password_hash("sha512")}}

[alice@control ansible]$ ansible node1 -m user -a 'name=dongfang uid=1234 groups=users append=yes'
.. .. //添加新用戶,加入到users組
[alice@control ansible]$ ansible node1 -m user -a "name=bubai password={{' 123456'|password_hash('sha512') }}"
.. .. //添加新用戶并設定密碼
[alice@control ansible]$ ansible node1 -m user -a 'name=dongfang state=absent remove=yes'
.. .. //洗掉用戶
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 '任務引數'
[alice@control ansible]$ ansible node1 -m service -a "name=crond state=restarted enabled=yes"
.. .. //重啟crond服務,并設定開機自啟


練習 —— 從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
[alice@control ansible]$ ansible node2 -m yum -a 'name=httpd state=installed'
node2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": "Nothing to do",
"rc": 0,
"results": [
"Installed: httpd"
]
}
[alice@control ansible]$ ansible node2 -m copy -a 'content="LIRUILONG I LOVE .." dest=/var/www/html/index.php'
node2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"checksum": "fc99d7c0185aef310990bb4c4e153c353921f25c",
"dest": "/var/www/html/index.php",
"gid": 0,
"group": "root",
"md5sum": "8ac9bcd94020e2284a3522af4a13d1a3",
"mode": "0644",
"owner": "root",
"secontext": "system_u:object_r:httpd_sys_content_t:s0",
"size": 19,
"src": "/home/alice/.ansible/tmp/ansible-tmp-1613309455.7519739-91578945277811/source",
"state": "file",
"uid": 0
}
[alice@control ansible]$ ansible node2 -m service -a 'name=httpd state=started enabled=yes'
node2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"enabled": true,
"name": "httpd",
"state": "started",
"status": {
"ActiveEnterTimestampMonotonic": "0",
"ActiveExitTimestampMonotonic": "0",
"ActiveState": "inactive",
"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",
"AllowIsolate": "no",
...
}
}
[alice@control ansible]$ curl http://node2/
curl: (7) Failed to connect to node2 port 80: No route to host
[alice@control ansible]$ ansible node2 -m service -a 'name=firewalld state=stopped enabled=no'
node2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"enabled": false,
"name": "firewalld",
"state": "stopped",
"status": {
"ActiveEnterTimestamp": "Sun 2021-02-14 20:59:54 CST",
"ActiveEnterTimestampMonotonic": "99056499",
"ActiveExitTimestampMonotonic": "0",
"ActiveState": "active",
"After": "basic.target sysinit.target polkit.service system.slice dbus.socket dbus.service",
"AllowIsolate": "no",
}
}
[alice@control ansible]$ curl http://node2/
LIRUILONG I LOVE ..[alice@control ansible]$
安全控制模塊(firewalld/sefcontext)
1. firewalld模塊
- Linux防火墻服務 firewalld,默認是開啟的
- 防火墻規則的作用范圍:運行時(臨時)、永久(重啟后仍有效)
- 默認安全區使用的 public (僅允許ping本機、SSH遠程連本機,拒絕其他幾乎任何訪問)
2.其他常用安全區:
- trusted 信任區(允許任何訪問,辦公區域,允許SSH、Samba少數幾個服務)
- block 阻塞區(阻止任何訪問)
- drop 丟棄區(丟棄任何來訪資料包)
|| firewall-cmd --get-default-zone ==》查看當前使用的默認安全區
|| firewall-cmd --set-default-zone=區域名 ==》設定默認使用哪一個安全區
預設保護服務:
http、https、dns……
防火墻管理工具:
firewall-cmd、firewall-config
防火墻規則的作用范圍:
++ 運行配置 —— 當前有效,重啟firewalld服務后失效
++ 永久配置 —— 當前無效,重啟firewalld服務后有效 ,通過添加 --permanent 選項設定
++ 在默認使用public安全區的情況下,如何管理防火墻規則
- 如何開放xx服務(執行firewall-cmd --get-services 了解防火墻預設的服務有哪些)
- 命令列 firewall-cmd --add-service=服務名
- 如何開放xx埠(埠號/協議)
- 命令列 firewall-cmd --add-port=埠號/協議
- 如何封鎖一個網段
- 命令列 firewall-cmd --add-source=來源IP地址或網段地址 --zone=drop
++ 常用引數:permanent(永久開啟)、port(埠)、service(服務)、source、state、immediate(立即生效)

2. sefcontext模塊
sefcontext ==》設定檔案的SELinux安全背景關系/屬性
- 查看檔案的安全屬性:ls -Z /var/www
- 設定指定目錄允許作為網頁目錄 semanage fcontext -a -t httpd_sys_content_t /網頁目錄的路徑
基本用法:
[alice@control ansible]$ ansible node1 -m sefcontext -a "target='/webdev(/.*)?' setype=httpd_sys_content_t state=present"
.. .. //將node1的/webdev目錄設定為網頁目錄
ansible node2 -m yum -a 'name=policycoreutils-python-utils state=present'
yum provides semanage
ansible node2 -m sefcontext -a 'path="/webdev(/.*)?" setype=httpd sys content t'
ansible node2 -a 'restorecon -R /webdev'
練習:
- 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屬性
[alice@control ansible]$ ansible node2 -m file -a 'name=/webdev state=directory'
node2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/webdev",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
[alice@control ansible]$ ansible node2 -m file -a 'name=/webdev state=directory'
node2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/webdev",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
[alice@control ansible]$ ansible node2 -a 'ls -lZd /webdev /var/www/html'
node2 | CHANGED | rc=0 >>
drwxr-xr-x. 2 root root system_u:object_r:httpd_sys_content_t:s0 23 Feb 14 21:30 /var/www/html
drwxr-xr-x. 2 root root unconfined_u:object_r:default_t:s0 6 Feb 15 10:15 /webdev
[alice@control ansible]$ ansible node2 -a 'setenforce 0'
node2 | CHANGED | rc=0 >>
[alice@control ansible]$ curl http://node2/webdev/
SElinux Love[alice@controansible node2 -a 'cat /var/www/html/webdev/index.html'
node2 | CHANGED | rc=0 >>
SElinux Love
[alice@control ansible]$ curl http://node2/webdev/
SElinux Love[alice@control ansible]$
方法二,通過sefcontext修改SElinux權限設定,
ansible node2 -m yum -a 'name=policycoreutils-python-utils state=present'
yum provides semanage
ansible node2 -m sefcontext -a 'path="/webdev(/.*)?" setype=httpd sys content t'
ansible node2 -a 'restorecon -R /webdev'
[alice@control ansible]$ ansible node2 -m yum -a 'name=policycoreutils-python-utils state=present'
node2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"msg": "",
"rc": 0,
"results": [
"Installed: policycoreutils-python-utils",
"Installed: python3-setools-4.2.2-2.el8.x86_64",
"Installed: policycoreutils-python-utils-2.9-9.el8.noarch",
"Installed: python3-libsemanage-2.9-2.el8.x86_64",
"Installed: python3-policycoreutils-2.9-9.el8.noarch",
"Installed: checkpolicy-2.9-1.el8.x86_64",
"Installed: python3-audit-3.0-0.17.20191104git1c2f876.el8.x86_64"
]
}
[alice@control ansible]$ ansible node2 -m sefcontext -a 'path="/webdev(/.*)?" setype=httpd_sys_content_t'
node2 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"ftype": "a",
"serange": "s0",
"setype": "httpd_sys_content_t",
"seuser": "system_u",
"state": "present",
"target": "/webdev(/.*)?"
}
[alice@control ansible]$ ansible node2 -a 'restorecon -R /webdev'
node2 | CHANGED | rc=0 >>
[alice@control ansible]$ curl http://node2/webdev/
SElinux Love[alice@control ansible]$

磁盤管理模塊(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" //創建|洗掉|查看資訊
[alice@control ansible]$ ansible node2 -m parted -a 'device=/dev/vdb state=info'
node2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"disk": {
"dev": "/dev/vdb",
"logical_block": 512,
"model": "Virtio Block Device",
"physical_block": 512,
"size": 1048576.0,
"table": "gpt",
"unit": "kib"
},
"partitions": [
{
"begin": 1024.0,
"end": 684032.0,
"flags": [],
"fstype": "",
"name": "primary",
"num": 1,
"size": 683008.0,
"unit": "kib"
}
],
"script": "unit 'KiB' print"
}
[alice@control ansible]$ ansible node4 -m ping
node4 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
[alice@control ansible]$ ansible node4 -m parted -a 'device=/dev/vdb state=info'
node4 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"disk": {
"dev": "/dev/vdb",
"logical_block": 512,
"model": "Virtio Block Device",
"physical_block": 512,
"size": 2097152.0,
"table": "unknown",
"unit": "kib"
},
"partitions": [],
"script": "unit 'KiB' print"
}
[alice@control ansible]$ ansible node4 -m parted -a 'device=/dev/vdb state=
present number=1 part_start=0% part_end=300MiB'
node4 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"disk": {
"dev": "/dev/vdb",
"logical_block": 512,
"model": "Virtio Block Device",
"physical_block": 512,
"size": 2097152.0,
"table": "msdos",
"unit": "kib"
},
"partitions": [
{
"begin": 1024.0,
"end": 307200.0,
"flags": [],
"fstype": "",
"name": "",
"num": 1,
"size": 306176.0,
"unit": "kib"
}
],
"script": "unit KiB mklabel msdos mkpart primary 0% 300MiB"
}
[alice@control ansible]$ ansible node4 -m parted -a 'device=/dev/vdb state=info'
node4 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"disk": {
"dev": "/dev/vdb",
"logical_block": 512,
"model": "Virtio Block Device",
"physical_block": 512,
"size": 2097152.0,
"table": "msdos",
"unit": "kib"
},
"partitions": [
{
"begin": 1024.0,
"end": 307200.0,
"flags": [],
"fstype": "",
"name": "",
"num": 1,
"size": 306176.0,
"unit": "kib"
}
],
"script": "unit 'KiB' print"
}
[alice@control ansible]$ ansible node4 -a 'lsblk'
node4 | CHANGED | rc=0 >>
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
vda 252:0 0 50G 0 disk
├─vda1 252:1 0 1G 0 part /boot
└─vda2 252:2 0 49G 0 part
├─rhel-root 253:0 0 46.9G 0 lvm /
└─rhel-swap 253:1 0 2.2G 0 lvm [SWAP]
vdb 252:16 0 2G 0 disk
└─vdb1 252:17 0 299M 0 part
[alice@control ansible]$ ansible node4 -m parted -a 'device=/dev/vdb state=absent'
node4 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": "state is absent but all of the following are missing: number"
}
[alice@control ansible]$ ansible node4 -m parted -a 'device=/dev/vdb number=1 state=absent'
node4 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"disk": {
"dev": "/dev/vdb",
"logical_block": 512,
"model": "Virtio Block Device",
"physical_block": 512,
"size": 2097152.0,
"table": "msdos",
"unit": "kib"
},
"partitions": [],
"script": "rm 1"
}
[alice@control ansible]$ ansible node4 -a 'lsblk'
node4 | CHANGED | rc=0 >>
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
vda 252:0 0 50G 0 disk
├─vda1 252:1 0 1G 0 part /boot
└─vda2 252:2 0 49G 0 part
├─rhel-root 253:0 0 46.9G 0 lvm /
└─rhel-swap 253:1 0 2.2G 0 lvm [SWAP]
vdb 252:16 0 2G 0 disk
[alice@control ansible]$
lvg模塊:
管理卷組,vg、pvs、pesize、state
基本用法:
# ansible 清單主機 -m lvg -a '任務引數'
- vg="卷組名" //指定操作的卷組名(必選引數)
- state="present|absent" //創建|洗掉卷組
- force="yes|no" //是否強制洗掉卷組(即使有邏輯卷)
- pvs="物理卷串列" //新建卷組時,指定由哪些物理設備組成
- pesize="PE大小" //指定Physical Extent的大小
[alice@control ansible]$ ansible node4 -a 'lsblk'
node4 | CHANGED | rc=0 >>
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
vda 252:0 0 50G 0 disk
├─vda1 252:1 0 1G 0 part /boot
└─vda2 252:2 0 49G 0 part
├─rhel-root 253:0 0 46.9G 0 lvm /
└─rhel-swap 253:1 0 2.2G 0 lvm [SWAP]
vdb 252:16 0 2G 0 disk
├─vdb1 252:17 0 299M 0 part
└─vdb2 252:18 0 700M 0 part
[alice@control ansible]$ ansible node4 -m lvg -a 'vg=redhat pvs=/dev/vdb2'
node4 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true
}
[alice@control ansible]$ ansible node4 -a 'lsblk'
node4 | CHANGED | rc=0 >>
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
vda 252:0 0 50G 0 disk
├─vda1 252:1 0 1G 0 part /boot
└─vda2 252:2 0 49G 0 part
├─rhel-root 253:0 0 46.9G 0 lvm /
└─rhel-swap 253:1 0 2.2G 0 lvm [SWAP]
vdb 252:16 0 2G 0 disk
├─vdb1 252:17 0 299M 0 part
└─vdb2 252:18 0 700M 0 part
[alice@control ansible]$ ansible node4 -a 'vgscan'
node4 | CHANGED | rc=0 >>
Found volume group "redhat" using metadata type lvm2
Found volume group "rhel" using metadata type lvm2
[alice@control ansible]$ ansible node4 -m lvg -a 'vg=redhat pvs=/dev/vdb2 start=absent'
node4 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": "Unsupported parameters for (lvg) module: start Supported parameters include: force, pesize, pv_options, pvs, state, vg, vg_options"
}
[alice@control ansible]$ ansible node4 -m lvg -a 'vg=redhat pvs=/dev/vdb2 state=absent'
node4 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true
}
[alice@control ansible]$ ansible node4 -a 'vgscan'
node4 | CHANGED | rc=0 >>
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" //是否強制洗掉或調整邏輯卷大小
[alice@control ansible]$ ansible node4 -m lvg -a 'vg=redhat pvs=/dev/vdb2 state=present pesize=300MiB'
node4 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true
}
[alice@control ansible]$ ansible node4 -a 'vgscan'
node4 | CHANGED | rc=0 >>
Found volume group "redhat" using metadata type lvm2
Found volume group "rhel" using metadata type lvm2
[alice@control ansible]$ ansible node4 -m lvol -a 'lv=rhcsa size=200M vg=redhat start=present'
node4 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": "Unsupported parameters for (lvol) module: start Supported parameters include: active, force, lv, opts, pvs, resizefs, shrink, size, snapshot, state, thinpool, vg"
}
[alice@control ansible]$ ansible node4 -m lvol -a 'lv=rhcsa size=200M vg=redhat state=present'
node4 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true,
"msg": ""
}
[alice@control ansible]$ ansible node4 -a 'lvscan'
node4 | CHANGED | rc=0 >>
ACTIVE '/dev/redhat/rhcsa' [300.00 MiB] inherit
ACTIVE '/dev/rhel/swap' [2.16 GiB] inherit
ACTIVE '/dev/rhel/root' [<46.84 GiB] inherit
[alice@control ansible]$
filesystem:格式化,dev、fstype、force
# ansible 清單主機 -m filesystem -a '任務引數'
- dev="邏輯卷名" //指定要格式化的設備路徑(必選引數)
- fstype="檔案系統型別" //指定格式化型別(xfs、ext4等)
- force="yes|no" //是否強制格式化(即使已經有檔案系統)
[alice@control ansible]$ ansible node4 -a 'blkid /dev/redhat/rhcsa'
node4 | FAILED | rc=2 >>
non-zero return code
[alice@control ansible]$ ansible node4 -m filesystem -a 'dev=/dev/redhat/rhcsa fstype=ext3'
node4 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true
}
[alice@control ansible]$ ansible node4 -a 'blkid /dev/redhat/rhcsa'
node4 | CHANGED | rc=0 >>
/dev/redhat/rhcsa: UUID="a25eff1d-31c8-4568-b01b-4f9fd2da23b5" SEC_TYPE="ext2" TYPE="ext3"
[alice@control ansible]$ ansible node4 -m filesystem -a 'dev=/dev/redhat/rhcsa fstype=xfs force=yes'
node4 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": true
}
[alice@control ansible]$ ansible node4 -a 'blkid /dev/redhat/rhcsa'
node4 | CHANGED | rc=0 >>
/dev/redhat/rhcsa: UUID="54cf0807-92cd-4aeb-ba40-47b4e9e30dba" TYPE="xfs"
[alice@control ansible]$
練習:
- 1)為node4的/dev/vdb建立2個磁區,分別300M、700M,
- 2)使用node4的/dev/vdb2創建一個名為redhat的卷組,
- 3)在node4上的redhat卷組中創建一個200M、名為rhcsa的邏輯卷,
- 4)將node4上的邏輯卷/dev/redhat/rhcsa格式為xfs檔案系統,
ansible node4 -m parted -a 'device=/dev/vdb state=present number=1 part_start=0% part_end=300MiB'
ansible node4 -m parted -a 'device=/dev/vdb state=present number=2 part_start=300MiB part_ end=1000MiB'
ansible node4 -m lvg -a 'vg=redhat pvs=/dev/vdb2'
ansible node4 -m lvol -a 'lv=rhcsa size=200M vg=redhat state=present force=yes'
ansible node4 -m filesystem -a 'dev=/dev/redhat/rhcsa fstype=xfs force=yes'
檔案修訂模塊(replace/lineinfile)
replace模塊:
使用replace模塊,修改檔案中的關鍵詞,替換檔案內的xx關鍵詞,path、regexp、replace,
基本用法:
# ansible 清單主機 -m replace -a '任務引數'
- ++ dest="檔案路徑" //指定要修改的檔案路徑(必選引數)
- ++ regexp="舊字串" //指定要替換的字串(必選引數),使用正則運算式
- ++ replace="新字串" //指定要替換的新字串
[alice@control ansible]$ ansible node2 -m replace -a 'path=/etc/selinux/config regexp="=enforcing" replace=disabled'
node2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"msg": ""
}
[alice@control ansible]$ ansible node2 -a 'cat /etc/selinux/config'
node2 | CHANGED | rc=0 >>
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
# SELINUXTYPE= can take one of these three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
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標簽型別

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),加載預設的任務角色(劇本+變數+模板……等資源套餐)

2)執行playbook劇本
- 通過ansible-playbook加載劇本,任務按順序依次執行
- 添加 --syntax-check 選項時,可以對劇本做語法檢查
- 添加 -C 選項時,只測驗劇本,不真正執行
- 回傳結果時,changed表示有更改(橙色),ok表示已經執行過(綠色),failed表示失敗(紅色)
比如:
[alice@control ansible]$ ansible-playbook file.yml
PLAY [configure yum repository] ************************************************
TASK [Gathering Facts] *********************************************************
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}
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}
ok: [node2]
ok: [node1]
ok: [node5]
TASK [base] ********************************************************************
ok: [node2]
ok: [node1]
ok: [node5]
TASK [stream] ******************************************************************
ok: [node1]
ok: [node2]
ok: [node5]
PLAY RECAP *********************************************************************
node1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node3 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
node4 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
node5 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[alice@control ansible]$
- hosts: all
tasks:
- yum_repository:
name: abc
description: abcabc
file: test
baseurl: http://study.lab0.example.com/rhel8/BaseOS gpgcheck=yes gpgkey=http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release'
- 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替換為空格)
比如:
[alice@control ansible]$ vim ~/.vimrc //修改vim個性化配置(" 是注釋行標記)
#方法一
"autocmd FileType yaml setlocal autoindent shiftwidth=2 tabstop=2 expandtab
# 方法二
au FileType yaml set ai sw=2 ts=2 et
# 方法三
set ai
set ts=2
++ 鍵值對使用 : 分隔,串列/陣列使用 - ,后面必須有空格標記
++ 鍵值對可以寫成一行、縮進的多行
比如,以下兩種寫法等效:

- hosts: node1,node2
tasks:
- yum: name=httpd state=present
- copy: content="RHCE Test" dest=/var/www/html/index.html force=yes
- service: name=httpd state=restarted enabled=yes
- service: name=firewalld state=restarted enabled=yes
- firewalld: service=http state=enabled permanent=yes immediate=yes
~
~
~
~
[alice@control ansible]$ ansible-playbook -C demo.yml
PLAY [node1,node2] *************************************************************
TASK [Gathering Facts] *********************************************************
ok: [node2]
ok: [node1]
TASK [yum] *********************************************************************
changed: [node2]
changed: [node1]
TASK [copy] ********************************************************************
changed: [node1]
changed: [node2]
TASK [service] *****************************************************************
changed: [node2]
changed: [node1]
TASK [firewalld] ***************************************************************
changed: [node2]
changed: [node1]
PLAY RECAP *********************************************************************
node1 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node2 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[alice@control ansible]$


gnore_errors:
4)ignore_errors忽略錯誤
++ 在劇本中即使遇到錯誤,仍然執行后續操作

register接受shell模塊輸出變數

使用loop回圈
- ++ 通過loop陳述句可以構造一個值串列(佇列)
- ++ 針對loop佇列中的值,可以共享同一個任務操作,從而節省代碼量、提高效率
- ++ 任務要呼叫佇列中的值時,使用固定變數 {{item}},需要時
比如:
[alice@control ansible]$ cat lamp.yml
---
- name: Deploy LAMP Platform
hosts: host1
tasks:
- name: install LAMP packages
yum: name={{item}} state=present //呼叫回圈變數(固定名稱item)
loop: //配置串列回圈項
- httpd
- mariadb
- mariadb-server
- php
- php-mysqlnd
- name: enable LAMP services
service: name={{item}} state=started enabled=yes
loop:
- httpd
- mariadb
使用when條件(if)
when條件用來判斷系統指標,當滿足條件時才會執行某個任務
- ++ 常見條件運算子如下:==、!=、>、>=、<、<=、in、not in、is defined、is not defined
- ++ 使用and或or可以組合多個條件
- ++ when運算式中呼叫變數時,不需要使用 {{ }}
[alice@control ansible]$ cat when.yml
---
- name: when test
hosts: node1,node3
tasks:
- file: path="/tmp/yes.txt" state=touch //在目錄/tmp/下創建檔案yes.txt
when: ('web' in group_names) //當主機屬于web組時執行
- debug: msg="vg myvg not found" //顯示一段文本
when: ('myvg' not in ansible_lvm.vgs) //當卷組myvg不存在時
...
failed_when中斷控制
- ++ failed_when條件的用法與when類似
- ++ 但是當滿足failed_when的條件時,playbook就認為失敗,不再執行后續任務
block陳述句塊的使用(Java的try{}catch(){}finally{})
block陳述句可以將多個任務操作捆綁到一起,當成一個整體
- ++ 當滿足when條件后要執行多個操作時,就可以使用block把這些操作捆在一塊
- ++ 當然,when條件也不是必需的,可以只是捆綁多個任務
- ++ rescue搶救機制(非必需),當block任務失敗時,可以執行rescue任務
- ++ always完結機制(非必需),無論block任務是否成功,最后都去執行always任務
block:
- 任務1: .. ..
- 任務2: .. ..
when:條件測驗
rescue:
- 任務3: .. ..
- 任務4: .. ..
always:
- 任務5: .. ..
—— 執行結果是:
- 當條件測驗不成立時,任務1-5都不執行
- 當條件測驗成立時,執行任務1、任務2;如果任務1、2中有失敗的,則執行任務3、4
- 當條件測驗成立時,任務5始終都會執行
[alice@control ansible]$ cat block.yml
---
- name: block test
hosts: node1
tasks:
- block:
- debug: msg="vg myvg not found" //提示卷組沒找到
- debug: msg="create vg myvg .. .." //做其他操作(比如創建這個卷組...)
when: ('myvg' not in ansible_lvm.vgs) //當卷組myvg不存在時
rescue:
- debug: msg="creating failed .. .." //block失敗時提示創建卷組失敗
always:
- shell: vgscan //列出卷組資訊
register: list //保存到名為list的變數
- debug: msg={{list.stdout_lines}} //提示卷組掃描結果
...
handlers任務處理(布雷)、notify通知觸發(引爆)
handlers可以設定一個或一塊任務,僅當收到某個任務通知時才會執行
- ++ 每個劇情中handlers任務只會執行一次,即使收到多個任務的觸發通知
- ++ handlers組的每一個任務都要設定名稱(name)
- ++ handlers的層次與tasks平級
- ++ 其他任務在必要時,使用notify陳述句通知handlers任務名
- ++ 僅當發起notify的任務的執行狀態為changed時,handlers任務才會被執行
比如:
[alice@control ansible]$ cat handlers.yml
---
- name: handlers test
hosts: node5
tasks:
- lvol: lv=vo001 size=100M vg=search //創建邏輯卷vo001
notify: mkfs //如果changed則通知格式化(否則無需格式化)
handlers:
- name: mkfs //定義格式化操作處理
filesystem: dev=/dev/search/vo001 fstype=xfs force=yes
...
ansible-vault
ansible的vault保險庫:
- ++ 為了方便保護一些敏感檔案(如賬號的密碼)而設定的檔案加密機制
- ++ 加密/解密主要工具 ansible-vault
- ++ 通過ansible-playbook呼叫保險庫檔案時,添加 --ask-vault-pass 選項會提示從鍵盤輸入密碼
- ++ 需要驗證密碼的地方,都可以添加 --vault-password-file= 來指定密碼檔案以免除互動
- ++ 在重設密碼時,可以添加 --new-vault-password-file 來指定存放新密碼的檔案

ansible-vault基本操作(以下為手動驗密):
[alice@control ansible]$ ansible-vault create new.txt //直接創建新加密檔案
.. .. //根據提示設定密碼
[alice@control ansible]$ ansible-vault view new.txt //查看已加密的檔案
.. .. //根據提示輸入正確的密碼驗證
[alice@control ansible]$ ansible-vault decrypt new.txt //將檔案解密(恢復成明文資料)
.. .. //根據提示輸入正確的密碼驗證
[alice@control ansible]$ ansible-vault encrypt new.txt //將現有檔案加密(變成密文)
.. .. //根據提示設定密碼
[alice@control ansible]$ ansible-vault rekey new.txt //修改已加密檔案的密碼
.. .. //根據提示驗證舊密碼
.. .. //再設定新密碼
[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引數用來過濾出特定名稱的系統指標,未知指標名部分可以使用 * 通配符
[alice@control ansible]$ ansible node1 -m setup //查看node1的所有系統指標
node1 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"172.25.254.101"
],
"ansible_all_ipv6_addresses": [
"fe80::6a52:a669:ccc3:13cc"
],
"ansible_apparmor": {
"status": "disabled"
},
.. ..
[alice@control ansible]$ ansible node1 -m setup -a "filter=ansible_all_ipv4_addresses"
.. .. //查看指定名稱的系統指標
[alice@control ansible]$ ansible node1 -m setup -a "filter=*_ipv4_addresses"
.. .. //指定系統指標時,名稱中允許使用通配符 *

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查看
[alice@control ansible]$ ansible node1 -m debug -a 'msg={{hostvars}}' |grep playbook_*
"ansible_playbook_python": "/usr/libexec/platform-python",
"playbook_dir": "/ansible"
"ansible_playbook_python": "/usr/libexec/platform-python",
"playbook_dir": "/ansible"
"ansible_playbook_python": "/usr/libexec/platform-python",
"playbook_dir": "/ansible"
"ansible_playbook_python": "/usr/libexec/platform-python",
"playbook_dir": "/ansible"
"ansible_playbook_python": "/usr/libexec/platform-python",
"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串列項定義
[alice@control ansible]$ cat var.yml //定義v1、v2兩個變數
---
- name: vars test
hosts: node1
vars: //直接定義變數
- yonghu: zhsan
- mima: ab1234
tasks:
- debug:
msg: msg="username:{{yonghu}}, password:{{mima}}"
...
[alice@control ansible]$ ansible-playbook var.yml //測驗劇本
.. ..
TASK [debug] ***************************************************************************************
ok: [node1] => {
"msg": "username:zhsan, password:ab1234"
}
.. ..
使用vars_files串列項定義,從外部變數檔案加載變數
[alice@control ansible]$ cat vars_files.yml
---
- name: vars_files test
hosts: node1
vars_files: //呼叫變數檔案
- v3v4.txt
tasks:
- debug: msg="username:{{yonghu}}, password:{{mima}}"
...
[alice@control ansible]$ ansible-playbook vars_files.yml
.. ..
TASK [debug] ***************************************************************************************
ok: [node1] => {
"msg": "username:lisi, password:cd5678"
}
.. ..
使用vars_prompt從鍵盤輸入變數值
[alice@control ansible]$ cat vars_prompt.yml
---
- name: vars_prompt test
hosts: node1
vars_prompt: //人機互動為變數賦值
- name: ilogin
prompt: "login"
private: no //回顯
- name: ipass
prompt: "password"
private: yes //不回顯(預設)
tasks:
- name: create an user
user: name="{{ilogin}}" password="{{ ipass | password_hash('sha512') }}"
...
[alice@control ansible]$ ansible-playbook vars_prompt.yml //執行劇本
login: wangwu //輸入用戶名
password: //輸入密碼(不顯示)
.. ..
[alice@control ansible]$ ansible node1 -a 'id wangwu' //檢查結果
node1 | CHANGED | rc=0 >>
uid=1002(wangwu) gid=1004(wangwu) groups=1004(wangwu)
通過register模塊保存命令結果(類似于Shell的重定向)
[alice@control ansible]$ cat register.yml
---
- name: register test
hosts: node1
ignore_errors: yes //即使遇到錯誤,仍然執行后續操作
tasks:
- shell: ls -lh /etc/hosts /etc/null
register: result //將螢屏輸出保存到result變數
- debug: msg="{{result.stdout}}" //提取標準輸出
- debug: msg="{{result.stderr}}" //提權標準錯誤
- debug: msg="{{result}}" //提取變數result的所有內容
...
[alice@control ansible]$ ansible-playbook register.yml //執行劇本
.. ..
TASK [debug] ***************************************************************************************
ok: [node1] => {
"msg": "-rw-r--r--. 1 root root 617 Mar 27 19:10 /etc/hosts"
}
TASK [debug] ***************************************************************************************
ok: [node1] => {
"msg": "ls: cannot access '/etc/null': No such file or directory"
}
.. ..
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 檔案,可以定義角色變數
[alice@control ansible]$ cp -r /usr/share/ansible/roles/rhel-system-roles.timesync roles/
[alice@control ansible]$ vim roles/rhel-system-roles.timesync/vars/main.yml
.. ..
timesync_ntp_servers:
- hostname: 172.25.254.250
iburst: yes
通過playbook劇本呼叫xx系統角色:
- 使用roles陳述句,指定角色名稱即可呼叫角色任務、變數等批量資料
[alice@control ansible]$ cat timesync.yml
---
- name: timesync
hosts: all
roles:
- rhel-system-roles.timesync //呼叫xx角色
...
ansible-galaxy工具:
- galaxy的本意為“銀河系”,ansible-galaxy工具可以用來統一管理大量角色
- 聯網情況下,可以通過ansible-galaxy工具訪問ansible官網的公共倉庫 https://galaxy.ansible.com/api/
[alice@control ansible]$ ansible-galaxy list
.. .. //列出已經安裝的角色
[alice@control ansible]$ ansible-galaxy init roles/myrole
.. .. //創建名為myrole的自定義角色(目錄結構)
[alice@control ansible]$ ansible-galaxy remove myrole
.. .. //洗掉名為myrole的角色
[alice@control ansible]$ ansible-galaxy search nginx
.. .. //從ansible官網搜索可用的角色(需聯網)
[alice@control ansible]$ ansible-galaxy info haproxy --offline
.. .. //查詢已安裝的haproxy角色的描述資訊
[alice@control ansible]$ ansible-galaxy install -r 角色串列檔案
.. .. //根據角色串列檔案的定義,下載并安裝新的角色
[alice@control ansible]$ vim roles/down.yml //配置角色匯入資訊
- name: haproxy //指定角色1的新名稱
src: http://study.lab0.example.com/roles/haproxy.tar //指定角色tar包的下載地址
- name: myphp //指定角色2的新名稱
src: acandid.httpd //通過名稱直接從ansible官網下載(需聯網)
模板中的for回圈應用
- ++ 通過魔法變數 groups.all 取得所有清單主機名
- ++ 通過魔法變數 hostvars["node1"] 取得node1的魔法變數和系統變數資訊(如果使用目標主機的系統變數,需要在劇本中提前搜集)
[alice@control ansible]$ vim newhosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for id in groups.all %}
{{hostvars[id].ansible_eth0.ipv4.address}} {{hostvars[id].ansible_fqdn}}
{{hostvars[id].ansible_hostname}}
{% endfor %}
[alice@control ansible]$ vim newhosts.yml
- hosts: all //搜集所有主機的資訊
- hosts: test01 //為 xx 組部署
tasks:
- template: src=newhosts.j2 dest=/etc/newhosts force=yes //通過模板部署檔案


模板檔案中的if分支應用
[alice@control ansible]$ vim newissue.yml
- name: deploy /etc/issue
hosts: all
tasks:
- copy:
content: | //準備文本內容
{% if "test01" in group_names %} //如果所在組包括 dev
test01
{% elif "test02" in group_names %} //如果所在組包括 test
test02
{% elif "web" in group_names %} //如果所在組包括 prod
Webserver
{% endif %}
dest: /etc/issue //復制到指定目標檔案
[alice@control ansible]$ ansible-playbook newissue.yml
實戰題目:
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
[root@control ~]# yum -y install ansible //安裝ansible軟體包
[root@control ~]# su - alice //切換為指定用戶
[alice@control ~]$ mkdir -p ~/ansible/roles ; cd ~/ansible/ //進入作業目錄
[alice@control ansible]$ vim ansible.cfg
[defaults]
inventory = inventory //主機清單檔案
remote_user = alice //連接受管機的遠程用戶名
roles_path = roles //角色目錄
[privilege_escalation] //設定用戶sudo提權
become=True
become_method=sudo
become_user=root
become_ask_pass=False
[alice@control ansible]$ vim inventory
[test01]
node1
[test02]
node2
[web]
node3
node4
[test05]
node5
[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 倉庫為啟用狀態
[alice@control ansible]$ vim adhoc.sh
#!/bin/bash
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'
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'
[alice@control ansible]$ chmod +x adhoc.sh
[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主機組中的主機上所有軟體包升級到最新版
[alice@control ansible]$ vim tools.yml
- name: 1. install php and mariadb on test01, test02, web
hosts: test01, test02, web
tasks:
- yum: pkg=php state=present //安裝php軟體包
- yum: pkg=tftp state=present //安裝mariadb軟體包
- name: 2. install @RPM Development Tools on test01
hosts: test01
tasks:
- yum: name="@RPM Development Tools" state=present //安裝xx包組
- name: 3. update all packages
hosts: test01
tasks:
- yum: name="*" state="latest" //升級所有包
[alice@control ansible]$ ansible-playbook tools.yml
- hosts: test01,test02,web
tasks:
- yum: name="php,tftp" state=present
- hosts: test01
tasks:
- yum: name="@RPM Development Tools" state=present
- yum: name="*" state=latest


4.安裝并使用系統角色
安裝RHEL角色軟體包,并創建劇本 /home/alice/ansible/timesync.yml,滿足以下要求:
1) 在所有受管理節點運行
2) 使用timesync角色
3) 配置該角色,使用時間服務器172.25.254.250,并啟用iburst引數
[root@control ~]# yum -y install rhel-system-roles //安裝rhel系統角色
[root@control ~]# su - alice
[alice@control ~]$ cd ansible/
[alice@control ansible]$ cp -r /usr/share/ansible/roles/rhel-system-roles.timesync roles/
//復制角色目錄
[alice@control ansible]$ vim timesync.yml
- name: timesync
hosts: all
vars:
- timesync_ntp_servers: //設定NTD服務器變數
- hostname: 172.25.254.250
iburst: yes
roles:
- rhel-system-roles.timesync //呼叫角色
[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
[alice@control ansible]$ vim /home/alice/ansible/roles/down.yml
- name: haproxy
src: http://study.lab0.example.com/roles/haproxy.tar
- name: myphp //配置角色匯入資訊
src: http://study.lab0.example.com/roles/myphp.tar
[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角色,
[alice@control roles]$ cd ~/ansible/roles
[alice@control roles]$ ansible-galaxy init httpd //在roles/目錄下初始化角色
[alice@control roles]$ vim httpd/templates/index.html.j2 //撰寫角色模板(網頁)
Welcome to {{ ansible_facts.fqdn }} on {{ ansible_facts.eth0.ipv4.address }}
[alice@control roles]$ vim httpd/tasks/main.yml //配置角色主任務
- name: 1. install httpd //裝包
yum: pkg=httpd state=present
- name: 2. deploy index.html //配置網頁資源
template: src=index.html.j2 dest=/var/www/html/index.html
- name: 3. httpd //起服務
service: name=httpd state=restarted enabled=yes
- name: 4. firewalld //起服務
service: name=firewalld state=restarted enabled=yes
- name: 5. configure firewall rules //配置防火墻規則
firewalld: service=http state=enabled permanent=yes immediate=yes
[alice@control roles]$ cd ~/ansible/
[alice@control ansible]$ vim myrole.yml //撰寫啟動腳本
- name: use role
hosts: webtest
roles:
- httpd
[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也輸出不同主機的歡迎頁面
[alice@control ansible]$ vim web.yml
- name: use role B //先部署web節點
hosts: webtest
roles:
- myphp
- name: use role A
hosts: test05 //再配置負載均衡器
roles:
- haproxy
tasks:
- 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)不需要掛載邏輯卷
[alice@control ansible]$ vim lvm.yml
- name: manager volume
hosts: all
tasks:
- name: 1. failed when VG not found
debug: msg="VG not found"
when: "'search' not in ansible_facts.lvm.vgs" //目標VG不存在時報錯
failed_when: "'search' not in ansible_facts.lvm.vgs" //停止后續任務
- name: 2. lvcreate
block: //配置指令塊
- lvol: lv=mylv size=1000M vg=search
notify: mkfs //lv建成功后通知mkfs
rescue: //若塊操作失敗,則執行補救
- debug: msg="insufficient free space"
- lvol: lv=mylv size=500M vg=search
notify: mkfs //lv建成功后通知mkfs
handlers: //收到通知后執行
- name: mkfs
filesystem: dev=/dev/search/mylv fstype=ext4 force=yes
[alice@control ansible]$ ansible-playbook lvm.yml //定義通知介面名mkfs
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
[alice@control ansible]$ sudo yum -y install wget
[alice@control ansible]$ wget http://study.lab0.example.com/materials/newhosts.j2
[alice@control ansible]$ vim newhosts.j2 //制作J2動態模板檔案
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for id in groups.all %}
{{hostvars[id].ansible_facts.eth0.ipv4.address}} {{hostvars[id].ansible_facts.fqdn}}
{{hostvars[id].ansible_facts.hostname}}
{% endfor %}
[alice@control ansible]$ vim newhosts.yml
- name: gather groups facts
hosts: all //搜集所有主機的資訊
- name: deploy /etc/newhosts
hosts: test01 //只為xx組部署
tasks:
- template: src=newhosts.j2 dest=/etc/newhosts //通過模板部署檔案
[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
[alice@control ansible]$ vim newissue.yml
- name: deploy /etc/issue
hosts: all
tasks:
- copy: content: | //準備文本內容
{% if "test01" in group_names %} //如果所在組包括dev
test01
{% elif "test02" in group_names %} //如果所在組包括test
test02
{% elif "web" in group_names %}
Webserver
{% endif %} //如果所在組包括prod
dest: /etc/issue
[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!
[alice@control ansible]$ vim webdev.yml
- name: Prepare Web Directory
hosts: test01
tasks:
- group: name=webdev state=present
- file: name=/webdev group=webdev mode=2775 state=directory //建目錄
- file: src=/webdev name=/var/www/html/webdev state=link force=yes //建鏈接
- copy: content="It's works!" dest=/webdev/index.html force=yes //部署網頁
- yum: name=policycoreutils-python-utils.noarch state=present //安裝semanage工具
- sefcontext: target='/webdev(/.*)?' setype=httpd_sys_content_t //設定目錄安全背景關系
- command: restorecon -iR /webdev //應用背景關系策略
- firewalld: service=http state=enabled permanent=yes immediate=yes
- service: name=httpd state=restarted enabled=yes
[alice@control ansible]$ ansible-playbook webdev.yml

[alice@control ansible]$ ansible test01 -a 'cat /etc/selinux/config'
node1 | CHANGED | rc=0 >>
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
# SELINUXTYPE= can take one of these three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
SELINUX=enforcing
[alice@control ansible]$ ansible-playbook webde.yml
PLAY [test01] ******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [node1]
TASK [group] *******************************************************************
changed: [node1]
TASK [file] ********************************************************************
changed: [node1]
TASK [file] ********************************************************************
[WARNING]: Cannot set fs attributes on a non-existent symlink target. follow
should be set to False to avoid this.
changed: [node1]
TASK [copy] ********************************************************************
changed: [node1]
TASK [lineinfile] **************************************************************
changed: [node1]
TASK [service] *****************************************************************
changed: [node1]
TASK [command] *****************************************************************
changed: [node1]
TASK [firewalld] ***************************************************************
ok: [node1]
PLAY RECAP *********************************************************************
node1 : ok=9 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[alice@control ansible]$ ansible test01 -a 'cat /etc/selinux/config'
node1 | CHANGED | rc=0 >>
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
# SELINUXTYPE= can take one of these three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
SELINUX=disabled
[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,
[alice@control ansible]$ vim hardware.yml
- name: hardware report
hosts: all
ignore_errors: yes //忽略個別錯誤
vars: //提取硬體檢測結果
- sfile: /root/hardware.txt //硬體報告檔案路徑
- host: "{{inventory_hostname}}" //提取清單主機名
- mem: "{{ansible_facts.memtotal_mb}}" //提取總記憶體大小(MB)
- bios: "{{ansible_facts.bios_version}}" //提取BIOS版本
- vdasize: "{{ansible_facts.devices.vda.size}}" //提取磁盤vda大小
- vdbsize: "{{ansible_facts.devices.vdb.size if ansible_facts.devices.vdb.size is defined else 'NONE' }}" //提取磁盤vdb大小,或NONE
tasks: //修改報告(根據模板內容查找替換)
- get_url: url=http://study.lab0.example.com/materials/hardware.empty dest={{sfile}} force=yes
- replace: name={{sfile}} regexp=inventoryhostname replace={{host}}
- replace: name={{sfile}} regexp=memory_in_MB replace={{mem}}
- replace: name={{sfile}} regexp=BIOS_version replace={{bios}}
- replace: name={{sfile}} regexp=disk_vda_size replace={{vdasize}}
- 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,值為ab1234pw_man,值為cd5678
2) 加密和解密該庫的密碼是pwd@1234 ,密碼存在/home/alice/ansible/secret.txt中
[alice@control ansible]$ echo 'pwd@1234' > secret.txt //創建保險庫鑰匙檔案
[alice@control ansible]$ ansible-vault create passdb.yml --vault-password-file=secret.txt //創建保險庫檔案
pw_dev: ab1234
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密碼檔案運行
解題參考:
[alice@control ansible]$ wget http://study.lab0.example.com/materials/name_list.yml
//獲取用戶串列檔案
[alice@control ansible]$ cat name_list.yml //確認串列內容
users:
- name: tom
job: dev //用戶崗位a
- name: jerry
job: man //用戶崗位b
[alice@control ansible]$ vim users.yml
- name: batch users
hosts: test01, test02, web
vars_files:
- passdb.yml //加載密碼變數
- name_list.yml //加載用戶名變數
tasks:
- group: name=devops //確保補充組1在指定主機已存在
when: ('test01' in group_names or 'test02' in group_names)
- group: name=opsmgr //確保補充組2在指定主機已存在
when: ('web' in group_names)
- user: name={{item.name}} password={{pw_dev|password_hash('sha512')}} groups=devops append=yes
when: (item.job == 'dev') and ('test01' in group_names or 'test02' in group_names)
loop: "{{users}}" //按條件添加a崗用戶
- user: name={{item.name}} password={{pw_man|password_hash('sha512')}} groups=opsmgr append=yes
when: (item.job == 'man') and ('web' in group_names)
loop: "{{users}}" //按條件添加b崗用戶
[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,請更新該庫密碼
[alice@control ansible]$ wget http://study.lab0.example.com/materials/topsec.yml
//下載指定保險庫檔案
[alice@control ansible]$ ansible-vault rekey topsec.yml //為保險庫設定新的密碼
Vault password: 輸入當前的庫密碼
New Vault password: 輸入新的庫密碼
confirm New Vault password: 再次輸入新的庫密碼確認
Rekey successful
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/264894.html
標籤:其他
上一篇:三子棋實作(源代碼)
