編者按:本文節(jié)選自節(jié)選自《基于Linux的企業(yè)自動化》第五章。“第5章,使用Ansible構建用于部署的虛擬機模板,通過構建虛擬機模板來探索部署Linux的最佳實踐,虛擬機模板將以實際操作的方式大規(guī)模部署在虛擬機管理程序上。”
名詞解釋:
- cloud-init: 提供云實例初始時自定義配置的能力,支持多個發(fā)行版和多個平臺;
- docker-compose:業(yè)務只需要單個容器場時,可以用docker命令管理。如果業(yè)務需要多個容器,可以用docker-compose定義和運行它們;
- Ansible-vault:提供文件和變量的加密能力,可以用于保護密碼等敏感數(shù)據(jù)。
5.3.3 編輯配置文件
到目前為止,我們已經(jīng)執(zhí)行的所有的配置工作都非常黑白分明,我們要么安裝一些東西(無論是一個文件或一個軟件包),或者我們可以同樣容易地刪除它(關于這一點的更多內(nèi)容在清理一節(jié)敘述)。但是,如果需要更微妙的內(nèi)容呢?在本章前面的“將文件傳輸?shù)接诚瘛币还?jié)中,我們將用我們自己的版本替換整個chrony.conf文件。然而,這可能有點太暴力了。例如,我們可能只需要更改文件中的一行,而將替換整個文件變成更改一行的工作量有點繁重,特別是當你考慮到配置文件可能會在將來的軟件包版本中更新時。
讓我們看看另一個常見的操作系統(tǒng)映像配置要求:SSH守護進程安全性。默認情況下,CentOS 7安裝(如我們之前創(chuàng)建的安裝)允許從root賬戶進行遠程登錄。出于安全原因,這是不可取的,所以問題是,我們?nèi)绾胃耂SH守護程序配置而不必替換整個文件呢?幸運的是,Ansible有用于此類任務的模塊。
要執(zhí)行此任務,lineinfile模塊將派上用場。考慮以下角色,我們將其稱為securesshd:
---
- name: Disable root logins over SSH
lineinfile:
dest: /etc/ssh/sshd_config
regexp: "^PermitRootLogin"
line: "PermitRootLogin no"
state: present
在這里,我們使用lineinfile模塊來處理/etc/ssh/sshd_config文件。
我們告訴它尋找以PermitRootLogin開頭的行(這可以防止我們意外地編輯已注釋掉的行),然后用PermitRootLogin no替換這一行。
讓我們在CentOS 7測試系統(tǒng)上嘗試一下:
這正是我們想要的。不過,編寫正則表達式需要非常小心。例如,SSH守護進程將處理在行首包含空格的配置行。但是,前面代碼中的簡單正則表達式不考慮空格,因此很容易錯過其他有效的SSH配置指令。考慮所有可能的情況和文件的排列來設計正則表達式本身就是一門藝術,因此在創(chuàng)建和使用正則表達式時一定要小心謹慎。
提示
請注意,在正在運行的系統(tǒng)上,你還需要重新啟動SSH服務以使此更改生效;但是,由于這是一個映像,我們將對其進行清理,然后關閉以供將來部署,因此無須在此處執(zhí)行此操作。
在上傳一個完整的文件和編輯一個現(xiàn)有的文件之間,使用模板是一個中間選擇。Ansible Jinja2模板功能非常強大,非常有用,因為文件的內(nèi)容可能會隨某些變量參數(shù)的變化而變化。
再次考慮前面的chrony配置示例,我們傳輸了一個靜態(tài)文件,其中包含一個硬編碼的NTP服務器地址。如果你的企業(yè)依賴于一個靜態(tài)NTP服務器(或一組靜態(tài)NTP服務器),那么這是很好的,但是有些服務器依賴于不同的NTP服務器,具體取決于要部署的映像的位置。
讓我們用一個名為templatentp的新角色來演示這一點。為了這個,我們將在roles/templatentp/templates中定義一個模板目錄,并將一個包含以下內(nèi)容的名為chrony.conf.j2的文件放在里面:
pool {{ ntpserver }} iburst maxsources 4
keyfile /etc/chrony/chrony.keys
driftfile /var/lib/chrony/chrony.drift
logdir /var/log/chrony
maxupdateskew 100.0
rtcsync
makestep 1 3
注意這個文件與前面的示例幾乎相同,只是我們現(xiàn)在在文件的第一行有一個Ansible變量名來代替靜態(tài)主機名。
讓我們創(chuàng)建此角色的main.yml文件如下:
---
- name: Deploy chrony configuration template
template:
src: templates/chrony.conf.j2
dest: /etc/chrony.conf
owner: root
group: root
mode: '0644'
backup: yes
請注意,它與copy示例非常相似。我們的site.yml也只是略有不同,我們將用NTP服務器主機名定義此變量。Ansible中有許多地方都可以定義此類變量,由用戶自行確定定義它的最佳位置:
---
- name: Run example roles
hosts: all
become: yes
vars:
ntpserver: time.example.com
roles:
- templatentp
最后,我們可以運行劇本并查看結果:
這樣,Ansible為你提供了強大的工具,不僅可以將整個配置復制或下載到位,還可以操縱現(xiàn)有配置以適應你的環(huán)境。
假設我們的映像現(xiàn)在已經(jīng)完成了。我們可以相信這一點,但良好的實踐表明,我們應該始終測試任何構建過程的結果,尤其是自動構建過程的結果。幸好,Ansible可以幫助我們驗證我們根據(jù)需求創(chuàng)建的映像,我們將在下一節(jié)中對此進行探討。
5.3.4 驗證映像構建
以及安裝和配置映像時,你可能還希望驗證某些關鍵組件以及你假定存在的組件是否確實存在。當你下載由其他人創(chuàng)建的映像時尤其如此。
在Ansible中,有許多方法都可以執(zhí)行此任務,我們舉一個簡單的例子。假設你有一個存檔腳本,它使用bzip2壓縮實用程序來壓縮文件。這只是一個很小的工具,但是如果你出于某些目的依賴它,那么如果它不存在,你的腳本就會中斷。這也是一個相關的例子,因為CentOS 7的最小安裝(正如我們之前執(zhí)行的)實際上并不包括它!如何解決這個問題呢?我們可以采取兩種方法。首先,我們從Ansible的早期背景工作中了解到,大多數(shù)模塊都是冪等的,也就是說,它們的設計目的是在目標主機上實現(xiàn)所需的狀態(tài),而不會重復已經(jīng)執(zhí)行的操作。
因此,我們可以很容易地在配置劇本中包含這樣一個角色:
---
- name: Ensure bzip2 is installed
yum:
name: bzip2
state: present
當運行此角色而未安裝bzip2時,它將執(zhí)行安裝并返回changed的結果。當它檢測到安裝了bzip2時,它將返回ok并且不執(zhí)行進一步的操作。然而,如果我們真的想檢查一些東西,而不是僅僅執(zhí)行一個操作,也許作為一個構建后步驟呢?在本書后面,我們將研究更詳細的審計系統(tǒng)的方法,但是現(xiàn)在,讓我們用Ansible進一步說明這個示例。
如果你使用的是shell命令,那么可以通過以下兩種方法之一檢查bzip2的存在,即查詢RPM數(shù)據(jù)庫以查看是否安裝了bzip2包,或者檢查文件系統(tǒng)上是否存在/bin/bzip2。
讓我們在Ansible中看看后一個示例。Ansible stat模塊可用于驗證文件是否存在。考慮以下代碼,我們將以常規(guī)的方式在名為checkbzip2的角色中創(chuàng)建這些代碼:
---
- name: Check for the existence of bzip2
stat:
path: /bin/bzip2
register: bzip2result
failed_when: bzip2result.stat.exists == false
- name: Display a message if bzip2 exists
debug:
msg: bzip2 installed.
這里,我們使用stat模塊告訴我們關于/bin/bzip2文件的狀態(tài)(是否存在)。我們在一個名為bzip2result的變量中register(注冊)stat模塊運行的結果,然后在任務上定義一個自定義故障條件,如果文件不存在,該條件將導致任務失敗(從而使整個劇本運行失敗)。請注意,當遇到故障情況時,Ansible會停止整個劇本的運行,迫使你在繼續(xù)之前解決問題。
顯然,這可能是你想要的行為,也可能不是,但是很容易相應地改變故障條件。
2.讓我們實際看看這個:
如你所見,由于遇到故障,debug語句從未運行過。因此,在運行這個角色時,我們完全可以確定我們的映像將安裝bzip2,如果不安裝,我們的劇本將失敗。
3.一旦安裝了bzip2,運行情況看起來就完全不同了:
它的行為非常明確,這正是我們想要的。Ansible不僅僅局限于檢查文件,盡管我們還可以檢查sshd_config文件是否具有我們之前查看過的Permitrologin no行:
1.我們可以使用如下角色來完成此操作:
---
- name: Check root login setting in sshd_config
command: grep -e "^PermitRootLogin no" /etc/ssh/sshd_config
register: grepresult
failed_when: grepresult.rc != 0
- name: Display a message if root login is disabled
debug:
msg: root login disabled for SSH
2.現(xiàn)在,在設置未就位時再次運行此命令將導致故障:
3.然而,如果我們把這個設置到位,我們會看到以下情況:
同樣,這是非常明確的。注意前面輸出中的changed狀態(tài),這是因為我們使用了command(命令)模塊,它成功地運行了命令,因此,它總是返回changed。如果需要的話,我們可以通過對該任務使用changed_when子句來更改此行為。
通過這種方式,多個Ansible 劇本可以放在一起,不僅可以自定義構建,還可以驗證最終結果。這對于測試目的,并且安全性是一個考慮因素時尤其有用。
在完成本章之前,讓我們在下一節(jié)中看一看,我們?nèi)绾螌⑽覀兤駷橹褂懻撨^的所有不同角色和代碼片段組合在一起,形成一個內(nèi)聚的自動化解決方案。
5.3.5 綜合
在本章的這一節(jié)中,你將注意到我們在所有示例中都使用了角色。當然,當談到建立你的最終映象時,你不想像我們在這里所做的那樣單獨運行大量的劇本。幸運的是,如果我們要合并所有內(nèi)容,我們需要做的就是將所有角色全都放在roles/子目錄中,然后在site.yml劇本中引用它們。角色目錄應該是這樣的:
~/hands-on-automation/chapter05/example09/roles> tree -d
.
├── checkbzip2
│ └── tasks
├── checksshdroot
│ └── tasks
├── filecopyexample
│ ├── files
│ └── tasks
├── installbzip2
│ └── tasks
├── packageinstall
│ └── tasks
├── securesshd
│ └── tasks
└── templatentp
├── tasks
└── templates
然后,我們的site.yml文件將如下所示:
---
- name: Run example roles
hosts: all
become: yes
roles:
- filecopyexample
- packageinstall
- templatentp
- installbzip2
- securesshd
- checkbzip2
- checksshdroot
運行此代碼留給讀者作為練習,因為我們已經(jīng)在本章前面運行了它的所有組成部分。但是,如果一切順利,那么當所有角色都完成時,應該沒有failed的狀態(tài),只有changed和ok的混合狀態(tài)。
如果你已經(jīng)完成了構建后定制的過程(如本章所述),那么生成的映像可能需要再次清理。我們可以再次使用virtsysprep命令,不過,Ansible也可以幫助我們。在下一節(jié)中,我們將探討如何使用Ansible清理映像以進行大規(guī)模部署。
-
Linux
+關注
關注
87文章
11225瀏覽量
208911 -
容器
+關注
關注
0文章
494瀏覽量
22044 -
虛擬機
+關注
關注
1文章
908瀏覽量
28086
原文標題:使用Ansible構建虛擬機模板二
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論