Erlang/Elixir: 使用 Edeliver 進行自動化的持續部署

Elixir 部署系列html

Erlang/Elixir: 用Distillery替換Exam打包器
Erlang/Elixir: Edeliver 持續部署 Checklist
Erlang/Elixir: 使用 Edeliver 進行持續部署node

增長 2016-08-19
Erlang/Elixir: 用Distillery替換Exam打包器
更新 2016-07-25
這裏有一篇Gitbooks上的文章專門簡介如何搭建,配置一個Phoenix應用程序的自動化構建,部署的過程Phoenix持續部署git

Edeliver 是一個基於 deliver 的構建和部署工具.
它提供了一個 Bash 腳原本幫助你構建, 部署, 以及執行熱代碼升級github

部署相關的系列文章
Edeliver 持續部署Checklistsegmentfault

Edeliver 部署關係圖示
Edeliver 部署關係圖示api

本文咱們來聊一聊關於 Erlang/Elixir 的部署問題. 最原始的 Erlang, 咱們要使用一大堆工具, 好比 reltool, 後來有了rebar, 還後來 relx 也出來了, Elixir 生態鏈中還有個 Exrm 打包工具, 是基於 relx 建立發佈包的, 打包好了呢, 須要部署到服務器上去運行.bash

Exrm 打好的包, 通常狀況, 我直接用 scp 複製到服務器上的某個目錄, 而後在登陸到遠程服務器解壓, 升級等操做. 而 Edeliver 讓這個過程徹底自動化, 提升了效率, 而且更加適用於中等規模的應用程序部署.服務器

構建 Erlang/Elixir 初始發佈版本, 並部署到產品服務器.cookie

mix edeliver build release --branch=master -V
mix edeliver deploy release to production -V
mix edeliver start production -V

把上面三個單獨的命令合併爲一個app

mix edeliver update production --branch=master --start-deploy -V

配置

在項目目錄下建立一個 .deliver 目錄, 而後在其中添加 config 文件.

#!/usr/bin/env bash

APP="your-erlang-app" # name of your release

# 構建主機的地址, 用戶名, 和構建目錄
BUILD_HOST="build-system.acme.org"
BUILD_USER="build"
BUILD_AT="/tmp/erlang/my-app/builds"

# 測試目標主機的地址, 用戶名, 和部署目錄, 多個目標服務器地址用空格分隔開
STAGING_HOSTS="test1.acme.org test2.acme.org"
STAGING_USER="test"
TEST_AT="/test/my-erlang-app"

# 產品目標主機的地址, 用戶名, 和部署目錄, 多個目標服務器地址用空格分隔開
PRODUCTION_HOSTS="deploy1.acme.org deploy2.acme.org"
PRODUCTION_USER="production"
DELIVER_TO="/opt/my-erlang-app"

本質上, Edeliver 使用 SSH 和 scp 來部署發佈. 若是須要無密碼登錄, 可經過 ssh-keygen 工具建立密鑰對, 把公鑰添加到服務器的 ~/.ssh/authorized_keys 文件中便可.

項目配置

defp deps do
    [{:edeliver, ">= 1.2.8"}]
end

def application, do: [
    applications: [
      # ...
      :edeliver,
    ],
  ]

不一樣的部署目標不一樣的配置

對於一個須要實現 Failover/Takeover 分佈式應用程序來說, 每一個節點的配置是不同的, 這樣在部署的時候就要去編寫不一樣的配置文件.

Edeliver 提供了這樣一個功能

TODO::目前項目尚未到這個階段之後再研究.

構建

必須在和目標系統相似 (建議徹底同樣的系統) 的系統上構建. 若是想在 Linux 上部署產品系統, 那麼發佈也應該在 Linux 系統上構建(建議使用相同廠商的 Linux 髮型版). 不要求在產品系統上安裝 Erlang/OTP 和 Elixir 運行時, 他們會隨打包系統自動包含進發布包分發到產品系統上. 下面的配置變量是必須的:

Name Description
APP 發佈的應用程序名稱
BUILD_HOST 構建發佈包的主機名稱或IP地址
BUILD_USER 構建主機上的本地用戶名稱
BUILD_AT 在構建主機上構建發佈包的目錄.

