12-factor Style
通常,應(yīng)用的 配置 在不同 部署 (預(yù)發(fā)布、生產(chǎn)環(huán)境哼蛆、開發(fā)環(huán)境等等)間會有很大差異。這其中包括:
- 數(shù)據(jù)庫霞赫,Memcached腮介,以及其他 后端服務(wù) 的配置
- 第三方服務(wù)的證書,如 Amazon S3端衰、Twitter 等
- 每份部署特有的配置叠洗,如域名等
有些應(yīng)用在代碼中使用常量保存配置,這與 12-factor
所要求的代碼和配置嚴(yán)格分離顯然大相徑庭靴迫。配置文件在各部署間存在大幅差異惕味,代碼卻完全一致。
判斷一個應(yīng)用是否正確地將配置排除在代碼之外玉锌,一個簡單的方法是看該應(yīng)用的基準(zhǔn)代碼是否可以立刻開源名挥,而不用擔(dān)心會暴露任何敏感的信息。
12-Factor
推薦將應(yīng)用的配置存儲于 環(huán)境變量 中( env vars, env )主守。環(huán)境變量可以非常方便地在不同的部署間做修改禀倔,卻不動一行代碼。更多關(guān)于12-factor
的內(nèi)容請訪問 12factor.net.
Rails Style 存在的問題
Rails中大部分實踐是遵守了 12-Factor 規(guī)則参淫,除了日志和配置救湖。Rails Way的配置方式是yml文件,例如:database.yml涎才、secret.yml等鞋既。簡單的應(yīng)用使用yml文件和 12-factor
推薦的環(huán)境變量其實區(qū)別不大,不過當(dāng)項目不斷膨脹耍铜,配置數(shù)量也隨著增加邑闺,yml方式變得越來越難以維護。yml存在的問題表現(xiàn)在:
- 需要不斷的修改.gitignore文件
- 搭建各種環(huán)境(dev棕兼、production陡舅、test、staging)時需要不斷copy example文件
- 配置散落各處
- 每增加yml文件伴挚,需要在應(yīng)用里增加load和parse邏輯
- 不小心會被簽進版本控制里
下面是目前項目的配置文件靶衍,每次搭建環(huán)境修改這些配置文件是最痛苦的事情...
shared/config$ ls |grep yml
s3.yml
redis.yml
twilio.yml
paypal.yml
sunspot.yml
database.yml
icontact.yml
http_auth.yml
beanstream.yml
commercehub.yml
canada_post.yml
google_content_api.yml
系統(tǒng)環(huán)境變量
最直接的方式是使用shell 環(huán)境變量:
$ export TWILIO_ACCOUNT_SID=AC1234...
$ export TWILIO_AUTH_TOKEN=abc12...
在Ruby中使用ENV讀仍痔俊:
puts ENV['TWILIO_ACCOUNT_SID']
puts ENV['TWILIO_AUTH_TOKEN']
shell環(huán)境變量由于沒有持久化,又引出了 .bashrc颅眶、.bash_profile蜈出、~/.profile、/etc/environment等方式帚呼。都不是很完美掏缎,權(quán)限問題皱蹦、login shell問題的坑都等著你呢煤杀。最重要的是,上面提到這些都不方便應(yīng)付單機部署多個應(yīng)用的場景沪哺。
Envyable沈自、dotenv、Figaro
Envyable辜妓、dotenv枯途、Figaro等工具,在應(yīng)用程序中把配置注入到ENV
中避免了上面提到的各種問題籍滴。Envyable酪夷、dotenv、Figaro 無論是實現(xiàn)上還是使用上其實大同小異孽惰,下面只拿dotenv來說:
In Gemfile:
gem 'dotenv-rails', :require => 'dotenv/rails-now'
config/application.rb
Bundler.require(*Rails.groups)
Dotenv::Railtie.load
HOSTNAME = ENV['HOSTNAME']
.env 文件:
S3_BUCKET=YOURS3BUCKET
SECRET_KEY=YOURSECRETKEYGOESHERE
gitignore忽略.env晚岭,并且cap設(shè)置軟鏈:
set :linked_files, fetch(:linked_files, []).push('config/database.yml', '.env')
調(diào)用的時候仍然是 ENV['SECRET_KEY']
。當(dāng)然勋功,dotenv還支持多環(huán)境模式坦报,比如 .env.production
文件只對production環(huán)境生效。
Heroku-style
dotenv已經(jīng)很完美了狂鞋,但用過Heroku的都知道這還不夠片择,看一下Heroku設(shè)置環(huán)境變量的方式:
heroku config:set GITHUB_USERNAME=joesmith
Adding config vars and restarting myapp... done, v12GITHUB_USERNAME: joesmith
$ heroku config
GITHUB_USERNAME: joesmith
OTHER_VAR: production
$ heroku config:get
GITHUB_USERNAMEjoesmith
$ heroku config:unset GITHUB_USERNAME
Unsetting GITHUB_USERNAME and restarting myapp... done, v13
capistrano-twelvefactor + dotenv 可以打造出和Heroku一樣酷的體驗。
詳細(xì)的步驟capistrano-twelvefactor上面都有寫骚揍,下面只說和dotenv配合需要做的:
# config/deploy/production.rb
set :environment_file, deploy_path.join("shared/.env")
after 'config:set', "deploy:symlink:linked_files"
after 'config:unset', "deploy:symlink:linked_files"
然后就可以使用這幾個命令查看和修改環(huán)境配置了:
- bundle exec cap production config:list
- bundle exec cap production config:set[FOO=bar]
- bundle exec cap production config:unset[FOO]
注:上面需要capistrano 3 + dotenv字管,Envyable和Figaro目前無法使用Heroku style.
Multi Server && Apps
對于單臺服務(wù)器的應(yīng)用,capistrano-twelvefactor + dotenv 足以應(yīng)付信不,同時嘲叔,由于capistrano支持集群部署,單個應(yīng)用多服務(wù)器其實也是可以搞定的浑塞。但有時候不同應(yīng)用之間其實也需要共享配置文件的借跪,比如,S3配置變化了酌壕,依賴這個帳號的所有應(yīng)用都應(yīng)該得到同步掏愁。另外的一個問題是歇由,對于多服務(wù)器場景,配置存儲在.env會出現(xiàn)服務(wù)器之間配置不同步現(xiàn)象果港。如果要解決上述問題沦泌,可能引入etcd或 zookeeper是一個不錯的選擇。