41
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Money ForwardAdvent Calendar 2015

Day 18

itamaeを使って開発環境を構築してみる

Last updated at Posted at 2015-12-17

はじめに

新しい人がチームに入った場合に、最初にやってもらうこととして開発環境構築があると思います。で、プロダクトが最初の頃はまだそれほどコード量も多くなく、使っているミドルウェアも少ないので環境構築もそれほど苦ではないと思いますが、月日が経ちコード量も増え、使っているミドルウェアが多くなってくると、その分環境を新しく作るのが大変になってきます。
そういう時にChefAnsible、そして今回紹介するitamaeが役に立つと思います。

筆者もChef(正確にはChef Solo)を使っていた時期もありました。ただChef Soloが終了となり、Chef Zeroの切り替えてということになりました。そこでChef Zeroを使おうとやってみたのですが乗り換えが結構大変だったので、これを機に別にものを使おうと思い検討た結果itamaeを使うことにしました。

理由は

  • ライトに使える
  • 覚えることが少ない
  • sshが使える(Chefとの大きな違い)
    といった点からです。

この記事ではitamaeを使って環境構築をする例を紹介しようと思います。

環境

  • ruby2.2
  • github
  • elasticsearch2
  • redis
  • java 1.8
  • itamae 1.9
  • vagrant

レシピ

今回やることは次の項目をやっていきます。

  1. ruby、javaのインストール
  2. elasticsearch、redis等ミドルウェアのインストール
  3. githubから対象リポジトリを取得

レシピの構成

先日itamae meet upが開催され、その時にフォルダ構成の話も出ました。今回はその時紹介されたような構成に変更するのが間に合わなかったので若干「むむむ!!」というところがあるかもしれませんが、そこはご了承いただければと思います。
簡単にいうと以下のようにフォルダを分けています。

- recipes
  - elasticsearch
  - redis
  app.rb
- nodes
- templates

nodeの設定

nodeの設定はyaml形式でも書けますが、今回はjsonの形式で書かせていただきます。

nodes/app.json
{
  "rbenv": {
    "user": "vagrant",
    "versions": ["2.2.1", "2.2.2"],
    "global": "2.2.2",
    "gems": ["bundler", "rails"]
  },
  "elasticsearch": {
    "cluster_name": "nakamura-elasticsearch",
    "version": "2.1.0",
    "index_shards_num": "5",
    "index_replicas_num": "1"
  },
  "redis": {
    "version": "3.0.4"
  },
  "git": {
    "git_user": "#{ENV['git_user']}",
    "git_password": "#{ENV['git_password']}",
    "repository": "hoge/fuga_repo",
    "app_path": "rails_app"
    }
}

ruby、javaのインストール

今回rubyのインストールは公開されているプラグインを使います。javaはpackageで提供されているものを使うことにします。java以外にもgitとか後々使うので、ここで一緒にインストールしてしまいます。

gem 'itamae-plugin-recipe-rbenv'
recipes/app.rb
%w( yum wget java-1.8.0-openjdk git ).each do |pkg|
  package pkg do
    action :install
  end
end

# rubyをinstall
include_recipe "rbenv::user"

elasticsearch、redis等ミドルウェアのインストール

続いてミドルウェアを入れます。
mysqlやelasticsearch、redisのレシピは別のファイルで書いて、cookbooks/app.rbの中ではそれをinclude_recipeすることにします。
elasticsarchのレシピは次のようになります

recipes/elasticsearch/elasticsearch.rb
if  /\A1.*/ =~ node[:elasticsearch][:version]
  include_recipe 'version/1_x.rb'
else
  include_recipe 'version/2_x.rb'
end

バージョン毎にレシピを分けています。

recipes/elasticsearch/elasticsearch1.rb
%w( yum java-1.8.0-openjdk wget ).each do |pkg|
  package pkg do
    action :install
  end
end

execute 'rm elasticsearch.tar.gz' do
  only_if "test -e ~/elaticsearch.tar.gz"
end

execute 'elasticsearch file get' do
  command "wget https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-#{node[:elasticsearch][:version]}.tar.gz -O elasticsearch.tar.gz"
end

execute 'file unzip' do
  command 'tar -zxf elasticsearch.tar.gz'
end

execute 'sudo rm -R /usr/local/share/elasticsearch' do
  only_if 'ls /usr/local/share/elasticsearch'
end

