使用 Ansible 來管理你的工作站:設定自動化

2019-01-16 16:25:00

學習如何使 Ansible 自動對一系列桌上型電腦和筆電應用設定。

Ansible 是一個令人驚訝的自動化的設定管理工具。其主要應用在伺服器和雲部署上,但在工作站上的應用(無論是桌上型電腦還是筆電)卻鮮少得到關注,這就是本系列所要關注的。

在這個系列的,我向你展示了 ansible-pull 命令的基本用法,我們建立了一個安裝了少量包的劇本。它本身是沒有多大的用處的,但是為後續的自動化做了準備。

在這篇文章中,將會達成閉環,而且在最後部分,我們將會有一個針對工作站自動設定的完整的工作解決方案。現在,我們將要設定 Ansible 的設定,這樣未來將要做的改變將會自動的部署應用到我們的工作站上。現階段,假設你已經完成了的工作。如果沒有的話,當你完成的時候回到本文。你應該已經有一個包含第一篇文章中程式碼的 GitHub 庫。我們將直接在之前建立的部分之上繼續。

首先,因為我們要做的不僅僅是安裝包檔案,所以我們要做一些重新的組織工作。現在,我們已經有一個名為 local.yml 並包含以下內容的劇本:

- hosts: localhost  become: true  tasks:  - name: Install packages    apt: name={{item}}    with_items:      - htop      - mc      - tmux

如果我們僅僅想實現一個任務那麼上面的設定就足夠了。隨著向我們的設定中不斷的新增內容,這個檔案將會變的相當的龐大和雜亂。最好能夠根據不同型別的設定將我們的動作play分為獨立的檔案。為了達到這個要求,建立一個名為任務手冊taskbook的東西,它和劇本playbook很像但內容更加的流線型。讓我們在 Git 庫中為任務手冊建立一個目錄。

mkdir tasks

local.yml 劇本中的程式碼可以很好地過渡為安裝包檔案的任務手冊。讓我們把這個檔案移動到剛剛建立好的 task 目錄中,並重新命名。

mv local.yml tasks/packages.yml

現在,我們編輯 packages.yml 檔案將它進行大幅的瘦身,事實上,我們可以精簡除了獨立任務本身之外的所有內容。讓我們把 packages.yml 編輯成如下的形式:

- name: Install packages  apt: name={{item}}  with_items:    - htop    - mc    - tmux

正如你所看到的,它使用同樣的語法,但我們去掉了對這個任務無用沒有必要的所有內容。現在我們有了一個專門安裝包檔案的任務手冊。然而我們仍然需要一個名為 local.yml 的檔案,因為執行 ansible-pull 命令時仍然會去找這個檔案。所以我們將在我們庫的根目錄下(不是在 task 目錄下)建立一個包含這些內容的全新檔案:

- hosts: localhost  become: true  pre_tasks:    - name: update repositories      apt: update_cache=yes      changed_when: False  tasks:    - include: tasks/packages.yml

這個新的 local.yml 扮演的是匯入我們的任務手冊的索引的角色。我已經在這個檔案中新增了一些你在這個系列中還沒見到的內容。首先,在這個檔案的開頭處,我新增了 pre_tasks,這個任務的作用是在其他所有任務執行之前先執行某個任務。在這種情況下,我們給 Ansible 的命令是讓它去更新我們的發行版的軟體庫的索引,下面的設定將執行這個任務要求:

apt: update_cache=yes

通常 apt 模組是用來安裝包檔案的,但我們也能夠讓它來更新軟體庫索引。這樣做的目的是讓我們的每個動作在 Ansible 執行的時候能夠以最新的索引工作。這將確保我們在使用一個老舊的索引安裝一個包的時候不會出現問題。因為 apt 模組僅僅在 Debian、Ubuntu 及它們的衍生發行版下工作。如果你執行的一個不同的發行版,你要使用特定於你的發行版的模組而不是 apt。如果你需要使用一個不同的模組請檢視 Ansible 的相關文件。

下面這行也需要進一步解釋:

changed_when: False

在某個任務中的這行阻止了 Ansible 去報告動作改變的結果,即使是它本身在系統中導致的一個改變。在這裡,我們不會去在意庫索引是否包含新的資料;它幾乎總是會的,因為庫總是在改變的。我們不會去在意 apt 庫的改變,因為索引的改變是正常的過程。如果我們刪除這行,我們將在過程報告的後面看到所有的變動,即使僅僅庫的更新而已。最好忽略這類的改變。

