1. 程式人生 > 實用技巧 >記錄:部署Ansible,Ansible ad-hoc應用(123)

記錄:部署Ansible,Ansible ad-hoc應用(123)

1 案例1:部署Ansible

1.1 問題

本案例要求先快速搭建好一個Ansible平臺,並測試環境,要求如下:

  • 建立實驗主機(控制端和被控制端)
  • 配置SSH實驗環境
  • 安裝Ansible自動化軟體
  • 修改Ansible配置

1.2 方案

準備如表-1所示的實驗環境,作業系統為RHEL8,配置主機名稱、IP地址、YUM源。

ansible原理:

控制端主機自帶很多模組(模組就是指令碼);

ansible通過ssh遠端被管理主機,將控制端的模組(指令碼)或命令傳輸到被管理主機;

在被管理端主機執行模組(指令碼)或命令,執行不同的模組或命令可以實現不同的功能;

最後ansible退出ssh遠端。

絕大多數模組(指令碼)都需要引數才能執行成功!!!類似於shell指令碼的位置變數!

拓撲結構如圖-1所示。

提醒:全天的實驗不需要死記硬背每個模組的每個引數,所有引數都可以檢視幫助!

1.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:準備基礎環境

控制節點要求:

  • 域名解析(為了方便後期操作,可以不做)
  • 配置SSH金鑰(ansible是基於ssh實現遠端控制)
  • 安裝Ansible軟體

1)Control控制節點

修改/etc/hosts,在檔案中手動新增如下內容,修改該檔案的目的是做域名解析。

[root@control ~]# vim  /etc/hosts        #修改檔案,手動新增如下內容(不要刪除檔案原來的內容)
192.168.4.253 control 192.168.4.11 node1 192.168.4.12 node2 192.168.4.13 node3 192.168.4.14 node4 192.168.4.15 node5

如何驗證?

[root@control ~]# ping  node1               #可以使用ping命令依次ping所有域名 

配置SSH金鑰實現免密碼登入(非常重要)

Ansible是基於SSH遠端的原理實現遠端控制,如果控制端主機無法免密登入被管理端主機,後續的所有試驗都會失敗!!

[root@control ~]#  ssh-keygen  -f  /root/.ssh/id_rsa   -N  ''       #生成ssh金鑰
#-f指定金鑰檔案存放在哪個目錄,檔案叫什麼名字,-N ''設定金鑰的密碼為空
[root@control ~]#  for i in node1 node2 node3 node4 node5
do
ssh-copy-id   $i 
done
#拷貝金鑰到遠端主機
#提示:拷貝金鑰到遠端主機時需要輸入對方電腦的賬戶密碼才可以!!
#拷貝金鑰到node1就需要輸入node1對應賬戶的密碼,拷貝金鑰到node2就需要輸入node2對應的密碼

如何驗證?

警告:如果有任何一臺主機遠端還需要密碼,就不要往下繼續操作,後面實驗都會失敗!!!

[root@control ~]# ssh  node1            #使用ssh命令依次遠端所有主機都可以免密碼登入

2)部署Ansible軟體(僅Control主機操作,軟體包在ansible_soft目錄)。

[root@control ~]# tar -xf   ansible_soft.tar.gz
[root@control ~]# cd ansible_soft
[root@control ansible_soft]# dnf  -y  install   *

被控制節點要求:

  • Ansible預設通過SSH協議管理機器
  • 被管理主機要開啟SSH服務,並允許控制主機登入
  • 被管理主機需要安裝有Python

步驟二:修改配置檔案

主配置檔案說明:

主配置檔案ansible.cfg(主配置檔案的內容可以參考/etc/ansible/ansible.cfg)

ansible配置檔案查詢順序

首先檢測ANSIBLE_CONFIG變數定義的配置檔案(預設沒有這個變數)

其次檢查當前目錄下的./ansible.cfg檔案

再次檢查當前使用者家目錄下~/ansible.cfg檔案

最後檢查/etc/ansible/ansible.cfg檔案

1) 修改主配置檔案。

