旧ブログ

sambaiz.net に引っ越しました

ItamaeでCentOS7にGitbucket + Jenkins + Redmineの環境構築

社会人になりました。 研修でサーバー構築自動化の課題があり、Itamaeを使ってみました。

github.com

Itamaeとは

github.com

軽量版Chefのようなもので、その分学習コストがかからず、シンプルなのがいいですね。

今回やったこと

CentOS7にGitbucket + Jenkins + Redmine の環境構築に加えて連携するのに必要なプラグインも入れました。 GitbucketとJenkinsはApacheをリバースプロキシとして用い、Tomcat上で動かしました。 RedmineはPassenger+Apache上で動かし、DBにはMariaDBを使いました。

ディレクトリ構成は自由みたいですが、今回はドキュメントにあるベストプラクティスに沿っています。

https://github.com/itamae-kitchen/itamae/wiki/Best-Practice

Resource

まず、今回使ったリソースについて簡単に説明します。 Chefを使ったことがあれば読み飛ばして実際の例から見てもいいかもしれません。

package resource

パッケージを(インストール/アンインストール)します。

nameのデフォルトがリソース名、actionのデフォルトが:installなので、

package "install ruby" do
    name "ruby"
    action :install
end

package "ruby"

と同じです。なので、まとめてインストールする際は

%w(ruby ruby-devel mariadb-server).each do |p|
    package p
end

と書くこともできます。 %w(ruby ruby-devel mariadb-server)というのは['ruby', 'ruby-devel', 'mariadb-server']を表すRubyの配列記法です。

service resource

サービスに関する操作を行います。

actionは以下のように配列で指定できます。

service 'httpd' do
  action [:start, :enable]
end

git resource

gitリポジトリからひっぱってきます。

リソース名はrepositoryではなくdestination、つまり設置先のデフォルトです。 repositoryは必須です。

git "/var/lib/redmine/plugins/redmine_github_hook" do
    repository "https://github.com/koppen/redmine_github_hook.git"
end

gem_package resource

gemを(インストール/更新)します。

gem_package "bundler"

remote_file resource

ローカルにあるファイルをリモートに設置します。

remote_file "/var/lib/redmine/config/database.yml"

sourceでローカルにあるファイルを指定することもできますが、デフォルトでは:autoになっていて指定しなくてもいいようになっています。

ではどうやって見つけるかというと、上の例であれば、/files/var/lib/.../config/database.ymlから探しにいくのです。その後の探す順序については以下のページに書いてありますが、基本的にはこのようにファイルを置くのが推奨されています。

https://github.com/itamae-kitchen/itamae/wiki/Best-Practice#use-source-auto-for-remote_file-and-template-resources

execute resource

コマンドを実行します。いままでのリソースでできないことがあればコマンドを打つしかないですね。

execute "setenforce 0"

まとめて実行する場合はcommandにヒアドキュメントを指定することができます。<<-で囲まれた部分で、Rubyリテラルです。

execute "migration" do
    command <<-EOL
        cd /var/lib/redmine
        /usr/local/bin/bundle install
        RAILS_ENV=production /usr/local/bin/rake db:migrate
        /usr/local/bin/rake generate_secret_token
    EOL
end

最後に、リソースには、only_if、not_ifで条件を付けることができます。test -eはファイルが存在すればtrueを返すコマンドです。したがって、以下のexecute resourceは一度実行されファイルが置かれると次は実行されなくなります。

execute "sudo wget https://github.com/takezoe/gitbucket/releases/download/3.1.1/gitbucket.war -P /var/lib/tomcat/webapps" do
    not_if "test -e /var/lib/tomcat/webapps/gitbucket.war"
end

構築

Vagrantで立ち上げた仮想環境に構築する場合、Vagrantfileに以下の設定が必要です。 デフォルトのメモリサイズだとpassenger-install-apache2-moduleの実行の際に失敗するからです。

config.vm.network "private_network", ip: "192.168.33.10"
config.vm.provider "virtualbox" do |vb|
  vb.memory = "2048"
end

この場合、実行コマンドは以下の通りです。

itamae ssh -h 192.168.33.10 -u vagrant

まず、先に完成形のroles/web.rbから説明します。 これは、firewalldからredmineまで全てのレシピを読み込んでいるものです。そのため、実行するときにこのファイルを指定すると全てのレシピが順番に実行されます。

%w(firewalld apache mysql tomcat gitbucket jenkins redmine).each do |cookbook|
  include_recipe "../cookbooks/#{cookbook}/default.rb"
end

firewalld

firewalldはRHEL7から採用されたデフォルトのファイアウォールで、iptablesにゾーンという概念を加えたものみたいです。

package 'firewalld'

service 'firewalld' do
  action [:start, :enable]
end

Apache

ここで、firewall-cmdコマンドを用い、http(80)ポートを開けています。

package 'httpd'

# index.htmlなどがないときにファイル一覧が表示されなくする
execute 'sudo sed -ie "s/Options Indexes FollowSymLinks/# Options -Indexes FollowSymLinks/g" /etc/httpd/conf/httpd.conf'

service 'httpd' do
  action [:start, :enable]
end

%w(http).each do |service|
  execute "sudo firewall-cmd --zone public --add-service #{service} --permanent" do
    not_if "sudo firewall-cmd --list-service --zone=public | grep ' #{service} '"
  end
end

# 再起動して設定を適用
execute "firewall-cmd --reload"

MySQL

MySQLの互換性のあるフォークであるMariaDBを使います。

/etc/my.cnf文字コードの設定を追加したものです。 mysql_secure_installationではこのコマンドで実行されるクエリを並べています。execute "mysql_secure_installation"としてしまうと、入力待ちとなり止まってしまうからです。

