LoginSignup
398
401

More than 5 years have passed since last update.

RailsのDeploy環境+運用を考慮したサーバー構築

Last updated at Posted at 2014-01-11

Ruby on RailsでDev環境は使ったことあるけど、test・prod環境を考慮した環境構築をしたことがない人にお勧めの内容です。

サーバー構成図

スクリーンショット 2014-01-11 12.15.17.png

サーバーの役割

リバースプロキシサーバー(ホスト名:rp01)

  • ロードバランサ機能を使ってWEBサーバ二台に処理を振り分け、アクセスを1台のサーバーに集中させない
  • WEBサーバーを外部から隠せることでセキュリティ面の向上

WEBサーバー(web01、web02)

  • webサーバーを2台用意することでアクセスが1つのサーバーに集中しないため、レスポンスを早くできる

マスターDBサーバー(db01m)

  • DB内容をもう1台のDBサーバー(スレーブ)へリアルタイムにコピーし、障害でマスターが停止したときはスレーブに切り替える

スレーブDBサーバー(db01s)

  • 読み込み専用のサーバー。書き込みをしない分レスポンスが早くなる
  • マスターの内容を常にコピーする(レプリケーションという)

開発環境(dev01)

  • 開発はこの環境だけで行い、完成物をWEBサーバーにアップロードする(デプロイという)

DNS(rp01)

  • 各サーバーのホスト名を管理するDNS。リバースプロキシと同じサーバー内で動作させる

準備

  • VPS等でサーバーを5台借りておく(rp01、web01、web02、db01m、db01s)
  • リバースプロキシはグローバルIP必須
  • 開発環境(手持ちにMacやUnix環境がないならvpsで借りる)

サーバー仕様

WEBサーバー・リバースプロキシ

  • Apache/2.2.15 (Unix)

データベース

  • MySQL Server 5.1.71

DNS

  • mydns 1.2.8.31

Ruby

  • ruby-2.0.0-p353

Ruby on Rails

  • Rails 4.0.2

全サーバーに共通するセットアップ

ログインユーザーのセキュリティ設定編

初期インストールされたパッケージをアップデート

$ sudo yum update

ログインユーザー(deploy01)の作成

$ useradd deploy01
$ passwd  deploy01

deploy01をsudo権限が使えるグループに所属させる

$ usermod –G wheel deploy01

wheelグループ以外はsudo権限を与えない設定。
下記行のコメントを外す。

/etc/pam.d/su
#auth  required pam_wheel.so use_uid

wheelグループのみrootユーザーにログイン可能にする。
下記行を追加

/etc/login.defs
SU_WHEEL_ONLY yes

wheelグループのユーザーのみ sudoコマンドを実行許可。
下記コマンドを実行する。

$ visudo

すると、設定ファイルが開くので下記行のコメントを外す

# %wheel ALL=(ALL) ALL

rootユーザーでのsshログインを禁止する。
下記行をコメント化する

/etc/ssh/sshd_config
PermitRootLogin no

SSHのポートを狙った攻撃を回避するため、ポート番号を変更する。
Portの後ろに変更したいポート番号を入れる

/etc/ssh/sshd_config
Port 3243

SSHの変更を有効にするため、SSHを再起動するコマンドを実行

$ /etc/init.d/sshd restart

ファイアウォール編

下記コマンドを実行するとファイアウォールの設定情報を確認できる

$ /sbin/iptables -L --line-number

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

上記と同じ表示の場合、すべての通信を許可しているためセキュリティ上問題がある。
各サーバーごとにファイアウォールを設定する。

リバースプロキシ(rp01)のファイアウォール設定

外部パケットから入ってくるパケットのうち
http、https、ssh(ポートは3824)、DNSのみ許可する。

/etc/sysconfig/iptables
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
## allow well-known port ##
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
## allow port(SSH,http,https,DNS) ##
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3824 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80   -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443  -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 53   -j ACCEPT
COMMIT

WEBサーバー(web01、web02)の設定

※IPアドレスをホスト名に置き換えてます。