[root@control ~]# mkdir  ~/ansible
[root@control ~]# vim  ~/ansible/ansible.cfg
[defaults]
inventory = ~/ansible/inventory            
#主機清單配置檔案(inventory可以是任意檔名),英語詞彙:inventory(清單、財產清單)
#forks = 5                                    #ssh併發數量
#ask_pass = True                             #使用金鑰還是密碼遠端,True代表使用密碼
#host_key_checking = False                  #是否校驗金鑰(第一次ssh時是否提示yes/no)

2) 修改主機清單檔案(清單檔名必須與主配置檔案inventory定義的一致)。

[root@control ~]# vim  ~/ansible/inventory
[test]                    #定義主機組(組名稱任意)
node1                    #定義組中的具體主機,組中包括一臺主機node1
[proxy]                    #定義主機組(組名稱任意),英語詞彙:proxy(代理人,委託人)
node2                      #proxy組中包括一臺主機node2
[webserver]
node[3:4]                 #這裡的node[3:4]等同於node3和node4
[database]
node5
[cluster:children]        #巢狀組(children為關鍵字),不需要也可以不建立巢狀組
webserver                  #巢狀組可以在組中包含其他組
database

2 案例2:Ansible ad-hoc應用一

2.1 問題

沿用練習一,練習Ansible ad-hoc具體應用,要求如下:

  • 測試主機列表中的主機是否可以ping通
  • 檢視被管理主機的伺服器資訊(如時間、版本、記憶體等)
  • 學習ansible-doc命令的用法
  • 測試command與shell模組的區別
  • 使用script模組在遠端主機執行指令碼(裝軟體包、啟服務)

2.2 方案

Ansible ad-hoc是一種通過命令列批量管理的方式,命令基本格式如下:

格式:ansible 主機集合 -m 模組名 -a "引數"

2.3 步驟

實現此案例需要按照如下步驟進行。

步驟一:測試環境

1)檢視主機列表

[root@control ~]# cd  ~/ansible                            #非常重要
[root@control ansible]# ansible  all  --list-hosts           #檢視所有主機列表
# --list-hosts是ansible這個命令的固定選項,如同ls -a一樣(-a是ls命令的固定選項)
#英語詞彙:list(列表,清單)、host(主機、主辦、主人)

2) 測試遠端主機是否能ping通。

當需要遠端多個主機或者多個組時,中間使用逗號分隔!!!

[root@control ansible]# ansible  node1  -m  ping              #呼叫ping模組
[root@control ansible]# ansible  node1,webserver  -m  ping

常見報錯(有問題可以參考,沒問題可以忽略):

node1 | UNREACHABLE! => {
"changed": false, 
"msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", 
"unreachable": true
}
問題分析:
英語詞彙:Failed(失敗),connect(連線),to(到),host(主機),via(通過)
permission(許可權),denied(被拒絕)
Failed to connect to host via ssh(通過ssh遠端連線到主機失敗)
Permission denied(因為無法連線,所以報錯說許可權被拒絕)
解決辦法:手動ssh其他主機(如node1),看看是否可以實現免密碼登入。
          Ansible的原理是基於ssh遠端管理,如果無法實現免密碼登入,後面的實驗無法成功!
        如何實現免密碼登入,可以參考案例上面的命令,或者第一階段知識。

提示:該模組雖然叫ping,但是它不會發送任何ICMP協議的ping資料包,控制端主機僅僅是ssh遠端被管理端主機,檢查其是否有python環境,能順利遠端並且有Python環境就會返回正確的提示資訊,否則報錯。拓撲如圖-2所示。

3)快速入門。

模組就是指令碼(多數為Python指令碼),多數指令碼都支援引數,預設模組為command。

[root@control ansible]# ansible  node1  -m  command  -a   "uptime"     #檢視CPU負載
[root@control ansible]# ansible  node1  -m command -a  "uname -r"      #檢視核心版本
[root@control ansible]# ansible  node1   -a   "ip a s"                  #檢視網絡卡資訊
[root@control ansible]# ansible  all   -a   "date"                      #檢視時間

