Ansible

Linux小菜鸟發表於2024-06-29

環境準備

ansible:192.168.12.10(主節點)

web01:192.168.121.11

web02:192.168.121.12

db:192.168.121.13

只需在主節點安裝ansible即可,從屬節點不需要安裝

一、Ansible簡介

Ansible是一個自動化統一配置管理工具,自動化主要體現在Ansible整合了豐富模組以及功能元件,可以透過一個命令完成一系列的操作,進而能減少重複性的工作和維護成本,可以提高工作效率。

1.遠端執行
批次執行遠端命令,可以對多臺機器遠端操作

2.配置管理
批次配置軟體,可以自動分發配置檔案,服務統一管理啟動或停止

3.事件驅動
透過Ansible的模組,對服務進行不同的事件驅動
比如:
1)修改配置後重啟
2)只修改配置檔案,不重啟
3)修改配置檔案後,重新載入
4)遠端啟停服務管理

4.管理公有云
透過API介面的方式管理公有云,不過這方面做的不如saltstack
saltstack本身可以透過saltcloud管理各大雲廠商的雲平臺。

5.二次開發
因為語法是Python,所以便於運維進行二次開發。

6.任務編排
可以透過playbook的方式來統一管理服務,並且可以使用一條命令,實現一套框架的部署

7.跨平臺,跨系統
幾乎不受到平臺和系統的限制,比如安裝apache和啟動服務

Ansible是epel源提供的,一次在安裝Ansible之前需要安裝epel

# 安裝epel
yum install -y epel-release
# 安裝ansible
yum install -y ansible

二、ansible配置

【1】、配置hosts

修改/etc/hosts檔案

