主頁 >  其他 > Ansible(自動化運維工具)知識梳理

Ansible(自動化運維工具)知識梳理

2021-03-01 16:41:56 其他


寫在前面:

筆記是因為考紅帽所以整理的,主要是常用模塊整理,后面有些類似考試的實戰題目,還在完善中.. 額,不是教程,教程建議大家到下面的學習網站,適合溫習用,

建議學習網站: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,值為ab1234

pw_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

標籤:其他

上一篇:三子棋實作(源代碼)

下一篇:無需Avatarify 無需剪輯工具 一鍵生成多人版 “螞蟻呀嘿“視頻

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more