拓撲如圖-3所示。

通過ansible-doc獲取幫助。

[root@control ansible]# ansible-doc  -l                      #列出所有模組
[root@control ansible]# ansible-doc -l | grep yum            #在所有模組中過濾關鍵詞
[root@control ansible]# ansible-doc yum                         #檢視模組幫助

4)Shell模組。

command和shell模組的區別,command不支援bash的特性(bash有哪些特性可以參考Shell課程第一天的PPT),如管道和重定向等功能,但是shell模組可以支援。

不可以使用shell模組執行互動命令,如vim、top等。

[root@control ansible]# ansible test -m command -a "ps | wc -l"         #報錯
[root@control ansible]# ansible test -m command -a  "ls &"               #報錯
[root@control ansible]# ansible test -m shell -a  "ps aux | wc -l"       #程序數量
[root@control ansible]# ansible test -m shell -a  "who"                   #登陸資訊
[root@control ansible]# ansible test -m shell -a  "touch /tmp/txt.txt"  
#使用shell模組建立檔案會有Warning警告提示,正常!!!

5)script模組

script模組會把-a後面的指令碼拷貝到被管理端主機,然後執行這個指令碼。

[root@control ansible]# vim  ~/ansible/test.sh  
#!/bin/bash
dnf -y install httpd
systemctl start httpd
[root@control ansible]# ansible  test  -m script  -a  "./test.sh"    
#test是主機組的名稱,-m呼叫script模組,-a後面的./test.sh是上面建立指令碼的相對路徑和檔名
#./是當前目錄的意思,在當前目錄下有個指令碼叫test.sh

拓撲如圖-4所示。

如何驗證?

因為ansible遠端的是node1,所以開啟node1這臺電腦,檢視下是否安裝了httpd軟體、是否啟動了服務。

[root@node1 ~]# rpm -q  httpd
[root@node1 ~]# systemctl  status  httpd

3 案例3:Ansible ad-hoc應用二

3.1 問題

沿用練習二,繼續練習Ansible ad-hoc應用案例,具體要求如下:

  • 遠端目標主機新建檔案和目錄、修改檔案或目錄的許可權
  • 在遠端目標主機建立連結檔案
  • 刪除遠端目標主機上的檔案或目錄
  • 將控制端本地的檔案拷貝到被管理端
  • 從被管理端下載檔案到本地
  • 修改遠端目標主機上的檔案內容

3.2 方案

很多ansible模組都具有冪等性的特徵。

冪等性:任意次執行所產生的影響均與一次執行的影響相同。

步驟一:file模組

file模組可以建立檔案、目錄、連結;修改許可權與屬性等(ansible-doc file)

[root@control ansible]# ansible  test  -m  file  -a  "path=/tmp/file.txt state=touch"         #遠端test組中所有主機,新建檔案,path後面指定要建立的檔案或目錄的名稱
#state=touch是建立檔案,state=directory是建立目錄
## 驗證: 到node1主機,使用ls /tmp/file.txt看看檔案是否被建立成功   ##

拓撲如圖-5所示。

常見報錯(有問題可以參考,沒問題可以忽略):

node1 | FAILED! => {
   … …
    "changed": false,
    "msg": "value of state must be one of: absent, directory, file, hard, link, touch, got: touc"
}
英語詞彙:value(值),must(必須),be(是),of(…的),one(一個)
value of state must be one of:【state的值必須是後面給出的其中一個值】
解決辦法:檢查state的值是否有字母錯誤,上面報錯例子中輸入的是touc,不是touch

常見錯誤(有問題可以參考,沒問題可以忽略):

node1 | FAILED! => {
   … …
   "msg": "Unsupported parameters for (file) module: nmae Supported parameters include: _diff_peek, _original_basename, access_time, 
access_time_format, attributes, backup, content, delimiter, directory_mode,
 follow, force, group, mode, modification_time, modification_time_format, owner,
 path, recurse, regexp, remote_src, selevel, serole, setype, seuser, src, state,
 unsafe_writes"
}
英語詞彙:unsupported(不支援的),parameters(引數),supported(支援的)include(包括)
問題分析:file模組不支援nmae這個引數,它支援的引數包括哪些,後面有提示.
解決辦法:檢查模組的引數是否有字母錯誤,上面錯誤案例將name錯寫為nmae。

