使用Ansible來(lái)管理你的工作站:配置自動(dòng)化
學(xué)習(xí)如何使 Ansible 自動(dòng)對(duì)一系列臺(tái)式機(jī)和筆記本應(yīng)用配置。
Ansible 是一個(gè)令人驚訝的自動(dòng)化的配置管理工具。其主要應(yīng)用在服務(wù)器和云部署上,但在工作站上的應(yīng)用(無(wú)論是臺(tái)式機(jī)還是筆記本)卻鮮少得到關(guān)注,這就是本系列所要關(guān)注的。
在這個(gè)系列的***部分,我向你展示了 ansible-pull
命令的基本用法,我們創(chuàng)建了一個(gè)安裝了少量包的劇本。它本身是沒有多大的用處的,但是為后續(xù)的自動(dòng)化做了準(zhǔn)備。
在這篇文章中,將會(huì)達(dá)成閉環(huán),而且在***部分,我們將會(huì)有一個(gè)針對(duì)工作站自動(dòng)配置的完整的工作解決方案?,F(xiàn)在,我們將要設(shè)置 Ansible 的配置,這樣未來(lái)將要做的改變將會(huì)自動(dòng)的部署應(yīng)用到我們的工作站上。現(xiàn)階段,假設(shè)你已經(jīng)完成了***部分的工作。如果沒有的話,當(dāng)你完成的時(shí)候回到本文。你應(yīng)該已經(jīng)有一個(gè)包含***篇文章中代碼的 GitHub 庫(kù)。我們將直接在之前創(chuàng)建的部分之上繼續(xù)。
首先,因?yàn)槲覀円龅牟粌H僅是安裝包文件,所以我們要做一些重新的組織工作?,F(xiàn)在,我們已經(jīng)有一個(gè)名為 local.yml
并包含以下內(nèi)容的劇本:
- hosts: localhost
become: true
tasks:
- name: Install packages
apt: name={{item}}
with_items:
- htop
- mc
- tmux
如果我們僅僅想實(shí)現(xiàn)一個(gè)任務(wù)那么上面的配置就足夠了。隨著向我們的配置中不斷的添加內(nèi)容,這個(gè)文件將會(huì)變的相當(dāng)?shù)凝嫶蠛碗s亂。***能夠根據(jù)不同類型的配置將我們的動(dòng)作分為獨(dú)立的文件。為了達(dá)到這個(gè)要求,創(chuàng)建一個(gè)名為任務(wù)手冊(cè)的東西,它和劇本很像但內(nèi)容更加的流線型。讓我們?cè)?Git 庫(kù)中為任務(wù)手冊(cè)創(chuàng)建一個(gè)目錄。
mkdir tasks
local.yml
劇本中的代碼可以很好地過渡為安裝包文件的任務(wù)手冊(cè)。讓我們把這個(gè)文件移動(dòng)到剛剛創(chuàng)建好的 task
目錄中,并重新命名。
mv local.yml tasks/packages.yml
現(xiàn)在,我們編輯 packages.yml
文件將它進(jìn)行大幅的瘦身,事實(shí)上,我們可以精簡(jiǎn)除了獨(dú)立任務(wù)本身之外的所有內(nèi)容。讓我們把 packages.yml
編輯成如下的形式:
- name: Install packages
apt: name={{item}}
with_items:
- htop
- mc
- tmux
正如你所看到的,它使用同樣的語(yǔ)法,但我們?nèi)サ袅藢?duì)這個(gè)任務(wù)無(wú)用沒有必要的所有內(nèi)容?,F(xiàn)在我們有了一個(gè)專門安裝包文件的任務(wù)手冊(cè)。然而我們?nèi)匀恍枰粋€(gè)名為 local.yml
的文件,因?yàn)閳?zhí)行 ansible-pull
命令時(shí)仍然會(huì)去找這個(gè)文件。所以我們將在我們庫(kù)的根目錄下(不是在 task
目錄下)創(chuàng)建一個(gè)包含這些內(nèi)容的全新文件:
- hosts: localhost
become: true
pre_tasks:
- name: update repositories
apt: update_cache=yes
changed_when: False
tasks:
- include: tasks/packages.yml
這個(gè)新的 local.yml
扮演的是導(dǎo)入我們的任務(wù)手冊(cè)的索引的角色。我已經(jīng)在這個(gè)文件中添加了一些你在這個(gè)系列中還沒見到的內(nèi)容。首先,在這個(gè)文件的開頭處,我添加了 pre_tasks
,這個(gè)任務(wù)的作用是在其他所有任務(wù)運(yùn)行之前先運(yùn)行某個(gè)任務(wù)。在這種情況下,我們給 Ansible 的命令是讓它去更新我們的發(fā)行版的軟件庫(kù)的索引,下面的配置將執(zhí)行這個(gè)任務(wù)要求:
apt: update_cache=yes
通常 apt
模塊是用來(lái)安裝包文件的,但我們也能夠讓它來(lái)更新軟件庫(kù)索引。這樣做的目的是讓我們的每個(gè)動(dòng)作在 Ansible 運(yùn)行的時(shí)候能夠以***的索引工作。這將確保我們?cè)谑褂靡粋€(gè)老舊的索引安裝一個(gè)包的時(shí)候不會(huì)出現(xiàn)問題。因?yàn)?apt
模塊僅僅在 Debian、Ubuntu 及它們的衍生發(fā)行版下工作。如果你運(yùn)行的一個(gè)不同的發(fā)行版,你要使用特定于你的發(fā)行版的模塊而不是 apt
。如果你需要使用一個(gè)不同的模塊請(qǐng)查看 Ansible 的相關(guān)文檔。
下面這行也需要進(jìn)一步解釋:
changed_when: False
在某個(gè)任務(wù)中的這行阻止了 Ansible 去報(bào)告動(dòng)作改變的結(jié)果,即使是它本身在系統(tǒng)中導(dǎo)致的一個(gè)改變。在這里,我們不會(huì)去在意庫(kù)索引是否包含新的數(shù)據(jù);它幾乎總是會(huì)的,因?yàn)閹?kù)總是在改變的。我們不會(huì)去在意 apt
庫(kù)的改變,因?yàn)樗饕母淖兪钦5倪^程。如果我們刪除這行,我們將在過程報(bào)告的后面看到所有的變動(dòng),即使僅僅庫(kù)的更新而已。***忽略這類的改變。
接下來(lái)是常規(guī)任務(wù)的階段,我們將創(chuàng)建好的任務(wù)手冊(cè)導(dǎo)入。我們每次添加另一個(gè)任務(wù)手冊(cè)的時(shí)候,要添加下面這一行:
tasks:
- include: tasks/packages.yml
如果你現(xiàn)在運(yùn)行 ansible-pull
命令,它應(yīng)該基本上像上一篇文章中做的一樣。不同的是我們已經(jīng)改進(jìn)了我們的組織方式,并且能夠更有效的擴(kuò)展它。為了節(jié)省你到上一篇文章中去尋找,ansible-pull
命令的語(yǔ)法參考如下:
sudo ansible-pull -U https://github.com/<github_user>/ansible.git
如果你還記得話,ansible-pull
的命令拉取一個(gè) Git 倉(cāng)庫(kù)并且應(yīng)用它所包含的配置。
既然我們的基礎(chǔ)已經(jīng)搭建好,我們現(xiàn)在可以擴(kuò)展我們的 Ansible 并且添加功能。更特別的是,我們將添加配置來(lái)自動(dòng)化的部署對(duì)工作站要做的改變。為了支撐這個(gè)要求,首先我們要?jiǎng)?chuàng)建一個(gè)特殊的賬戶來(lái)應(yīng)用我們的 Ansible 配置。這個(gè)不是必要的,我們?nèi)匀荒軌蛟谖覀冏约旱挠脩粝逻\(yùn)行 Ansible 配置。但是使用一個(gè)隔離的用戶能夠?qū)⑵涓綦x到不需要我們參與的在后臺(tái)運(yùn)行的一個(gè)系統(tǒng)進(jìn)程中,
我們可以使用常規(guī)的方式來(lái)創(chuàng)建這個(gè)用戶,但是既然我們正在使用 Ansible,我們應(yīng)該盡量避開使用手動(dòng)的改變。替代的是,我們將會(huì)創(chuàng)建一個(gè)任務(wù)手冊(cè)來(lái)處理用戶創(chuàng)建任務(wù)。這個(gè)任務(wù)手冊(cè)目前將會(huì)僅僅創(chuàng)建一個(gè)用戶,但你可以在這個(gè)任務(wù)手冊(cè)中添加額外的動(dòng)作來(lái)創(chuàng)建更多的用戶。我將這個(gè)用戶命名為 ansible
,你可以按照自己的想法來(lái)命名(如果你做了這個(gè)改變要確保更新所有出現(xiàn)地方)。讓我們來(lái)創(chuàng)建一個(gè)名為 user.yml
的任務(wù)手冊(cè)并且將以下代碼寫進(jìn)去:
- name: create ansible user
user: name=ansible uid=900
下一步,我們需要編輯 local.yml
文件,將這個(gè)新的任務(wù)手冊(cè)添加進(jìn)去,像如下這樣寫:
- hosts: localhost
become: true
pre_tasks:
- name: update repositories
apt: update_cache=yes
changed_when: False
tasks:
- include: tasks/users.yml
- include: tasks/packages.yml
現(xiàn)在當(dāng)我們運(yùn)行 ansible-pull
命令的時(shí)候,一個(gè)名為 ansible
的用戶將會(huì)在系統(tǒng)中被創(chuàng)建。注意我特地通過參數(shù) uid
為這個(gè)用戶聲明了用戶 ID 為 900。這個(gè)不是必須的,但建議直接創(chuàng)建好 UID。因?yàn)樵?1000 以下的 UID 在登錄界面是不會(huì)顯示的,這樣是很棒的,因?yàn)槲覀兏緵]有需要去使用 ansibe
賬戶來(lái)登錄我們的桌面。UID 900 是隨便定的;它應(yīng)該是在 1000 以下沒有被使用的任何一個(gè)數(shù)值。你可以使用以下命令在系統(tǒng)中去驗(yàn)證 UID 900 是否已經(jīng)被使用了:
cat /etc/passwd |grep 900
不過,你使用這個(gè) UID 應(yīng)該不會(huì)遇到什么問題,因?yàn)槠駷橹乖谖沂褂玫娜魏伟l(fā)行版中我還沒遇到過它是被默認(rèn)使用的。
現(xiàn)在,我們已經(jīng)擁有了一個(gè)名為 ansible
的賬戶,它將會(huì)在之后的自動(dòng)化配置中使用。接下來(lái),我們可以創(chuàng)建實(shí)際的定時(shí)作業(yè)來(lái)自動(dòng)操作。我們應(yīng)該將其分開放到它自己的文件中,而不是將其放置到我們剛剛創(chuàng)建的 users.yml
文件中。在任務(wù)目錄中創(chuàng)建一個(gè)名為 cron.yml
的任務(wù)手冊(cè)并且將以下的代碼寫進(jìn)去:
- name: install cron job (ansible-pull)
cron: user="ansible" name="ansible provision" minute="*/10" job="/usr/bin/ansible-pull -o -U https://github.com/<github_user>/ansible.git > /dev/null"
cron
模塊的語(yǔ)法幾乎不需加以說明。通過這個(gè)動(dòng)作,我們創(chuàng)建了一個(gè)通過用戶 ansible
運(yùn)行的定時(shí)作業(yè)。這個(gè)作業(yè)將每隔 10 分鐘執(zhí)行一次,下面是它將要執(zhí)行的命令:
/usr/bin/ansible-pull -o -U https://github.com/<github_user>/ansible.git > /dev/null
同樣,我們也可以添加想要我們的所有工作站部署的額外的定時(shí)作業(yè)到這個(gè)文件中。我們只需要在新的定時(shí)作業(yè)中添加額外的動(dòng)作即可。然而,僅僅是添加一個(gè)定時(shí)的任務(wù)手冊(cè)是不夠的,我們還需要將它添加到 local.yml
文件中以便它能夠被調(diào)用。將下面的一行添加到末尾:
- include: tasks/cron.yml
現(xiàn)在當(dāng) ansible-pull
命令執(zhí)行的時(shí)候,它將會(huì)以用戶 ansible
每隔十分鐘設(shè)置一個(gè)新的定時(shí)作業(yè)。但是,每個(gè)十分鐘運(yùn)行一個(gè) Ansible 作業(yè)并不是一個(gè)好的方式,因?yàn)檫@個(gè)將消耗很多的 CPU 資源。每隔十分鐘來(lái)運(yùn)行對(duì)于 Ansible 來(lái)說是毫無(wú)意義的,除非我們已經(jīng)在 Git 倉(cāng)庫(kù)中改變一些東西。
然而,我們已經(jīng)解決了這個(gè)問題。注意我在定時(shí)作業(yè)中的命令 ansible-pill
添加的我們之前從未用到過的參數(shù) -o
。這個(gè)參數(shù)告訴 Ansible 只有在從上次 ansible-pull
被調(diào)用以后庫(kù)有了變化后才會(huì)運(yùn)行。如果庫(kù)沒有任何變化,它將不會(huì)做任何事情。通過這個(gè)方法,你將不會(huì)無(wú)端的浪費(fèi) CPU 資源。當(dāng)然在拉取存儲(chǔ)庫(kù)的時(shí)候會(huì)使用一些 CPU 資源,但不會(huì)像再一次應(yīng)用整個(gè)配置的時(shí)候使用的那么多。當(dāng) ansible-pull
執(zhí)行的時(shí)候,它將會(huì)遍歷劇本和任務(wù)手冊(cè)中的所有任務(wù),但至少它不會(huì)毫無(wú)目的的運(yùn)行。
盡管我們已經(jīng)添加了所有必須的配置要素來(lái)自動(dòng)化 ansible-pull
,它仍然還不能正常的工作。ansible-pull
命令需要 sudo
的權(quán)限來(lái)運(yùn)行,這將允許它執(zhí)行系統(tǒng)級(jí)的命令。然而我們創(chuàng)建的用戶 ansible
并沒有被設(shè)置為以 sudo
的權(quán)限來(lái)執(zhí)行命令,因此當(dāng)定時(shí)作業(yè)觸發(fā)的時(shí)候,執(zhí)行將會(huì)失敗。通常我們可以使用命令 visudo
來(lái)手動(dòng)的去設(shè)置用戶 ansible
去擁有這個(gè)權(quán)限。然而我們現(xiàn)在應(yīng)該以 Ansible 的方式來(lái)操作,而且這將會(huì)是一個(gè)向你展示 copy
模塊是如何工作的機(jī)會(huì)。copy
模塊允許你從庫(kù)復(fù)制一個(gè)文件到文件系統(tǒng)的任何位置。在這個(gè)案列中,我們將會(huì)復(fù)制 sudo
的一個(gè)配置文件到 /etc/sudoers.d/
以便用戶 ansible
能夠以管理員的權(quán)限執(zhí)行任務(wù)。
打開 users.yml
,將下面的的動(dòng)作添加到文件末尾。
- name: copy sudoers_ansible
copy: src=files/sudoers_ansible dest=/etc/sudoers.d/ansible owner=root group=root mode=0440
正如我們看到的,copy
模塊從我們的倉(cāng)庫(kù)中復(fù)制一個(gè)文件到其他任何位置。在這個(gè)過程中,我們正在抓取一個(gè)名為 sudoers_ansible
(我們將在后續(xù)創(chuàng)建)的文件并將它復(fù)制為 /etc/sudoers/ansible
,并且擁有者為 root
。
接下來(lái),我們需要?jiǎng)?chuàng)建我們將要復(fù)制的文件。在你的倉(cāng)庫(kù)的根目錄下,創(chuàng)建一個(gè)名為 files
的目錄:
mkdir files
然后,在我們剛剛創(chuàng)建的 files
目錄里,創(chuàng)建名為 sudoers_ansible
的文件,包含以下內(nèi)容:
ansible ALL=(ALL) NOPASSWD: ALL
就像我們正在這樣做的,在 /etc/sudoer.d
目錄里創(chuàng)建一個(gè)文件允許我們?yōu)橐粋€(gè)特殊的用戶配置 sudo
權(quán)限。現(xiàn)在我們正在通過 sudo
允許用戶 ansible
不需要密碼提示就擁有完全控制權(quán)限。這將允許 ansible-pull
以后臺(tái)任務(wù)的形式運(yùn)行而不需要手動(dòng)去運(yùn)行。
現(xiàn)在,你可以通過再次運(yùn)行 ansible-pull
來(lái)拉取***的變動(dòng):
sudo ansible-pull -U https://github.com/<github_user>/ansible.git
從這里開始,ansible-pull
的定時(shí)作業(yè)將會(huì)在后臺(tái)每隔十分鐘運(yùn)行一次來(lái)檢查你的倉(cāng)庫(kù)是否有變化,如果它發(fā)現(xiàn)有變化,將會(huì)運(yùn)行你的劇本并且應(yīng)用你的任務(wù)手冊(cè)。
所以現(xiàn)在我們有了一個(gè)完整的可工作方案。當(dāng)你***次設(shè)置一臺(tái)新的筆記本或者臺(tái)式機(jī)的時(shí)候,你要去手動(dòng)的運(yùn)行 ansible-pull
命令,但僅僅是在***次的時(shí)候。從***次之后,用戶 ansible
將會(huì)在后臺(tái)接手后續(xù)的運(yùn)行任務(wù)。當(dāng)你想對(duì)你的機(jī)器做變動(dòng)的時(shí)候,你只需要簡(jiǎn)單的去拉取你的 Git 倉(cāng)庫(kù)來(lái)做變動(dòng),然后將這些變化回傳到庫(kù)中。接著,當(dāng)定時(shí)作業(yè)下次在每臺(tái)機(jī)器上運(yùn)行的時(shí)候,它將會(huì)拉取變動(dòng)的部分并應(yīng)用它們。你現(xiàn)在只需要做一次變動(dòng),你的所有工作站將會(huì)跟著一起變動(dòng)。這方法盡管有一點(diǎn)不同尋常,通常,你會(huì)有一個(gè)包含你的機(jī)器列表和不同機(jī)器所屬規(guī)則的清單文件。然而,ansible-pull
的方法,就像在文章中描述的,是管理工作站配置的非常有效的方法。
我已經(jīng)在我的 Github 倉(cāng)庫(kù)中更新了這篇文章中的代碼,所以你可以隨時(shí)去瀏覽來(lái)對(duì)比檢查你的語(yǔ)法。同時(shí)我將前一篇文章中的代碼移到了它自己的目錄中。
在第三部分,我們將通過介紹使用 Ansible 來(lái)配置 GNOME 桌面設(shè)置來(lái)結(jié)束這個(gè)系列。我將會(huì)告訴你如何設(shè)置你的墻紙和鎖屏壁紙、應(yīng)用一個(gè)桌面主題以及更多的東西。
同時(shí),到了布置一些作業(yè)的時(shí)候了,大多數(shù)人都有我們所使用的各種應(yīng)用的配置文件??赡苁?Bash、Vim 或者其他你使用的工具的配置文件?,F(xiàn)在你可以嘗試通過我們?cè)谑褂玫?Ansible 庫(kù)來(lái)自動(dòng)復(fù)制這些配置到你的機(jī)器中。在這篇文章中,我已將向你展示了如何去復(fù)制文件,所以去嘗試以下看看你是都已經(jīng)能應(yīng)用這些知識(shí)。