Ansible自動化運維工具

misakivv發表於2024-05-19

目錄
  • 一、什麼是Ansible
    • 1、簡介
    • 2、架構
    • 3、工作流程
  • 二、部署Ansible批次管理
    • 1、涉及主機
    • 2、安裝部署Ansible
      • 2.1、yum安裝
      • 2.2、其他方式
    • 3、設定免密登入
      • 3.1、控制節點設定hosts解析
      • 3.2、生成金鑰對
      • 3.3、將公鑰傳送給受管節點
      • 3.4、測試免密登入
    • 4、定義主機清單
      • 4.1、ansible常見的配置檔案
      • 4.2、備份主機清單檔案
      • 4.3、修改主機清單,設定分組
  • 三、Ansible引數說明及執行狀態
    • 1、引數說明
    • 2、Ansible的執行狀態
  • 四、Ansible常用模組
    • 1、ping模組
    • 2、command模組
      • 2.1、選項及描述
      • 2.2、結合chdir和removes、creates列出指定目錄下內容
      • 2.3、檢視磁碟空間
    • 3、shell模組
      • 3.1、選項及引數
      • 3.2、檢查遠端主機的系統版本
      • 3.3、檢視遠端主機防火牆狀態
      • 3.4、建立、檢視指定目錄
    • 4、user模組
      • 4.1、選項及描述
      • 4.2、新增系統使用者,指定uid、家目錄及註釋
      • 4.3、檢視新建立的使用者
      • 4.4、刪除新建立的使用者
    • 5、group模組
      • 5.1、選項及描述
      • 5.2、建立或更新組
      • 5.3、刪除組
    • 6、copy模組
      • 6.1、選項及描述
      • 6.2、給定內容生成檔案,並修改許可權資訊
      • 6.3、修改檔案內容,選擇覆蓋備份
    • 7、fetch模組
      • 7.1、選項及描述
      • 7.2、從遠端主機抓取檔案
      • 7.3、限制抓取檔案的大小、新增檔案存在檢測
    • 8、file模組
      • 8.1、選項及描述
      • 8.2、在指定路徑下建立目錄
      • 8.3、建立軟連結檔案
      • 8.4、建立硬連結檔案
      • 8.5、刪除檔案
    • 9、yum模組
      • 9.1、選項及描述
      • 9.2、安裝httpd服務
      • 9.3、更新所有的軟體包
    • 10、cron模組
      • 10.1、選項及描述
      • 10.2、新增計劃任務
      • 10.3、刪除指定計劃任務
    • 11、service模組
      • 11.1、選項及描述
      • 11.2、遠端開啟/關閉防火牆
    • 12、script模組
      • 12.1、選項及描述
      • 12.2、編輯並部署指令碼
        • 1、控制節點本地編輯指令碼並新增執行許可權
        • 2、透過script模組部署到遠端主機執行
    • 13、setup模組
      • 13.1、選項及描述
      • 13.2、檢視記憶體資訊
        • 透過free -m命令檢視記憶體大小是否一致
      • 13.3、儲存資訊
    • 14、synchronize模組
      • 14.1、選項及描述
      • 14.2、將源目錄同步至目標目錄(增量同步)
      • 14.3、將源目錄同步至目標目錄(完全同步)
  • 五、Ansible playbook
    • 1、簡介
    • 2、playbook的YAML格式
      • 2.1、示例:
      • 2.2、解析
    • 3、playbook的執行與語法檢查
    • 4、playbook的核心元素
    • 5、基本元件及格式
    • 6、安裝nginx並修改配置檔案
      • 6.1、準備檔案存放目錄
      • 6.2、編寫yaml檔案
      • 6.3、編寫conf檔案
      • 6.4、檢查語法錯誤,執行playbook
      • 6.5、驗證nginx啟動狀態
    • 7、安裝nginx,並新增handlers和notify
      • 7.1、修改對應的nginx.yml和nginx.conf檔案
      • 7.2、驗證nginx程序資訊
      • 7.3、測試標籤
      • 7.4、測試notify
        • 7.4.1、notify的觸發條件是配置檔案被改變
        • 7.4.2、重新執行劇本
        • 7.4.3、重新檢視埠號
    • 8、變數(variables)
      • 8.1、定義變數的方式
        • 1. Facts(Facts變數)
        • 2. 使用者自定義變數
        • 3. 透過Roles傳遞變數
        • 4. Host Inventory(主機清單)中定義變數
      • 8.2、優先順序
      • 8.3、案例:使用變數安裝keepalived
        • 1、編寫劇本
        • 2、複製配置檔案
        • 3、執行劇本,變數由命令列傳入
        • 4、或者直接再劇本里定義變數
        • 5、執行定義過變數的劇本
    • 9、模板(templates)
      • 9.1、簡介
      • 9.2、基本資料型別和運算子
      • 9.3、案例:生成hosts解析檔案
        • 1、修改Ansible主機清單
        • 2、修改主機名
        • 3、準備模板檔案
        • 4、編寫劇本
        • 5、執行劇本
        • 6、驗證
    • 10、條件判斷
      • 10.1、舉例
    • 11、迴圈迭代
      • 11.1舉例
      • 11.2、案例:迴圈建立使用者
        • 1、迴圈建立以下使用者資訊
        • 2、迴圈建立出以上使用者並指定使用者資訊
        • 3、執行劇本
        • 4、驗證
    • 12、字典
      • 12.1、舉例
    • 13、角色(role)
      • 13.1、簡介
      • 13.2、角色的目錄結構
    • 14、案例:使用角色安裝nginx
      • 14.1、建立對應的目錄結構
      • 14.2、定義配置檔案
      • 14.3、放置檔案到指定目錄
      • 14.4、修改變數檔案
      • 14.5、定義handlers檔案
      • 14.6定義劇本檔案
      • 14.7、剩餘的配置檔案
      • 14.8、啟動服務
      • 14.9、驗證埠號
    • 15、案例:使用角色安裝httpd
      • 15.1、建立對應的目錄結構
      • 15.2、編寫site.yaml檔案
      • 15.3、編寫tasks裡的main.yml檔案
      • 15.4、執行劇本
      • 15.5、驗證
    • 16、案例:使用角色安裝java+nginx+halo
      • 16.1、準備角色
      • 16.2、編寫site.yml
      • 16.3、編寫nginx角色
      • 16.4、編寫java角色
      • 16.5、編寫halo角色
      • 16.6、執行劇本
      • 16.7、驗證

一、什麼是Ansible

1、簡介

Ansible是一款自動化運維工具,基於Python開發,集合了眾多運維工具(puppet、cfengine、chef、func、fabric)的優點,實現了批次系統部署、批次程式部署,批次執行命令等功能。

Ansible是基於模組工作的,本身沒有批次部署的能力,真正具有批次部署能力的是Ansible執行的模組,Ansible只是提供一個框架。Ansible不需要在遠端主機上安裝client/agents,因為它們是基於ssh來和遠端主機通訊的。

2、架構

2Q==

  • ansbile:核心程式
  • modules:包括ansible自帶的核心模組以及自定義模組
  • plugins:完成模組功能的補充,包括連線外掛,郵箱外掛
  • palybooks:劇本,定義ansbile多工配置檔案,由ansible自動執行
  • inventory:定義ansbile管理的主機清單
  • connection plugins:負責和被監控端實現通訊

3、工作流程

  1. 載入配置檔案: Ansible 預設查詢 /etc/ansible/ansible.cfg 配置檔案,這個檔案包含了Ansible執行時的行為設定,如連線方式、外掛路徑等。
  2. 解析Inventory: Ansible 使用 Inventory 檔案(預設是 /etc/ansible/hosts)來確定需要操作的目標主機或主機組。
  3. 編譯Playbook或命令: Ansible 準備執行的Playbook或直接執行的Ad-Hoc命令,並解析其中的任務和模組呼叫。
  4. 模組載入與執行策略準備: 對於每個任務,Ansible 載入相應的模組(如 command 模組),並準備執行上下文,包括變數、環境等。
  5. 生成並傳輸臨時指令碼: Ansible 會根據任務和模組生成一個或多個臨時的Python指令碼,並透過SSH連線傳輸到目標主機的臨時目錄,通常位於目標使用者的 ~/.ansible/tmp/ansible-tmp-<UNIQUE_ID>/ 目錄下。
  6. 賦予執行許可權: 在目標主機上,Ansible 會給這個臨時Python指令碼加上執行許可權,以便能夠執行。
  7. 執行遠端指令碼: Ansible 透過SSH在目標主機上執行這個臨時指令碼,並收集執行結果。
  8. 結果收集與處理: 執行完畢後,各個主機的執行結果被收集並彙總,Ansible根據這些結果決定是否繼續執行後續任務,或是根據Playbook中的錯誤處理邏輯(如 rescuealways 塊)進行操作。
  9. 清理: 一旦任務執行完成,無論成功還是失敗,Ansible 會清理目標主機上的臨時檔案,包括刪除之前上傳的Python指令碼。
  10. 退出與報告: 清理完成後,Ansible 程序在目標主機上退出,並向控制機報告最終的執行狀態和結果。