更多file模組的案例:

[root@control ansible]# ansible  test  -m  file  \
-a  "path=/tmp/mydir state=directory"       
#遠端test組中所有主機,建立目錄,path後面指定要建立的檔案或目錄的名稱
## 驗證:到node1主機,使用ls /tmp/看看tmp目錄下是否有mydir子目錄
[root@control ansible]# ansible  test  -m  file \
-a  "path=/tmp/file.txt owner=sshd group=adm mode=0777"  
#修改檔案或目錄許可權,path後面指定要修改的檔名或目錄名稱,owner後面指定使用者,group後面指定組,mode後面指定要修改的許可權(0777中第一個0代表的是無特殊許可權,如SUID、SGID等)
## 驗證:到node1主機,使用ls -l /tmp/file.txt檢視檔案的詳細資訊是否正確
[root@control ansible]# ansible test -m file -a "path=/tmp/mydir state=absent"
#state=absent代表刪除(刪除目錄)
[root@control ansible]# ansible test -m file -a "path=/tmp/file.txt state=absent"
# state=absent代表刪除(刪除檔案)
[root@control ansible]# ansible test -m file \
-a "src=/etc/hosts  path=/tmp/host.txt state=link"  
#給/etc/hosts檔案建立一個連結檔案/tmp/host.txt(src指定原始檔,path是軟連結檔名)
#相當於執行命令 ln -s  /etc/hosts  /tmp/host.txt
## 驗證:到node1主機使用ls -l  /tmp/hosts檢視檔案是否為軟連結

步驟二:copy模組

copy模組可以將檔案拷貝到遠端主機 (ansible-doc copy)。

[root@control ansible]# echo AAA > ~/a3.txt                   #新建測試檔案
[root@control ansible]# ansible test -m copy -a "src=~/a3.txt dest=/root/"
#把管理端本機的a3.txt檔案,拷貝到test組中所有主機的/root/目錄
#src代表原始檔,dest代表目標檔案
## 驗證:到node1主機使用ls /root/a3.txt檢視是否有該檔案

拓撲如圖-6所示

步驟三:fetch模組

fetch模組與copy類似,但是作用相反,可以將其他主機的檔案拷貝到本地(ansible-doc fetch)。

[root@control ansible]# ansible test -m fetch -a "src=/etc/hostname   dest=~/"
#將遠端test組中所有主機的hostname檔案下載到本地家目錄
#src代表原始檔,dest代表目標檔案
[root@control ansible]# ls  ~/          #使用ls檢視下是否下載成功
#不能下載目錄,如果需要下載目錄,可以先打包後再下載

拓撲如圖-7所示。

步驟四:lineinfile|replace模組

在修改單個檔案的單行內容時可以使用lineinfile模組(ansible-doc lineinfile)。

[root@control ansible]# ansible test -m lineinfile  \
-a "path=/etc/issue line='hello world'"
#在/etc/issue檔案中新增一行內容hello world,預設新增到最後,line後面跟的是需要新增的檔案內容
## 驗證:到node1主機執行命令cat /etc/issue檢視檔案內容是否正確
[root@control ansible]# ansible test -m lineinfile \
-a "path=/etc/issue line='hello world'"
#基於冪等原則,重複執行,不會建立多行內容
[root@control ansible]# ansible test -m lineinfile \
-a "path=/etc/issue line='insert' insertafter='Kernel'"
#將line後面的內容插入到/etc/issue檔案中Kernel行的後面
#英語詞彙:insert(插入),after(在…後面)
## 驗證:到node1主機執行命令cat /etc/issue檢視檔案內容是否正確

lineinfile會替換一整行,replace可以替換關鍵詞(ansible-doc replace)。