/etc/sysconfig/iptables
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#------------------------------------------------------
# ping、ループバックアドレスを許可
#------------------------------------------------------
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
#------------------------------------------------------
# RPのみ、webサーバーへの通信を許可
# 80は本番環境(prod)のサイト表示
# 8000はテスト環境(test)のサイト表示
#------------------------------------------------------
-A INPUT -s rp01 -p tcp --dport 80   -j ACCEPT
-A INPUT -s rp01 -p tcp --dport 8000 -j ACCEPT
#------------------------------------------------------
# SSHを許可
#------------------------------------------------------
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3843 -j ACCEPT
COMMIT

DBサーバー(db01m)の設定

※IPアドレスをホスト名に置き換えてます。

*filter
#------------------------------------------------------
# メンテナンス可能リスト
# web01
# web02
# db01s
#------------------------------------------------------
#------------------------------------------------------
# ポリシー:全ての送受信パケットを破棄。必要な用途に応じて開けていく。
#------------------------------------------------------
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
#------------------------------------------------------
# pingとループバックアドレス(自分自身のIP)からの送受信を許可
#------------------------------------------------------
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A INPUT  -p icmp -j ACCEPT
-A OUTPUT -p icmp -j ACCEPT
#------------------------------------------------------
# 内部からのDNS送信を許可
#------------------------------------------------------
-A OUTPUT -m state --state NEW -m udp -p udp --dport 53   -j ACCEPT
#------------------------------------------------------
# 内部からのhttp送信を許可(yum等)
#------------------------------------------------------
-A OUTPUT -m state --state NEW -m tcp -p tcp --dport 80   -j ACCEPT
#------------------------------------------------------
# メンテナンスのみSSH接続を許可
#------------------------------------------------------
-A INPUT  -s web01 -p tcp --dport 3843 -j ACCEPT
-A OUTPUT -d web01 -p tcp --sport 3843 -j ACCEPT
-A INPUT  -s web02 -p tcp --dport 3843 -j ACCEPT
-A OUTPUT -d web02 -p tcp --sport 3843 -j ACCEPT
-A INPUT  -s db01s -p tcp --dport 3843 -j ACCEPT
-A OUTPUT -d db01s -p tcp --sport 3843 -j ACCEPT
#------------------------------------------------------
# メンテナンスのみMySQL接続を許可
#------------------------------------------------------
-A INPUT  -s web01 -p tcp --dport 3306 -j ACCEPT
-A OUTPUT -d web01 -p tcp --sport 3306 -j ACCEPT
-A INPUT  -s web02 -p tcp --dport 3306 -j ACCEPT
-A OUTPUT -d web02 -p tcp --sport 3306 -j ACCEPT
-A INPUT  -s db01s -p tcp --dport 3306 -j ACCEPT
-A OUTPUT -d db01s -p tcp --sport 3306 -j ACCEPT
#------------------------------------------------------
# 接続済みパケットの送受信を許可
#------------------------------------------------------
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
COMMIT

DBサーバー(db01s)の設定

※IPアドレスをホスト名に置き換えてます。

