天天看點

幹貨:Ansible 日常維護和使用

作者:譽天教育ICT認證教育訓練

本文将介紹如何維護Ansible的Inventory,來管理不同業務的不同機器;如何使用Ansible的一些常用元件,完成一些基本的自動化運維工作;如何編寫和使用Playbook,來完成複雜環境下的自動化運維工作;如何利用Facts元件來采集被管用戶端的裝置資訊,來實作配置管理系統(CMDB)的自動采集能力等等。

1、Ansible Inventory維護

  • Inventory檔案

在日常維護中,Ansible通過Inventory(可管理的主機集合),對遠端伺服器或者主機進行統一操作和管理。在Ansible中,描述主機的預設方法是将他們列在一個文本檔案中,這個檔案稱為Inventory檔案,預設的路徑和檔案為:/etc/ansible/hosts,可以通過ANSIBLE_HOSTS環境變量來指定,也可以在ansible.cfg檔案中通過inventory參數指定,或者在運作ansible和ansible-playbook的時候使用-i參數來臨時指定。

下面舉例說明,如何在inventory元件的/etc/ansible/hosts檔案中定義主機和主機組:

幹貨:Ansible 日常維護和使用

第一行定義了一個主機X.X.X.100,并使用inventory内置變量ansible_ssh_pass定義了該主機的登入密碼,如果建立了互信,則不需要這個參數;

第二、三、四行定義了一個名為groupname1的主機組,其中包含X.X.X.101-X.X.X.109,X.X.X.201-X.X.X.209共計18台主機;

第五、六行為groupname1的主機組定義了一個共同的變量:ansible_ssh_pass,以定義該組内所有主機的登入密碼;

第七、八行定義了一個更大的組:groupname2,其下包含了groupname1組下的所有主機。

定義好之後,我們在ansible指令行和ansible-playbook中,可以非常靈活的使用,便于批量操作。例如批量檢視groupname1組下所有主機的目前時間:

ansible groupname1 -a date

  • Inventory内置參數

除了前面介紹的ansible_ssh_pass參數,Ansible Inventory内置了一些參數,這些參數在我們實際工作中也會經常使用,我們可以直接在Inventory檔案中定義它。

幹貨:Ansible 日常維護和使用

我們也可以在ansible.cfg檔案中的[defaults]部分更改一些Inventory内置參數的預設值,可以支援更改的有:

幹貨:Ansible 日常維護和使用
  • 動态Inventory

在實際的應用中,會存在大量的主機清單資訊,如果手動維護Ansible中的Inventory檔案将會非常的繁瑣,是以支援動态Inventory将會讓問題變得統一、清晰、簡單許多。動态Inventory也就是Ansible所有的Inventory檔案裡面的主機清單和變量資訊都支援從外部拉取,例如我們常用的CMDB,我們可以通過定義的腳本,将外部CMDB等其他運維系統中的主機資訊同步至Ansible中。在實際的配置中僅需要更改ansible.cfg檔案中的inventory參數為一個可執行的腳本即可。

[defaults]
inventory = /etc/ansible/inventory.sh           

腳本的内容不受任何程式設計語言限制,但該腳本必須支援以下規範的參數,腳本的執行結果也有一定的要求:

--list或者-l,腳本運作該參數須顯示所有主機群組的資訊(Json格式)。

--host或者-H,腳本的該參數後需指定一個主機,運作結果也會傳回該主機的所有資訊(同樣也必須為Json格式)。

腳本調試好之後,ansible将利用inventory變量所指向的腳本,擷取主機群組資訊(或者通過-i參數指定),來向主機執行指令。

  • Inventory分割

如果我們想要同時使用正常Inventory檔案和動态Inventory腳本,或者按不同業務/系統分割成的多個Inventory檔案,我們可以把所有這些檔案全部都放到同一個目錄,并配置ansible.cfg檔案的hostfile參數,讓Ansible使用hostfile參數所指定的目錄作為Inventory即可,也可以在指令行中使用-i指令來指定特定的Inventory檔案。Ansible将會處理目錄裡所有的檔案并将結果合并為一個完整的Inventory。

[defaults]
hostfile = /etc/ansible/inventory           

2、Ansible Ad-Hoc指令使用