構建完成後, 發佈包會被複制到你的本地 .deliver/releases 目錄. 而後經過下面的命令發佈到產品服務器. 若是成功編譯和生成發佈包. 發佈包會從構建主機複製到發佈存儲, 默認發佈存儲的位置在項目根目錄下的 .deliver 目錄的 releases 子目錄, 但能夠經過配置環境變量來自定義, 例如:

準確的講, 是複製到 RELEASE_STORE 環境變量指定的位置, 若是設置了該環境變量的話. 若是沒有設置 RELEASE_STORE 環境變量, 默認爲項目根目錄的 .deliver/releases 子目錄.

RELEASE_STORE=/tmp/.deliver                                       # 本地目錄
RELEASE_STORE=user@releases.acme.org:/releases                    # 遠程主機
RELEASE_STORE=s3://AWS_ACCESS_KEY_ID@AWS_SECRET_ACCESS_KEY:bucket # 亞馬遜S3

發佈使用RELEASE_DIR=環境變量來肯定發佈歸檔包的位置. 若是未設置, 默認目錄包含RELEASES文件的目錄. 好比: 若是$APP=myApp, RELEASES的位置爲rel/myApp/myApp/releases/RELEASE. 關於完整的 edeliver 命令, 能夠經過運行 mix help edeliver 查看:

別本身建立 $BUILD_AT, $TEST_AT, $DELIVER_TO 目錄. config/*.secret.exs 應該放在$CONFIG_AT目錄, *.vm.args 文件處理節點名稱, 集羣等配置參數

構建一個全新的版本

mix edeliver build release --version=0.0.1

圖片描述

部署第一個版本

mix edeliver deploy release to production --version=0.0.1 --start-deploy

構建一個升級版本

熱升級包含該兩條路徑

  • 從Git倉庫發佈一個升級包

  • 從以前發佈的版本構建一個升級包

提高版本號, 在 mix.exs 提高項目的版本號, 下面的命令是直接從源碼倉庫構建一個熱升級包

git commit -m 'Bump version to 0.0.2'              # 提交
git tag 0.0.2                                      # 打TAG
mix edeliver build upgrade --from=0.0.1 --to=0.0.2 # 構建

部署一個升級版本

mix edeliver deploy upgrade to production --version=0.0.2

構建從 v1.0 到 v2.0 的升級包, 並部署升級到產品環境

mix edeliver build upgrade --from=v1.0 --to=v2.0
mix edeliver deploy upgrade to production

或者, 若是在發佈存在有舊的發佈版本, 能夠用那個舊的發佈版原本構建升級而不是Git的舊版修訂/Tag

mix edeliver build upgrade --with=v1.0 --to=v2.0
mix edeliver deploy upgrade to production

注意 --from=--with= 的區別. --from=指定git倉庫的tag, --with=指定舊的release版本號. 能夠經過命令mix edeliver show releases查看當前有哪些版本可用.

# 運行Ecto 移植
mix edeliver migrate production

或者使用 --run-migrations 選項在升級期間自動運行

升級 Patch 版本號

mix edeliver build release --increment-version=patch -V

這個命令也是用於構建一個發佈包, 只是他會從Git工做區讀取最新的Tag版本, 並在此基礎上加1, 好比當前倉庫中的Tag最新爲 1.0.2, 那麼該命令會建立一個 1.0.3 的發佈版本.

單個命令完成升級

mix edeliver upgrade production -V

上面這個命令將會執行以下步驟:

  • 檢查全部運行節點的當前版本

  • 驗證全部節點運行在相同的版本

  • 構建從該版本到當前版本的升級包

  • 自動給 relup 文件打補丁

  • 節點運行的同事部署升級包(熱更新)

  • 驗證全部的節點運行在已升級的版本

  • 部署發佈包到其餘沒有處於運行狀態的節點

排錯

構建主機須要安裝好 Erlang/Elixir 的構建環境, 推薦使用 kerl 編譯 Erlang, kiex 安裝 Elixir. 而後把下面兩行腳本添加到用戶目錄的 .profile 文件中. 目的是讓 Edeliver 可以找到 Elixir 工具的位置

. /home/ycc/.kerl/installs/18.3_systemtap/activate
test -s "$HOME/.kiex/scripts/kiex" && source "$HOME/.kiex/scripts/kiex"
kiex use 1.2.5 > /dev/null 2>&1

關於熱升級的問題

根據實踐驗證, 請保證你的項目中 applications, deps 升級先後保持一致, 不然熱升級可能致使失敗, 若是applications, deps有修改, 這種狀況下最好用下面的命令作一次全新部署.

mix edeliver build release --version=<new_version> -V
mix edeliver deploy to production --version=<new_version> -V
mix edeliver start production -V

關於 -V, --verbose 參數

咱們在構建發佈包的時候, 有時候會出錯, 能夠經過構建是添加 -V 參數來看到構建過程的大量信息, 包括 git 本地工做區的 HEAD 的指向, 編譯的詳細輸出(mix compile的輸出), 默認狀況 Edeliver 會從拉取 HEAD 指向的分支來構建發佈.

集羣設置

vm.args設置節點名稱cookie

參數配置

在配置文件 prod.exs 中配置 :kernel 模塊的 :sync_nodes_mandator:sync_nodes_optional 選項

use Mix.Config
config :kernel, distributed: [{:opencv_thumbnail_server, 5000, [
  :"node1@192.168.212.45",
  :"node2@192.168.212.45",
  :"node3@192.168.212.45",
  :"node4@192.168.212.45",
  :"node5@192.168.212.45"
]}]
config :kernel, inet_dist_listen_min: 9100
config :kernel, inet_dist_listen_max: 9105
config :kernel, sync_nodes_mandatory: [
  :"node2@192.168.212.45",
  :"node3@192.168.212.45"
]
config :kernel, sync_nodes_optional: [
  :"node4@192.168.212.45",
  :"node5@192.168.212.45"
]
config :kernel, sync_nodes_timeout: 10000

上傳到服務器的壓縮包解壓後, 須要修改,下面兩個文件的節點名字和 distributed 配置.

./releases/0.0.1/sys.config
./releases/0.0.1/vm.args

其餘管理命令

# 顯示發佈版本清單
$ mix edeliver show releases
# 中止線上的服務器
$ mix edeliver stop production
# 顯示線上服務器當前運行的版本
$ mix edeliver version production
# 重啓線上服務器
$ mix edeliver restart production
# 啓動
$ mix edeliver start production

圖片描述

總結

大致上一個全新的部署過程就是三個命令

mix edeliver build release --V                # 構建發佈包
mix edeliver deploy release to production --V # 部署(上傳, 解壓)到產品服務器
mix edeliver start production --V             # 啓動產品服務器

若是上線前還須要部署到 staging 服務器進行測試, 或者灰度發佈

熱升級的過程爲

mix edeliver build upgrade --with=0.1.3 --to=0.1.14 -V        # 構建一個從0.1.13到0.1.14的升級包
mix edeliver deploy upgrade to production --version=0.1.14 -V # 部署升級包0.1.14到線上

關於Git倉庫的問題

咱們通常在 develop 分支下進行開發, 而 edeliver 構建發佈包的時候是去 master 分支拉取源碼進行構建的, 所以咱們在開發過程當中須要注意版本和分支的管理.

這裏我使用了 gitflow 這個工具來管理項目的版本和發佈. 假設咱們如今須要向線上發佈一個新版本, develop 分支須要合併到master, 先修改 mix.exs 提高一下版本, 並提交, 而後:

git add .
git commit -m 'bump version to 0.1.14'
git push

發佈

git flow release start 0.1.14
git flow release publish 0.1.14 # Push發佈分支0.1.14到遠程倉庫,以便在構建主機上編譯,打包和部署
git flow release finish 0.1.14
git push 
git push --tags
git checkout develop            # 回到 develop 繼續開發

參考資料

Fast Continuous Deployment of an Elixir Gameserver
Real World Elixir Deployment
Edeliver API Reference

相關文章
相關標籤/搜索