package 'mariadb-server'

service 'mariadb' do
  action [:start, :enable]
end

remote_file "/etc/my.cnf"

execute "mysql_secure_installation" do
  user "root"
  only_if "mysql -u root -e 'show databases' | grep information_schema" # パスワードが空の場合
  command <<-EOL
    mysqladmin -u root password "password"
    mysql -u root -ppassword -e "DELETE FROM mysql.user WHERE User='';"
    mysql -u root -ppassword -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1');"
    mysql -u root -ppassword -e "DROP DATABASE test;"
    mysql -u root -ppassword -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';"
    mysql -u root -ppassword -e "FLUSH PRIVILEGES;"
  EOL
end

Tomcat

package 'tomcat'

service 'tomcat' do
  action [:start, :enable]
end

Gitbucket

GitHubクローンです。

SELinuxをOffにします。他でも同じことをしている部分がありますが、それは単体で動くことを期待してのことです。

# SELinuxをoffに
execute "setenforce 0"
execute "sudo sed -i s/SELINUX=enforcing/SELINUX=disabled/ /etc/sysconfig/selinux"

execute "sudo wget https://github.com/takezoe/gitbucket/releases/download/3.1.1/gitbucket.war -P /var/lib/tomcat/webapps" do
    not_if "test -e /var/lib/tomcat/webapps/gitbucket.war"
end
remote_file "/etc/httpd/conf.d/gitbucket.conf"

%w(tomcat httpd).each do |s|
    service s do
        action [:restart]
    end
end

gitbucket.confは以下の通りです。Jenkinsも同様にこれだけで動くので楽ですね。

<Location /gitbucket>
    ProxyPass ajp://localhost:8009/gitbucket
</Location>

Jenkins

プラグインを入れるためにjenkins-cli.jarを持ってくるのですが、Apacheが再起動する必要があるのでとりあえず30秒待つことにしています。

# SELinuxをoffに
execute "setenforce 0"
execute "sudo sed -i s/SELINUX=enforcing/SELINUX=disabled/ /etc/sysconfig/selinux"

package "wget"

execute "sudo wget http://mirrors.jenkins-ci.org/war/latest/jenkins.war -P /var/lib/tomcat/webapps" do
    not_if "test -e /var/lib/tomcat/webapps/jenkins.war"
end
remote_file "/etc/httpd/conf.d/jenkins.conf"

%w(tomcat httpd).each do |s|
    service s do
        action [:restart]
    end
end

# 再起動を待つ
execute "sleep 30"

# gitとgitbucketのプラグインを入れる
execute "wget http://localhost/jenkins/jnlpJars/jenkins-cli.jar -P /tmp" do
    not_if "test -e /tmp/jenkins-cli.jar"
end
execute "java -jar /tmp/jenkins-cli.jar -s http://localhost/jenkins/ install-plugin git gitbucket -deploy"

Redmine

passenger-install-apache2-moduleは入力待ちで止まらないように--autoを付けて実行します。 passengerのインストールの際にバージョンを指定しているのは、簡単のためredmine.confのパスにバージョンを直書きしているためです。これはtemplateを使うことで解消することができます。

# SELinuxをoffに
execute "setenforce 0"
execute "sudo sed -i s/SELINUX=enforcing/SELINUX=disabled/ /etc/sysconfig/selinux"

execute "svn co http://svn.redmine.org/redmine/branches/3.0-stable /var/lib/redmine" do
    not_if "test -e /var/lib/redmine"
end

remote_file "/var/lib/redmine/config/database.yml"

%w(mariadb-server ruby).each do |p|
    package p
end

execute "create db and user for redmine" do
    command <<-EOL
        mysql -u root -ppassword -e "create database db_redmine default character set utf8;"
        mysql -u root -ppassword -e "grant all on db_redmine.* to user_redmine@localhost identified by 'password';"
        mysql -u root -ppassword -e "create database db_redmine default character set utf8;"
        mysql -u root -ppassword -e "flush privileges;"
    EOL
end

gem_package "passenger" do
    version '5.0.7'
end

gem_package "bundler"


# passenger-install-apache2-module/bundle install に必要なもの
%w(libcurl-devel openssl-devel zlib-devel httpd-devel ruby-devel apr-devel
apr-util-devel mariadb-devel ImageMagick ImageMagick-devel).each do |p|
    package p
end

execute "migration" do
    command <<-EOL
        cd /var/lib/redmine
        /usr/local/bin/bundle install
        RAILS_ENV=production /usr/local/bin/rake db:migrate
        /usr/local/bin/rake generate_secret_token
    EOL
end

# PassengerのApache用モジュールのインストール
execute "/usr/local/bin/passenger-install-apache2-module --auto"

# Apacheを実行するユーザー・グループ("apache")が読み書きできるように権限を与える
execute "sudo chown -R apache:apache /var/lib/redmine"

# ApacheのDocumentRootに指定されているディレクトリにシンボリックリンクを張る
execute "sudo ln -s /var/lib/redmine/public /var/www/html/redmine" do
    not_if "test -e /var/www/html/redmine"
end

remote_file "/etc/httpd/conf.d/redmine.conf"

# redmine_github_hook pluginをインストール
git "/var/lib/redmine/plugins/redmine_github_hook" do
    repository "https://github.com/koppen/redmine_github_hook.git"
end

service 'httpd' do
  action [:restart]
end

これで必要なものは入れ終わりました。ここから実際に連携する方法はリポジトリのREADMEを見てください。

おわりに

おわり

参考

CentOS 7 で GitHubクローンの GitBucket を動かして、Jenkins で自動デプロイ - BLACKND

Redmine 3.0をCentOS 7.0にインストールする手順 | Redmine.JP Blog