Ansible系統由控制主機對被管節點的操作方式可分為兩類,即 Ad-Hoc和Playbook:

Ad-Hoc模式使用單個子產品,支援批量執行單條指令。

Playbook模式是Ansible主要管理方式,也是Ansible功能強大的關鍵所在,Playbook通過多個Task集合完成一類功能,如 Web 服務的安裝部署、資料庫伺服器的批量備份等,可以簡單地把 Playbook了解為通過

組合多條Ad-Hoc操作的配置檔案。

下面将通過兩個小節的内容,來說明如何使用Ad-Hoc和Playbook。其中Ad-Hoc将重點介紹指令參數和幾個常用的子產品。

通常我們會以指令行的形式使用Ansible子產品,或者将Ansible指令嵌入到腳本中去執行。Ansible自帶了很多子產品,我們可以直接使用他們。當我們不知道如何使用這些子產品時,可以ansible-doc指令擷取幫助,

例如:使用“ansible-doc -l”指令可以顯示所有自帶的子產品和相關簡介,使用“ansible-doc 子產品名”指令可以顯示該子產品的參數及用法等内容。

  • Ansible Ad-Hoc指令參數

我們可以使用“ansible -h”指令來列出所有的指令參數,下面列舉了常用的一些參數,部分參數如果不指定将采用ansible.cfg中的設定值,或者采用原始預設值。

幹貨:Ansible 日常維護和使用
  • Ansible常用子產品介紹

連通性測試

通常采用Ping子產品來測試遠端主機的運作狀态:

ansible ip -m ping           

執行指令

執行指令可以采用四種方式,第一種方式是利用Command子產品在遠端主機上執行指令,但Command子產品不支援管道指令,例如,檢視某個主機的日期:

ansible ip -m command -a date -o           

值得注意的是,Ansible預設的子產品是Command,是以上面的指令可以簡化為:

ansible ip -a date -o           

第二種方式是利用Shell子產品,切換到某個Shell執行遠端主機上的Shell/Python腳本,或者執行指令,Shell支援管道指令,功能較Command更強大靈活,例如:

ansible ip -m shell -a 'bash /root/test.sh' -o
ansible ip -m shell -a 'echo "123456"|passwd --stdin root'           

第三種方式是利用Raw子產品,Raw支援管道指令。Raw有很多地方和Shell類似,但是如果是使用老版本Python(低于2.4),無法通過Ansible的其他子產品執行指令,則需要先用到Raw子產品遠端安裝Python-sim-plejson後才能受管;又或者是受管端是路由裝置,因為沒有安裝Python環境,那就更需要使用Raw子產品去管控了。例如:

ansible ip -m raw -a "cd /tmp;pwd"           

第四種方式是利用Script子產品,傳輸Ansible中控端上的Shell/Python腳本到遠端主機上執行,即使遠端主機沒有安裝Python也可以執行,有點類似Raw子產品。但Script隻能執行腳本,不能調用其他指令,且不支援管道指令,例如:

ansible ip -m script -a '/root/test.sh' -o           

removes參數用來判斷遠端主機上是不是存在test.sh檔案,如果存在,就執行管控機上的test.sh,不存在就不執行:

ansible ip -m script -a 'removes=/root/test.sh /root/test.sh' -o           

creates用來判斷遠端主機上是不是存在test.sh檔案,如果存在,就不執行,不存在就執行管控機上的test.sh檔案:

ansible ip -m script -a 'creates=/root/test.sh /root/test.sh' -o           

複制檔案

常用的檔案操作子產品就是Copy子產品,它主要用于将本地或遠端機器上的檔案拷貝到遠端主機上。其主要參數有以下幾個:

幹貨:Ansible 日常維護和使用

複制本地檔案的到遠端主機:

ansible ip -m copy -a 'src=/root/test.sh dest=/tmp/test.sh'           

複制并修改檔案的權限:

ansible ip -m copy -a 'src=/root/test.sh dest=/tmp/test.sh mode=755'           

複制并修改檔案的屬主:

ansible ip -m copy -a 'src=/root/test.sh dest=/tmp/test.sh mode=755 owner=root'           

複制檔案前備份:

ansible ip -m copy -a 'src=test.sh backup=yes dest=/tmp'           

服務管理