*filter
#------------------------------------------------------
# メンテナンス可能リスト
# web01
# web02
# db01m
#------------------------------------------------------
#------------------------------------------------------
# ポリシー:全ての送受信パケットを破棄。必要な用途に応じて開けていく。
#------------------------------------------------------
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
#------------------------------------------------------
# pingとループバックアドレス(自分自身のIP)からの送受信を許可
#------------------------------------------------------
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A INPUT  -p icmp -j ACCEPT
-A OUTPUT -p icmp -j ACCEPT
#------------------------------------------------------
# 内部からのDNS送信を許可
#------------------------------------------------------
-A OUTPUT -m state --state NEW -m udp -p udp --dport 53   -j ACCEPT
#------------------------------------------------------
# 内部からのhttp送信を許可(yum等)
#------------------------------------------------------
-A OUTPUT -m state --state NEW -m tcp -p tcp --dport 80   -j ACCEPT
#------------------------------------------------------
# メンテナンスのみSSH接続を許可
#------------------------------------------------------
-A INPUT  -s web01 -p tcp --dport 3843 -j ACCEPT
-A OUTPUT -d web01 -p tcp --sport 3843 -j ACCEPT
-A INPUT  -s web02 -p tcp --dport 3843 -j ACCEPT
-A OUTPUT -d web02 -p tcp --sport 3843 -j ACCEPT
-A INPUT  -s db01m -p tcp --dport 3843 -j ACCEPT
-A OUTPUT -d db01m -p tcp --sport 3843 -j ACCEPT
#------------------------------------------------------
# メンテナンスのみMySQL接続を許可
#------------------------------------------------------
-A INPUT  -s web01 -p tcp --dport 3306 -j ACCEPT
-A OUTPUT -d web01 -p tcp --sport 3306 -j ACCEPT
-A INPUT  -s web02 -p tcp --dport 3306 -j ACCEPT
-A OUTPUT -d web02 -p tcp --sport 3306 -j ACCEPT
-A INPUT  -s db01m -p tcp --dport 3306 -j ACCEPT
-A OUTPUT -d db01m -p tcp --sport 3306 -j ACCEPT
#------------------------------------------------------
# 接続済みパケットの送受信を許可
#------------------------------------------------------
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
COMMIT

すべての設定を書き終えたらiptablesを再起動してファイアウォールを有効化

$ service iptables restart

ファイアウォールの設定は以上。
開発環境のファイアウォールは任意で設定してください。

MySQL(データベースサーバー)のインストール

Mysqlのパッケージについて

mysqlのパッケージには大きく分けて3種類ある

  • mysql:client用
  • mysql-server:server用
  • mysql-devel:アプリケーションとの連携用

そのため、用途によってはインストールするパッケージを絞ることが可能

terminalからmysqlに接続する

  • mysql

railsやmydns等のアプリケーションからmysqlサーバーに接続

  • mysql、mysql-devel

データベース運用

  • mysql-server

今回はサーバーごとにインストールするパッケージを変える

MySQLのインストール

rp01(DNSサーバー用として使う)

$ yum install mysql mysql-devel mysql-server

web01、web02(rails用にインストール)

$ yum install mysql mysql-devel

db01m、db01s(mysqlデータベース用)

$ yum install mysql mysql-server

mysqlの設定

以下をサーバー5台全てに設定する

mysqlの設定ファイルをバックアップする

$ sudo cp /etc/my.cnf /etc/my.cnf.org

MySQLの設定ファイルをバックアップ

$ sudo cp /etc/my.cnf /etc/my.cnf.org

MySQLの設定ファイルを下記のように設定

/etc/my.cnf

[mysqld]
character-set-server = utf8
skip-character-set-client-handshake
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
symbolic-links=0

innodb_buffer_pool_size = 512MB # サーバのメモリ7080%
innodb_log_file_size = 100MB # 100-500MB程度
innodb_flush_log_at_trx_commit = 2

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid          

rootのパスワード設定

$ sudo mysqladmin -u root password 'パスワード'

mysql-serverをインストールしている
rp01とdb01m、db02mのみMySQLの自動起動をONにする

$ sudo service mysqld start
$ sudo chkconfig mysqld on

MySQLにログインし、不要なユーザーとデータベースを削除する

$ mysql -u root -p ****

mysql > use mysql;
mysql > select user,password, host from user;
+------+-------------------------------------------+-------------------------+
| user | password                                  | host                    |
+------+-------------------------------------------+-------------------------+
| root | *hogehogehogehogehogehogehogehogehogehoge | localhost               |
| root |                                           | hogehogehogehogeh.ne.jp |
| root |                                           | 127.0.0.1               |
|      |                                           | localhost               |
|      |                                           | hogehogehogehogeh.ne.jp |
+------+-------------------------------------------+-------------------------+
mysql > DELETE FROM user WHERE user = '' OR ( user = 'root' AND host != 'localhost' );
Query OK, 4 rows affected (0.00 sec)