execute 'sudo mv elasticsearch-* /usr/local/share/elasticsearch' do
  not_if 'ls /usr/local/share/elasticsearch'
end

execute 'sudo chmod -R 755 /usr/local/share/elasticsearch' do
  only_if 'ls /usr/local/share/elasticsearch'
end

execute 'mkdir /usr/local/share/elasticsearch/plugins' do
  not_if 'ls /usr/local/share/elasticsearch/plugins'
end

# elasticsearch.ymlをコピー
template "/usr/local/share/elasticsearch/config/elasticsearch.yml" do
  path "/usr/local/share/elasticsearch/config/elasticsearch.yml"
  source "../../../templates/elasticsearch/config/elasticsearch_yml.erb"
  variables({cluster_name: 'nakamura-elasticsearch', index_shards_num: "5", index_replicas_num: "1"})
end

# プラグイン
execute 'bin/plugin --remove mobz/elasticsearch-head' do
  only_if 'cd /usr/local/share/elasticsearch/plugins/head'
  cwd '/usr/local/share/elasticsearch'
end

execute 'bin/plugin -install mobz/elasticsearch-head' do
  cwd '/usr/local/share/elasticsearch'
end

execute 'bin/plugin --remove elasticsearch/marvel/latest' do
  only_if 'cd /usr/local/share/elasticsearch/plugins/mavel'
  cwd '/usr/local/share/elasticsearch'
end

execute 'bin/plugin -install elasticsearch/marvel/latest' do
  cwd '/usr/local/share/elasticsearch'
end

execute "bin/plugin --remove elasticsearch/elasticsearch-analysis-kuromoji/#{node['elasticsearch']['plugin']['kuromoji']['version']}" do
  only_if 'cd /usr/local/share/elasticsearch/plugins/analysis-kuromoji'
  cwd '/usr/local/share/elasticsearch'
end

execute "bin/plugin -install elasticsearch/elasticsearch-analysis-kuromoji/#{node['elasticsearch']['plugin']['kuromoji']['version']}" do
  cwd '/usr/local/share/elasticsearch'
end

version2を使った場合

recipes/elasticsearch/version/2_x.rb
%w( yum java-1.8.0-openjdk wget ).each do |pkg|
  package pkg do
    action :install
  end
end

execute 'rm elasticsearch.tar.gz' do
  only_if "test -e ~/elaticsearch.tar.gz"
end

execute 'elasticsearch file get' do
  command "wget https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/#{node[:elasticsearch][:version]}/elasticsearch-#{node[:elasticsearch][:version]}.tar.gz -O elasticsearch.tar.gz"
end

execute 'file unzip' do
  command 'tar -zxf elasticsearch.tar.gz'
end

execute 'sudo rm -R /usr/local/share/elasticsearch' do
  only_if 'ls /usr/local/share/elasticsearch'
end

execute 'sudo mv elasticsearch-* /usr/local/share/elasticsearch' do
  not_if 'ls /usr/local/share/elasticsearch'
end

execute 'sudo chmod -R 755 /usr/local/share/elasticsearch' do
  only_if 'ls /usr/local/share/elasticsearch'
end

execute 'mkdir /usr/local/share/elasticsearch/plugins' do
  not_if 'ls /usr/local/share/elasticsearch/plugins'
end

# プラグイン
## HEAD
execute 'bin/plugin remove mobz/elasticsearch-head' do
  only_if 'cd /usr/local/share/elasticsearch/plugins/head'
  cwd '/usr/local/share/elasticsearch'
end

execute 'bin/plugin install mobz/elasticsearch-head' do
  cwd '/usr/local/share/elasticsearch'
end

## kuromoji
execute "bin/plugin remove analysis-kuromoji" do
  only_if 'cd /usr/local/share/elasticsearch/plugins/analysis-kuromoji'
  cwd '/usr/local/share/elasticsearch'
end

execute "bin/plugin install analysis-kuromoji" do
  cwd '/usr/local/share/elasticsearch'
end

# elasticsearch.yml
template "/usr/local/share/elasticsearch/config/elasticsearch.yml" do
  path "/usr/local/share/elasticsearch/config/elasticsearch.yml"
  source "../../../templates/elasticsearch/config/elasticsearch2_yml.erb"
  variables({cluster_name: 'nakamura-elasticsearch', index_shards_num: "5", index_replicas_num: "1"})