[root@control ansible]# ansible test -m replace \
-a "path=/etc/issue.net regexp=Kernel replace=Ocean"
#將node1主機中/etc/issue.net檔案全文所有的Kernel替換為Ocean
#regexp後面是需要替換的舊內容;replace後面是需要替換的新內容
## 驗證:到node1主機執行命令cat /etc/issue.net檢視檔案內容是否正確

---------------------------------------------------------------------------

4 案例4:Ansible ad-hoc應用三

4.1 問題

沿用練習三,繼續練習Ansible ad-hoc應用案例,具體要求如下:

  • 遠端目標主機建立、刪除系統賬戶;設定系統賬戶屬性、修改賬戶密碼
  • 為目標主機建立、刪除yum源配置檔案;遠端目標主機安裝、解除安裝軟體包
  • 使用service模組管理遠端主機的服務
  • 建立、刪除邏輯卷

步驟一:user模組

user模組可以實現Linux系統賬戶管理(ansible-doc user)。

[root@control ansible]# ansible test -m user -a "name=tuser1"
#遠端test組中的所有主機並建立系統賬戶tuser1,預設state的值為present,代表建立使用者
## 驗證:到node1主機執行命令id  tuser1檢視是否有該使用者

拓撲如圖-8所示。

[root@control ansible]# ansible test -m user -a \
"name=tuser2 uid=1010 group=adm groups=daemon,root home=/home/tuser2"
#建立賬戶並設定對應的賬戶屬性,uid指定使用者ID號,group指定使用者屬於哪個基本組
#groups指定使用者屬於哪些附加組,home指定使用者的家目錄
## 驗證: 到node1主機執行命令id tuser2檢視是否有該使用者

拓撲如圖-9所示

[root@control ansible]# ansible test -m user \
-a "name=tuser1 password={{'abc'| password_hash('sha512')}}"
#修改賬戶密碼,使用者名稱是tuser1,密碼是abc,密碼經過sha512加密
[root@control ansible]# ansible test -m user \
-a "name=tuser1 state=absent"
#刪除賬戶tuser1,state=absent代表刪除賬戶的意思,name指定要刪除的使用者名稱是什麼
#賬戶的家目錄不會被刪除,相當於執行userdel tuser1
[root@control ansible]# ansible test -m user \
-a "name=tuser2 state=absent remove=true"
#刪除tuser2賬戶同時刪除家目錄、郵箱,相當於執行userdel  -r  tuser2

步驟二:yum_repository模組

使用yum_repository可以建立或修改yum源配置檔案(ansible-doc yum_repository)。

[root@control ansible]# ansible test -m yum_repository \
-a "name=myyum description=hello baseurl=ftp://192.168.4.254/centos gpgcheck=no"
#新建一個yum源配置檔案/etc/yum.repos.d/myyum.repo
#yum原始檔名為myyum,該檔案的內容如下:
[myyum]
baseurl = ftp://192.168.4.254/centos
gpgcheck = 0
name = hello
## 驗證:到node1主機ls /etc/yum.repos.d/檢視該目錄下是否有新的yum檔案
[root@control ansible]# ansible test -m yum_repository \
-a "name=myyum description=test baseurl=ftp://192.168.4.254/centos gpgcheck=yes gpgkey=…"
#修改yum原始檔內容
[root@control ansible]# ansible test -m yum_repository -a "name=myyum state=absent"
#刪除yum原始檔myyum

步驟三:yum模組

使用yum模組可以安裝、解除安裝、升級軟體包(ansible-doc yum),

state: present(安裝)|absent(解除安裝)|latest(升級)。

[root@control ansible]# ansible test -m yum -a "name=unzip state=present"
#安裝unzip軟體包,state預設為present,也可以不寫
## 驗證:到node1主機執行命令rpm -q unzip檢視是否有該軟體
[root@control ansible]# ansible test -m yum -a "name=unzip state=latest"
#升級unzip軟體包,軟體名稱可以是*,代表升級所有軟體包
[root@control ansible]# ansible test -m yum -a "name=unzip state=absent"
#呼叫yum模組,解除安裝unzip軟體包,state=absent代表解除安裝軟體
## 驗證:到node1主機執行命令rpm -q unzip檢視該軟體是否已經被解除安裝