mysql > select user,password, host from user;
+------+-------------------------------------------+-----------+
| user | password                                  | host      |
+------+-------------------------------------------+-----------+
| root | *hogehogehogehogehogehogehogehogehogehoge | localhost |
+------+-------------------------------------------+-----------+
1 row in set (0.00 sec)

続いて、不要なデータベースを削除

mysql > show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
+--------------------+
3 rows in set (0.00 sec)

mysql> DROP DATABASE test;
Query OK, 0 rows affected (0.00 sec)

文字セットの確認

show variables like 'character_set%';
# ↓ のようになっていれば成功
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

rails用のデータベースを作成

mysql > create database app;
mysql > create database app_test;
mysql > create database app_dev;

mydns(DNSサーバー)のインストール

mydnsとは?

MySQLのデータベースを使って、ホスト名の管理ができる。
ホストを追加するときはinsert文を1つ打つだけで設定可能なので管理が楽。

インストールについて

MyDNSのインストールは任意。
SSH接続やiptables、apache設定でipを使わずホスト名を使いたい人は
設定してください。(この記事は全てホスト名になっています)

インストール方法

インストールはrp01で行います。

mydnsをダウンロードするためのリポジトリを追加

rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

mydnsパッケージのインストール

$ yum install mydns
$ yum install mydns-mysql

mysqlにログインし、mydns用データベースを作成

mysql > create database mydns;

ターミナルから下記コマンドを実行

$ mydns --create-tables | mysql -u root -p mydns

mysqlにログインし、mydns用のテーブルができているか確認

mysql > use mydns;

Database changed
mysql> show tables;
+-----------------+
| Tables_in_mydns |
+-----------------+
| rr              |
| soa             |
+-----------------+

mydns用のユーザーを作成する。
※データベースmydnsに対して、全ての権限を持ったユーザー(全てのホストからのアクセス許可)

GRANT ALL ON mydns.* TO 'mydns'@'%' IDENTIFIED BY 'mydns';
Query OK, 0 rows affected (0.01 sec)

DNSゾーンとレコードの作成

※ネットワークをxxx.localにする
※xxx.xxx.xxx.xxxはIPアドレスです