[root@ansible ~]# echo -e "192.168.121.11\tweb01" >> /etc/hosts
[root@ansible ~]# echo -e "192.168.121.12\tweb02" >> /etc/hosts
[root@ansible ~]# echo -e "192.168.121.13\tdb" >> /etc/hosts
[root@ansible ~]# echo -e "192.168.121.10\tansible" >> /etc/hosts
[root@ansible ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.121.11	web01
192.168.121.12	web02
192.168.121.13	db
192.168.121.10	ansible

【2】、ssh免密

 [root@ansible ~]# ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:iF5fPyuXd8VbGOmKpicRTmVdiAFtEf001NMnQdSbh5o root@ansible
The key's randomart image is:
+---[RSA 3072]----+
|        .o+B **+.|
|          * + +.=|
|         +   o ==|
|     . .o     =o.|
|    . ooS..  + +.|
|   . . .o. .E o +|
|    .   .. .oo  +|
|        . = +o...|
|        .= o.. . |
+----[SHA256]-----+
ssh-copy-id web01
ssh-copy-id web02
ssh-copy-id db

【3】、配置ansible管理環境

修改主配置檔案

  • 主配置檔案
    • 參考/etc/ansible/ansible.cfg
  • ansible配置檔案查詢順序
    • 首先檢測ANSIBLE_CONFIG變數定義的配置檔案
    • 其次檢測當前目錄下的./ansible.cfg
    • 再次檢查當前使用者家目錄下~/ansible.cfg
    • 最後檢查/etc/ansible/ansible.cfg
# 修改主配置檔案(在工作目錄中建立主配置檔案和主機清單檔案)
[root@ansible ansible]# vim  ansible.cfg
[defaults]
inventory=inventory  # 主機清單要和你自己建立的主機清單名字一致
host_key_checking=false

# 修改主機清單,ansible後面的物件一定要出現在inventory清單檔案中
[root@ansible ansible]# vim inventory
[webservers]
web[01:02]
# 也可以寫成:web01 web02

[dbservers]
db

[cluster:children] # 定義組巢狀的語法
webservers
dbservers

【4】、測試

# 批次執行ping命令,檢測主機存活
[root@ansible ansible]# ansible all -m ping
db | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
web02 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
web01 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
# ansible後面可以跟多個物件,用逗號隔開
[root@ansible:192.168.121.10 ~/ansible]$ansible web01,db -m ping

# 批次新增使用者
[root@ansible ansible]# ansible all -a "useradd zhangsan"
db | CHANGED | rc=0 >>

web02 | CHANGED | rc=0 >>

web01 | CHANGED | rc=0 >>

# 批次建立目錄
[root@ansible ansible]# ansible all -a "mkdir /tmp/demo"
web02 | CHANGED | rc=0 >>

db | CHANGED | rc=0 >>

web01 | CHANGED | rc=0 >>

三、ansible管理

  • ansible進行程序管理的兩個方法
    • adhoc臨時命令。就是在命令列上執行管理命令
    • playbook劇本。把管理任務用特定格式寫到檔案中
  • 無論哪種方式都是透過模組載入引數進行管理

【1】、adhoc臨時命令

ansible 主機或組列表 -m 模組 -a "引數"  # -a是可選的

1、ping模組

測試能否ping同主機

類似ping但是不完全等於ping

2、ansbile檔案操作模組

  • 在ansible中,透過模組完成某一特定任務
  • 學習模組,主要知道實現某種功能,需要哪個模組
  • 模組的使用方式都一樣。主要是檢視模組有哪些引數
# 檢視ansible可用模組
[root@ansible:192.168.121.10 ~/ansible]$ansible-doc -l | wc -l
8354
# 檢視ansible可用模組數量
[root@ansible:192.168.121.10 ~/ansible]$ansible-doc -l | wc -l
8354

(1)、command模組

這是ansible預設模組,如果執行ansible命令時,沒有加模組,預設是command模組

[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -a "ls -lh /etc/hosts"
web01 | CHANGED | rc=0 >>
-rw-r--r--. 1 root root 158 Sep 10  2018 /etc/hosts
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m command -a "ls -lh /etc/hosts"
web01 | CHANGED | rc=0 >>
-rw-r--r--. 1 root root 158 Sep 10  2018 /etc/hosts
###  在command模組中執行命令時不支援shell特性,如管道、重定向等
[root@ansible:192.168.121.10 ~/ansible]$ansible web01  -a "ifconfig  ens33 | head"  
web01 | FAILED | rc=1 >>
|: Unknown host
ifconfig: `--help' gives usage information.non-zero return code

(2)、shell模組

在shell模組中執行命令支援shell特性

[root@ansible:192.168.121.10 ~/ansible]$ansible web01  -m shell -a "ifconfig  ens33 | grep 192"
web01 | CHANGED | rc=0 >>
        inet 192.168.121.11  netmask 255.255.255.0  broadcast 192.168.121.255

(3)、script模組

如果要執行復雜的命令,可以寫入指令碼使用script模組可以執行指令碼

在使用script模組執行指令碼時,指令碼可以沒有x許可權

# test指令碼內容
#!/bin/bash
for user in user{6..8}
do
        useradd $user
        echo "123456" | passwd --stdin $user
done
# 
[root@ansible:192.168.121.10 ~/ansible]$ansible all -m script -a "test.sh"

⚠️command、shell、script不建議使用

因為這三個模組沒有冪等性

(4)、file模組

  • 可以建立檔案、目錄、連結等,還可以修改許可權屬性等
  • 常用的選項
  • path:指定檔案路徑
  • owner:設定檔案所有者,一定要是提前存在的
  • group:設定檔案所屬組,一定要是提前存在的
  • state:狀態。touch表示建立檔案,directory表示建立目錄,link表示建立軟連線,absent表示刪除
  • mode:設定許可權
  • scr:source的縮寫,源
  • dest:目的路徑
# 在webservers組中建立檔案
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/file.txt state=touch"

# 在webservers組中建立目錄
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/demp  state=directory"

# 指定許可權和屬組,屬主
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/bbb.txt  mode='0777'  state=touch owner=user1 group=user1"

# 刪除檔案
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/bbb.txt  mode='0777'  state=absent owner=user1 group=user1"

# 刪除目錄
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/demp  mode='0777'  state=absent owner=user1 group=user1"

# 建立連結
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "src=/etc/passwd  dest=/tmp/passwd  state=link"

file模組冪等性的體現

在建立目錄時,第一次建立是CHANGED,後面再建立相同的目錄時就是SUCESS,不會報錯

web01 | SUCCESS =>

在建立檔案時不存在冪等性,因為雖然建立的檔案是一樣的,但是每一次touch時,檔案的時間都會改變

web02 | CHANGED =>

(5)、copy模組

  • 用於將檔案從控制端複製到被控端
  • 常用選項
  • scr:源,控制端檔案路徑
  • dest:目的,被控端檔案路徑
# 複製檔案
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m copy -a "src=test.sh dest=/tmp/"

# 複製目錄,不能上傳空目錄
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m copy -a "src=/etc/passwd dest=/tmp/"

# 我們可以使用copy模組直接在被控端主機上建立檔案並寫入內容,不需要再控制端建立好後在上傳到被控端
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m copy -a "dest=/tmp/a.txt  content='hello world\n'"

(6)、fetch模組

  • 與copy相反,copy是上傳,fetch是下載
  • 常用選項
    • src:源,被控端檔案的路徑,不支援下載目錄
    • dest:目標,控制端檔案的路徑
# 將被控端的/etc/hosts檔案下載下來,下載下來之後會在dest_path下自動劃分目錄
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m fetch -a "src=/etc/hosts dest=~/"
[root@ansible:192.168.121.10 ~]$ll|grep web
drwxr-xr-x. 3 root root   17 Jun 25 18:25 web01
drwxr-xr-x. 3 root root   17 Jun 25 18:25 web02

(7)、lineinfile模組

  • 用於確保目標檔案中有某一行內容
  • 常用選項
  • path:待修改的檔案路徑
  • line:寫入檔案的一行內容
  • regexp:正規表示式,用於查詢檔案中的內容
# 向檔案中寫入一行內容
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m lineinfile -a "path=/etc/issue line='Hello World\n'"

# 使用regexp正則匹配替換,替換匹配到的一行
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m lineinfile -a "path=/etc/issue regexp='Hello' line='chilema\n'"

(8)、replace模組

  • lineinfile會替換一行,replace可以替換關鍵詞
  • 常用選項
  • path:待修改的檔案路徑
  • replace:將正規表示式匹配到的內容,替換成replace中的內容
  • regexp:正規表示式,用於查詢檔案中的內容
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m replace -a "path=/etc/issue regexp='chi' replace='he'"
[root@web01:192.168.121.11 /tmp]$cat /etc/issue
\S
Kernel \r on an \m

helema

(10)、檔案操作綜合練習

  • 所有操作均對webservers組中的主機生效
  • 在目標主機上建立/tmp/mydemo目錄,屬主和屬組都是adm,許可權0777
  • 將控制端的/etc/hosts檔案上傳到目標主機的/tmp/mydemo目錄中,屬主和屬組都是adm,許可權為0600
  • 替換目標主機的/tmp/mydemo/hosts檔案中的db1為database1
  • 將目標主機/tmp/mydemo/hosts檔案下載到控制短的當前目錄
# 在目標主機上建立/tmp/mydemo目錄,屬主和屬組都是adm,許可權0777
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m file -a "path=/tmp/mydemo state=directory owner=adm group=adm mode='0777'"

# 將控制端的/etc/hosts檔案上傳到目標主機的/tmp/mydemo目錄中,屬主和屬組都是adm,許可權為0600
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m copy  -a "src=/etc/hosts dest=/tmp/mydemo owner=adm group=adm mode=0600"

# 替換目標主機的/tmp/mydemo/hosts檔案中的db1為database1
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m replace -a "path=/tmp/mydemo/hosts regexp="db" replace=database"

# 將目標主機/tmp/mydemo/hosts檔案下載到控制短的當前目錄
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m fetch -a "src=/tmp/mydemo/hosts dest=./"

3、使用者操作模組

(1)、user模組

  • 實現Linux的使用者管理
  • 常用選項
  • name:帶建立使用者名稱
  • uid:使用者UID
  • group:設定主組
  • groups:這隻附加組
  • home:設定家目錄
  • password:設定使用者密碼
  • state:狀態。present表示建立,他是預設選項。absent表示刪除
  • remove:刪除家目錄、郵箱等。值為yes或true都行
# 直接建立使用者
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers  -m user -a "name=zhangsan"

# 指定條件建立使用者
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers  -m user -a "name=lisi uid=1011 group=adm groups=adm,root home=/home/lisi "
[root@web01:192.168.121.11 /tmp/mydemo]$id lisi
uid=1011(lisi) gid=4(adm) groups=4(adm),0(root)

# 修改使用者密碼
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m user -a "name=zhangsan password={{'123456'|password_hash('sha512')}}"

# 刪除使用者
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m user -a "name=zhangsan state=absent remove=yes"

(2)、group模組

建立使用者組

  • name:帶建立的組名
  • gid:組的id號
  • stat:present表示建立,他是預設選項。absent表示刪除
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m group -a "name=devops"
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m group -a "name=devops state=absent"

4、軟體包相關模組

(1)、yum_repository模組

  • 用於配置yum
  • 常用選項
  • file:指定檔名
  • name:軟體倉庫名
  • description:描述名稱
  • 其他選項,請與檔案內容對照
# 我們可以使用file模組和copy模組實現yum的repo檔案傳輸
ansible all -m file "path=/etc/yum.repos.d/local.repo state=absent"
ansible all -m copy "src=/etc/yum.repos.d/local.repo dest=/etc/yum.repos.d/local.repo"
# 使用yum_repository模組進行配置
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m yum_repository -a "file=myrepo name=MyApp description='My App' baseurl=file:///mnt/mydvd/AppStream enabled=yes gpgcheck=no "
# 如果在寫一個相同檔名的repo檔案,不會覆蓋原有的repo檔案,而是在原始檔中追加

(2)、yum模組

管理軟體

常用選項

  • name:包名
  • state:狀態
    • present:表示安裝,如果安裝則忽略;latest表示安裝或者升級到最新版本;absent表示解除安裝
# 安裝一個軟體
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m yum -a "name=tar state=present"
# 安裝多個軟體,軟體之間使用逗號隔開
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m yum -a "name=tar,wget  state=present"
# 解除安裝軟體
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m yum -a "name=wget  state=absent"
# 使用latest更新安裝軟體(軟體版本以軟體倉庫中的為主)
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m yum -a "name=nginx  state=latest"

5、服務相關模組

(1)、service模組

  • 常用選項
  • name:服務名稱
  • state:對服務執行的操作。started啟動,stopped停止,restarted重啟服務,reloaded重新載入服務
  • enable:是否開機自啟。yes開機自啟,no開機不自啟
# 啟動服務
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m service -a "name=nginx state=started enabled=yes"
# 重啟服務
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m service -a "name=nginx state=reloaded  enabled=yes"

6、邏輯卷相關模組

(1)、lvg模組

建立卷組

vg:卷組名字,pvs:組成卷組的物理分割槽

[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m lvg  -a "vg=myvg pvs=/dev/sdb1"
[root@web01:192.168.121.11 ~]$vgs
  VG   #PV #LV #SN Attr   VSize   VFree 
  myvg   1   0   0 wz--n-  <5.00g <5.00g
  rl     1   3   0 wz--n- <99.00g     0 
# 刪除卷組
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m lvg -a "vg=myvg state=absent"

(2)、lvol模組

建立邏輯卷

vg:邏輯卷名字 lv:邏輯卷名字 size:邏輯卷大小

常用選項

  • vg:製作邏輯卷的卷組名字
  • lv:邏輯卷的名字
  • force:刪除邏輯卷時必須加的,force=yes
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m lvol  -a "vg=myvg lv=mylv size=2G"
[root@web01:192.168.121.11 ~]$lvs
  LV   VG   Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  mylv myvg -wi-a-----   2.00g                                                    
  home rl   -wi-ao---- <31.82g                                                    
  root rl   -wi-ao----  65.17g                                                    
  swap rl   -wi-ao----  <2.0 1g
  
# 要對邏輯捲進行擴容時,直接修改size即可,通知檔案系統
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m lvol  -a "vg=myvg lv=mylv size=4G resizefs=yes"
[root@web01:192.168.121.11 ~]$lvs
  LV   VG   Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  mylv myvg -wi-a-----   4.00g                                                    
  home rl   -wi-ao---- <31.82g                                                    
  root rl   -wi-ao----  65.17g                                                    
  swap rl   -wi-ao----  <2.01g
# 刪除邏輯卷
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m lvol -a "vg=myvg lv=mylv  state=absent force=yes"

(3)、filesystem模組

  • 用於格式化,也就是建立檔案系統
  • 常用選項
  • fstype:指定檔案系統型別
  • dev:指定要格式化的裝置,可以是分割槽,可以是邏輯卷

Windows:ntfs

Linux:xfs(適合大檔案)、ext4(適合小檔案)

存在冪等性,當我們格式化一次後,再要格式化時就不會執行了

[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m filesystem -a "dev=/dev/myvg/mylv fstype=xfs"
[root@web01:192.168.121.11 ~]$blkid /dev/myvg/mylv
/dev/myvg/mylv: UUID="22ef21b3-51b2-4bbf-a546-45c3e83005d8" BLOCK_SIZE="512" TYPE="xfs"

(4)、mount模組

  • 用於掛載檔案系統,掛在完成後會自動寫入/etc/fstab檔案中
  • 常用選項
  • path:掛載點。如果掛載點不存在,自動建立
  • src:待掛在裝置,支援透過UUID進行掛載
  • fstype:檔案系統型別
  • state:unmounted解除安裝,mounted掛載
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m mount -a "src=/dev/myvg/mylv path=/data state=mounted fstype=xfs"
[root@web01:192.168.121.11 ~]$grep data /etc/fstab 
/dev/myvg/mylv /data xfs defaults 0 0

# 解除安裝掛載點
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m mount -a "path=/data state=absent"

(5)、parted模組

用於磁碟分割槽管理

常用選項

  • device:待分割槽裝置
  • number:分割槽編號
  • state:present表示建立,absent表示刪除
  • part_start:分割槽的起始位置,不屑表示從開頭
  • part_end:表示分割槽結束的位置,不寫表示到結尾
---
- name: disk manage
  hosts: web01
  tasks:
    - name: create a partition
      parted:
        device: /dev/sdc
        state: present
        number: 1
        part_end: 5GiB

    - name: create a new partition
      parted:
        device: /dev/sdc
        state: present
        number: 2
        part_start: 5GiB
        part_end: 8GiB
- name: create lvm
  hosts: web01
  tasks:
    - name: create vg
      lvg:
        vg: my_vg
        pvs: /dev/sdc1,/dev/sdc2
    - name: create lv
      lvol:
        vg: my_vg
        lv: my_lv
        size: 2G
- name: make fs
  hosts: web01
  tasks:
    - name: make xfs
      filesystem:
        fstype: xfs
        dev: /dev/my_vg/my_lv
- name: mount
  hosts: web01
  tasks:
    - name: mount parted
      mount:
        path: /mnt/xfs_my
        src: /dev/my_vg/my_lv
        fstype: xfs
        state: present

7、防火牆相關模組

(1)、firewalld模組

  • 用於配置防火牆模組
  • 常用選項
  • port:宣告埠
  • permanent:永久生效,但不會立即生效
  • immediate:立即生效,但不會永久生效
  • state:enable放行,disable拒絕
  • 防火牆一般預設拒絕,明確寫入允許的服務
  • 有一些服務有名字,有些服務沒有名字。但是最終都是基於TCP或UDP的某些埠。比如http服務基於TCP80埠。服務名和埠號對應關係的說明檔案是:/etc/services
  • 配置伺服器的防火牆,一般來說只要配置開放哪些服務或者埠即可。沒有明確開放的,都預設拒絕
---
- name: configure webservers
  hosts: webservers
  tasks:
    - name: install nginx and firewalld
      yum:
        name: nginx,firewalld
        state: present
    - name: start nginx
      service:
        name: nginx
        state: started
        enabled: yes
    - name: start firewalld
      service:
        name: firewalld
        state: started
        enabled: yes
# 配置防火牆規則
- name: set firewalld
  hosts: webservers
  tasks:
    - name: set firewalld rule
      firewalld:
        port: 80/tcp
        permanent: yes
        immediate: yes
        state: enabled

8、template模組

  • copy模組可以上傳檔案,但是檔案內容固定
  • template模組可以上傳具有特定格式的檔案(如檔案中包含變數)
  • 當遠端主機接收到檔案之後,檔案中的變數將會變成具體的值
  • template模組上傳的檔案,使用的語法叫做Jinja2
  • 常用選項:和copy一樣
  • src:
  • dest:

【2】、playbook劇本

  • 常用於複雜任務的管理,以及管理經常要完成的任務
  • playbook也是透過模組和它的引數,在特定的主機上執行任務
  • playbook是一個檔案,該檔案中需要透過yaml格式書寫

1、yaml

YAML Ain‘t Markup Language

語法規範:

  • yaml檔案的檔名,一般以yml或yaml作為副檔名
  • 檔案以---作為第一行
  • 鍵值對使用:表示,冒號後面必須有空格
  • 陣列使用-表示,-後面必須有空格
  • 相同層級必須有相同的縮排。如果縮排不對,則有語法錯誤。每一級縮排,建議兩個空格
  • 全文不能使用tab,應該使用空格

2、配置vim適應yaml語法

# 檔案位置和名字都是固定的,用於設定 vim的格式
[root@ansible:192.168.121.10 ~]$vim  ~/.vimrc
  1 set nu  # 顯示行號
  2 set ai  # 換行時自動縮排
  3 set et  # 讓tab以空格的形式出現
  4 set ts=2 # 按一次tab空兩格

3、編寫playbook

  • 一個劇本(即playbook),可以包含多個play
  • 每個play用於在指定的主機上,透過模組和引數執行相應的任務
  • 每個play可以包含多個任務
  • 任務由模組和引數構成
# 第一個劇本
  1 ---
  2 - name: 測試能否管理
  3   hosts: all
  4   tasks:
  5     - name: test
  6       ping:
# ansible有專門執行劇本的命令
[root@ansible:192.168.121.10 ~/ansible]$ansible-playbook test.yaml 
# 每一個play
PLAY [測試能否管理]  *****************************************************************************************************************************************
# ansible會自動執行的任務
TASK [Gathering Facts] **************************************************************************************************************************************
ok: [web01]
ok: [web02]
ok: [db]
# 我們自己定義的任務
TASK [test] *************************************************************************************************************************************************
ok: [db]
ok: [web01]
ok: [web02]
# 回放,執行完成後的總結
PLAY RECAP **************************************************************************************************************************************************
db                         : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
web01                      : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
web02                      : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  1 ---
  2 - name: create dir and copy file
  3   hosts: db,web01
  4   tasks:
  5     - name: create dir
  6       file:
  7         path: /tmp/demo
  8         state: directory
  9         mode: '0755'
 10 
 11     - name: copy file
 12       copy:
 13         src: /etc/hosts
 14         dest: /tmp/demo
# 在webservers組中的主機上,建立使用者bob,附加組是adm;在db主機上,建立/tmp/hi.txt 其內容為hello world
---
- name: user and  file context manage
  hosts: webservers
  tasks:
    - name: create usre
      user:
        name: bob
        groups: adm
- name: context
  hosts: db
  tasks:
    - name: create file
      file:
        path: /tmp/hi.txt
        state: touch
    - name: change file context
      copy:
        dest: /tmp/hi.txt
        content: "hello world\n"
# 在一個劇本中可以存在兩個play

4、|和>區別

---
- name: play 1
  hosts: db
  tasks:
    - name: mkfi
      copy:
        dest: /tmp/1.txt
        content: |
          Hello
          nihao
[root@db:192.168.121.13 /tmp]$cat /tmp/1.txt 
Hello
nihao
---
- name: play 2
  hosts: db
  tasks:
    - name: mkfi
      copy:
        dest: /tmp/2.txt
        content: >
          Hello
          nihao
[root@db:192.168.121.13 /tmp]$cat /tmp/2.txt 
Hello nihao

5、引號問題

---
- name: user11
  hosts: webservers
  tasks:
    - name:
      user:
        name: john
        uid: 1040
        group: daemon
        password: "{{'123456'|password_hash('sha512')}}"
# 如果是大括號開頭必須用引號括起來,數字必須是str不能是int

6、安裝軟體包

# 安裝多個軟體包
寫法1:
---
- name: install packages
  hosts: webservers
  tasks:
   - name: install httpd,php,php-mysqlnd
     yum:
       name: 
         - httpd
         - php
         - php-mysqlnd
       state: present
寫法二:
---
- name: install packages
  hosts: webservers
  tasks:
   - name: install httpd,php,php-mysqlnd
     yum:
       name: [httpd,php,php-mysqlnd]
       state: present
寫法三:
---
- name: install packages
  hosts: webservers
  tasks:
   - name: install httpd,php,php-mysqlnd
     yum:
       name: httpd,php,php-mysqlnd
       state: present

Linux將一系列軟體放到一個組中,安裝軟體包,將會把很多軟體一起安裝上,比如gcc、java等都是開發工具,安裝開發工具包組,將會把他們一起安裝

# 列出所有的軟體包組
[root@web01:192.168.121.11 ~]$yum grouplist 
Last metadata expiration check: 11:30:08 ago on Wed 26 Jun 2024 05:44:48 AM CST.
Available Environment Groups:
   Server with GUI
   Server
   Workstation
   KDE Plasma Workspaces
   Virtualization Host
   Custom Operating System
Installed Environment Groups:
   Minimal Install
Available Groups:
   Container Management
   .NET Core Development
   RPM Development Tools
   Development Tools
   Graphical Administration Tools
   Headless Management
   Legacy UNIX Compatibility
   Network Servers
   Scientific Support
   Security Tools
   Smart Card Support
   System Tools
   Fedora Packager
   Xfce
# 安裝軟體包組
[root@web01:192.168.121.11 ~]$yum groupinstall "Development Tools"
# 劇本寫法,要將軟體包組加上引號,並且在組名前加@,來告訴yaml要安裝的是一個軟體組
---
- name: install packages
  hosts: webservers
  tasks:
   - name: install group
     yum:
       name: "@Development Tools"
       state: present

系統更新,將yum源換為更高的版本,然後全部更新即可

---
- name: install packages
  hosts: webservers
  tasks:
   - name: update system
     yum:
       name: "*"
       state: latest

四、ansible變數

【1】、facts變數

  • facts翻譯過來就是事實
  • facts變數是ansible自帶的預定義變數,用於描述被控端軟硬體資訊
  • facts變數透過setup模組
# 檢視所有的ansible變數
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m setup
# filter:過濾變數
[root@ansible:192.168.121.10 ~/ansible]$ansible web01 -m setup -a "filter=ansible_all_ipv4_addresses"
web01 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.121.11"
        ],
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false
}

常用的facts變數

  • ansible_all_ipv4_addresses----所有的IP地址
  • ansible_bios_version----BIOS版本資訊
  • ansible_memtotal_mb----總記憶體大小
  • ansible_hostname---主機名

【2】、debug模組

用來列印變數

在輸出時需要加上{{變數名}}

---
- name: display host info
  hosts: webservers
  tasks:
    - name: display hostname and memory
      debug:
        msg: "hostname: {{ansible_hostname}}, mem {{ansible_memtotal_mb}}MB"
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m setup | grep -E "hostname|mem"
        "ansible_hostname": "web01",
        "ansible_memfree_mb": 211,
        "ansible_memory_mb": {
        "ansible_memtotal_mb": 1734,
        "ansible_hostname": "web02",
        "ansible_memfree_mb": 221,
        "ansible_memory_mb": {
        "ansible_memtotal_mb": 1734,

【3】、執行劇本時的順序

在我們執行劇本時,在執行每一個play時系統會自己執行一個任務

TASK [Gathering Facts] ****************************************************************************************************************************************
ok: [web02]
ok: [web01]

這個任務的作用是收集facts,只有透過setup模組收集了事實,才可以使用debug模組去輸出

# 如果我們在adhoc中直接輸出facts,會未定義的錯誤
[root@ansible:192.168.121.10 ~/ansible]$ansible webservers -m debug -a "msg='{{ansible_ens33.ipv4.address}}'"
web01 | FAILED! => {
    "msg": "The task includes an option with an undefined variable. The error was: 'ansible_ens33' is undefined. 'ansible_ens33' is undefined. 'ansible_ens33' is undefined. 'ansible_ens33' is undefined"
}
# 如果我們將facts寫入劇本中,在執行劇本時,劇本會自己生成一個task(透過setup去收集facts),這樣你在後面如果要使用debug去輸出facts就不會再報錯了

【4】、ansible變數格式

ansible變數的格式類似於python中的字典,

我們在查詢變數時,要嚴格遵循層層遞進的關係去寫

父.子的格式,中間使用”.“表示巢狀關係

---
- name: display host info
  hosts: web01
  tasks:
    - name: display hostname and memory
      debug:
        msg: |
          hostname: {{ansible_hostname}}
          mem: {{ansible_memtotal_mb}}MB
          ens33_ip: {{ansible_ens33.ipv4.address}}
          sdb2: {{ansible_devices.sdb.partitions.sdb2.size}}
ok: [web01] => {
    "msg": "hostname: web01\nmem: 1734MB\nens33_ip: 192.168.121.11\nsdb2: 15.00 GB\n"
}

【5】、自定義變數

  • 引入變數,可以方便playbook重用。比如裝包的playbook,包名使用變數,多次執行playbook,只要改變變數名即可,不用重新編寫playbook
  • ansible支援10種以上的變數定義方式。常用變數來源如下:
  • inventory變數。變數來自於主機清單
  • facts變數。
  • playbook變數。變數在playbook中定義。
  • 變數檔案。專門建立用於儲存變數的檔案。推薦變數寫入單獨的檔案
# 在webservers組中建立zhaoliu使用者,在db上建立wangwu
---
- name: create user
  hosts: webservers
  tasks:
    - name: create zhaoliu
      user:
        name: zhaoliu
- name: create wangwu
  hosts: db
  tasks:
    - user:
        name: wangwu
# 我們無法使用一個play去實現

因此我們就需要自定義變數

在劇本中使用變數,讓不同的主機建立不同的使用者

# 修改劇本
---
- name: create user
  hosts: webservers,db
  tasks:
    - name: create zhaoliu
      user:
        name: "{{username}}"
# 在主機清單中建立變數
[webservers]
web[01:02]

# 給整個webservers組定義了一個變數
[webservers:vars]
username=zhaoliu

[dbservers]
# 只給dbservers中的db定義了變數
db username=zhaoliu

[cluster:children]
webservers
dbservers

在劇本中定義變數,使用vars:

在劇本中定義變數如果和invention中定義的變數重名,劇本中的變數的優先順序高於invention中定義的變數

---
- name: create jack
  hosts: webservers
  vars:
    username: jack
    password: "123"
  tasks:
    - user:
        name: "{{username}}"
        password: "{{password|password_hash('sha512')}}"

定義變數檔案,將變數寫入變數檔案中

# 劇本
---
- name: create user
  hosts: webservers
  vars_files: vars.yaml   # 引用變數檔案
  tasks:
    - name: create user
      user:
        name: "{{yonghu}}"
        state: present
        password: "{{mima|password_hash('sha512')}}"
        
# 變數檔案
---
yonghu: rose
mima: abc

五、進階語法

【1】、錯誤處理

當playbook中包含很多工時,當某一個任務遇到錯誤,他將崩潰,終止執行

---
- name: my errors
  hosts: webservers
  tasks:
    - name: start mysqld
      service:
        name: mysqld
        state: started
        enabled: yes
    - name: touch file
      file:
        path: /tmp/service.txt
        state: touch
# 由於主機上沒有mysql,當執行ansible時
# 我們可以加一個ignore_errors.引數來忽略錯誤,繼續向下執行
---
- name: my errors
  hosts: webservers
  ignore_errors: yes     # ignore如果寫在這裡,則表示可以忽略所有的任務中的錯誤
  tasks:
    - name: start mysqld
      service:
        name: mysqld
        state: started
        enabled: yes
      ignore_errors: yes   # ignore寫在這裡表示忽略這一個任務的錯誤
    - name: touch file
      file:
        path: /tmp/service.txt
        state: touch
ASK [start mysqld] *******************************************************************************************************************************************
fatal: [web01]: FAILED! => {"changed": false, "msg": "Could not find the requested service mysqld: host"}
...ignoring
fatal: [web02]: FAILED! => {"changed": false, "msg": "Could not find the requested service mysqld: host"}
...ignoring

【2】、觸發執行任務

  • 透過handlers定義觸發執行的任務
  • handlers中定義的任務,不是一定會執行的
  • 在task中定義的任務,透過notify關鍵通知handlers中的哪個任務要執行
  • 只有task中的任務狀態是changed才會進行通知
# 下載nginx配置檔案到當前目錄
---
- name: download file
  hosts: web01
  tasks:
    - name: get nginx.conf
      fetch:
        src: /etc/nginx/nginx.conf
        dest: ./
        flat: yes
# flat的作用是:扁平下載,只下載檔案,不會巢狀著目錄
---
- name: configure nginx
  hosts: webservers
  vars:
    http_port: "80"
  tasks:
    - name: upload file
      template:
        src: ./nginx.conf
        dest: /etc/nginx/nginx.conf
      notify: restart nginx        # 當這個任務發生修改後,在執行handlers的任務,如果notify的任務沒有執行,那就不會給handlers傳送訊號,handlers的任務也不會去執行

  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

【3】、when條件

---
- name: install mysql-server
  hosts: db
  tasks:
    - name: mysql-server
      yum:
        name: mysql-server
        state: present
      when: ansible_memtotal_mb > 2048
# when後面的變數不需要加雙大括號
TASK [mysql-server] *******************************************************************************************************************************************
skipping: [db]

# 如果不滿足when的條件,則跳過,不執行

多條件判斷

---
- name: whens
  hosts: webservers
  tasks:
    - name: whens
      copy:
        src: ./motd
        dest: /etc/motd
      when: >
        ansible_distribution == "Rocky"
        and
        ansible_distribution_major_version == "8"

【4】、regitster註冊變數

Ansible的”regitster“模組是用於捕獲和儲存任務執行結果的,它允許將其他任務的輸出作為變數使用。register是一個關鍵字,它可以將任務的執行結果賦值給指定的變數名稱。這個變數可以在後續任務中使用。register模組可以捕獲各種型別的輸出,包括stdout、stderr、rc、changed等。他可以與其他模組一起使用,例如”when“條件、”loop“迴圈等。

---
- name: create file
  hosts: web01
  tasks:
    - name: create /tmp/reg1.txt
      file:
        path: /tmp/reg1.txt
        state: touch
      register: result
    - name: display
      debug:
        msg: "{{result}}"

TASK [display] ************************************************************************************************************************************************
ok: [web01] => {
    "msg": {
        "changed": true,
        "dest": "/tmp/reg1.txt",
        "diff": {
            "after": {
                "atime": 1719419743.2074833,
                "mtime": 1719419743.2074833,
                "path": "/tmp/reg1.txt",
                "state": "touch"
            },
            "before": {
                "atime": 1719419530.2680113,
                "mtime": 1719419517.1950111,
                "path": "/tmp/reg1.txt",
                "state": "file"
            }
        },
        "failed": false,
        "gid": 0,
        "group": "root",
        "mode": "0644",
        "owner": "root",
        "secontext": "unconfined_u:object_r:user_tmp_t:s0",
        "size": 0,
        "state": "file",
        "uid": 0
    }
}
 ---
 - name: create file
   hosts: web01
   tasks:
     - name: create /tmp/reg1.txt
       file:
         path: /tmp/reg1.txt
         state: touch
       register: result
     - name: display
       debug:
         msg: "failed:{{result.failed}},owner:{{result.owner}},mode:{{result.mode}}"

TASK [display] ************************************************************************************************************************************************
ok: [web01] => {
    "msg": "failed:False,owner:root,mode:0644"
}

register和when結合使用

---
- name: create file
  hosts: web01
  ignore_errors: yes
  tasks:
    - name: file
      file:
        path: /tmp/a
        state: touch
      register: result

    - name: debug
      debug:
        msg: "create fail"
      when: result.failed
      
# 根據上一個任務執行結束

六、任務塊

【1】、block

可以透過block關鍵字,將多個任務組合到一起

可以將整個block任務組,一起控制是否要執行

---
- name: block
  hosts: webservers
  tasks:
    - name: install nginx
      yum:
        name: nginx
        state: present
      when ansible_distribution == "Rocky"
    - name: start nginx
      service: 
        name: nginx
        state: started
        enabled: yes
      when ansible_distribution == "Rocky"
# 如果不用block就會進行重複的判斷
# 設定block
---
- name: block
  hosts: webservers
  tasks:
    - name: define a group of tasks
      block:
        - name: install nginx
          yum:
            name: nginx
            state: present
        - name: start nginx
          service:
            name: nginx
            state: started
            enabled: yes
      when: ansible_distribution == "Rocky"

【2】、rescue和always

block、rescue和anlways是三兄弟分別表示

block:正常執行

rescue:補救,如果block不能正常執行(執行出錯),rescue則執行,如果block可以正常執行(執行沒有出錯),rescue則不執行

always:不論block和rescue執不執行,always永遠執行

 ---
 - name: block
   hosts: web01
   tasks:
     - name: block / rescue / always
       block:
         - name: create test1
           file:
             path: /tmp/test1.txt
             state: touch
 
       rescue:
         - name: create test2
           file:
             path: /tmp/test2.txt
             state: touch
 
       always:
         - name: create test3
           file:
             path: /tmp/test3.txt
             state: touch
# block模組可以正確執行,因此rescue模組不執行,always執行。最後的結果就是,會在web01的 /tmp目錄下test1和test3檔案
 ---
 - name: block
   hosts: web01
   tasks:
     - name: block / rescue / always
       block:
         - name: create test1
           file:
             path: /tmp/aaa/test1.txt
             state: touch
 
       rescue:
         - name: create test2
           file:
             path: /tmp/test2.txt
             state: touch
 
       always:
         - name: create test3
           file:
             path: /tmp/test3.txt
             state: touch
# block模組不能正確執行,因此rescue模組執行,always執行。最後的結果就是,會在web01的 /tmp目錄下test2和test3檔案

七、loop迴圈

相當於是shell中的for迴圈

ansible中迴圈用到的變數名是固定的,叫item

# 寫法1:
---
- name: use loop
  hosts: web01
  tasks:
    - name: create dir
      file:
        path: /tmp/{{item}}
        state: directory
      loop:
        - aaa
        - bbb
        - ccc
        - ddd
        - eee
# 寫法2
---
- name: use loop
  hosts: web01
  tasks:
    - name: create dir
      file:
        path: /tmp/{{item}}
        state: directory
      loop: [aaa,bbb,ccc,ddd,eee]
# 控制多個服務,停止多個服務
---
- name: control server
  hosts: webservers
  tasks:
    - name: stop nginx and firewalld
      service:
        name: "{{item}}"
        state: stopped
        enabled: no
      loop: [nginx,firewalld]

在使用yum安裝軟體時儘量不要使用loop

1、yum本身就支援安裝多個包

2、如果使用loop去安裝軟體,則表示執行多次yum,效率降低

字典

建立兩個賬號

zhangsan:123

lisi:456

 ---
 - name: create user
   hosts: webservers
   tasks:
     - name: del user
       user:
         name: "{{item}}"
         state: absent
         remove: yes
       loop: [zhangsan,lisi]
     - name: create user
       user:
         name: "{{item['user']}}"
         password: "{{item['pass']|password_hash('sha512')}}"
         state: present
       loop: [{"user":"zhangsan","pass":"123"},{"user":"lisi","pass":"456"}]

八、role角色

  • 為了實現playbook重用,可以使用role角色
  • 角色role相當於把任務打散,放到不同的目錄中
  • 在把一些固定的值,如使用者名稱、軟體包、服務等,用變數來表示
  • role角色定義好後,可以在其他playbook中直接呼叫

【1】、配置角色

# 宣告存放角色的 位置
roles_path = roles
# 建立roles目錄
[root@ansible:192.168.121.10 ~/ansible]$mkdir roles
# 生成具體的某一個角色
[root@ansible:192.168.121.10 ~/ansible]$ansible-galaxy init roles/motd
# 檢視生成的角色motd,如下的所有目錄和檔案不是每一個都必須的,沒有用到的目錄可以刪除,等到後面需要的時候可以再新建
[root@ansible:192.168.121.10 ~/ansible]$ll roles/motd/
total 4
drwxr-xr-x. 2 root root   22 Jun 27 05:36 defaults  #  存放變數,優先順序最低
drwxr-xr-x. 2 root root    6 Jun 27 05:36 files  # 存放劇本(不包含變數的劇本)
drwxr-xr-x. 2 root root   22 Jun 27 05:36 handlers 
drwxr-xr-x. 2 root root   22 Jun 27 05:36 meta  #後設資料:role的建立者、建立日期等
-rw-r--r--. 1 root root 1328 Jun 27 05:36 README.md
drwxr-xr-x. 2 root root   22 Jun 27 05:48 tasks  # 存放任務
drwxr-xr-x. 2 root root   18 Jun 27 05:46 templates # 存放劇本(有變數的劇本)
drwxr-xr-x. 2 root root   39 Jun 27 05:36 tests  # 測試案例
drwxr-xr-x. 2 root root   22 Jun 27 05:49 vars    # 存放變數
# 配置角色具體內容
	# 將劇本放入template
[root@ansible:192.168.121.10 ~/ansible]$mv motd roles/motd/templates/
	# 編寫任務,將原劇本中的tasks複製到roles/motd/tasks/main.yml中
[root@ansible:192.168.121.10 ~/ansible]$vim roles/motd/tasks/main.yml
---
# tasks file for roles/motd
- name: motd
  template:
    src: motd
    dest: /etc/motd
	# 定義變數,將劇本中會使用到的變數寫入roles/motd/vars/main.yml中
[root@ansible:192.168.121.10 ~/ansible]$vim roles/motd/vars/main.yml
---
# vars file for roles/motd
admin: xuruizhao00@163.com
# 編寫劇本引用角色
[root@ansible:192.168.121.10 ~/ansible]$vim role_motd.yaml
---
- name: modify motd
  hosts: webservers
   # 呼叫設定好的角色,首先會去roles/motd/task/中找任務,再去template目錄中找要上傳的檔案,最後去vars目錄中找變數
  roles:
    - motd

【2】、role練習

1、建立名為pkgs的角色,用於裝包,包名使用變數pkg代表

2、建立inst_nginx.yaml,呼叫pkgs角色,安裝nginx

3、建立inst_mysql.yaml,呼叫pkgs角色,安裝mysql

# 新建角色,我們不使用ansible-galaxy,直接使用mkdir建立所需要的目錄,因為在建立角色的過程中,有很多的目錄不是我們所需要的
[root@ansible:192.168.121.10 ~/ansible]$mkdir -p roles/pkgs/{task,defaults}
# 設定任務
[root@ansible:192.168.121.10 ~/ansible/roles/start_svc]$vim tasks/main.yaml
---
- name: Install the pkgs
  yum:
    name: "{{pkg}}"
    state: present
# 編寫變數,將變數寫入defaults中,因為defaults中的變數的優先順序最低,我們後續可以在劇本中定義新的變數,新的變數的值就可以覆蓋defaults中的值了
[root@ansible:192.168.121.10 ~/ansible/roles/start_svc]$vim defaults/main.yaml
 ---
 pkg: nginx
# 編寫劇本
[root@ansible:192.168.121.10 ~/ansible]$vim inst_nginx.yaml
---
- name: intall nginx
  hosts: webservers
  roles:
    - pkgs
[root@ansible:192.168.121.10 ~/ansible]$vim inst_mysql.yaml
---
- name: intall mysql
  hosts: db
  vars:
  # 此處定義的變數,就會覆蓋defaults中定義的變數
    pkg: mysql-server
  roles:
    - pkgs

定義一個start_svcjuese,控制服務

變數svc

# 編寫任務
[root@ansible:192.168.121.10 ~/ansible]$vim roles/start_svc/tasks/main.yaml
---
- name: control server
  service:
    name: "{{svc}}"
    state: "{{single}}"
    enabled: "{{panduan}}"
# 編寫變數
[root@ansible:192.168.121.10 ~/ansible]$vim roles/start_svc/defaults/main.yaml
---
svc: nginx
single: start
panduan: yes

# 編寫劇本
[root@ansible:192.168.121.10 ~/ansible]$vim role_nginx.yaml
---
- name: control serv
  hosts: webservers
  vars:
    pkg: nginx
    svc: nginx
    single: restarted
  roles:
    - pkgs
    - start_svc
  tasks:
    - name: create index web page
      copy:
        dest: /usr/share/nginx/html/test.html
        content: "role test"

在劇本中允許role和tasks同時存在

當一個劇本中既有role又有tasks時,不管書寫的順序如何,一定是role先執行,tasks後執行

九、ansible加解密檔案

ansible加解密檔案使用ansible-vault命令

# 檔案加密
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault encrypt hello.txt 
New Vault password: 
Confirm New Vault password: 
Encryption successful
# 檔案解密
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault decrypt hello.txt 
Vault password: 
Decryption successful
# 在不解密的情況下檢視檔案內容
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault view hello.txt 
Vault password: 
在嗎
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault view hello.txt  > output
Vault password:


# 將密碼寫入檔案中,透過檔案進行加密和解密
[root@ansible:192.168.121.10 ~/ansible]$echo "aaa" > pass.txt# 
[root@ansible:192.168.121.10 ~/ansible]$echo 'hello' > data.txt
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault encrypt --vault-id=pass.txt data.txt 
Encryption successful
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault decrypt --vault-id=pass.txt data.txt
Decryption successful

# 先將劇本檔案進行加密,在執行的時候輸入密碼
[root@ansible:192.168.121.10 ~/ansible]$ansible-vault encrypt loop2.yaml --vault-id=pass.txt
Encryption successful
[root@ansible:192.168.121.10 ~/ansible]$ansible-playbook loop2.yaml --ask-vault-pass   # 互動式輸入密碼
Vault password:
[root@ansible:192.168.121.10 ~/ansible]$ansible-playbook loop2.yaml --vault-id=pass.txt   # 非互動式

十、sudo命令

  • 一般用於普通使用者需要執行root許可權的命令
  • 在web01上配置zhangsan擁有sudo許可權
# 普通使用者的sudo許可權要進行設定才能使用
# 配置檔案/etc/sudoers
# 我們在修改sudoers時,一般使用visudo去修改而不使用,vim。因為visudo具備語法檢查功能,如果你修改sudoers後,有語法錯誤,visudo會自動檢查出來
# 我們可以過濾出除註釋和空行的內容,方便檢視
[root@web01:192.168.121.11 ~]$grep -E -v "^#|^$" /etc/sudoers
Defaults   !visiblepw
Defaults    always_set_home
Defaults    match_group_by_gid
Defaults    always_query_group_plugin
Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin
root	ALL=(ALL) 	ALL
# 這裡的%代表wheel是一個使用者組,ALL表示可以使用sudo做任何提權操作
%wheel	ALL=(ALL)	ALL
# 我們可以將zhangsan加到這個組中
[root@web01:192.168.121.11 ~]$usermod -aG wheel zhangsan 
[root@web01:192.168.121.11 ~]$id zhangsan 
uid=1016(zhangsan) gid=1016(zhangsan) groups=1016(zhangsan),10(wheel)
# 這是zhangsan就具備了sudo提權許可權
# 給lisi設定sudo許可權,NOPASSWD表示在進行sudo時不輸入密碼
lisi    ALL=(ALL)       NOPASSWD:ALL

# 不給tom使用者ALL許可權
# 設定命令別名,tom只能執行允許的命令
Cmnd_Alias USER = /usr/sbin/useradd,/usr/sbin/usermod,/usr/sbin/userdel,/bin/passwd
tom     ALL=(ALL)       NOPASSWD:USER

十一、特殊的主機清單變數

  • 如果遠端主機沒有使用免密登入,如果遠端主機ssh不是標準22埠,可以設定特殊的主機清單變數
  • ansible_ssh_user:指定登入遠端主機的使用者名稱
  • ansible_ssh_pass:指定登入遠端主機的密碼
  • ansible_ssh_port:指定登入遠端主機的埠號
# 先取消免密登入,刪除遠端主機中的公鑰
[root@ansible:192.168.121.10 ~/ansible]$ansible all -m file -a "path=/root/.ssh/authorized_keys state=absent"
# 修改web01的ssh登入的埠號
vim /etc/ssh/sshd_config   # sshd_config:是伺服器端的ssh配置檔案
vim /etc/ssh/ssh_config    # ssh_config:是客戶端的ssh配置檔案

# 修改ssh連線埠為220,重啟服務
[root@web01:192.168.121.11 ~/.ssh]$echo 'Port 220' >> /etc/ssh/sshd_config 
[root@web01:192.168.121.11 ~]$systemctl restart sshd

# 客戶端測試連結
[root@ansible:192.168.121.10 ~/ansible]$ssh 192.168.121.11
ssh: connect to host 192.168.121.11 port 22: Connection refused
[root@ansible:192.168.121.10 ~/ansible]$ssh 192.168.121.11 -p 220
root@192.168.121.11's password: 
Hostname: web01
Date: 2024-06-27
Contact to: xuruizhao00@163.com
Last login: Thu Jun 27 18:36:10 2024 from 192.168.121.10
# 準備一個新的ansible目錄
[root@ansible:192.168.121.10 ~]$mkdir myansible
[root@ansible:192.168.121.10 ~]$cp ansible/ansible.cfg myansible/
[root@ansible:192.168.121.10 ~]$cd myansible/
[root@ansible:192.168.121.10 ~/myansible]$ll
total 4
-rw-r--r--. 1 root root 85 Jun 27 18:43 ansible.cfg
[root@ansible:192.168.121.10 ~/myansible]$vim inventory
[group1]
web01
web02
db
# 此時去使用ansible是不通的
# 設定主機清單變數
[group1]
web01 ansible_ssh_user=root ansible_ssh_pass=123 ansible_ssh_port=220
web02 ansible_ssh_user=root ansible_ssh_pass=123
db ansible_ssh_user=root ansible_ssh_pass=123