在Ansible Ad-Hoc中,Service子產品可以幫助我們管理遠端主機上的服務。例如,啟動或停止遠端主機中的某個服務。但是該服務本身必須要能夠通過作業系統的管理服務的元件所管理,例如Redhat6中預設通過SysV進行服務管理,Redhat7中預設通過Systemd管理服務,如果該服務本身都不能被作業系統的服務管理元件所管理,那麼也不能被Service子產品管理。該子產品的幾個常用參數如下:

幹貨:Ansible 日常維護和使用

啟動服務:

ansible all -m service -a "name=sshd state=started"           

停止服務:

ansible all -m service -a "name=sshd state=stopped"           

開啟服務自啟動:

ansible all -m service -a "name=sshd enable=yes"           

安裝包管理

在Ansible Ad-Hoc中,可以通過Yum子產品實作在遠端主機上通過Yum源管理軟體包,包括安裝、更新、降級、删除和列出軟體包等。該子產品的幾個常用參數如下:

幹貨:Ansible 日常維護和使用

安裝軟體包:

ansible all -m yum -a 'name=nginx state=installed’           

解除安裝軟體包:

ansible all -m yum -a 'name=nginx state=removed'           

臨時啟用local yum源安裝最新版軟體包:

ansible all -m yum -a 'name=nginx state=latest enablerepo=local'           

使用者管理

在Ansible Ad-Hoc中,可以通過User子產品幫助我們管理遠端主機上的使用者,比如建立使用者、修改使用者、删除使用者、為使用者建立密鑰對等操作。該子產品的幾個常用參數如下:

幹貨:Ansible 日常維護和使用

增加使用者、組和密碼:

ansible ip -m group -a "name=testg”
ansible ip -m user -a "name=test group=testg password=123456 home=/home/test”           

删除使用者和使用者主目錄:

ansible ip -m user -a "name=test state=absent remove=yes"           

3、Ansible Playbook使用

在Ansible Ad-Hoc中,可以通過Yum子產品實作在遠端主機上通過Yum源管理軟體包,包括安裝、更新、降級、删除和列出軟體包等。該子產品的幾個常用參數如下:

我們在使用Ansible時,絕大部分時間将花費在編寫Playbook上,Playbook是一個Ansible術語,指的是用于配置管理的腳本。Ansible的Playbook是使用YAML文法編寫的。YAML是一種類似于Json的檔案格式,不過YAML更适合人來讀寫。我們在開始編寫Playbook時,需要對YAML的文法有一定的了解,否則将經常碰到文法錯誤。下面首先通過一個安裝和配置ntpd服務的Playbook案例來介紹:

幹貨:Ansible 日常維護和使用
幹貨:Ansible 日常維護和使用

第一行僅表示該檔案為YAML格式檔案,非必須。

第二行定義了該Playbook所針對的主機,all表示所有,也可以填寫Inventory檔案中的IP位址或者主機組名稱。

第三行表示下面開始定義Task任務。

第四、五行定義了一個具體Task任務(通過Yum安裝ntpd服務),包含任務名稱和執行動作,其中任務名稱為非必須,可以直接定義執行動作。

第六、七、八、九行定義了另一個具體Task任務(同步ntpd配置檔案模闆),并更改檔案的屬主、屬組和檔案權限。notify和下面的handlers為配對使用,當ntpd配置檔案模闆同步至遠端主機後,檔案的MD5值将發生變化,觸發restart ntpd service這個handler。

第十、十一、十二行定義了上述handler的具體内容,包括名稱和執行動作,也就是利用service子產品來重新開機ntpd服務。

編制好了Playbook,我們需要使用--syntax-check參數來對該腳本進行文法檢查:

ansible-playbook ntpd.yaml --syntax-check
playbook: ntpd.yaml           

文法檢測過後,可以用--list-task參數來檢視該Playbook中的所有Task:

幹貨:Ansible 日常維護和使用

确認無誤後,開始使用指令運作名為ntpd.yaml的Playbook:

ansible-playbook ntpd.yaml           

後續如果我們的ntpd.conf.j2配置模闆需要變更,并需要批量分發下去,我們可以指定copy ntp.conf這個Task,隻運作該Task:

ansible-playbook ntpd.yaml --start-at-task=’copy ntp.conf’           

除了上述參數之外,ansible-playbook還有幾個常用的參數:

--step同一時間隻執行一個Task,每個Task執行前都會提示确認一遍。

--tags=TAGS當Play和Task的Tag為該參數指定的值時才執行,多個Tag以逗号分隔。

--skip-tags=SKIP_TAGS當Play和Task的Tag不比對該參數指定的值時才執行。

根據前面的案例,我們對Playbook的大體寫法和用法有了一個大緻的認識,下面重點介紹幾個Play-book常用的使用要點:

  • Playbook的組成

一個Playbook包括一個或多個Play。一個Play由Host的無序集合與Task的有序清單組成。每一個Task僅由一個子產品構成。見下圖所示:

幹貨:Ansible 日常維護和使用
  • Tasks List和Action

Play的主體部分是Task清單,Task清單中的各任務按次序逐個在Hosts中指定的主機上執行,即在所有主機上完成第一個任務後再開始第二個任務。在運作Playbook時(從上到下執行),如果一個Host執行Task失敗,整個Task都會復原,我們需要修正Playbook中的錯誤,然後重新執行即可。Task的目的是使用指定的參數執行子產品,而在子產品參數中可以使用變量,子產品執行時幂等等,這意味着多次執行是安全的,因為其結果一緻。

另外,按照規範寫法,每一個Task必須有一個名稱Name,雖然這不是必須的,但這樣在運作Playbook時,從其輸出的任務執行資訊中可以很好的辨識出是屬于哪一個Task。如果沒有定義Name,Action的值将會用作輸出資訊中标記特定的Task,結果不好分辨。定義一個Task,常見的格式為“module: options”,例如:“yum: name=httpd”。值得注意的是,Ansible的自帶子產品中,Command子產品和Shell子產品無需使用key=value格式,直接編寫要執行的指令即可。

  • Handlers

Handlers也是一些Task的清單,和一般的Task并沒有什麼差別。它是由通知者進行的Notify,如果沒有被Notify,則Handlers不會執行,如果被Notify了,則Handlers被執行。不管有多少個通知者進行了Notify,等到Play中的所有Task都執行完成之後,Handlers也隻會被執行一次。例如:

幹貨:Ansible 日常維護和使用
  • 變量引用

我們可以在PlayBook中通過“vars: 變量名”的方式聲明變量,并通過“{{變量名}}”的方式使用已聲明的變量。另外,我們還可以直接引用Ansible的變量,包括采集到的主機Fact中的變量,例如:通過ansible_all_ipv4_address來擷取IPV4位址,或者通過ansible_distribution、ansible_distribution_version來擷取操作類型和版本資訊。除此之外,還能引用已編輯好的Inventory檔案中定義的主機變量,這樣當安裝完一些軟體,需要根據主機中定義的變量來做一些自動化配置時,将會非常好用。例如:

vi /etc/ansible/hosts #定義Inventory檔案中的變量與值
X.X.108.2 hostname="test"           
幹貨:Ansible 日常維護和使用

上面的案例是通過vars的方式定義了package和service兩個變量,并在下面的yum和service兩個Task中進行引用,第三個Task則是直接引用setup生成的Fact變量和來自Inventory檔案中定義的主機變量hostname,來實作将内容資訊傳遞至遠端主機的檔案中,輸出結果如下:

cat /tmp/test.txt
test:RedHat 7.2           
  • 條件判斷

我們可以在PlayBook中通過“when: 變量==值”的方式聲明一個條件判斷,可以看出when的值是一個條件表達式,如果條件判斷成立,Task就執行,如果判斷不成立,則task不執行。例如當我們需要根據變量、Facts(setup)或此前任務的執行結果來作為某Task執行與否的前提時,則要用到條件判斷,這時可以在Playbook中使用when子句:在Task後添加when子句。另外,when子句支援jinjia2表達式或文法。

幹貨:Ansible 日常維護和使用
  • 疊代

當我們有需要重複性執行的任務時,可以使用疊代機制。其使用格式為将需要疊代的内容定義為item變量引用,并通過with_items語句指明疊代的元素清單即可。例如:

幹貨:Ansible 日常維護和使用
幹貨:Ansible 日常維護和使用
  • Templates