mysql> insert into soa (origin, ns) values ('local.', 'ns.local');
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into rr (zone, name, type, data) values(1, 'web01', 'A', ‘xxx.xxx.xxx.xxx’);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into rr (zone, name, type, data) values(1, 'web02', 'A', 'xxx.xxx.xxx.xxx’);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into rr (zone, name, type, data) values(1, 'db01m', 'A', 'xxx.xxx.xxx.xxx’);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into rr (zone, name, type, data) values(1, 'db01s', 'A', 'xxx.xxx.xxx.xxx’);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into rr (zone, name, type, data) values(1, ‘rp01,   'A', 'xxx.xxx.xxx.xxx’);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into rr (zone, name, type, data) values(1, ‘dev01’, 'A', 'xxx.xxx.xxx.xxx’);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select * from rr;
+----+------+-------+------------------+-----+-------+------+
| id | zone | name  | data             | aux | ttl   | type |
+----+------+-------+------------------+-----+-------+------+
|  1 |    1 | web01 | xxx.xxx.xxx.xxx  |   0 | 86400 | A    |
|  2 |    1 | web02 | xxx.xxx.xxx.xxx  |   0 | 86400 | A    |
|  3 |    1 | db01m | xxx.xxx.xxx.xxx  |   0 | 86400 | A    |
|  4 |    1 | db01s | xxx.xxx.xxx.xxx  |   0 | 86400 | A    |
|  5 |    1 | rp01  | xxx.xxx.xxx.xxx  |   0 | 86400 | A    |
|  6 |    1 | dev01 | xxx.xxx.xxx.xxx  |   0 | 86400 | A    |
+----+------+-------+------------------+-----+-------+------+

mysql > select * from soa;
+----+--------+----------+------+--------+---------+-------+--------+---------+-------+
| id | origin | ns       | mbox | serial | refresh | retry | expire | minimum | ttl   |
+----+--------+----------+------+--------+---------+-------+--------+---------+-------+
|  1 | local. | ns.local |      |      1 |   28800 |  7200 | 604800 |   86400 | 86400 |
+----+--------+----------+------+--------+---------+-------+--------+---------+-------+
1 row in set (0.00 sec)

DNSの設定とmydnsの起動

ホスト名で通信したいすべてのサーバーで下記を設定

xxx.xxx.xxx.xxxはrp01のグローバルIPアドレス

/etc/resolv.conf
search local
nameserver xxx.xxx.xxx.xxx

mydnsを起動

$ service mydns start

設定したホスト名でpingが通るか確認

ping web01

レプリケーションの設定

レプリケーションとは

データベースの内容を別のデータベースにリアルタイムで同期させる。
コピ元をマスター、コピー先をスレーブという。

レプリケーションの設定方法

マスターのdb01mのmy.cnfを下記のように設定

/etc/my.cnf
[mysqld]
log-bin=mysql-bin
server-id=1001

スレーブのdb01sにマスターに接続するmysqlユーザーを作成するため、
db01sのmysqlにログインして、下記を実行
※xxx.xxx.xxx.xxxはmasterのipアドレス

GRANT REPLICATION SLAVE ON *.* TO 'repl’@‘xxx.xxx.xxx.xxx’ IDENTIFIED BY 'slavepass';

スレーブのmy.cnfファイル内で以下の通り設定

/etc/my.cnf
[mysqld]
server-id=1002

マスター側のpositionを確認

mysql>  SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000002 |      379 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

それぞれの意味

File : バイナリログ名
Position : ファイル内のオフセット(現在位置)

Positionとファイル名をメモしておき、マスターのデータベースのテーブルをロックしておく

mysql > FLUSH TABLES WITH READ LOCK

マスターのデータベースのバックアップを取る

$ mysqldump -u root -p --all-databases --lock-all-tables > /tmp/dbdump.db

スレーブ側でSCPコマンドを使って、マスターのdbファイルを取得

$ scp -P sshのポート番号 deploy01@db01m :/tmp/dbdump.db /tmp/

スレーブのデータベースにマスターの内容を反映

# mysql -u root -p /tmp/dbdump.db

スレーブ側でマスター情報を登録

xxx.xxx.xxx.xxxにはマスターのipアドレスを入れる

mysql > CHANGE MASTER TO
           MASTER_HOST=‘xxx.xxx.xxx.xxx’,
           MASTER_USER='repl',
           MASTER_PASSWORD='XXXXXX',
           MASTER_LOG_FILE='mysql-bin.000002',
           MASTER_LOG_POS=379;

レプリケーション開始するため、スレーブ側で下記コマンドを実行

mysql > START SLAVE;

レプリケーションが開始されているか確認

show slave status;

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: xxx.xxx.xxx.xxx
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 450
               Relay_Log_File: mysqld-relay-bin.000003
                Relay_Log_Pos: 251
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

下記を確認できればDBの同期が取れている

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

Rubyのインストール

作業はweb01とweb02で行う

rootユーザーでインストールすると、root権限が必要なときがあるため
deploy01ユーザーにインストールを行う。(シングルインストール)

rvmを使ったRubyのインストール

rvmはRubyのバージョン管理を容易に行える。
コマンド1つでバージョンを切り替えたり、バージョンごとのインストールが可能

必要なパッケージのインストール

$ sudo yum -y install curl curl-devel gcc gcc-c++ httpd-devel readline-devel tk-devel make zlib-devel libffi-devel

rvmをインストール

$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )
$ echo "source $HOME/.rvm/scripts/rvm" >> ~/.bash_profile
$ source ~/.bash_profile

Rubyのver 2.0.0をインストール

$ rvm install 2.0.0

RVMの設定確認

$ rvm list
=* ruby-2.0.0-p247 [ x86_64 ] # 

railsの導入

railsのインストール(RDocのインストール部分で結構時間かかる)

$ gem install rails

RDocが不要な場合は下記でインストールする

$ gem install rails –no-ri –no-rdoc

passangerのインストールを行う

$ gem install passenger
$ passenger-install-apache2-module