二、部署Ansible批次管理

1、涉及主機

主機名 角色 IP地址
server 控制節點 192.168.112.10
host1 受管節點 192.168.112.20
host2 受管節點 192.168.112.30
host3 受管節點 192.168.112.40

2、安裝部署Ansible

控制節點

2.1、yum安裝

yum install -y epel-release		#Centos需要安裝EPEL倉庫
yum install -y ansible		#yum包管理安裝Ansible
ansible --version		#檢視Ansible安裝版本

image-20240514193101699

2.2、其他方式

安裝管理主機

3、設定免密登入

3.1、控制節點設定hosts解析

[root@server ~]# vim /etc/hosts
192.168.112.10 server
192.168.112.20 host1
192.168.112.30 host2
192.168.112.40 host3

3.2、生成金鑰對

[root@server ~]# ssh-keygen -P "" -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
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:eSgh2wm7WxXS8n61UI4wKK0yEl3mLlzwIFBdOQSAgag root@server
The key's randomart image is:
+---[RSA 2048]----+
|B+=o++o.         |
|+o B..oo         |
|o . B *.=   .    |
|Eo o O * * +     |
|. = = + S + o    |
| . + . + . o .   |
|    . . . . .    |
|     o   .       |
|    .            |
+----[SHA256]-----+
  • -P "":設定空密碼
  • -t rsa: 指定生成金鑰的型別為RSA
  • 簡化後續實驗輸密碼操作

3.3、將公鑰傳送給受管節點

ssh-copy-id -i /root/.ssh/id_rsa.pub root@host1
ssh-copy-id -i /root/.ssh/id_rsa.pub root@host2
ssh-copy-id -i /root/.ssh/id_rsa.pub root@host3

image-20240514194147934

過程中需要輸入受管節點的密碼

3.4、測試免密登入

ssh root@host1
ssh root@host2
ssh root@host3

image-20240514195408504

4、定義主機清單

4.1、ansible常見的配置檔案

  • /etc/ansible/ansible.cfg:主配置檔案
  • /etc/ansible/hosts:主機清單檔案
  • /etc/ansible/roles:角色目錄

4.2、備份主機清單檔案

cp -f hosts hosts.bak

image-20240515154201487

4.3、修改主機清單,設定分組

vim /etc/ansible/hosts
[all-servers]
server
host1
host2
host3
[node1]
host1
[node2]
host2
[node3]
host3
[mysql_test]
host1
host2
[web_test]
host2
host3
[manager]
server

image-20240516112421403

三、Ansible引數說明及執行狀態

1、引數說明

引數 說明
-h 顯示幫助資訊,包含可用的命令和選項。
-i 指定Inventory檔案的路徑,預設為/etc/ansible/hosts
-l 限制playbook或命令的作用範圍,僅對匹配的主機執行。
-u 指定連線遠端主機時使用的使用者名稱。
-b 在遠端主機上執行操作時臨時提升許可權,相當於使用sudo
--become-user=USER 提升許可權後切換到的使用者。
-m 用於ad-hoc命令,指定要使用的模組名。
-a 指定模組的引數。
-f 指定併發程序數,預設為5。
-v 增加輸出的詳細程度,多次使用可獲得更多除錯資訊。
-vvv 設定更詳細的輸出級別,有助於除錯。
--check 執行模擬執行,不實際改變系統狀態,用以預覽操作效果。
--diff 修改檔案時,顯示修改前後的差異。
-C 檢查執行結果
-e 指明變數名
--syntax-check 檢查執行命令是否存在語法錯誤

2、Ansible的執行狀態

  • 綠色:執行成功並且不需要做改變的操作
  • 黃色:執行成功並且對目標主機做變更
  • 紅色:執行失敗
  • 粉色:警告資訊
  • 藍色:顯示ansible命令執行的過程

四、Ansible常用模組

1、ping模組

主機連通性測試

#一個一個測試
ansible -m ping node1
ansible -m ping node2
ansible -m ping node3
ansible -m ping manager

#以組為單位測試
ansible -m ping all-servers

image-20240515175627840

image-20240516111257062

2、command模組

ansible的預設模組,用於在遠端主機上執行簡單的Linux命令,並將結果返回主機

不支援管道,變數及重定向等

2.1、選項及描述

ansible-doc -s command
選項 描述
argv 將命令作為列表而非字串傳遞。使用argv可避免對原本會被誤解的值(例如使用者名稱中帶空格的情況)進行引用。只能提供字串或列表形式之一,不能同時提供。
chdir 在執行命令前切換到此目錄。
cmd 要執行的命令。
creates 如果該檔案已經存在,此步驟不會執行。
removes 如果該檔案存在,此步驟將會執行。
stdin 直接將指定的值設定為命令的stdin。
stdin_add_newline 如果設定為yes,在stdin資料末尾追加換行符。
strip_empty_ends 從stdout/stderr結果的結尾去除空行。
warn 啟用或禁用任務警告。

2.2、結合chdir和removes、creates列出指定目錄下內容

#node1組先切換到root目錄下aliyun.sh檔案存在不執行ls
ansible node1 -m command -a 'chdir=/root/ creates=aliyun.sh ls'

#node1組先切換到root目錄下aliyun.sh檔案存在就執行ls
ansible node1 -m command -a 'chdir=/root/ removes=aliyun.sh ls'

image-20240516121432943

2.3、檢視磁碟空間

#檢視mysql_test組中所有主機的磁碟空間
ansible mysql_test -m command -a 'df -h'

#檢視web_test組中所有主機的磁碟空間
ansible web_test -m command -a 'df -h'

image-20240516115223289

3、shell模組

shell模組可以在遠端主機上呼叫shell直譯器執行命令,支援shell的各種功能,例如管道等。

3.1、選項及引數

ansible-doc -s command
選項 描述
chdir 在執行命令前切換到此目錄。
cmd 要執行的命令及其可選引數。
creates 當指定的檔案已存在時,此步驟將不執行。
executable 更改用於執行命令的shell。這需要shell可執行檔案的絕對路徑。
free_form 要執行的Linux指令,一般使用Ansible的-a引數代替。
removes 當指定的檔案存在時,此步驟將執行。
stdin 直接將指定的值設定為命令的stdin。
stdin_add_newline 是否在stdin資料末尾新增換行符。
warn 是否啟用任務警告。

3.2、檢查遠端主機的系統版本

#檢視mysql_test組遠端主機的系統版本
ansible mysql_test -m shell -a 'cat /etc/os-release | grep PRETTY_NAME | cut -d "=" -f2'

#檢視web_test組遠端主機的系統版本
ansible web_test -m shell -a 'cat /etc/os-release | grep PRETTY_NAME | cut -d "=" -f2'

image-20240516204041385

3.3、檢視遠端主機防火牆狀態

#檢視mysql_test組中所有的主機防火牆firewalld和selinux的狀態
ansible mysql_test -m shell -a 'systemctl status firewalld ; getenforce'

