課程指數(shù)
難度指數(shù): 4星(滿星5星)
技術(shù)指數(shù): 5星(滿星5星)
理論指數(shù): 3星(滿星5星)
面向人群: 自動(dòng)化運(yùn)維&初中級(jí)運(yùn)維
分享目錄
1.1 添加額外的源 1
1.2 部署一個(gè)Node.js app 4
1.3 運(yùn)行一個(gè)Node.js app 6
1.4 Node.js app服務(wù)器總結(jié)。 7
1.5 問題: 7
下面我們將要在我們的CentOS6.x服務(wù)器上配置Nodejs硬萍,啟動(dòng)一個(gè)簡單的nodejs實(shí)例绊起,這個(gè)服務(wù)器有很簡單的架構(gòu)际跪。
開始了洲劣,首先創(chuàng)建一個(gè)playbook文件,我們盡量讓它保持簡單。
---
- hosts: all
tasks:
定義一些運(yùn)行這個(gè)playbook的主機(jī)默责,然后下面列出一系列的tasks。
1.1 添加額外的源
在準(zhǔn)備應(yīng)用一個(gè)服務(wù)器的時(shí)候咸包,為了確保指定些軟件包可以用或者在最新的版本桃序,管理員經(jīng)常首先添加額外的源。
下面的腳本烂瘫,我們想要添加EPEL和Remi源媒熊,以便于我們可以得到類似node.js的軟件包。如果使用shell腳本處理的話坟比,如下所示芦鳍。
# 導(dǎo)入 Remi GPG 密鑰 – 請參閱: http://rpms.famillecollet.com/RPM-GPG-KEY-remi
wget http://rpms.famillecollet.com/RPM-GPG-KEY-remi \
-O /etc/pki/rpm-gpg/RPM-GPG-KEY-remi
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-remi
# 安裝 Remi repo, Remi repo里面包含了很多的PHP擴(kuò)展
rpm -Uvh --quiet \
http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
# 安裝EPEL源
yum install epel-release
# 安裝 Node.js (npm + 和它的依賴關(guān)系).
yum --enablerepo=epel install npm
這個(gè)shell腳本用于導(dǎo)入EPEL和Remi的GPG keys葛账,然后添加這源柠衅,最后安裝Nodejs。這對(duì)于簡單的部署是沒有問題的籍琳,但是運(yùn)行這么多命令是比較笨的方法菲宴,如果你的連接不小心斷開了贷祈,那么你的腳本也會(huì)停止的。而如果這個(gè)時(shí)候喝峦,你的腳本剛準(zhǔn)備完成呢势誊?
提示:如果你想跳過指定的步驟,你可以跳過添加GPG keys的步驟谣蠢,只需要在運(yùn)行命令的時(shí)候加上—nogpgcheck.或者在Ansible中键科,yum模塊中設(shè)置disable_gpg_check參數(shù)為yes,但是最好還是添加GPG keys漩怎。使用GPG勋颖,你可以知道包的作者是誰,包有沒有修改稿勋锤,除非你知道你正在做什么饭玲,否則最好不要禁止GPG檢查。
Ansible讓事情變的更有健壯性叁执,下面使用Ansible的案例顯得更加詳細(xì)茄厘,它和上面的shell腳本有同樣的功能,但是更容易理解谈宛,更加結(jié)構(gòu)化次哈。 下面使用了Ansible的變量和其它的一些有用的特性。接著上面的playbook吆录,我們繼續(xù)往下寫窑滞。
tasks:
- name: Import Remi GPG key
rpm_key: "key={{ item }} state=present"
with_items:
- "http://rpms.famillecollet.com/RPM-GPG-KEY-remi"
- name: Install Remi repo.
command: "rpm -Uvh --force {{ item.href }} creates={{ item.creates }}"
with_items:
- href: "http://rpms.famillecollet.com/enterprise/remi-release-6.rpm"
creates: "/etc/yum.repos.d/remi.repo"
- name: Install epel repo
yum: name=epel-release state=present
- name: Stop the firewall
service: name=iptables state=stopped
- name: Install NodeJS and npm
yum: name=npm state=present enablerepo=epel
我們看一下具體步驟。
- rpm_key 是一個(gè)的Ansible模塊用于從你的RPM數(shù)據(jù)庫中添加或移除GPG key恢筝。我們正在從Remi的源中導(dǎo)入一個(gè)key哀卫。
- 因?yàn)锳nsible沒有rpm命令,因此我們使用command模塊來使用rpm命令撬槽,這樣我們可以做其它的兩件事情此改。
a) 使用creatse參數(shù)告訴Ansible什么時(shí)候不運(yùn)行這個(gè)命令,這個(gè)例子里侄柔,我們告訴Ansible共啃,這個(gè)命令成功執(zhí)行后,將會(huì)創(chuàng)建那些文件暂题。當(dāng)這個(gè)文件存在的時(shí)候移剪,這個(gè)命令將不會(huì)運(yùn)行。
b) 使用with_items定義一個(gè)URL和用于creates檢查的文件敢靡。 - yum負(fù)責(zé)安裝EPEL源挂滓。
- 因?yàn)檫@個(gè)服務(wù)器我們將用來做測試用,所以我們使用service模塊禁止系統(tǒng)防火墻,防止它干涉我們測試赶站。
- yum安裝Node.js(同時(shí)安裝npm幔虏,Node’s package manager),我們使用enablerepo來指定在EPEL源中搜索它贝椿,當(dāng)然也可以使用disablerepo來指定不使用那個(gè)源(repository)想括。
- 因?yàn)镹PM現(xiàn)在被安裝了,我們使用Ansible 的npm模塊安裝Node.JS工具forever烙博,forever來運(yùn)行我們的app瑟蜈,設(shè)置global為yes,告訴NPM安裝模塊在/usr/lib/node_modules位置渣窜,然后所有的用戶都可以使用它了铺根。
我們已經(jīng)有一個(gè)Node.js app 服務(wù)器了,讓我們部署一個(gè)簡單的Node.js app乔宿,在80端口響應(yīng)HTTP請求
1.2 部署一個(gè)Node.js app
這一步是在我們的服務(wù)器上部署簡單的Node.js app位迂。首先,通過創(chuàng)建一個(gè)新的文件夾详瑞,我們創(chuàng)建一個(gè)簡單的Node.js app掂林,這個(gè)文件夾和你上面的ymal文件處于相同的路徑下面。然后創(chuàng)建新的文件坝橡,app.js泻帮,在這個(gè)文件夾里面,編輯下面的文件
//app.js
// 加載express 模塊.
var express = require('express'),
app = express.createServer();
// 響應(yīng)”/”請求為 'Hello World'.
app.get('/', function(req, res){
res.send('Hello World! Yunzhonge');
});
// 像一個(gè)真實(shí)服務(wù)器那樣監(jiān)聽在80端口
app.listen(80);
console.log('Express server started successfully.')
不要擔(dān)心node.js的語法的和我們的案例计寇。我們需要一個(gè)快速的部署案例锣杂,這個(gè)案例可以用Python,Perl饲常,Java蹲堂,PHP或者其他編程語言來寫狼讨,但是因?yàn)镹ode是非常簡單的語言贝淤,運(yùn)行一個(gè)簡單的輕量級(jí)的環(huán)境,它是一個(gè)非常不錯(cuò)的語言來測試你的服務(wù)器政供。
因?yàn)檫@個(gè)小app依賴于Express(一個(gè)簡單的Node的HTTP框架)播聪,我們同樣需要通過一個(gè)package.json文件告訴NPM關(guān)于它的依賴關(guān)系,這個(gè)文件與app.js處于相同的路徑下面。
{
"name": "examplenodeapp",
"description": "Example Express Node.js app.",
"author": "yunzhonghe",
"dependencies": {
"express": "3.x.x"
},
"engine": "node >= 0.10.6"
}
然后添加下面內(nèi)容到你的playbook里面布隔,拷貝整個(gè)app到這個(gè)服務(wù)器离陶,然后讓npm下載依賴的東西,(這里為express.)
- name: Ensure Node.js app folder exists.
file: "path={{ node_apps_location }} state=directory"
- name: Copy example Node.js app to server.
copy: "src=app dest={{ node_apps_location }}"
- name: Install app dependencies defined in package.json.
npm: "path={{ node_apps_location }}/app"
- 首先我們使用file模塊確保我們安裝的app目錄存在。{{ node_apps_location }}變量可以在vars部分定義衅檀,vars部分位于playbook的頂部招刨。當(dāng)然也可以在inevntory中定義,也可以在運(yùn)行ansible-playbook的時(shí)候定義哀军。
- 我們使用Ansible的copy模塊拷貝這整個(gè)app文件夾到測試服務(wù)器沉眶,copy模塊可以聰明的區(qū)分單一的文件和包含文件的目錄打却,然后在目錄中遞歸,就像rsync或scp谎倔。Ansible的copy模塊在單個(gè)文件或少量文件時(shí)候非常好用柳击,但是如果你拷貝大量的文件,嵌套幾層的目錄片习,copy模塊就不能勝任捌肴。這種情形下,如果你想拷貝整個(gè)目錄藕咏,你最好考慮使用synchronize模塊状知,如果你想拷貝一個(gè)歸檔,然后展開它孽查,最好使用unarchive模塊试幽。
- 第三步,我們使用npm模塊卦碾,這次除了app的路徑之外沒有額外的參數(shù)铺坞。這告訴NPM來解析package.json文件,然后確保所有的依賴關(guān)系都存在洲胖。
已經(jīng)都完成了济榨,最后一步是啟動(dòng)這個(gè)app
1.3 運(yùn)行一個(gè)Node.js app
我們現(xiàn)在使用forever來啟動(dòng)這個(gè)app。
- name: Check list of running Node.js apps.
command: forever list
register: forever_list
changed_when: false
- name: Start example Node.js app.
command: "forever start {{ node_apps_location }}/app/app.js"
when: "forever_list.stdout.find('{{ node_apps_location }}/app/app.js') == -1"
在這個(gè)play中绿映,我們做了兩件新的事情擒滑。
- register 創(chuàng)建了一個(gè)新的變量,forever_list叉弦,以便于下次task的時(shí)候使用用于判斷是否允運(yùn)行下一個(gè)命令丐一。register用于保存命令的輸出包括標(biāo)準(zhǔn)輸出和錯(cuò)誤輸出,然后賦給變量名淹冰。
- changed_when告訴Ansible什么時(shí)候這個(gè)play會(huì)導(dǎo)致改變库车。在這里,forever list命令永遠(yuǎn)都不會(huì)導(dǎo)致服務(wù)器的改變樱拴,因?yàn)槲覀冎付薴alse柠衍。
第二個(gè)play實(shí)際上使用forever啟動(dòng)了這個(gè)app。我們可以啟動(dòng)這個(gè)app通過調(diào)用node {{ node_apps_location }}/app/app.js晶乔,不過這種方式更難控制珍坊。
Forever跟蹤它管理的Node app,然后我們使用Forever的list選項(xiàng)正罢,打印一系列的運(yùn)行app阵漏。我們第一次運(yùn)行這個(gè)playbook時(shí)候,這list明顯是空的,但是判斷為空之后就會(huì)運(yùn)行履怯,如果app正在運(yùn)行川无,我們不會(huì)啟動(dòng)另外一個(gè)實(shí)例了,為了避免這種情形虑乖,我們使用when語句懦趋,指定,當(dāng)app的路徑不在forever list的輸出信息的時(shí)候疹味,我們啟動(dòng)這個(gè)app仅叫。
1.4 Node.js app服務(wù)器總結(jié)。
在這時(shí)候上糙捺,你已經(jīng)完成了playbook诫咱,然后安裝一個(gè)簡單的Node.js app,在80端口響應(yīng)HTTP請求洪灯。
為了運(yùn)行這個(gè)playbook在一個(gè)服務(wù)器上坎缭,使用下面的命令,傳遞node_apps_location變量通過命令
ansible-playbook --extra-vars="node_apps_location=/usr/local/opt/node"
當(dāng)服務(wù)器完成配置和部署服務(wù)器的時(shí)候签钩,在瀏覽器中指定測試服務(wù)器的主機(jī)名查看效果
簡單掏呼,但是有效,我們已經(jīng)在少于50行的YMAL文件中配置了一個(gè)Nodejs應(yīng)用服務(wù)器
到此結(jié)束铅檩,非常感謝朋友們的關(guān)注憎夷。
1.5 問題:
問題1:當(dāng)我在給100臺(tái)服務(wù)器進(jìn)行nodejs app部署的時(shí)候,到20臺(tái)中斷了昧旨,我再重新執(zhí)行拾给,他是一個(gè)怎么個(gè)過程,前面已經(jīng)安裝的軟件包兔沃,進(jìn)行的配置的會(huì)重新的再進(jìn)行執(zhí)行一遍還是跳過呢蒋得?麻煩大牛解答
答:Ansible自身有冪等特性使其能有效保證所有操作的安全可靠性,針對(duì)執(zhí)行失敗的情況會(huì)自動(dòng)在家目錄下生成 對(duì)應(yīng)的錯(cuò)誤服務(wù)器列表 通過 --limit 再次有針對(duì)性的完成剩余工作
問題2: 請問大俠的nodejs 是通過工具部署的? npm 好復(fù)雜啊
哈乒疏,npm的配置是一次性的额衙,初始配置確認(rèn)比較耗時(shí)且麻煩,yum 或 npm 各有優(yōu)劣缰雇,視業(yè)務(wù)而定吧
問題3: --extra-vars= 請問企業(yè)中應(yīng)用的多嗎弃秆?
答:多焚鹊,最少在我們的工作中一直有應(yīng)用骗灶,前幾期的分享大家應(yīng)該也有看到距淫,這個(gè)參數(shù)應(yīng)用的很多省艳。但官網(wǎng)介紹的卻一筆代過邮破。還是建議大家多用
問題4:當(dāng)我通過ansible執(zhí)行任務(wù)的過程中低零,會(huì)出現(xiàn)任務(wù)被長時(shí)間卡主的原因副硅,這一般需要重哪些地方排查呢
答:
很多朋友遇到這個(gè)問題,一直有問爸业,根據(jù)個(gè)人的經(jīng)驗(yàn)建議如下幾個(gè)方面排查:
- 確實(shí)當(dāng)前命令執(zhí)行時(shí)間不長其骄,
- pong 檢測服務(wù)器存活
- 有些命令需連接外網(wǎng)下載更新耗時(shí)較長的可檢查網(wǎng)絡(luò)寬帶情況
- -vvv 是非常好的排查方式
- 如若卻無解,/etc/ansible/ansible.cfg 中縮短操作執(zhí)行時(shí)長扯旷,等待最終結(jié)束嘗試