インストール完了後、下記のような表示が出るのでコピー

LoadModule passenger_module /usr/lib64/ruby/gems/1.8/gems/passenger-4.0.19/buildout/apache2/mod_passenger.so
PassengerRoot /usr/lib64/ruby/gems/1.8/gems/passenger-4.0.19
PassengerDefaultRuby /usr/bin/ruby

passenger.confに上記設定とオプションを記入

/etc/httpd/conf.d/passnger.conf
# Passengerの基本設定
LoadModule passenger_module /usr/local/rvm/gems/ruby-2.0.0-p247@global/gems/passenger-4.0.18/buildout/apache2/mod_passenger.so
PassengerRoot /usr/local/rvm/gems/ruby-2.0.0-p247@global/gems/passenger-4.0.18
PassengerDefaultRuby /usr/local/rvm/wrappers/ruby-2.0.0-p247@global/ruby

# Passengerが追加するHTTPヘッダを削除するための設定
Header always unset "X-Powered-By"
Header always unset "X-Rack-Cache"
Header always unset "X-Content-Digest"
Header always unset "X-Runtime"

# 必要に応じてPassengerのチューニングのための設定を追加
PassengerMaxPoolSize 20
PassengerMaxInstancesPerApp 4
PassengerPoolIdleTime 3600
PassengerHighPerformance on
PassengerStatThrottleRate 10
RailsSpawnMethod smart
RailsAppSpawnerIdleTime 86400
PassengerMaxPreloaderIdleTime 0

デプロイ用のディレクトリを作成

test環境とprod環境の2つを用意する

$ sudo mkdir /var/www/deploy01/
$ sudo chown deploy01:deploy01 /var/www/deploy01/
$ chmod 775 /var/www/deploy01/
$ mkdir /var/www/deploy01/prod/
$ mkdir /var/www/deploy01/test/

開発環境側の設定

開発環境側(dev01)はappというアプリが出来ている状況とします。

database.ymlにslaveとmasterのdb情報を設定する

config/database.yml
development:
  adapter: mysql2
  encoding: utf8
  database: app_dev
  pool: 5
  username: root
  password: xxxx
  host: localhost

test_slave_database:
  adapter: mysql2
  encoding: utf8
  database: app_test
  pool: 5
  username: root
  password: xxx
  host: db01s

test:
  adapter: mysql2
  encoding: utf8
  database: app_test
  pool: 5
  username: root
  password: xxx
  host: db01m

production_slave_database:
  adapter: mysql2
  encoding: utf8
  database: app
  pool: 5
  username: root
  password: xxx
  host: db01s

production:
  adapter: mysql2
  encoding: utf8
  database: app
  pool: 5
  username: root
  password: xxx
  host: db01m

Gemfileに下記パッケージを記載する

Gemlife
gem 'multi_db'

デプロイツールのインストール

web01とweb02にgitをインストール

$ sudo yum install git

appアプリ配下で下記を実行

$ gem install capistrano

インストールが完了したらcapifyコマンドを実行

capify .
> [add] writing './Capfile'
> [add] writing './config/deploy.rb'
> [done] capified!

test環境とprod環境用のCapistrano設定ファイルを作成

$ mkdir config/deploy
$ touch config/deploy/test.rb
$ touch config/deploy/production.rb

共通のデプロイ情報をdeploy.rbに記入

ipアドレスをホスト名に変えてます。

app/config/deploy.rb
# -*- coding: utf-8 -*-
set :default_stage, "production"

# 複数環境にデプロイできるようにする
require "capistrano/ext/multistage"

# capistranoの出力をカラーに
require 'capistrano_colors'

# cap deploy時に自動で bundle installを実行
require "bundler/capistrano"

# RVM
require "rvm/capistrano"
set :rvm_ruby_string, 2.0.0-p353
set :rvm_type, :user

# gitリポジトリの設定
#### gitリポジトリをセット ####
set :repository,  gitのリポジトリ”
set :scm, :git
set :deploy_via, :remote_cache

# SSH
set :use_sudo, false
set :default_run_options, :pty => true
ssh_options[:port] = 22
ssh_options[:forward_agent] = true

