編者按:本文節(jié)選自節(jié)選自《基于Linux的企業(yè)自動化》第五章。“第5章,使用Ansible構(gòu)建用于部署的虛擬機(jī)模板,通過構(gòu)建虛擬機(jī)模板來探索部署Linux的最佳實(shí)踐,虛擬機(jī)模板將以實(shí)際操作的方式大規(guī)模部署在虛擬機(jī)管理程序上。”
名詞解釋:
- cloud-init: 提供云實(shí)例初始時自定義配置的能力,支持多個發(fā)行版和多個平臺;
- docker-compose:業(yè)務(wù)只需要單個容器場時,可以用docker命令管理。如果業(yè)務(wù)需要多個容器,可以用docker-compose定義和運(yùn)行它們;
- Ansible-vault:提供文件和變量的加密能力,可以用于保護(hù)密碼等敏感數(shù)據(jù)。
以下是原文
5.3 使用Ansible來構(gòu)建和標(biāo)準(zhǔn)化模板
你現(xiàn)在應(yīng)該有一個基本的Linux映像,以便在企業(yè)中部署。如果你選擇下載一個現(xiàn)成的模板(或者確實(shí)是使用公共云提供商提供的模板),那么你的映像將是一個非常空白的模板,隨時可以定制。如果你之前選擇構(gòu)建自己的映像,那么你可能已經(jīng)選擇執(zhí)行了少量定制,例如我們之前執(zhí)行的cloud-init安裝。然而,你會注意到,我們是手工完成這些的,這與我們在本書早期所稱贊的可伸縮、可重復(fù)、可審核的流程很不一樣。在我們繼續(xù)閱讀本章的這一節(jié)時,我們將了解如何使用Ansible自定義一個基本模板,而不管它來自何處。
沒有適合所有人的普適的Linux映像,因此,本章介紹的方法并不一定是最佳的。但是,我們將研究一些與自定義為要部署的映像相關(guān)聯(lián)的更常見的任務(wù),例如:
將文件傳輸?shù)接诚裰?/p>
安裝軟件包
編輯配置文件
驗(yàn)證映像
通過這些示例的組合,大多數(shù)讀者都應(yīng)該能夠輕松地根據(jù)自己的需求定制自己的映像。讓我們開始更深入地探討這個問題,看看如何將文件傳輸?shù)轿覀冎笆褂肁nsible創(chuàng)建的虛擬機(jī)映像中。
5.3.1 將文件傳輸?shù)接诚裰?/strong>
根據(jù)作者的經(jīng)驗(yàn),通常需要將文件注入(inject)到操作系統(tǒng)映像中,以確保它滿足給定的一組要求。這些文件可能是簡單的文本文件,例如當(dāng)前的企業(yè)標(biāo)準(zhǔn)每日消息(message of the day)、現(xiàn)有軟件包的配置文件,甚至可能是軟件包中不存在的二進(jìn)制文件。Ansible可以輕松地處理所有這些問題,所以讓我們看一些具體的例子。一般來說,在角色中編寫Ansible代碼以支持重用和可讀性是一種很好的做法,因此我們將在這里為示例定義一個角色。在這個例子中,我做了以下假設(shè):
我們已經(jīng)下載/構(gòu)建了本章上一節(jié)中概述的Linux模板。
我們正在虛擬機(jī)中運(yùn)行此裸模板。
此虛擬機(jī)的IP地址為192.168.81.141。
虛擬機(jī)已使用以下憑據(jù)設(shè)置了用戶賬戶:
用戶名:imagebuild。
口令:Password。
此賬戶已啟用sudo。
很自然,我們不會分發(fā)一個其中包含一個使用這樣的弱口令的啟用sudo的賬戶的云映像,因此我們假設(shè)我們只在構(gòu)建階段使用該賬戶,然后在清理階段將其刪除。Ansible需要能夠連接到遠(yuǎn)程主機(jī)來執(zhí)行它的工作,但是它使用的賬戶在本質(zhì)上可能是暫時的,并且在使用后會被刪除:
1.在我們的示例中,我們將創(chuàng)建一個類似于下面的清單文件。你的實(shí)際清單文件無疑會有所不同,為你的映像和環(huán)境定制它是留給你的一個練習(xí):
[imagesetup]
192.168.81.141
[imagesetup:vars]
ansible_user=imagebuild
ansible_password=password
ansible_sudo_pass=password
這是一個非常簡單的示例;在許多方面,當(dāng)我們沒有配置SSH密鑰身份驗(yàn)證時,它是這個過程所需的最低限度的配置。SSH密鑰通常是處理SSH身份驗(yàn)證的最佳方法,因?yàn)樗鼈兲峁┝艘恍┖锰帲绕涫侨蝿?wù)可以在沒有口令提示的情況下運(yùn)行。
提示
盡管此清單文件本質(zhì)上是暫時的,但使用ansible-vault存儲口令仍然是最佳實(shí)踐,這里建議這樣做。為了本章的簡單性和減少你需要完成的步驟的數(shù)量,我們將不加密口令(采用明文)。
接下來,我們將為角色創(chuàng)建基本目錄結(jié)構(gòu):
$ mkdir -p roles/filecopyexample/tasks
$ mkdir -p roles/filecopyexample/files
3.現(xiàn)在,讓我們創(chuàng)建幾個示例文件進(jìn)行復(fù)制。首先,創(chuàng)建一個要附加到roles/filecopyexample/files/motd中的當(dāng)天消息的自定義消息:
------------------------
Enteprise Linux Template
Created with Ansible
-----------------------
4.我們還要為chrony服務(wù)創(chuàng)建一個新的配置文件來同步我們的公司時間服務(wù)器,在roles/filecopyexample/files/chrony.conf中輸入:
pool ntp.example.com 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
我們打算將這兩個文件復(fù)制到遠(yuǎn)程服務(wù)器。但是,Ansible并不局限于從Ansible主機(jī)復(fù)制文件,它還可以將文件從遠(yuǎn)程服務(wù)器直接下載到目標(biāo)主機(jī):
1.假設(shè)你的構(gòu)建需要docker-compose,我們可以從內(nèi)部服務(wù)器下載它,如果你的映像服務(wù)器可以訪問internet,甚至可以直接從internet下載。假設(shè)我們想在映像中安裝docker-compose1.18.0,我們可以指示Ansible直接從https://github.com/docker/compose/releases/download/1.18.0/docker-compose-Linux-x86_64下載。
2.現(xiàn)在,讓我們構(gòu)建我們的角色來復(fù)制兩個文件并把docker-compose下載到我們的映像中,這必須寫在roles/filecopyexample/tasks/main.yml中。此角色的第一部分顯示在以下代碼中,用于跨我們前面討論的兩個配置文件進(jìn)行復(fù)制:
---
- name: Copy new MOTD file, and backup any existing file if it exists
copy:
src: files/motd
dest: /etc/motd
owner: root
group: root
mode: '0644'
backup: yes
- name: Copy across new chrony configuration, and backup anyexisting file if it exists
copy:
src: files/chrony.conf
dest: /etc/chrony.conf
owner: root
group: root
mode: '0644'
backup: yes
然后此角色繼續(xù)在VM映像上安裝docker-compose的任務(wù):
- name: Install docker-compose 1.18.0
get_url:
url: https://github.com/docker/compose/releases/download/1.18.0/docker-compose-Linux-x86_64
dest: /usr/local/bin/docker-compose
mode: 0755
owner: root
group: root
因此,我們的角色現(xiàn)在已經(jīng)完成了,不過請確保為你的環(huán)境正確定制它。例如,docker-compose可能有較新的版本,這意味著前面的get_url模塊的url參數(shù)將發(fā)生更改。
提示
chrony配置文件的路徑可能會因操作系統(tǒng)而異。請在運(yùn)行前面的劇本之前檢查此項(xiàng)。示例中顯示的路徑適用于CentOS 7系統(tǒng),正如我們先前構(gòu)建的系統(tǒng)。
3.最后,我們將在頂級目錄中(從中創(chuàng)建roles/目錄)創(chuàng)建一個供調(diào)用的site.yml文件,并運(yùn)行此角色。這應(yīng)該包含以下內(nèi)容:
---
- name: Run example roles
hosts: all
become: yes
roles:
- filecopyexample
4.最后,讓我們用ansible-playbook -i hostssite.yml命令運(yùn)行我們的示例并查看發(fā)生了什么:
如我們所見,changed的狀態(tài)告訴我們所有三個文件都已成功傳輸或下載,作為示例,我們可以看到現(xiàn)在可以運(yùn)行docker-compose了,它是在劇本運(yùn)行期間安裝的(盡管這需要Docker正確運(yùn)行,在本例中沒有安裝它)。
顯然,這個示例已經(jīng)做出了一個基本假設(shè),即在構(gòu)建階段,chrony包安裝在我們的示例映像上。盡管出于我們前面討論的原因,從一個最小的操作系統(tǒng)映像開始是有意義的,但幾乎可以肯定的是,在基本構(gòu)建之上安裝一些補(bǔ)充軟件包是有必要的,我們將在下一節(jié)中對此進(jìn)行探討。
5.3.2 安裝軟件包
我們在上一節(jié)中已經(jīng)介紹了如何安裝獨(dú)立的二進(jìn)制文件,如docker-compose,但是如果我們需要實(shí)際安裝一些未安裝在我們的基本映像中的其他操作系統(tǒng)軟件包呢?例如,cloud-init在大多數(shù)云環(huán)境中非常有用,但它沒有包含在我們之前執(zhí)行的CentOS 7最小安裝中。
在這里,Ansible同樣可以提供幫助,這次,我們將定義一個角色來安裝我們需要的軟件包。我們將重用上一節(jié)中的清單文件,并以與之前相同的方式創(chuàng)建一個名為packageinstall的新角色:
1.現(xiàn)在,前面關(guān)于復(fù)制文件的示例將適用于所有Linux分發(fā)版,唯一需要注意的是目標(biāo)文件存在的位置可能不同。例如,CentOS 7虛擬機(jī)映像將在/etc/chrony.conf中安裝chrony配置文件,而Ubuntu 18.04 LTS服務(wù)器將在/etc/chrony/chrony.conf中安裝它。除了對copy模塊的dest:參數(shù)的這一小改動之外,代碼將保持不變。
遺憾的是,軟件包的安裝會變得更復(fù)雜一些。
2.假設(shè)我們想在CentOS 7 2示例映像上安裝cloud-init和docker,執(zhí)行此操作所需的角色可能如下所示:
---
- name: Install the epel-release package
yum:
name: epel-release
state: present
- name: Install cloud-init and docker
yum:
name: "{{ item }}"
state: present
loop:
- cloud-init
- docker
3.我們必須先安裝EPEL存儲庫,然后才能安裝所需的軟件包裝。當(dāng)我們運(yùn)行它時,輸出應(yīng)該是這樣的:
如果你使用的是不同的Linux發(fā)行版,那么你需要相應(yīng)地改變包管理器。例如,在使用apt包管理器的發(fā)行版(如Debian或Ubuntu)上,等效的Ansible角色類似于以下代碼塊:
---
- name: Install cloud-init and docker
apt:
name: "{{ item }}"
state: present
loop:
- cloud-init
- docker.io
注意模塊從yum到apt的變化,以及用于Docker容器服務(wù)的不同軟件包名。除此之外,劇本幾乎是一模一樣的。
我們可以進(jìn)一步改進(jìn),這種不同導(dǎo)致了需要為兩種不同的操作系統(tǒng)基礎(chǔ)維護(hù)兩個不同的角色,但是如果我們可以智能地將它們組合成一個角色呢?幸運(yùn)的是,Ansible在第一次運(yùn)行時收集的事實(shí)可以用來識別操作系統(tǒng),從而運(yùn)行正確的代碼。
我們將重新利用前面的示例代碼,將這兩個安裝組合成一個Ansible角色:
1.代碼的第一部分與前面的示例幾乎相同,只是我們現(xiàn)在已經(jīng)指定了when子句,以確保它只在基于Debian或Ubuntu的Linux發(fā)行版上運(yùn)行:
---
- name: Install cloud-init and docker
apt:
name: "{{ item }}"
state: present
loop:
- cloud-init
- docker.io
when: ansible_distribution == 'Debian' or ansible_distribution =='Ubuntu'
2.我們再添加兩個在CentOS或Red Hat Enterprise Linux上執(zhí)行安裝Docker 所需的步驟:
- name: Install the epel-release package
yum:
name: epel-release
state: present
when: ansible_distribution == 'CentOS' or ansible_distribution =='Red Hat enterprise Linux'
- name: Install cloud-init and docker
yum:
name: "{{ item }}"
state: present
loop:
- cloud-init
- docker
when: ansible_distribution == 'CentOS' or ansible_distribution =='Red Hat enterprise Linux'
再次注意每個任務(wù)下的when子句,這些具體示例用于根據(jù)Ansible在運(yùn)行的初始部分獲得的事實(shí)來確定是否應(yīng)該運(yùn)行任務(wù)。因此,如果我們現(xiàn)在在Ubuntu系統(tǒng)上運(yùn)行這個角色,我們會看到以下內(nèi)容:
3.如你所見,與apt相關(guān)的第一個任務(wù)是運(yùn)行的,但是下面基于yum的的兩個任務(wù)由于不滿足when子句的條件,已被跳過。現(xiàn)在,如果我們在CentOS 7目標(biāo)上運(yùn)行它,我們會看到:
現(xiàn)在情況正好相反:apt任務(wù)被跳過,但運(yùn)行了兩個與yum相關(guān)的任務(wù)。
通過這種方式,即使在處理幾個不同的基本操作系統(tǒng)時,也可以維護(hù)單個角色來安裝一組通用的軟件包需求。將when子句與Ansible事實(shí)相結(jié)合是一種非常有效的方法,可以確保單個代碼庫在跨各種系統(tǒng)時的正確行為,因此如果你的SOE確實(shí)擴(kuò)展到基于Debian和RedHat的系統(tǒng),那么你仍然可以輕松簡單地維護(hù)代碼。
一旦安裝了補(bǔ)充軟件包,通常必須對其進(jìn)行配置才能使其有用。在下一節(jié)中,我們將探討Ansible在編輯配置文件中的用法。
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7233瀏覽量
90725 -
Linux
+關(guān)注
關(guān)注
87文章
11420瀏覽量
212298 -
虛擬機(jī)
+關(guān)注
關(guān)注
1文章
955瀏覽量
28874
原文標(biāo)題:使用Ansible構(gòu)建虛擬機(jī)模板
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論