步驟四:service模組(ansible-doc service)

service為服務管理模組(啟動、關閉、重啟服務等),

state:started|stopped|restarted,

enabled:yes設定開機啟動。

[root@control ansible]# ansible test -m yum -a "name=httpd"
#呼叫yum模組,安裝httpd軟體包
## 驗證:到node1主機執行命令rpm -q httpd檢視該軟體是否被安裝
[root@control ansible]# ansible test -m service -a "name=httpd state=started"
#呼叫service模組,啟動httpd服務
## 驗證:到node1主機執行命令systemctl  status  httpd檢視服務狀態
[root@control ansible]# ansible test -m service -a "name=httpd state=stopped"
#呼叫service模組,關閉httpd服務
## 驗證:到node1主機執行命令systemctl  status  httpd檢視服務狀態
[root@control ansible]# ansible test -m service -a "name=httpd state=restarted"
#呼叫service模組,重啟httpd服務
[root@control ansible]# ansible test -m service -a "name=httpd enabled=yes"
#呼叫service模組,設定httpd服務開機自啟

步驟五:邏輯卷相關模組(ansible-doc lvg、ansible-doc lvol)

提示:做實驗之前需要給對應的虛擬機器新增額外磁碟,並建立磁碟2個分割槽

提示:可以使用前面學習過的parted或fdisk命令給磁碟建立分割槽

提示:這裡的磁碟名稱僅供參考,不要照抄!!!

lvg模組:建立、刪除卷組(VG),修改卷組大小,

state:present(建立)|absent(刪除)。

[root@control ansible]# ansible test -m yum -a "name=lvm2"
#安裝lvm2軟體包,安裝了lvm2軟體後,才有pvcreate、vgcreate、lvcreate等命令
[root@control ansible]# ansible test -m lvg -a "vg=myvg pvs=/dev/sdb1"
#建立名稱為myvg的卷組,該卷組由/dev/sdb1組成
#注意:這裡的磁碟名稱要根據實際情況填寫
## 驗證:到node1主機執行命令pvs和vgs檢視是否有對應的PV和VG
[root@control ansible]# ansible test -m lvg -a "vg=myvg pvs=/dev/sdb1,/dev/sdb2"
#修改卷組大小,往卷組中新增一個裝置/dev/sdb2

lvol模組:建立、刪除邏輯卷(LV),修改邏輯卷大小,

state:present(建立)|absent(刪除)。

[root@control ansible]# ansible test -m lvol -a "lv=mylv vg=myvg size=2G"
#使用myvg這個卷組建立一個名稱為mylv的邏輯卷,大小為2G
## 驗證:到node1主機執行命令lvs檢視是否有對應的LV邏輯卷
[root@control ansible]# ansible test -m lvol -a "lv=mylv vg=myvg size=4G"
#修改LV邏輯卷大小
[root@control ansible]# ansible test -m lvol -a "lv=mylv vg=myvg state=absent force=yes"
#刪除邏輯卷,force=yes是強制刪除
[root@control ansible]# ansible test -m lvg -a "vg=myvg state=absent"
#刪除卷組myvg

附加思維導圖,如圖-10所示:

附加思考題(假設在沒有建立ssh金鑰的情況下):

在沒有建立ssh金鑰的情況下,如果node1需要ssh遠端node2是否需要輸入密碼?

如果node1需要ssh遠端node2,應該輸入誰的使用者名稱和密碼?

node1使用自己系統的賬戶和密碼能否ssh遠端node2,node2可以被隨便登入還安全嗎?

路人甲能否使用自己家的鑰匙,去路人乙家(開路人乙家的門)?

node1執行命令ssh [email protected],這裡的root是誰的賬戶名?輸入誰的密碼?

如果使用真機windows的Xshell去ssh遠端node2虛擬機器,需要在windows也有一個root使用者嗎?

-----------------------------------------------------------------------------------------------------------------------------