set :normalize_asset_timestamps, false
# 過去のデプロイしたフォルダを履歴として保持する数
set :keep_releases, 5

# デプロイ先のサーバの設定
server web01:3843", :app, :web, :db, :primary => true
server “web02:3843", :app, :web, :db, :primary => true

# bundle install条件
set :bundle_flags, "--no-deployment --without test development"

# SSH
set :user, "deploy01"
set :user_group, "deploy01"
set :password, SSHのログインパスワード”

# RVM
set :rvm_path, '/home/deploy01/.rvm/'
set :rvm_bin_path, app/bin"
set :rvm_lib_path, “app/lib"

# assets:precompile
namespace :assets do
  task :precompile, :roles => :web do
    run "cd #{current_path} && RAILS_ENV=#{rails_env} bundle exec rake assets:precompile"
  end
end

# メンテナンスモード
namespace :maintenance do
  desc "Maintenance start"
  task :on, :roles => :web do
    on_rollback { run "rm #{current_path}/tmp/maintenance.yml" }
    page = File.read("config/maintenance.yml")
    put page, "#{current_path}/tmp/maintenance.yml", :mode => 0644
  end

  desc "Maintenance stop"
  task :off, :roles => :web do
    run "rm #{release_path}/tmp/maintenance.yml"
  end
end

namespace :deploy do
  # Passengerの実行ユーザー/Groupをセット
  task :set_file_process_owner do
    sudo "chown -R #{user}:#{user_group} #{deploy_to}"
  end

  #### sitemap_generatorを使ってない場合は削除 ####
  desc "sitemapの更新"
  task :refresh_sitemaps do
    run "cd #{latest_release} && RAILS_ENV=#{rails_env} bundle exec rake sitemap:refresh"
  end

  # 本番サーバでPassenger以外を使っている場合は適宜変更して下さい。
  desc "Passenger用に起動/停止タスクを変更"
  task :restart, :roles => :web do
    run "touch #{current_path}/tmp/restart.txt"
  end

  # page_cacheを使用していない場合は不要
  desc "キャッシュhtmlの削除(deploy中に不完全なhtmlを生成しないための対策)"
  task :remove_caches, :roles => :web do
    run "rm -rf #{current_path}/public/index.html"
  end

  #### Wheneverを使っていない場合は削除
  desc "wheneverのアップデート"
  task :whenever_update do
    run "cd #{latest_release} && RAILS_ENV=#{rails_env} bundle exec whenever --update-crontab #{application} -f config/schedule_#{rails_env}.rb"
  end
end
before :deploy, "deploy:set_file_process_owner"

prod用の設定

app/config/deploy/production.rb
#### デプロイ先のフォルダを設定 ####
set :deploy_to, "/var/www/deploy01/prod/app”
set :rails_env, "production"

# deploy ==========================
after :deploy, "maintenance:on"
after :deploy, "assets:precompile"
after :deploy, "deploy:migrate"
after :deploy, "deploy:restart"
after :deploy, "deploy:remove_caches"
after :deploy, "maintenance:off"
after :deploy, "deploy:cleanup"

test用の設定

app/config/deploy/test.rb
#### デプロイ先のフォルダを設定 ####
set :deploy_to, "/var/www/deploy01/test/app”
set :rails_env, “test”

# deploy ==========================
after :deploy, "assets:precompile"
after :deploy, "deploy:migrate"
after :deploy, "deploy:restart"
after :deploy, "deploy:remove_caches"
after :deploy, "deploy:cleanup"

メンテナンス画面表示用にconfig/maintenance.ymlを追加。

---
reason: メンテナンス中です
allowed_paths:
- ^/help
- ^/contact_us
allowed_ips:
- 127.0.0.1
- 192.168.0.0/24

リポジトリへのパスフレーズ入力を省略するため、ssh-agentの追加をする
※鍵にはgitリポジトリの秘密鍵を指定

# ssh-agent zsh
# ssh-agent ~/.ssh/id_rsa

デプロイができるかのテスト(初回のみ)

