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