這裡驗證了command模組不能使用命令別名、管道、重定向以及邏輯運算子(如;, &&, ||

由於command模組直接將整個字串傳遞給系統執行,分號;以及隨後的getenforce命令被視為命令的一部分,而不是獨立的指令。這導致系統嘗試查詢名為類似\x3b.service(分號;的ASCII轉義序列)的服務狀態,以及嘗試將getenforce當作一個服務單元來查詢,由於這兩個都不是有效的服務單元名稱,因此返回了錯誤資訊。

image-20240516210703587

3.4、建立、檢視指定目錄

#在mysql_test組下的主機迴圈建立/root/tmp_1/NOW+當前時間的目錄
ansible mysql_test -m shell -a "mkdir -p /root/tmp_1/NOW-$(date +'%H:%M:%S')"

#find查詢是否正確建立
ansible mysql_test -m shell -a "find /root/tmp_1 -mmin -5"

image-20240516221926779

4、user模組

主要用於管理遠端系統上的使用者賬戶,包括建立、修改和刪除使用者。

它允許你設定使用者的密碼、shell、主目錄、許可權等屬性

4.1、選項及描述

ansible-doc -s user
選項 描述
comment 使用者的描述資訊
createhom 是否建立家目錄
force 在使用state=absent時, 行為與userdel –force一致
group 指定基本組
groups 指定附加組,如果指定為(groups=)表示刪除所有組
home 指定使用者家目錄
move_home 如果設定為home=時, 試圖將使用者主目錄移動到指定的目錄
name 指定使用者名稱
non_unique 該選項允許改變非唯一的使用者ID值
password 指定使用者密碼
remove 在使用state=absent時, 行為是與userdel –remove一致
shell 指定預設shell
state 設定帳號狀態,預設為present表示新建使用者,指定值為absent表示刪除
system 當建立一個使用者,設定這個使用者是系統使用者。這個設定不能更改現有使用者
uid 指定使用者的uid
update_password 更新使用者密碼
expires 指明密碼的過期時間
append 新增一個新的組

4.2、新增系統使用者,指定uid、家目錄及註釋

#給web_test組中新增一個系統使用者zhangsan家目錄為/home/zhangsan,使用者id為111,註釋資訊為hello zhangsan
ansible web_test -m user -a "system=yes name=zhangsan home=/home/zhangsan uid=111 comment='hello zhangsan'"

image-20240516232453569

4.3、檢視新建立的使用者

#id zhangsan驗證使用者是否正確建立,使用grep+awk擷取/etc/passwd上關於zhangsan的註釋資訊
ansible web_test -m shell -a 'id zhangsan ; grep ^zhangsan: /etc/passwd | awk -F ":" '\''{print $5}'\'''

image-20240516233345659

4.4、刪除新建立的使用者

#刪除使用者zhangsan
ansible web_test -m user -a "name=zhangsan state=absent remove=yes"

image-20240516233919793

5、group模組

用於管理Linux系統中的使用者組。

這個模組允許你新增或刪除使用者組,並且可以設定組ID(GID)。

5.1、選項及描述

ansible-doc -s group
選項 描述
gid 用於設定使用者組的GID(組ID)。
local 強制使用平臺提供的本地命令替代品(如lgroupadd代替groupadd),適用於需要操作本地組的集中認證環境。此選項要求目標主機上存在這些命令,否則會導致致命錯誤。
name (必需)指定組的名稱。
non_unique 允許將組ID更改為非唯一值。需要與gid一起使用。不支援macOS或BusyBox發行版。
state 指定使用者組在遠端主機上應有的狀態,可以是present(存在)或absent(不存在)。
system 如果設定為yes,表示建立的使用者組是系統組。

5.2、建立或更新組

#在web_test組的所有主機上建立一個系統組web_test,組id為1010
ansible web_test -m group -a "name=web_test gid=1010 system=yes"

#透過/etc/group檢視系統組web_test資訊

image-20240517084145750

5.3、刪除組

#刪除web_test組所有主機上的系統組web_test
ansible web_test -m group -a "name=web_test gid=1010 state=absent"

image-20240517084723135

6、copy模組

用於將本地檔案或目錄複製到遠端主機上

支援檔案、目錄、許可權、使用者組功能

6.1、選項及描述

ansible-doc -s copy
選項 描述
backup 在覆蓋之前,將原始檔備份,備份檔案包含時間資訊。
content 用於替代“src”,可以直接設定指定檔案的值
dest 必選項。要將原始檔複製到的遠端主機的絕對路徑
directory_mode 遞迴設定目錄的許可權,預設為系統預設許可權
force 當目標主機包含該檔案,但內容不同時,設為"yes",表示強制覆蓋;設為"no",表示目標主機的目標位置不存在該檔案才複製。預設為"yes"
follow 支援link檔案複製
others 所有file模組裡的選項都可以在這裡使用
src 被複制到遠端主機的本地檔案。可以是絕對路徑,也可以是相對路徑。如果路徑是一個目錄,則會遞迴複製,用法類似於"rsync"

6.2、給定內容生成檔案,並修改許可權資訊

#將copy內容為copy test複製到node3主機的/root/copy.txt並設定許可權666
ansible node3 -m copy -a 'content="copy test" dest=/root/copy.txt mode=666'

image-20240517092416076

6.3、修改檔案內容,選擇覆蓋備份

#修改node3主機上copy.txt檔案內容,並選擇備份
ansible node3 -m copy -a 'content="copy test_1\n" backup=yes dest=/root/copy.txt mode=666'

image-20240517093301639

7、fetch模組

Ansible 的 fetch 模組用於從遠端節點抓取檔案並儲存到Ansible控制器(執行Ansible任務的機器)上的指定目錄

7.1、選項及描述

ansible-doc -s fetch
選項 描述
dest 必選項,用來存放檔案的目錄
src 必選項,在遠端拉取的檔案,並且必須是一個file,不能是目錄
flat 當設定為yes時,即使src是一個目錄,也會將所有內容扁平化儲存到指定的dest目錄下,而不是保留目錄結構。( 預設no
validate_checksum 當設定為yes時,在下載完成後校驗檔案的校驗和,確保檔案完整無誤。這可以用來防止因網路問題導致的檔案損壞。(預設no
fail_on_missing 當設定為yes時,如果遠端檔案不存在,則標記任務失敗,否則只是簡單地跳過該檔案。(預設no
size 限制要抓取的檔案大小,可以使用字尾如kMG來指定單位(千位元組、兆位元組、吉位元組)。如果遠端檔案超過指定大小,抓取操作將不會執行。
timeout 設定超時時間(秒),用於等待檔案傳輸完成。預設情況下,Ansible使用其內部的連線超時設定。
force 即使本地檔案已經存在,也強制重新抓取。如果設定為no,則只有當遠端檔案比本地檔案新或不同才執行抓取。(預設yes
unarchive 如果src是指向一個歸檔檔案(如.zip或.tar.gz),並且設定了此選項為yes,Ansible將在抓取後嘗試解壓該歸檔檔案。(預設no
list_files 當設定為yes時,模組將只列出遠端目錄下的檔案而不實際抓取它們,可用於預覽目的。(預設no

7.2、從遠端主機抓取檔案

#從mysql_test組的主機中抓取aliyun.sh檔案到本機的/tmp/data目錄下
ansible mysql_test -m fetch -a "src=/root/aliyun.sh dest=/tmp/data"

#透過檢查/tmp/data下的目錄結構可知檔案已完整獲取
ansible manager -m shell -a "tree -L 5 /tmp/data"

image-20240518153051479

7.3、限制抓取檔案的大小、新增檔案存在檢測

#從mysql_test組的主機中抓取install.sh檔案,限制最大抓取大小20kb,傳輸中校驗檔案完整性,新增檔案存在檢測(不存在任務失敗)
ansible mysql_test -m fetch -a "src=/root/install.sh dest=/tmp/data/ verify_checksum=yes fail_on_missing=yes size=20k"

image-20240518154431410

8、file模組

file模組主要用於對檔案的建立、刪除、修改、許可權、屬性

8.1、選項及描述

ansible-doc -s file
選項 描述
path 必選項,定義檔案/目錄的路徑
mode 定義檔案/目錄的許可權
force 需要在兩種情況下強制建立軟連結,一種是原始檔不存在,但之後會建立的情況下;另一種是目標軟連結已存在,需要先取消之前的軟鏈,然後建立新的軟鏈,有兩個選項:yes
group 定義檔案/目錄的屬組,後面可以加上mode:定義檔案/目錄的許可權
owner 定義檔案/目錄的屬主。後面必須跟上path:定義檔案/目錄的路徑
recurse 遞迴設定檔案的屬性,只對目錄有效,後面跟上src:被連結的原始檔路徑,只應用於state=link的情況
dest 被連結到的路徑,只應用於state=link的情況
src 被連結的原始檔路徑,只應用於state=link的情況
state 狀態,有以下選項:directoryfilelinkhardtouchabsent

8.2、在指定路徑下建立目錄

#在mysql_test組所有主機在/tmp/路徑下建立許可權都是隻讀、屬主屬組都是root的file1目錄
ansible mysql_test -m file -a "path=/tmp/file1 mode=444 owner=root group=root state=directory"

#檢視建立好的目錄
ansible mysql_test -m shell -a "ls -l /tmp/ | grep file1"

image-20240517104101964

8.3、建立軟連結檔案

#給mysql_test組的所有主機建立軟連結檔案test1指向/root/aliyun.sh
ansible mysql_test -m file -a "path=/tmp/test1 src=/root/aliyun.sh state=link"

image-20240517135611145

8.4、建立硬連結檔案

#給mysql_test組的所有主機建立硬連結檔案test1指向/root/aliyun.sh
ansible mysql_test -m file -a "path=/tmp/test2 src=/root/aliyun.sh state=hard"

image-20240517140146609

8.5、刪除檔案

#刪除mysql_test組中所有主機/tmp/目錄下test1
ansible mysql_test -m file -a "path=/tmp/test1 state=absent"

image-20240517141327165

9、yum模組

主要用於在基於 RPM 的 Linux 系統上管理軟體包。

它允許使用者安裝、更新、解除安裝軟體包,並可配置額外的選項以控制操作的具體行為。

9.1、選項及描述

ansible-doc -s yum
選項 描述
name 必選項,所安裝的包的名稱
state 安裝-> present ; 安裝最新版本的-> latest ;absent-> 解除安裝包
update_cache 強制更新yum的快取
conf_file 指定遠端yum安裝時所依賴的配置檔案(安裝本地已有的包)。
disable_pgp_check 是否禁止GPG checking,只用於presentor latest
disablerepo 臨時禁止使用yum庫。 只用於安裝或更新時。
enablerepo 臨時使用的yum庫。只用於安裝或更新時。
skip_borken 跳過異常軟體節點
autoremove 當設定為yes且狀態為absent時,自動移除不再被任何已安裝包依賴的包。

9.2、安裝httpd服務

#給web_test組的所有主機安裝httpd服務
ansible web_test -m yum -a "name=httpd state=present"

#遠端啟動httpd服務
ansible web_test -m shell -a "systemctl start httpd"

#遠端檢視http服務程序
ansible web_test -m shell -a "ps aux | grep httpd"

#遠端停止httpd服務
ansible web_test -m shell -a "systemctl stop httpd"

#遠端解除安裝httpd服務
ansible web_test -m yum -a "name=httpd state=absent"
安裝
image-20240518102615952
檢視程序
image-20240518102905585
解除安裝
image-20240518102701842

9.3、更新所有的軟體包

#給所有主機更新所有的軟體包
ansible all-servers -m yum -a "name=* state=latest"

image-20240518110821977

10、cron模組

用於新增、刪除、更新作業系統的Crontab計劃任務

10.1、選項及描述

ansible-doc -s cron
選項 描述
backup 如果設定,會在修改crontab前建立備份。備份檔案的位置透過backup_file變數返回。
cron_file 如果指定,將使用此檔案而非使用者個人的crontab。如果是相對路徑,則相對於/etc/cron.d/。絕對路徑通常為/etc/crontab。為了使用cron_file引數,必須同時指定user
day 任務應執行的月份中的日期 (1-31, *, */2, 等)。
disabled 如果任務應在crontab中被禁用(註釋掉)。僅當state=present時有效。
env 如果設定,管理crontab的環境變數。新變數會被新增到crontab的頂部。namevalue引數分別為環境變數的名稱和值。
hour 任務應執行的小時 (0-23, *, */2, 等)。
insertafter state=presentenv一起使用。如果指定,環境變數將在指定環境變數宣告之後插入。
insertbefore state=presentenv一起使用。如果指定,環境變數將在指定環境變數宣告之前插入。
job 要執行的命令,或者如果設定了env,則是環境變數的值。命令不應包含換行符。當state=present時必需。
minute 任務應執行的分鐘 (0-59, *, */2, 等)。
month 任務應執行的年份中的月份 (1-12, *, */2, 等)。
name crontab條目的描述,或者如果設定了env,則是環境變數的名稱。當state=absent時必需。注意,如果不設定name,且state=present,則總是會建立新的crontab條目,不管已有條目如何。此引數在未來的版本中將始終是必需的。
special_time 特殊的時間範圍,引數:reboot(重啟時),annually(每年),monthly(每月),weekly(每週),daily(每天),hourly(每小時)
state 確保任務或環境變數存在或不存在的狀態。
user 應修改其crontab的具體使用者。未設定時,預設為使用root
weekday 任務應執行的星期幾 (0-6 表示週日-週六,*, 等)。

10.2、新增計劃任務

#給mysql_test組中的所有主機新增一個以root使用者每天三點執行/root/aliyun.sh指令碼的計劃任務
ansible mysql_test -m cron -a "name='Daily Task' minute=0 hour=3 job='/root/aliyun.sh &> /dev/null' user=root"

image-20240518162626709

10.3、刪除指定計劃任務

#刪除名為Daily Task的計劃任務(沒有明確的計劃任務名稱寫完整的計劃任務也可以刪除)
ansible mysql_test -m cron -a "name='Daily Task' state=absent"

image-20240518163214996

11、service模組

Ansible的service模組用於管理系統服務(如啟動、停止、重啟服務等)。

這個模組與特定的系統服務管理工具(如systemd、sysvinit、upstart等)相容,能夠跨不同的Linux發行版和系統管理框架工作

11.1、選項及描述

ansible-doc -s service
選項 描述
arguments 額外的命令列引數,提供給服務管理命令。
enabled 服務是否應該在系統啟動時自動啟動。至少需要指定stateenabled中的一個。
name (必需)服務的名稱。
pattern 如果服務不響應狀態查詢命令,可以指定一個子字串作為查詢依據,該子字串應能在ps命令的輸出中找到,作為服務狀態的替代判斷。如果找到該字串,服務將被認為已啟動。
runlevel 僅針對OpenRC初始化指令碼(如Gentoo)使用。指定該服務屬於哪個執行級別。
sleep 當服務處於restarted狀態時,停止與啟動命令之間暫停的秒數。有助於解決那些在發出停止訊號後立即退出的不良行為初始化指令碼問題。並非所有服務管理器都支援此設定,例如使用systemd時,此設定會被忽略。
state 有四種狀態,分別為:started--->啟動服務, stopped--->停止服務, restarted--->重啟服務, reloaded--->過載配置
use 服務模組通常透過自動檢測使用系統特定的模組,此設定可以強制使用特定模組。預設情況下,它使用ansible_service_mgr事實的值,並且在找不到匹配項時回退到舊的service模組。

11.2、遠端開啟/關閉防火牆

#給web_test組中的所有主機重啟firewalld服務
ansible web_test -m service -a "name=firewalld state=restarted"

#檢視web_test組中所有主機的firewalld服務執行狀態
ansible web_test -m shell -a "systemctl status firewalld"

#給web_test組中的所有主機關閉firewalld服務
ansible web_test -m service -a "name=firewalld state=stopped"
開啟firewalld服務
image-20240518165922943
檢視firewalld服務狀態
image-20240518170027529
關閉firewalld服務
image-20240518170142857

12、script模組

Ansible的script模組允許你在遠端主機上執行位於Ansible控制節點上的本地指令碼

12.1、選項及描述

ansible-doc -s script
選項 描述
chdir 在遠端節點上執行指令碼之前切換到的目錄路徑。
cmd 要在遠端節點上執行的本地指令碼的路徑,後面可以跟上可選的引數。注意,這個選項與free_form二選一使用。
creates 指定遠端節點上的一個檔名,如果該檔案已存在,則此步驟將執行,可用於防止重複執行指令碼。
decrypt 控制是否自動解密使用Vault加密的原始檔。
executable 用於呼叫指令碼的可執行檔案的名稱或路徑,例如如果指令碼是Python指令碼,可以設定為/usr/bin/python
free_form 直接提供本地指令碼檔案的路徑以及可選的引數,與cmd選項作用相似但格式不同,兩者選其一使用。
removes 指定遠端節點上的一個檔名,如果該檔案不存在,則此步驟將執行,可以作為執行指令碼的另一個條件。

12.2、編輯並部署指令碼

1、控制節點本地編輯指令碼並新增執行許可權
vim /tmp/df.sh

#!/bin/bash
date >> /tmp/data/df.log
df -lh >> /tmp/data/df.log
[root@server ~]# chmod +x /tmp/df.sh

image-20240518173032713

2、透過script模組部署到遠端主機執行
#給web_test組的所有主機執行控制節點上的df.sh指令碼檔案
ansible web_test -m script -a "/tmp/df.sh”

image-20240518173943581

13、setup模組

Ansible的setup模組用於收集遠端主機的資訊,並將這些資訊以facts的形式返回給Ansible控制節點。

這些facts可以包括系統變數(如作業系統型別、架構、網路配置、已安裝軟體包等),並且在Playbook執行期間可以被其他任務使用。

13.1、選項及描述

ansible-doc -s setup
選項 描述
fact_path 用於存放本地Ansible事實(*.fact檔案)的路徑。此目錄下的檔案如果可執行,將被執行,其結果會被新增到ansible_local事實中;如果檔案不可執行,則會被讀取。適用於從2.1版本開始。檔案/結果格式可以是JSON或INI格式。預設的fact_path可以在ansible.cfg中為自動呼叫setup作為gather_facts一部分時指定。Windows環境下有特定選項,請檢視註釋。
filter 如果提供,僅返回匹配此shell風格(fnmatch萬用字元)的變數。這允許篩選出特定的facts進行檢視或使用。
gather_subset 如果提供,限制收集的額外事實子集。可能的值包括:all(全部)、min(最小集合)、hardware(硬體資訊)、network(網路資訊)、virtual(虛擬化資訊)、ohai(類似Chef Ohai的擴充套件資訊)、facter(使用Facter收集的資訊)。可以指定值的列表來定義更大的子集。值前可加!來排除特定子集的收集,例如:!hardware,!network,!virtual,!ohai,!facter。如果指定!all,則只收集最小集合。要避免收集最小集合,可以指定!all,!min。要僅收集特定事實,使用!all,!min並指定特定的事實子集。如果只想隱藏某些收集到的事實,使用filter引數。
gather_timeout 設定單個事實收集的預設超時時間(以秒為單位)。這有助於控制事實收集過程,避免因個別慢速收集導致整個任務超時。

13.2、檢視記憶體資訊

#檢視mysql_test組所有主機的記憶體資訊
ansible mysql_test -m setup -a "filter='*mem*'"

image-20240518180334853

透過free -m命令檢視記憶體大小是否一致
#透過free -m命令檢視mysql_test組主機的記憶體資訊
ansible mysql_test -m shell -a "free -m"

image-20240518180649443

13.3、儲存資訊

#將篩選的資訊儲存到控制節點的/tmp/data目錄下
ansible web -m setup -a 'filter="*mem*"' --tree /tmp/data

image-20240518181607518

14、synchronize模組

Ansible的synchronize模組提供了使用rsync進行檔案和目錄同步的功能。

rsync是一個快速且高效的檔案傳輸工具,支援增量更新,特別適合在遠端主機之間同步大量檔案或保持資料夾內容的一致性。

14.1、選項及描述

ansible-doc synchronize
選項 描述
archive 映象rsync的歸檔標誌,啟用遞迴、連結、許可權、時間戳、所有者、組標誌及-D。預設開啟。
checksum 基於校驗和而非修改時間和大小來跳過同步,注意“archive”選項預設仍啟用,"checksum"選項不會禁用它。預設關閉。從1.6版本起可用。
compress 在傳輸過程中壓縮檔案資料。大多數情況下應保持啟用狀態,除非引起問題。預設開啟。從1.7版本起可用。
copy_links 將符號連結作為它們指向的物件(被連結項)複製,而不是複製符號連結本身。預設關閉。
delete 刪除目標路徑中不存在於源路徑的檔案(在傳輸之後,不是之前)。此選項要求recursive=yes。表現得像rsync的--delete-excluded選項,忽略被排除的檔案。預設關閉。
dest 同步的目的地主機路徑,將從源路徑同步而來。路徑可以是絕對或相對的。此選項是必須的。
dest_port 目標主機SSH埠。在Ansible 2.0之前,ansible_ssh_port庫存變數優先於這個值。此引數預設為ansible_ssh_portansible_port的值、remote_port配置設定的值,或如果沒有設定前者,則使用SSH客戶端配置的值。從1.5版本起可用。
dirs 僅傳輸目錄而不遞迴進入。預設關閉。
existing_only 跳過在接收端建立新檔案。預設關閉。從1.5版本起可用。
group 保留組資訊。預設值取決於archive選項。
link_dest 新增一個硬連結目標,在rsync期間與之關聯。預設為無。從2.5版本起可用。
links 作為符號連結複製符號連結。預設值取決於archive選項。
mode 指定同步的方向。推模式下,本地主機或代理是源;拉模式下,上下文中的遠端主機是源。(可選值:pull, push)預設為push。
owner 保留所有者(僅超級使用者)。預設值取決於archive選項。
partial 告訴rsync保留部分檔案,這應該會使後續傳輸檔案剩餘部分快得多。預設關閉。從2.0版本起可用。
perms 保留許可權資訊。預設值取決於archive選項。
private_key 為基於SSH的rsync連線指定私鑰(如~/.ssh/id_rsa)。預設為無。從1.6版本起可用。
recursive 遞迴進入目錄。預設值取決於archive選項。
rsync_opts 透過傳遞陣列來指定額外的rsync選項。注意,rsync_opts中的空字串最終會傳輸當前工作目錄。預設為無。從1.6版本起可用。
rsync_path 指定在遠端主機上執行的rsync命令。參見rsync手冊頁上的--rsync-path。要指定在本地主機上執行的rsync命令,你需要設定任務變數ansible_rsync_path。預設為無。
rsync_timeout 為rsync命令指定一個超時時間(秒)。預設為0。
set_remote_user 為遠端路徑新增user@。如果你有自定義的ssh配置來為與庫存使用者不匹配的主機定義遠端使用者,應將此引數設為no。預設為True。
src 源主機上的路徑,將同步到目的地。路徑可以是絕對或相對的。此選項是必須的。
times 保留修改時間。預設值取決於archive選項。
use_ssh_args 使用ansible.cfg中指定的ssh_args。預設關閉。從2.0版本起可用。
verify_host 驗證目標主機金鑰。預設關閉。從2.0版本起可用。

14.2、將源目錄同步至目標目錄(增量同步)

#既然是基於rsync那麼所有主機安裝rsync
ansible all-servers -m shell -a "yum install -y rsync"

#將本地的/tmp/目錄同步到node1組的host1主機上
ansible node1 -m synchronize -a "src=/tmp/ dest=/tmp/"

#檢視node1組的host1主機的/tmp/目錄結構
ansible node1 -m shell -a "tree -L 5 /tmp/"
所有主機安裝rsync
image-20240518202630013
同步本地/tmp/到host1主機上
image-20240518202725638
檢視目錄結構
image-20240518202919470

14.3、將源目錄同步至目標目錄(完全同步)

#刪除目標路徑中不存在於源路徑的檔案(在傳輸之後)
ansible node1 -m synchronize -a "src=/tmp/ dest=/tmp/ delete=yes"

五、Ansible playbook

1、簡介

Ansible Playbook 是Ansible用於定義和執行自動化任務的配置、部署和編排的主要方式。它是一種使用YAML語言編寫的劇本檔案,允許使用者以簡潔、可讀性強的方式描述一系列步驟,這些步驟可以跨多臺主機執行,以實現系統的配置管理和應用程式部署。

playbook是由一個或者多個play組成的列表,可以讓這些列表按事先編排的機制執行;所謂task是呼叫ansible的具體模組,在模組引數中可以使用變數。模組執行是冪等性的,意味著多次執行結果相同。使用yaml語言編寫playbook,字尾名一般為.yml

2、playbook的YAML格式

  • 檔案的第一行應該以 "---" (三個連字元)開始,表明YMAL檔案的開始。
  • 在同一行中,#之後的內容表示註釋,類似於shell,python和ruby。
  • YMAL中的列表元素以”-”開頭然後緊跟著一個空格,後面為元素內容。
  • 同一個列表中的元素應該保持相同的縮排。否則會被當做錯誤處理。
  • play中hosts,variables,roles,tasks等物件的表示方法都是鍵值中間以":"分隔表示,":"後面還要增加一個空格。
  • 縮排:使用空格縮排(而非Tab),通常使用2個空格

2.1、示例:

---
- name: update web servers
  hosts: node1
  remote_user: root

  tasks:
  - name: ensure apache is at the latest version
    yum:
      name: httpd
      state: latest
  - name: write the apache config file
    template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf
  - name: ensure that htppd is started
    service:
      name: httpd
      state: started
- name: update db servers
  hosts: node1
  remote_user: root

  tasks:
  - name: ensure mariadb is at the latest version
    yum:
      name: mariadb-server
      state: latest
  - name: ensure that mariadb is started
    service:
      name: mariadb
      state: started

2.2、解析

Play 1: 更新Web伺服器

  • Play標題:"update web servers",表明本Play的目標是更新Web伺服器配置。
  • hostsnode1,指定該Play作用於名為node1的主機。
  • remote_userroot,指定執行任務的遠端使用者為root。
  • tasks
    • task 1: 確保Apache是最新的版本。使用yum模組安裝httpd包至最新版。
    • task 2: 寫入Apache配置檔案。使用template模組將模板檔案/srv/httpd.j2渲染後複製到/etc/httpd.conf,允許動態配置生成。
    • task 3: 確保Apache服務已啟動。使用service模組設定httpd服務的狀態為started,如果服務未執行則啟動。

Play 2: 更新資料庫伺服器

  • Play標題:"update db servers",目標是更新資料庫伺服器配置。
  • hosts:同樣為node1,指定該Play作用於名為node1的主機。
  • remote_userroot,指定執行任務的遠端使用者為root。
  • tasks
    • task 1: 確保MariaDB是最新的版本。使用yum模組安裝mariadb-server至最新版。
    • task 2: 確保MariaDB服務已啟動。使用service模組設定mariadb服務的狀態為started

3、playbook的執行與語法檢查

#執行playbook
ansible-playbook playbook.yml

#語法檢查
ansible-playbook --syntax-check playbook.yml 

4、playbook的核心元素

  1. Hosts(主機組):定義了Playbook將要操作的目標機器集合。可以是單個主機名、IP地址,也可以是主機組名。
  2. Tasks(任務列表):構成Play的主要部分,定義了在目標主機上執行的具體操作序列。每個任務通常關聯一個特定的Ansible模組及引數。
  3. Variables(變數):用於在Playbook中傳遞和管理配置資訊,支援多種設定方式(如直接賦值、變數檔案、環境變數、角色預設變數等),增加了Playbook的靈活性和可重用性。
  4. Templates(模板):使用Jinja2模板引擎動態生成配置檔案。允許根據變數插入動態內容,適用於需要根據不同環境定製配置的情況。
  5. Handlers(處理程式):特殊型別的任務,僅當被其他任務透過notify屬性明確告知時才會執行。常用於服務重啟等需要在特定條件滿足時進行的操作。

5、基本元件及格式

  • remote_user:指定執行Ansible任務的遠端使用者名稱。

  • sudo_user:定義需要臨時提升許可權執行任務時的目標使用者。

  • Tasks格式

    tasks:
      - name: 簡短任務描述
        module: 模組名稱
        arguments: 引數列表
        notify: 通知的處理程式名稱(可選)
    
  • Handlers格式

    handlers:
      - name: 處理程式描述
        module: 模組名稱
        arguments: 引數列表
    
    • Handlers觸發條件
      • 當某任務狀態變為changed時,可以觸發一個或多個預先定義好的處理程式。
      • 使用tags為任務和處理程式打標籤,可以在執行Playbook時透過--tags-t選項選擇性地執行帶有特定標籤的任務。
  • 模組與模組引數:Ansible透過各種模組執行具體操作,模組後跟隨的是該模組接受的引數。對於shellcommand這類直接執行系統命令的模組,引數直接是命令字串,而不是鍵值對形式。

6、安裝nginx並修改配置檔案

6.1、準備檔案存放目錄

[root@server ~]# mkdir -p /root/ansible/{conf,bin}

6.2、編寫yaml檔案

[root@server ~]# cd ansible/bin/
[root@server bin]# cat nginx.yml

---
- name: Update web servers
  hosts: node1
  remote_user: root
  tasks:
  - name: Install epel
    yum:
      name: epel-release.noarch
      state: latest
  - name: Install nginx
    yum:
      name: nginx
      state: present
  - name: Copy nginx configure file
    copy:
      src: /root/ansible/conf/nginx.conf
      dest: /etc/nginx/nginx.conf
      backup: yes
  - name: Start nginx
    service:
      name: nginx
      state: restarted
  - name: Create index.html
    shell: echo "hello playbook_nginx" > /usr/share/nginx/html/index.html

6.3、編寫conf檔案

[root@server conf]# cat site.conf

events {
    worker_connections  1024;
}

http {
    server {
        listen 8080;
        server_name 192.168.112.20:8080;

        location / {
            index index.html;
        }
    }
}

6.4、檢查語法錯誤,執行playbook

#語法檢查
ansible-playbook nginx.yml --syntax-check

#執行playbook
ansible-playbook nginx.yml

image-20240519071818027

6.5、驗證nginx啟動狀態

#ps aux|grep nginx顯示nginx的程序,curl -s 檢視實際的響應體內容
ansible node2 -m shell -a "ps aux | grep nginx ; curl -s 192.168.112.30:8080"

image-20240519073818831

7、安裝nginx,並新增handlers和notify

7.1、修改對應的nginx.yml和nginx.conf檔案

nginx2.yml

---
- name: Update web servers
  hosts: node2
  remote_user: root
  tasks:
  - name: Install epel
    yum:
      name: epel-release.noarch
      state: latest
  - name: Install nginx
    yum:
      name: nginx
      state: present
  - name: Copy nginx configure file
    copy:
      src: /root/ansible/conf/nginx2.conf
      dest: /etc/nginx/nginx2.conf
      backup: yes
    notify: reload		#當nginx.conf發生改變時,通知給相應的handlers
    tags: reloadnginx		#打標籤
  - name: Start nginx
    service:
      name: nginx
      state: restarted
    tags: startnginx		#打標籤
  - name: Create index.html
    shell: echo "hello playbook_nginx_2" > /usr/share/nginx/html/index.html
  handlers:		#注意,前面沒有-,是兩個空格
    - name: reload
      service:
        name: nginx
        state: restarted

nginx2.conf

[root@server conf]# cat nginx2.conf

events {
    worker_connections  1024;
}

http {
    server {
        listen 8080;
        server_name 192.168.112.30:8080;

        location / {
            index index.html;
        }
    }
}

7.2、驗證nginx程序資訊

#驗證埠和響應內容
ansible node2 -m shell -a "ss -tunlp | grep nginx ; curl -s 192.168.112.30:8080"

image-20240519075156982

7.3、測試標籤

#先關閉node3上的nginx服務以便測試
ansible node3 -m shell -a "systemctl stop nginx"

#再執行劇本並引用標籤startnginx
ansible-playbook nginx2.yml -t startnginx

image-20240519000329240

7.4、測試notify

7.4.1、notify的觸發條件是配置檔案被改變
#修改監聽的埠號
[root@server conf]# cat nginx2.conf

events {
    worker_connections  1024;
}

http {
    server {
        listen 8848;
        server_name 192.168.112.30:8080;

        location / {
            index index.html;
        }
    }
}

image-20240519075419174

7.4.2、重新執行劇本
#語法檢查
ansible-playbook nginx2.yml --syntax-check

#再執行劇本並引用標籤reloadnginx
ansible-playbook nginx2.yml -t reloadnginx

image-20240519001410850

7.4.3、重新檢視埠號
ansible node2 -m shell -a "ss -tnulp | grep nginx"

image-20240519075549066

埠號變為8848

8、變數(variables)

在Ansible劇本中,vars 是用來定義變數的一個關鍵字,它允許你為任務、play或整個劇本設定變數值。

這些變數可以在後續的任務中被引用,以提高劇本的靈活性和重用性。

8.1、定義變數的方式

1. Facts(Facts變數)
  • 描述:Facts是Ansible自動收集的目標主機資訊,如系統型別、網路配置等。它們不是直接定義的變數,而是透過執行setup模組獲取的。儘管不能直接定義Facts,但它們可以在劇本中像其他變數一樣使用。

  • 使用方式

    - name: Display hostname using a fact
      debug:
        msg: "The hostname is {{ ansible_hostname }}"
    
  • 檢視所有可以使用的變數:

    ansible node1 -m setup > variables
    
2. 使用者自定義變數
  • 直接在Playbook中定義

    • 可以在play或tasks級別定義變數。

      - hosts: web_test
        vars:
          my_var: "Hello, World!"
        tasks:
        - name: Use playbook-defined variable
          debug:
            msg: "{{ my_var }}"
      
  • 透過命令列引數(-e/--extra-vars)傳入

    • 在執行Ansible命令時動態新增變數。

      ansible-playbook my_playbook.yml -e "my_var=ValueFromCommandLine"
      
3. 透過Roles傳遞變數
  • 簡介:Roles是Ansible組織和複用任務的一種方式。變數可以透過角色的defaults, vars, environment目錄下的檔案來定義,或者在角色的tasks/main.yml等檔案中直接定義。

    • 例子:

      • roles/my_role/defaults/main.yml中定義:

        my_role_variable: default_value
        
      • 然後在使用該角色的playbook中,該變數自動可用,也可被更高優先順序的變數覆蓋。

4. Host Inventory(主機清單)中定義變數
  • 向不同主機傳遞不同變數

    [webservers]
    host1.example.com my_var=value1
    host2.example.com my_var=value2
    
  • 向組中的所有主機傳遞相同變數

    [webservers:vars]
    group_variable=value_for_all_hosts_in_group
    

8.2、優先順序

  1. 透過命令列指定變數優先順序最高
  2. /etc/ansible/hosts定義變數(針對單個主機定義,針對主機組進行定義)
  3. playbook中定義的變數

8.3、案例:使用變數安裝keepalived

1、編寫劇本
#先複製一份
[root@server bin]# cp nginx2.yml keepalived.yml

#再透過vim的替換將nginx替換為變數並最佳化一下src地址
[root@server bin]# cat keepalived.yml

---
- name: Update web servers
  hosts: node2
  remote_user: root
  tasks:
  - name: Install epel
    yum:
      name: epel-release.noarch
      state: latest
  - name: Install {{ rpmname }}
    yum:
      name: "{{ rpmname }}"
      state: present
  - name: Copy {{ rpmname }} configure file
    copy:
      src: /root/ansible/conf/{{ rpmname }}.conf
      dest: /etc/{{ rpmname }}/{{ rpmname }}.conf
      backup: yes
    notify: reload
    tags: reload{{ rpmname }}
  - name: Start {{ rpmname }}
    service:
      name: "{{ rpmname }}"
      state: restarted
    tags: start{{ rpmname }}
  handlers:
    - name: reload
      service:
        name: "{{ rpmname }}"
        state: restarted
全域性替換並新增確認動作
image-20240519085826481
輸入y確認替換
image-20240519085933294
替換好的劇本
image-20240519091914865
2、複製配置檔案

我們想要在被監管的機器上安裝什麼服務的話,就直接在我們的server端上把該服務的配置檔案複製到我們定義劇本的src目錄下。這樣我們的劇本才能正常執行。

cp /etc/keepalived/keepalived.conf /root/ansible/conf/keepalived.conf
3、執行劇本,變數由命令列傳入
#語法檢查
ansible-playbook keepalived.yml --syntax-check

#執行劇本-e 接變數
ansible-playbook keepalived.yml -e rpmname=keepalived

image-20240519093852380

4、或者直接再劇本里定義變數

我們可以直接在劇本中把變數定義好,這樣就不需要在透過命令列傳入了。

以後想要安裝不同的服務,直接在劇本里把變數修改一下即可。

[root@server bin]# vim keepalived.yml

---
- name: Update web servers
  hosts: node2
  remote_user: root
  vars:
    - rpmname: keepalived
  tasks:
  - name: Install epel
    yum:
      name: epel-release.noarch
      state: latest
  - name: Install {{ rpmname }}
    yum:
      name: "{{ rpmname }}"
      state: present
  - name: Copy {{ rpmname }} configure file
    copy:
      src: /root/ansible/conf/{{ rpmname }}.conf
      dest: /etc/{{ rpmname }}/{{ rpmname }}.conf
      backup: yes
    notify: reload
    tags: reload{{ rpmname }}
  - name: Start {{ rpmname }}
    service:
      name: "{{ rpmname }}"
      state: restarted
    tags: start{{ rpmname }}
  handlers:
    - name: reload
      service:
        name: "{{ rpmname }}"
        state: restarted
5、執行定義過變數的劇本
#語法檢查
ansible-playbook keepalived.yml --syntax-check

#執行劇本
ansible-playbook keepalived.yml

image-20240519094357159

9、模板(templates)

9.1、簡介

Templates主要用於自動生成和管理伺服器上的配置檔案,如nginx的配置、資料庫配置等。這有助於實現基礎設施的配置標準化和自動化。

  • 文字檔案,內部巢狀有模板語言的指令碼
  • jinja2是由python編寫的,在使用模板檔案時jinja2是很好的解決方案
  • 功能:將模板檔案中的變數轉換成對應的本地主機的確定值\

9.2、基本資料型別和運算子

  • 字串:在Jinja2模板中,無論是單引號還是雙引號,都可以用來定義字串。例如,{{ "Hello, World!" }}{{ 'Hello, World!' }}
  • 數字:Jinja2直接支援整數和浮點數的使用,無需特別的標記,如 {{ 42 }}{{ 3.14 }}
  • 列表(List)元組(Tuple):雖然Jinja2原生支援列表(使用方括號[]),但元組的直接表示不如Python中常見,因為模板更傾向於動態輸出而不是靜態結構。列表示例:{% for item in [1, 2, 3] %}...{% endfor %}
  • 字典(Dictionary):與Python類似,使用花括號{}定義,鍵值對之間用冒號:分隔。例如,{{ {"key": "value", "another_key": 42} }}
  • 布林型(Booleans):在Jinja2中,可以直接使用truefalse(全部小寫),用於條件判斷。
  • 算術運算:Jinja2支援所有基本的算術運算子,包括+, -, *, /, //, %, **。例如,{{ 5 + 3 }}{{ 10 // 2 }}
  • 比較操作:與Python相同,包括==, !=, >, >=, <, <=。用於條件判斷,如{% if variable > 10 %}...{% endif %}
  • 邏輯運算and, or, not用於邏輯條件組合。例如,{% if condition1 and condition2 %}...{% endif %}{% if not condition %}...{% endif %}

模板都是透過引用變數來引用的

9.3、案例:生成hosts解析檔案

使用模板替遠端主機生成hosts解析檔案(先把原來的hosts解析都去掉,在ansible配置檔案裡面替換為ip)

1、修改Ansible主機清單
[root@server1 ~]# egrep -v "^$|^#" /etc/ansible/hosts
[all-servers]
server1
server2
server3
server4
[all_ip]
192.168.112.10
192.168.112.20
192.168.112.30
192.168.112.40
2、修改主機名
hostnamectl set-hostname server1
hostnamectl set-hostname server2
hostnamectl set-hostname server3
hostnamectl set-hostname server4
3、準備模板檔案
[root@server1 ~]# vim hosts.j2

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

{% for host in groups.all_ip %}
{{hostvars[host].ansible_ens33.ipv4.address}} {{hostvars[host].ansible_hostname}}
{% endfor %}
4、編寫劇本
[root@server1 ~]# vim hosts.yml

---
- name: Config hosts file
  hosts: all_ip
  remote_user: root

  tasks:
  - name: copy hosts.j2 to group servers
    template:
      src: hosts.j2
      dest: /etc/hosts
5、執行劇本
ansible-playbook hosts.yml --syntax-check
ansible-playbook hosts.yml

image-20240519103229272

6、驗證
ansible all-servers -m shell -a "tail -4 /etc/hosts"

image-20240519104459086

10、條件判斷

when語句:在task中使用,jinja2的語法格式。

10.1、舉例

tasks:
- name: install conf file to centos7
  template: src=files/nginx.conf.c7.j2
  when: ansible_distribution_major_version == "7"
- name: install conf file to centos6
  template: src=files/nginx.conf.c6.j2
  when: ansible_distribution_major_version == "6"

11、迴圈迭代

迴圈:迭代,需要重複執行的任務;
對迭代項的引用,固定變數名為"item",而後,要在task中使用with_items給定要迭代的元素列表;

11.1舉例

#基於字串列表
tasks:
‐ name: create rsyncd file
  copy: src={{ item }} dest=/tmp/{{ item }}
  with_items:
    ‐ a
    ‐ b
    ‐ c
    ‐ d
*with_itmes 巢狀子變數*
#基於字典列表
‐ hosts: eagleslab
  remote_user: root
  tasks:
  ‐ name: add several users
    user: name={{ item.name }} state=present groups={{ item.groups }}
    with_items:
      ‐ { name: 'testuser1' , groups: 'wheel'}
      ‐ { name: 'testuser2' , groups: 'root' }

11.2、案例:迴圈建立使用者

1、迴圈建立以下使用者資訊
zhangsan xsb /home/xsb/zhangsan /bin/bash 銷售
lisi xsb /home/xsb/lisi /bin/bash 銷售
wangwu jsb /home/jsb/wangwu /bin/sh java工程師
maliu jsb /home/jsb/maliu /bin/sh linux工程師
zhaoqi cwb /home/cwb/zhaoqi /bin/sh 會計
2、迴圈建立出以上使用者並指定使用者資訊
[root@server1 ~]# vim user_manage.yml

---
- name: Manage user
  hosts: all-servers
  remote_user: root
  tasks:
  - name: ensure group xsb/jsb/cwb exists
    group:
      name={{ item.group }}
    with_items:
      - { group: 'xsb' }
      - { group: 'cwb' }
      - { group: 'jsb' }
  - name: create users zhangsan/lisi/wangwu/maliu/zhaoqi
    user:
      name={{ item.name }}
      group={{ item.group }}
      shell={{ item.shell }}
      comment={{ item.comment }}
      home={{ item.home }}
    with_items:
      - { name: 'zhangsan', group: 'xsb',home: '/home/xsb/zhangsan',shell: '/bin/bash',comment: '銷售'}
      - { name: 'lisi', group: 'xsb',home: '/home/xsb/zhangsan',shell: '/bin/bash',comment: '銷售'}
      - { name: 'wangwu', group: 'jsb',home: '/home/jsb/wangwu',shell: '/bin/sh',comment: 'java工程師'}
      - { name: 'maliu', group: 'jsb',home: '/home/jsb/maliu',shell: '/bin/sh',comment: 'linux工程師'}
      - { name: 'zhaoqi', group: 'cwb',home: '/home/cwb/zhaoqi',shell: '/bin/sh',comment: '會計'}
3、執行劇本
#語法檢查
ansible-playbook user_manage.yml --syntax-check

#執行劇本
ansible-playbook user_manage.yml

image-20240519151508668

4、驗證
ansible all-servers -m shell -a "id zhangsan ; id lisi ; id wangwu ; id maliu ; id zhaoqi"

image-20240519152054284

12、字典

ansible playbook 還支援字典這種資料型別

12.1、舉例

- name: install some packages
  yum: name={{ item }} state=present
  with_items:
    - nginx
    - memcached
    - php-fpm
- name: add some groups
  group: name={{ item }} state=present
  with_items:
    - group11
    - group12
    - group13
- name: add some users
  user: name={{ item.name }} group={{ item.group }} state=present
  with_items:
    - { name: 'user11', group: 'group11' }
    - { name: 'user12', group: 'group12' }
    - { name: 'user13', group: 'group13' }

13、角色(role)

13.1、簡介

Ansible的角色(Roles)是用於組織和複用配置任務的一種方式,它提供了一種結構化的方法來編寫和管理Playbooks,使得大型專案和重複使用的配置任務變得更加易於管理和維護。

角色設計的初衷是為了促進Playbooks的層次化和模組化,使得不同功能元件能夠清晰分離。

13.2、角色的目錄結構

角色集合:roles/

  • mysql/
  • httpd/
  • nginx/
    • files/:儲存由copy或script等模組呼叫的檔案;
    • tasks/:此目錄中至少應該有一個名為main.yml的檔案,用於定義各task;其它的檔案需要由main.yml進行“包含”呼叫;、
    • handlers/:此目錄中至少應該有一個名為main.yml的檔案,用於定義各handler;其它的檔案需要由main.yml進行“包含”呼叫;
    • vars/:此目錄中至少應該有一個名為main.yml的檔案,用於定義各variable;其它的檔案需要由main.yml進行“包含”呼叫;
    • templates/:儲存由template模組呼叫的模板文字;
    • meta/:此目錄中至少應該有一個名為main.yml的檔案,定義當前角色的特殊設定及其依賴關係;其它的檔案需要由main.yml進行“包含”呼叫;
    • default/:此目錄中至少應該有一個名為main.yml的檔案,用於設定預設變數;

14、案例:使用角色安裝nginx

14.1、建立對應的目錄結構

[root@server1 ~]# cd /etc/ansible/roles/
[root@server1 roles]# ls
[root@server1 roles]# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}

image-20240519155820069

14.2、定義配置檔案

需要修改的配置檔案為/tasks/main.yml

[root@server1 roles]# cat /etc/ansible/roles/nginx/tasks/main.yml

---
- name: cp
  copy: src=nginx-1.10.2-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm
- name: install
  yum: name=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm state=present
- name: conf
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
  tags: nginxconf
  notify: new conf to reload
- name: start service
  service: name=nginx state=started enabled=true

14.3、放置檔案到指定目錄

rpm包

#rpm包放在files目錄下
cp /tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm /etc/ansible/roles/nginx/files/

#模板放在templates目錄下
cp /tmp/nginx.conf.j2 /etc/ansible/roles/nginx/templates/

#檢視目錄結構
[root@server1 nginx]# tree

image-20240519162239997

14.4、修改變數檔案

[root@server1 nginx]# cat /etc/ansible/roles/nginx/vars/main.yml
nginxport: 6666

14.5、定義handlers檔案

[root@server1 nginx]# cat /etc/ansible/roles/nginx/handlers/main.yml
---
- name: new conf to reload
  service: name=nginx state=restarted

14.6定義劇本檔案

[root@server1 ansible]# cat /etc/ansible/roles.yml
---
- hosts: all-servers
  remote_user: root
  roles:
    - nginx

14.7、剩餘的配置檔案

  • nginx.conf.j2
events {
    worker_connections  1024;
}

http {
    server {
        listen   {{ nginxport }};
        }
}

14.8、啟動服務

#語法檢查
ansible-playbook roles.yml --syntax-check

#執行劇本
ansible-playbook roles.yml

image-20240519165513040

14.9、驗證埠號

ansible all-servers -m shell -a "ss -tunlp | grep nginx"

image-20240519165645659

15、案例:使用角色安裝httpd

15.1、建立對應的目錄結構

[root@server1 ~]# cd /etc/ansible/roles/
[root@server1 roles]# ls
[root@server1 roles]# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
#建立一個名為apache的新角色
[root@server1 roles]# ansible-galaxy init apache
- Role apache was created successfully

image-20240519172738160

15.2、編寫site.yaml檔案

[root@server1 roles]# cat /etc/ansible/roles/site.yml

---
- hosts: all-servers
  remote_user: root
  roles:
  - apache

15.3、編寫tasks裡的main.yml檔案

[root@server1 roles]# cat /etc/ansible/roles/apache/tasks/main.yml
---
- name: Install httpd
  yum:
    name: httpd
    state: present
- name: Start httpd
  service:
    name: httpd
    state: restarted
- name: Write index file
  shell: echo "http" > /var/www/html/index.html

15.4、執行劇本

#語法驗證
ansible-playbook site.yml --syntax-check

#執行劇本
ansible-playbook site.yml

image-20240519173423259

15.5、驗證

ansible all-servers -m shell -a "curl -s server1 ; curl -s server2 ; curl -s server3 ; curl -s server4"

image-20240519173703371

16、案例:使用角色安裝java+nginx+halo

16.1、準備角色

[root@server1 roles]# ansible-galaxy init halo
- Role halo was created successfully
[root@server1 roles]# ansible-galaxy init java
- Role java was created successfully
[root@server1 roles]# ansible-galaxy init nginx
- Role nginx was created successfully

image-20240519173958985

16.2、編寫site.yml

  • pre_tasks為執行play之前執行的任務
  • post_tasks為執行play之後執行的任務
[root@server1 roles]# cat site.yml

---
- hosts: node1
  remote_user: root
  strategy: free
  pre_tasks:
    - name: config nginx repo for centos 7
      yum_repository:
        name: nginx
        description: nginx
        baseurl: http://nginx.org/packages/centos/$releasever/$basearch/
        gpgcheck: no
      when: ansible_distribution_major_version == "7"
    - name: Disable SELinux
      selinux: state=disabled

  roles:
    - nginx

  post_tasks:
    - shell: echo 'Deplay halo finished.'
      register: ret
    - debug: var=ret.stdout

16.3、編寫nginx角色

nginx/tasks/main.yml

[root@server1 roles]# cat nginx/tasks/main.yml
---
# tasks file for nginx
- name: make sure nginx state is installed
  yum: name=nginx state=installed
- name: copy halo to nginx config file
  template: src=halo.conf dest="/etc/nginx/conf.d/halo.conf"
- name: make sure nginx service is running
  service: name=nginx state=started
- name: make sure port is open
  wait_for: port="{{ nginx_port }}"

meta/main.yml為role的依賴關係,要先執行這裡面的內容才會執行自己的nginx這個role。

[root@server1 roles]# cat nginx/meta/main.yml	#要修改的是dependencies部分

dependencies:
  - role: java
  - role: halo

nginx/templates/halo.conf

[root@server1 roles]# cat nginx/templates/halo.conf
upstream halo {
  server 127.0.0.1:8090;
}
server {
  listen 80;
  listen [::]:80;
  server_name {{ halo_domain }};
  client_max_body_size 1024m;
  location / {
    proxy_pass http://halo;
    proxy_set_header HOST $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

16.4、編寫java角色

為了安裝java

[root@server1 roles]# cat java/tasks/main.yml

---
# tasks file for java
- name: install java
  yum: name=java-11-openjdk state=installed

16.5、編寫halo角色

[root@server1 roles]# cat halo/tasks/main.yml

---
# tasks file for halo
- name: get halo
  get_url: url=https://dl.halo.run/release/halo-1.4.11.jar dest={{ halopath }}

- name: add halo service file
  template: src=halo.service dest=/etc/systemd/system/halo.service

- name: touch ~/.halo directory
  file: path=~/.halo state=directory

- name: copy halo config file
  template: src=application.yaml dest="~/.halo/application.yaml"

- name: restart halo
  systemd:
    daemon_reload: yes
    name: halo
    state: started
    enabled: yes

- name: wait to start halo
  wait_for: port={{ halo_port }}

修改變數檔案halo/vars/main.yml

[root@server1 roles]# cat halo/vars/main.yml

---
# vars file for halo
memory: 512m
halo_port: 8090
halopath: /root/halo.jar
halo_domain: 192.168.112.10
nginx_port: 80

下載servers檔案並編輯

[root@server1 roles]# wget https://dl.halo.run/config/halo.service -O halo/templates/halo.service

[root@server1 roles]# cat halo/templates/halo.service
[Unit]
Description=Halo Service
Documentation=https://docs.halo.run
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=root		#修改
ExecStart=/usr/bin/java -server -Xms256m -Xmx256m -jar /root/halo.jar		#修改
ExecStop=/bin/kill -s QUIT $MAINPID
Restart=always
StandOutput=syslog

StandError=inherit

[Install]
WantedBy=multi-user.target

[root@server1 roles]# wget https://dl.halo.run/config/application-template.yaml -O halo/templates/application.yaml

16.6、執行劇本

#語法檢查
ansible-playbook site.yml --syntax-check

#執行劇本
ansible-playbook site.yml

image-20240519181906858

16.7、驗證

透過IP+埠訪問

192.168.112.10:8090

image-20240519182050796

至此ansible的學習就告一段落啦

相關文章