接下來是常規任務的階段,我們將建立好的任務手冊匯入。我們每次新增另一個任務手冊的時候,要新增下面這一行:

tasks:  - include: tasks/packages.yml

如果你現在執行 ansible-pull 命令,它應該基本上像上一篇文章中做的一樣。不同的是我們已經改進了我們的組織方式,並且能夠更有效的擴充套件它。為了節省你到上一篇文章中去尋找,ansible-pull 命令的語法參考如下:

sudo ansible-pull -U https://github.com/<github_user>/ansible.git

如果你還記得話,ansible-pull 的命令拉取一個 Git 倉庫並且應用它所包含的設定。

既然我們的基礎已經搭建好,我們現在可以擴充套件我們的 Ansible 並且新增功能。更特別的是,我們將新增設定來自動化的部署對工作站要做的改變。為了支撐這個要求,首先我們要建立一個特殊的賬戶來應用我們的 Ansible 設定。這個不是必要的,我們仍然能夠在我們自己的使用者下執行 Ansible 設定。但是使用一個隔離的使用者能夠將其隔離到不需要我們參與的在後台執行的一個系統進程中,

我們可以使用常規的方式來建立這個使用者,但是既然我們正在使用 Ansible,我們應該盡量避開使用手動的改變。替代的是,我們將會建立一個任務手冊來處理使用者建立任務。這個任務手冊目前將會僅僅建立一個使用者,但你可以在這個任務手冊中新增額外的動作來建立更多的使用者。我將這個使用者命名為 ansible,你可以按照自己的想法來命名(如果你做了這個改變要確保更新所有出現地方)。讓我們來建立一個名為 user.yml 的任務手冊並且將以下程式碼寫進去:

- name: create ansible user  user: name=ansible uid=900

下一步,我們需要編輯 local.yml 檔案,將這個新的任務手冊新增進去,像如下這樣寫:

- 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

現在當我們執行 ansible-pull 命令的時候,一個名為 ansible 的使用者將會在系統中被建立。注意我特地通過引數 uid 為這個使用者宣告了使用者 ID 為 900。這個不是必須的,但建議直接建立好 UID。因為在 1000 以下的 UID 在登入介面是不會顯示的,這樣是很棒的,因為我們根本沒有需要去使用 ansibe 賬戶來登入我們的桌面。UID 900 是隨便定的;它應該是在 1000 以下沒有被使用的任何一個數值。你可以使用以下命令在系統中去驗證 UID 900 是否已經被使用了:

cat /etc/passwd |grep 900

不過,你使用這個 UID 應該不會遇到什麼問題,因為迄今為止在我使用的任何發行版中我還沒遇到過它是被預設使用的。

現在,我們已經擁有了一個名為 ansible 的賬戶,它將會在之後的自動化設定中使用。接下來,我們可以建立實際的定時作業來自動操作。我們應該將其分開放到它自己的檔案中,而不是將其放置到我們剛剛建立的 users.yml 檔案中。在任務目錄中建立一個名為 cron.yml 的任務手冊並且將以下的程式碼寫進去:

- 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 模組的語法幾乎不需加以說明。通過這個動作,我們建立了一個通過使用者 ansible 執行的定時作業。這個作業將每隔 10 分鐘執行一次,下面是它將要執行的命令:

/usr/bin/ansible-pull -o -U https://github.com/<github_user>/ansible.git > /dev/null

同樣,我們也可以新增想要我們的所有工作站部署的額外的定時作業到這個檔案中。我們只需要在新的定時作業中新增額外的動作即可。然而,僅僅是新增一個定時的任務手冊是不夠的,我們還需要將它新增到 local.yml 檔案中以便它能夠被呼叫。將下面的一行新增到末尾:

- include: tasks/cron.yml

現在當 ansible-pull 命令執行的時候,它將會以使用者 ansible 每隔十分鐘設定一個新的定時作業。但是,每個十分鐘執行一個 Ansible 作業並不是一個好的方式,因為這個將消耗很多的 CPU 資源。每隔十分鐘來執行對於 Ansible 來說是毫無意義的,除非我們已經在 Git 倉庫中改變一些東西。