cap deploy:check

デプロイコマンド一覧

セットアップ(初回に実行)
$ cap production deploy:setup
$ cap test deploy:setup

デプロイを実行
$ cap production deploy:cold
$ cap test deploy:cold

以前の状態に戻す
$ cap production deploy:rollback
$ cap test deploy:rollback

以前の状態のソースコードを削除
$ cap production deploy:cleanup
$ cap test deploy:cleanup

Apacheの設定

deployが完了したらweb01とweb02のhttpd.confにrailsアプリの設定を行う

xxx.xxx.xxx.xxxにはweb01ならweb01のIPを記入

/etc/httpd/conf/httpd.conf
# prod
<VirtualHost *:80>
  ServerName xxx.xxx.xxx.xxx
  DocumentRoot /var/www/deploy01/prod/app/current/public/
  ErrorLog  /var/log/httpd/prod_app_error.log
  CustomLog /var/log/httpd/prod_app_access.log combined
  <Directory "/var/www/deploy01/prod/app/current/public">
        Options -MultiViews
        AllowOverride All
        Order allow,deny
        Allow from all
  </Directory>
</VirtualHost>

# test
<VirtualHost *:8000>
  RailsEnv test
  ServerName xxx.xxx.xxx.xxx
  DocumentRoot /var/www/deploy01/test/app/current/public/
  ErrorLog  /var/log/httpd/test_app_error.log
  CustomLog /var/log/httpd/test_app_access.log combined
  <Directory "/var/www/deploy01/test/app/current/public">
        Options -MultiViews
        AllowOverride All
        Order allow,deny
        Allow from all
  </Directory>
</VirtualHost>

serverNameでvirtualhostを分ける設定をONにするため
下記行のコメントを外す

/etc/httpd/conf/httpd.conf
#NameVirtualHost *:80

web01とweb02のapacheを再起動

$ sudo service httpd restart

iptablesを停止して、testとprod環境にアクセスできるか確認

http://xxx.xxx.xxx.xxx:80/
http://xxx.xxx.xxx.xxx:8000/

testとprod環境が動いていることを確認できたらiptablesを再スタートする

$ sudo service iptables start

リバースプロキシの設定

rp01のhttp.confファイルに下記モジュールを設定

/etc/httpd/conf/httpd.conf
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so

さらに、rp01のhttp.confにロードバランサの処理を追加

※ipアドレスをホスト名に置き換えてます

#prod環境へのアクセスを「xxx.com」
#test環境へのアクセスを「test.xxx.com」のサブドメインにした場合の設定

#prod設定
<VirtualHost *:80>
  ServerName xxx.com:80

  ProxyPass /balancer-manager !
  <Location /balancer-manager>
          SetHandler balancer-manager
  </Location>

  ProxyPass / balancer://rp01/
  ProxyPassReverse / balancer://rp01/

  <Proxy balancer://rp01/>
          BalancerMember http://web01:80 loadfactor=5
          BalancerMember http://web02:80 loadfactor=5
  </Proxy>
</VirtualHost>

#test設定
<VirtualHost *:80>
  ServerName test.xxx.com:80

  ProxyPass /balancer-manager !
  <Location /balancer-manager>
          SetHandler balancer-manager
  </Location>

  ProxyPass / balancer://test-rp01/ 
  ProxyPassReverse / balancer://test-rp01/

  <Proxy balancer://test-rp01/>
          BalancerMember http://web01:8000 loadfactor=5
          BalancerMember http://web02:8000 loadfactor=5
  </Proxy>
</VirtualHost>

loadfactorの数字を大きくすると、使用頻度が大きくなります。

web01・web02のapacheを交互に停止して、xxx.comにアクセスできたらロードバランサの設定が完了している。

余談

DTIのVPSを借りれば、月420円 * 5台 = 2100円で実現可能です。
DTIの場合、aaa.bbb.ccc.1とaaa.bbb.ccc.2のように、グローバルIPの4桁目以外が同じの場合は
セキュリティ上、通信が出来ないようです(T_T)

398
401
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
398
401