Jinja是基于Python的模闆引擎。Template類是Jinja的另一個重要元件,可以看作一個編譯過的子產品檔案,用來生産目标文本,我們可以傳遞Python的變量給模闆去替換模闆中的标記。例如,我們在做Nginx安裝與配置時,有些監聽端口、服務名稱等配置可以通過變量的方式在Inventroy檔案中為不同主機預定義好,當我們定義好了一個模闆,并将模闆中的監聽端口和服務名稱設定為變量後,在運作Template這個Task時,将會把不同主機的這些變量資訊傳遞到模闆中使用,實作配置的自動化。例如:

vi /tmp/httpd.conf.j2 #定義模闆中的變量
Listen {{http_port}}
ServerName {{server_name}}
MaxClients {{access_num}}
vi /etc/ansible/hosts #定義Inventory檔案中的變量與值
[test]
X.X.X.2 http_port=X.X.X.2:80 access_num=50 server_name="test:80"           

安裝Nginx時,将把Inventory檔案中主機定義好的變量與值傳遞到模闆中,并拷貝至該遠端主機:

幹貨:Ansible 日常維護和使用
  • Tags

在一個Playbook中,我們一般會定義很多個Task,如果我們隻想執行其中的某一個Task或多個Task時就可以使用Tags标簽功能了,例如:

幹貨:Ansible 日常維護和使用
ansible-playbook test.yml --tags="nginx"           

4、Ansible Facts使用

Facts元件是Ansible用于采集被管主機裝置資訊的一個功能,當Ansible采集Fact的時候,它會收集被管主機的各種詳細資訊:CPU架構、作業系統、IP位址、記憶體資訊、磁盤資訊等,這些資訊儲存在被稱作Fact的變量中。Ansible使用一個名為Setup的特殊子產品來實作Fact的收集,在Playbook中預設會調用這個子產品進行Fact收集,在指令行中可以通過“ansible ip -m setup”來進行手動收集,整個Facts資訊被包裝JSON格式的資料結構中, Ansible Facts是最上層的值。例如:

幹貨:Ansible 日常維護和使用

Facts還支援通過filter參數來檢視指定資訊,例如下面隻檢視遠端主機的作業系統和版本:

幹貨:Ansible 日常維護和使用

檢視遠端主機的CPU和記憶體大小:

幹貨:Ansible 日常維護和使用

檢視遠端主機的各檔案系統大小和剩餘容量:

幹貨:Ansible 日常維護和使用

在Playbook中,Facts元件預設會收集很多的主機的基礎資訊,可以通過前面的Fact緩存機制,将這些資訊緩存到本地目錄或者記憶體資料庫中,在做配置管理的時候進行引用,也可以用來将擷取的主機基礎資訊自動同步到CMDB中去,實作基礎資訊的自動采集功能。下面通過通過示範,說明如何通過ansible-cmdb插件,實作遠端主機CPU自動同步至外部CMDB系統中。

首先,我們需要安裝ansible-cmdb插件,下載下傳連結如下:

https://files.pythonhosted.org/packages/37/1b/1fcff0a38a4e07d9d3f75113494ec0b25fd271b650bda52907ae1a80cbfb/ansible-cmdb-1.27.tar.gz

其次,開始安裝ansible-cmdb插件:

gzip -dc ansible-cmdb-1.27.tar.gz|tar -xvf -
cd ansible-cmdb-1.27
python setup.py install           

生成所有主機的Fact資訊并用filter過濾出主機CPU值:

ansible all -m setup -t /tmp/factout
ansible all -m setup -a “filter=ansible_processor_count” -t /tmp/cpu           

通過ansible-cmdb插件以csv或sql格式輸出IP位址和CPU顆數值:

PATH=/usr/local/bin:$PATH
ansible-cmdb -t csv -c name,cpus /tmp/cpu >/tmp/cpu.csv
ansible-cmdb -t sql /tmp/cpu >/tmp/cpu.sql           

以csv格式或者sql格式導入資訊至外部CMDB系統中(根據支援方式靈活選用),這裡以postgres資料庫為例,通過轉csv格式為sql格式導入至外部CMDB系統:

幹貨:Ansible 日常維護和使用

當然,以上僅僅是簡單的示例,事實上,我們可以利用好Ansible Fact的功能,實作更加複雜的CMDB自動化采集功能。

作者:鄧毓

來源:twt社群

繼續閱讀