end

execute "bin/elasticsearch -d" do
  cwd '/usr/local/share/elasticsearch'
end

elasticsearchはバージョン1系と2系で変わったところがあるので、今回レシピも分けて書くようにしました。どちらを使うかはnodeの中の値で変わるようにしました。

続いてredisです。

recipes/redis/redis.rb
%w( yum wget ).each do |pkg|
  package pkg do
    action :install
  end
end

execute "rm redis-#{node['redis']['version']}.tar.gz" do
  only_if "test -e redis-#{node['redis']['version']}.tar.gz"
end

execute 'redis file get' do
  command "wget http://download.redis.io/releases/redis-#{node['redis']['version']}.tar.gz"
end

execute 'unzip' do
  command "tar -zxf redis-#{node['redis']['version']}.tar.gz"
end

execute 'make' do
  cwd "redis-#{node['redis']['version']}"
end

有効なプラグインがあれば、それに乗り換えようと思っています。Chefに比べてitamaeはまだプラグインが十分でないので。若干力技な感じがしつつ、取り敢えずということで。

githubから対象リポジトリを取得

次にgithubからレシピは次のようになります。

recipes/app.rb
# アプリケーションの配置場所を作成
directory "#{node[:git][:app_path]}" do
  mode "755"
end

git "#{node[:git][:app_path]}" do
  repository "https://#{node[:git][:git_user]}:#{node[:git][:git_password]}@github.com/#{node[:git][:repository]}.git"
end

実行は次のようにやればできます。
ローカルの場合

bundle exec itamae local -j [nodeファイルを指定] -h [ホストを指定] [レシピファイルを指定]

SSH経由で他のマシンに構築する場合

bundle exec itamae ssh -j [nodeファイルを指定] -h [ホストを指定] [レシピファイルを指定]

vagrantを使ってVM上に構築する場合

bundle exec itamae ssh -j [nodeファイルを指定] -h [ホストを指定] --vagrant [レシピファイルを指定]

以上で必要なミドルウィエアのインストール等をitamaeで自動化してみました。これにより後はitamaeさえ動けば、環境構築が楽にできますね!

補足

先日のitamae meetup1で発表があった事の共有になるのですが、レシピの実行に「どこにどのくらいの時間がかかっているのかを見たい」という場合は、itamaeが最新のバージョンであれば、--profile profile.jsonとprofileオプションを実行時に指定するとプロファイリングの結果がjson形式で出力されます。あまりにも実行が遅い、何故だろうって思ったら使ってみると良いなと思いました。

複数のマシンに対してレシピをそれぞれ役割に応じて適用したい場合

rundockというgemを使うと簡単にできます。どのマシンに何を適用するかをyml形式のファイルに記述し実行時に、そのファイルを指定すると各マシンに必要な設定を入れることができます。ロール単位でレシピを記述し、それをrundockで指定します。

rundockのインストール

Gemfileに追加してbundle installでインストールします。

# rundocによる複数ホストの実行
gem 'rundock'
gem 'rundock-plugin-operation-itamae'

rundock.yml

rundockの設定の例です。dev-el2とdev-el4というVM上に作った2つのローカル環境にそれぞれミドルウェアをitamaeのレシピを指定してインストールしています。このようにしておけば、各環境ごとにyamlファイルを作成し、その中で必要なレシピを指定するように書いておけば、どの環境にどのバージョンの何が入っているのかが一目瞭然になります。

- target: dev-el2
  itamae:
    - cookbooks/redis_elasticsearch.rb
    - node_json: nodes/redis_elasticsearch.json
    - log_level: info
    - sudo: true
- target: dev-el4
  itamae:
    - recipes/redis/redis.rb
    - node_json: nodes/redis.json
    - log_level: info
    - sudo: true
---
dev-el2:
  host: 127.0.0.1
  ssh_opts:
    port: 2200
    user: vagrant
    key: /usr/local/project/itamae_recipe/.vagrant/machines/el4/virtualbox/private_key
dev-el4:
  host: 127.0.0.1
  ssh_opts:
    port: 2222
    user: vagrant
    key: /usr/local/project/itamae_recipe/.vagrant/machines/el2/virtualbox/private_key
---

まだレシピの書き方やフォルダ構成など見直す点が多々あると思っていますが、他の方々の何かの役に立つ事が出来たら幸いです。

参考

41
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
43

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?