然而,我們已經解決了這個問題。注意我在定時作業中的命令 ansible-pill 新增的我們之前從未用到過的引數 -o。這個引數告訴 Ansible 只有在從上次 ansible-pull 被呼叫以後庫有了變化後才會執行。如果庫沒有任何變化,它將不會做任何事情。通過這個方法,你將不會無端的浪費 CPU 資源。當然在拉取儲存庫的時候會使用一些 CPU 資源,但不會像再一次應用整個設定的時候使用的那麼多。當 ansible-pull 執行的時候,它將會遍歷劇本和任務手冊中的所有任務,但至少它不會毫無目的的執行。

儘管我們已經新增了所有必須的設定要素來自動化 ansible-pull,它仍然還不能正常的工作。ansible-pull 命令需要 sudo 的許可權來執行,這將允許它執行系統級的命令。然而我們建立的使用者 ansible 並沒有被設定為以 sudo 的許可權來執行命令,因此當定時作業觸發的時候,執行將會失敗。通常我們可以使用命令 visudo 來手動的去設定使用者 ansible 去擁有這個許可權。然而我們現在應該以 Ansible 的方式來操作,而且這將會是一個向你展示 copy 模組是如何工作的機會。copy 模組允許你從庫複製一個檔案到檔案系統的任何位置。在這個案列中,我們將會複製 sudo 的一個組態檔到 /etc/sudoers.d/ 以便使用者 ansible 能夠以管理員的許可權執行任務。

開啟 users.yml,將下面的的動作新增到檔案末尾。

- name: copy sudoers_ansible  copy: src=files/sudoers_ansible dest=/etc/sudoers.d/ansible owner=root group=root mode=0440

正如我們看到的,copy模組從我們的倉庫中複製一個檔案到其他任何位置。在這個過程中,我們正在抓取一個名為 sudoers_ansible(我們將在後續建立)的檔案並將它復制為 /etc/sudoers/ansible,並且擁有者為 root

接下來,我們需要建立我們將要複製的檔案。在你的倉庫的根目錄下,建立一個名為 files 的目錄:

mkdir files

然後,在我們剛剛建立的 files 目錄裡,建立名為 sudoers_ansible 的檔案,包含以下內容:

ansible ALL=(ALL) NOPASSWD: ALL

就像我們正在這樣做的,在 /etc/sudoer.d 目錄裡建立一個檔案允許我們為一個特殊的使用者設定 sudo 許可權。現在我們正在通過 sudo 允許使用者 ansible 不需要密碼提示就擁有完全控制許可權。這將允許 ansible-pull 以後台任務的形式執行而不需要手動去執行。

現在,你可以通過再次執行 ansible-pull 來拉取最新的變動:

sudo ansible-pull -U https://github.com/<github_user>/ansible.git

從這裡開始,ansible-pull 的定時作業將會在後台每隔十分鐘執行一次來檢查你的倉庫是否有變化,如果它發現有變化,將會執行你的劇本並且應用你的任務手冊。

所以現在我們有了一個完整的可工作方案。當你第一次設定一台新的筆電或者桌上型電腦的時候,你要去手動的執行 ansible-pull 命令,但僅僅是在第一次的時候。從第一次之後,使用者 ansible 將會在後台接手後續的執行任務。當你想對你的機器做變動的時候,你只需要簡單的去拉取你的 Git 倉庫來做變動,然後將這些變化回傳到庫中。接著,當定時作業下次在每台機器上執行的時候,它將會拉取變動的部分並應用它們。你現在只需要做一次變動,你的所有工作站將會跟著一起變動。這方法儘管有一點不同尋常,通常,你會有一個包含你的機器列表和不同機器所屬規則的清單檔案。然而,ansible-pull 的方法,就像在文章中描述的,是管理工作站設定的非常有效的方法。

我已經在我的 Github 倉庫中更新了這篇文章中的程式碼,所以你可以隨時去瀏覽來對比檢查你的語法。同時我將前一篇文章中的程式碼移到了它自己的目錄中。

第三部分,我們將通過介紹使用 Ansible 來設定 GNOME 桌面設定來結束這個系列。我將會告訴你如何設定你的牆紙和鎖屏桌布、應用一個桌面主題以及更多的東西。

同時,到了布置一些作業的時候了,大多數人都有我們所使用的各種應用的組態檔。可能是 Bash、Vim 或者其他你使用的工具的組態檔。現在你可以嘗試通過我們在使用的 Ansible 庫來自動複製這些設定到你的機器中。在這篇文章中,我已將向你展示了如何去複製檔案,所以去嘗試以下看看你是都已經能應用這些知識。