課程指數
難度指數: 4星(滿星5星)
技術指數: 5星(滿星5星)
理論指數: 3星(滿星5星)
面向人群: 自動化運維&國中級運維
分享目錄
1.1 添加額外的源 1
1.2 部署一個Node.js app 4
1.3 運作一個Node.js app 6
1.4 Node.js app伺服器總結。 7
1.5 問題: 7
下面我們将要在我們的CentOS6.x伺服器上配置Nodejs,啟動一個簡單的nodejs執行個體,這個伺服器有很簡單的架構。
開始了,首先建立一個playbook檔案,我們盡量讓它保持簡單。
---
- hosts: all
tasks:
定義一些運作這個playbook的主機,然後下面列出一系列的tasks。
1.1 添加額外的源
在準備應用一個伺服器的時候,為了確定指定些軟體包可以用或者在最新的版本,管理者經常首先添加額外的源。
下面的腳本,我們想要添加EPEL和Remi源,以便于我們可以得到類似node.js的軟體包。如果使用shell腳本處理的話,如下所示。
# 導入 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擴充
rpm -Uvh --quiet \
http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
# 安裝EPEL源
yum install epel-release
# 安裝 Node.js (npm + 和它的依賴關系).
yum --enablerepo=epel install npm
這個shell腳本用于導入EPEL和Remi的GPG keys,然後添加這源,最後安裝Nodejs。這對于簡單的部署是沒有問題的,但是運作這麼多指令是比較笨的方法,如果你的連接配接不小心斷開了,那麼你的腳本也會停止的。而如果這個時候,你的腳本剛準備完成呢?
提示:如果你想跳過指定的步驟,你可以跳過添加GPG keys的步驟,隻需要在運作指令的時候加上—nogpgcheck.或者在Ansible中,yum子產品中設定disable_gpg_check參數為yes,但是最好還是添加GPG keys。使用GPG,你可以知道包的作者是誰,包有沒有修改稿,除非你知道你正在做什麼,否則最好不要禁止GPG檢查。
Ansible讓事情變的更有健壯性,下面使用Ansible的案例顯得更加詳細,它和上面的shell腳本有同樣的功能,但是更容易了解,更加結構化。 下面使用了Ansible的變量和其它的一些有用的特性。接着上面的playbook,我們繼續往下寫。
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 是一個的Ansible子產品用于從你的RPM資料庫中添加或移除GPG key。我們正在從Remi的源中導入一個key。
-
因為Ansible沒有rpm指令,是以我們使用command子產品來使用rpm指令,這樣我們可以做其它的兩件事情。
a) 使用creatse參數告訴Ansible什麼時候不運作這個指令,這個例子裡,我們告訴Ansible,這個指令成功執行後,将會建立那些檔案。當這個檔案存在的時候,這個指令将不會運作。
b) 使用with_items定義一個URL和用于creates檢查的檔案。
- yum負責安裝EPEL源。
- 因為這個伺服器我們将用來做測試用,是以我們使用service子產品禁止系統防火牆,防止它幹涉我們測試。
- yum安裝Node.js(同時安裝npm,Node’s package manager),我們使用enablerepo來指定在EPEL源中搜尋它,當然也可以使用disablerepo來指定不使用那個源(repository)。
- 因為NPM現在被安裝了,我們使用Ansible 的npm子產品安裝Node.JS工具forever,forever來運作我們的app,設定global為yes,告訴NPM安裝子產品在/usr/lib/node_modules位置,然後所有的使用者都可以使用它了。
我們已經有一個Node.js app 伺服器了,讓我們部署一個簡單的Node.js app,在80端口響應HTTP請求
1.2 部署一個Node.js app
這一步是在我們的伺服器上部署簡單的Node.js app。首先,通過建立一個新的檔案夾,我們建立一個簡單的Node.js app,這個檔案夾和你上面的ymal檔案處于相同的路徑下面。然後建立新的檔案,app.js,在這個檔案夾裡面,編輯下面的檔案
//app.js
// 加載express 子產品.
var express = require('express'),
app = express.createServer();
// 響應”/”請求為 'Hello World'.
app.get('/', function(req, res){
res.send('Hello World! Yunzhonge');
});
// 像一個真實伺服器那樣監聽在80端口
app.listen(80);
console.log('Express server started successfully.')
不要擔心node.js的文法的和我們的案例。我們需要一個快速的部署案例,這個案例可以用Python,Perl,Java,PHP或者其他程式設計語言來寫,但是因為Node是非常簡單的語言,運作一個簡單的輕量級的環境,它是一個非常不錯的語言來測試你的伺服器。
因為這個小app依賴于Express(一個簡單的Node的HTTP架構),我們同樣需要通過一個package.json檔案告訴NPM關于它的依賴關系,這個檔案與app.js處于相同的路徑下面。
{
"name": "examplenodeapp",
"description": "Example Express Node.js app.",
"author": "yunzhonghe",
"dependencies": {
"express": "3.x.x"
},
"engine": "node >= 0.10.6"
}
然後添加下面内容到你的playbook裡面,拷貝整個app到這個伺服器,然後讓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的頂部。當然也可以在inevntory中定義,也可以在運作ansible-playbook的時候定義。
- 我們使用Ansible的copy子產品拷貝這整個app檔案夾到測試伺服器,copy子產品可以聰明的區分單一的檔案和包含檔案的目錄,然後在目錄中遞歸,就像rsync或scp。Ansible的copy子產品在單個檔案或少量檔案時候非常好用,但是如果你拷貝大量的檔案,嵌套幾層的目錄,copy子產品就不能勝任。這種情形下,如果你想拷貝整個目錄,你最好考慮使用synchronize子產品,如果你想拷貝一個歸檔,然後展開它,最好使用unarchive子產品。
-
第三步,我們使用npm子產品,這次除了app的路徑之外沒有額外的參數。這告訴NPM來解析package.json檔案,然後確定所有的依賴關系都存在。
已經都完成了,最後一步是啟動這個app
1.3 運作一個Node.js app
我們現在使用forever來啟動這個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"
在這個play中,我們做了兩件新的事情。
- register 建立了一個新的變量,forever_list,以便于下次task的時候使用用于判斷是否允運作下一個指令。register用于儲存指令的輸出包括标準輸出和錯誤輸出,然後賦給變量名。
- changed_when告訴Ansible什麼時候這個play會導緻改變。在這裡,forever list指令永遠都不會導緻伺服器的改變,因為我們指定了false。
第二個play實際上使用forever啟動了這個app。我們可以啟動這個app通過調用node {{ node_apps_location }}/app/app.js,不過這種方式更難控制。
Forever跟蹤它管理的Node app,然後我們使用Forever的list選項,列印一系列的運作app。我們第一次運作這個playbook時候,這list明顯是空的,但是判斷為空之後就會運作,如果app正在運作,我們不會啟動另外一個執行個體了,為了避免這種情形,我們使用when語句,指定,當app的路徑不在forever list的輸出資訊的時候,我們啟動這個app。
1.4 Node.js app伺服器總結。
在這時候上,你已經完成了playbook,然後安裝一個簡單的Node.js app,在80端口響應HTTP請求。
為了運作這個playbook在一個伺服器上,使用下面的指令,傳遞node_apps_location變量通過指令
ansible-playbook --extra-vars="node_apps_location=/usr/local/opt/node"
當伺服器完成配置和部署伺服器的時候,在浏覽器中指定測試伺服器的主機名檢視效果
簡單,但是有效,我們已經在少于50行的YMAL檔案中配置了一個Nodejs應用伺服器
到此結束,非常感謝朋友們的關注。
1.5 問題:
問題1:當我在給100台伺服器進行nodejs app部署的時候,到20台中斷了,我再重新執行,他是一個怎麼個過程,前面已經安裝的軟體包,進行的配置的會重新的再進行執行一遍還是跳過呢?麻煩大牛解答
答:Ansible自身有幂等特性使其能有效保證所有操作的安全可靠性,針對執行失敗的情況會自動在家目錄下生成 對應的錯誤伺服器清單 通過 --limit 再次有針對性的完成剩餘工作
問題2: 請問大俠的nodejs 是通過工具部署的? npm 好複雜啊
哈,npm的配置是一次性的,初始配置确認比較耗時且麻煩,yum 或 npm 各有優劣,視業務而定吧
問題3: --extra-vars= 請問企業中應用的多嗎?
答:多,最少在我們的工作中一直有應用,前幾期的分享大家應該也有看到,這個參數應用的很多。但官網介紹的卻一筆代過。還是建議大家多用
問題4:當我通過ansible執行任務的過程中,會出現任務被長時間卡主的原因,這一般需要重哪些地方排查呢
答:
很多朋友遇到這個問題,一直有問,根據個人的經驗建議如下幾個方面排查:
- 确實目前指令執行時間不長,
- pong 檢測伺服器存活
- 有些指令需連接配接外網下載下傳更新耗時較長的可檢查網絡寬帶情況
- -vvv 是非常好的排查方式
- 如若卻無解,/etc/ansible/ansible.cfg 中縮短操作執行時長,等待最終結束嘗試