1. 程式人生 > >Ansible部署Node.js,讓你從簡操作

Ansible部署Node.js,讓你從簡操作

下面我們將要在我們的CentOS6.x伺服器上配置Nodejs,啟動一個簡單的nodejs例項,這個伺服器有很簡單的架構。

開始了,首先建立一個playbook檔案,我們儘量讓它保持簡單。

---
- hosts: all
  tasks:

定義一些執行這個playbook的主機,然後下面列出一系列的tasks。

一、 新增額外的源

在準備應用一個伺服器的時候,為了確保指定些軟體包可以用或者在最新的版本,管理員經常首先新增額外的源。
下面的指令碼,我們想要新增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

我們看一下具體步驟

1、rpm_key 是一個的Ansible模組用於從你的RPM資料庫中新增或移除GPG key。我們正在從Remi的源中匯入一個key。

2、因為Ansible沒有rpm命令,因此我們使用command模組來使用rpm命令,這樣我們可以做其它的兩件事情。

  • 使用creatse引數告訴Ansible什麼時候不執行這個命令,這個例子裡,我們告訴Ansible,這個命令成功執行後,將會建立那些檔案。當這個檔案存在的時候,這個命令將不會執行。
  • 使用with_items定義一個URL和用於creates檢查的檔案。
  • yum負責安裝EPEL源。

4、因為這個伺服器我們將用來做測試用,所以我們使用service模組禁止系統防火牆,防止它干涉我們測試。

5、yum安裝Node.js(同時安裝npm,Node’s package manager),我們使用enablerepo來指定在EPEL源中搜索它,當然也可以使用disablerepo來指定不使用那個源(repository)。

6、因為NPM現在被安裝了,我們使用Ansible 的npm模組安裝Node.JS工具forever,forever來執行我們的app,設定global為yes,告訴NPM安裝模組在/usr/lib/node_modules位置,然後所有的使用者都可以使用它了。

二、 部署一個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

三、執行一個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中,我們做了兩件新的事情。

1、register 建立了一個新的變數,forever_list,以便於下次task的時候使用用於判斷是否允執行下一個命令。register用於儲存命令的輸出包括標準輸出和錯誤輸出,然後賦給變數名。

2、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。

四、 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應用伺服器

到此結束,非常感謝朋友們的關注。

五、問題:

問題一

當我在給100臺伺服器進行nodejs app部署的時候,到20臺中斷了,我再重新執行,他是一個怎麼個過程,前面已經安裝的軟體包,進行的配置的會重新的再進行執行一遍還是跳過呢?麻煩大牛解答

Ansible自身有冪等特性使其能有效保證所有操作的安全可靠性,針對執行失敗的情況會自動在家目錄下生成 對應的錯誤伺服器列表 通過 —limit 再次有針對性的完成剩餘工作

問題二

請問大俠的nodejs 是通過工具部署的?

npm 好複雜啊哈,npm的配置是一次性的,初始配置確認比較耗時且麻煩,yum 或 npm 各有優劣,視業務而定吧

問題三

—extra-vars= 請問企業中應用的多嗎?

多,最少在我們的工作中一直有應用,前幾期的分享大家應該也有看到,這個引數應用的很多。但官網介紹的卻一筆代過。還是建議大家多用

問題四

當我通過ansible執行任務的過程中,會出現任務被長時間卡主的原因,這一般需要重哪些地方排查呢

很多朋友遇到這個問題,一直有問,根據個人的經驗建議如下幾個方面排查:

  • 確實當前命令執行時間不長,
  • pong 檢測伺服器存活
  • 有些命令需連線外網下載更新耗時較長的可檢查網路寬頻情況
  • -vvv 是非常好的排查方式
  • 如若卻無解,/etc/ansible/ansible.cfg 中縮短操作執行時長,等待最終結束嘗試

文:Real_man