環境コピーで展開が速いって言うのがクラウドのウリになっているけど、それだけならデプロイが簡単で速ければ別にさくらのVPSでも良いって事だよね?
同じくらいのコンピューティングするならクラウドよりVPSの方が数倍コスパ良いんだし・・・
って事で、先日参加したセミナーで扱われてたAnsibleと言うヤツを試してみた。
職場だと展開系はChefなんだけど、Chef自体準備するの面倒くさいんで、簡単なスクリプトが動けば良いんだよ・・・ってところで、Ansibleは設定対象サーバに何か入れる必要が無いと言うところが非常に魅力的だった(実際はSSHとPythonが必要だけど、普通にセットアップされたサーバには基本入ってる。 Chefに必要なRubyは大抵入ってない)
そんなわけで、Ansible。 基本的に、Ansibleのツールを入れたサーバからコマンドとか、Playbook(レシピみたいなの)に従ったssh経由で処理してくれるツールで、ターゲットはsshの準備だけすれば良い。
さくらのVPSでテストしたけど、この場合は、
echo “SSH公開鍵” >> /root/.ssh/authorized_keys; chmod 644 /root/.ssh/authorized_keys;
だけ投げ込めば、後はAnsible側から操作できる。
Ansibleのベストプラクティスもあるけど、とにかく単機能のアプリを一発展開できるPlaybookをミニマムで作ってみて、どれだけ楽か試す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
--- - name: Deploy MyApp hosts: xxx.xxx.xxx.xxx vars: app_url: 'http://deploy.my.tld/MyApp.tgz' my_user: mysql-user my_pass: mysql-password remote_user: root tasks: - name: Add remi shell: rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm - name: Install middlewares yum: name={{ item }} state=latest enablerepo=remi with_items: - php - php-mysql - mysql - mysql-server - name: Start mysqld service: name=mysqld state=started - name: Create mysql user and database shell: | mysql << " _EOF_" CREATE USER {{ my_user }} IDENTIFIED BY '{{ my_pass }}'; CREATE DATABASE {{ my_user }}; GRANT ALL PRIVILEGES ON `{{ my_user }}`.* TO `{{ my_user }}`@`localhost`; FLUSH PRIVILEGES; _EOF_ - name: Config iptables blockinfile: dest: /etc/sysconfig/iptables insertafter: "^:OUTPUT" content: | -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 - name: reload iptables service: name=iptables state=reloaded - name: Config php lineinfile: dest=/etc/php.ini state=present backrefs=yes regexp='{{ item.regexp }}' line='{{ item.line }}' with_items: - regexp: '^short_open_tag =' line: 'short_open_tag = On' - regexp: ';date.timezone =' line: 'date.timezone = "Asia/Tokyo"' - name: Config httpd lineinfile: dest=/etc/httpd/conf/httpd.conf state=present backrefs=yes regexp='{{ item.regexp }}' line='{{ item.line }}' with_items: - regexp: '^DocumentRoot "/var/www/html"' line: 'DocumentRoot "/var/www/html/public"' - regexp: '^ AllowOverride None' line: ' AllowOverride All' - name: Set ProductionMode lineinfile: dest=/etc/httpd/conf/httpd.conf line='SetEnv FUEL_ENV production' - name: Download MyApp shell: | wget -O /tmp/myapp.tgz {{ app_url }} tar xzf /tmp/myapp.tgz -C /var/www/html chown apache:apache /var/www/html -R rm /tmp/myapp.tgz - name: Setup App stage1 lineinfile: dest=/var/www/html/fuel/app/config/production/db.php state=present backrefs=yes regexp='{{ item.regexp }}' line='{{ item.line }}' with_items: - regexp: "'dsn'" line: "'dsn'=>'mysql:host=localhost;dbname={{ my_user }}'," - regexp: "'username'" line: "'username'=>'{{ my_user }}'," - regexp: "'password'" line: "'password'=>'{{ my_pass }}'," - name: Setup App stage2 shell: | cd /var/www/html FUEL_ENV=production php oil r migrate - name: Start httpd service: name=httpd state=started |
ファイルはYAML形式。
hostsに対象のホストを書く。
今回はIP指定だけど、別途ホスト指定ファイルを用意して、グループ名を指定したりも出来る。
varsで、ここで使う変数を定義。
アプリパッケージを置いてあるURLをapp_url、そのアプリ用のMySQLユーザ名とパスワードをmy_user/my_passに入れた。
remote_userはSSHする先のユーザ名で、ansible-playbookを実行するユーザと違う場合に書く。 今回は手抜きで直接root実行させる。 もちろん、sudoさせることも出来る。
tasksで処理を書いていく。
name要素は処理実行時に見出しとしてAnsibleが表示してくれるので、どのステージまで進んだかわかりやすいように書いておいた方が良い。 無くても動く。
一番最初のAdd remiは、shell機能を呼び出す。
この場合は、単純にrpm …を実行してremiを追加している。
ちなみにコマンドの終了コードがnot 0(異常終了)の時はAnsibleがそこで止まるんで、remiが既に入っているとここで転ける。
次はyum機能を使って、対象のyumを呼び出す。
shell: yum install …みたいに書いても良いけど、それを書くとAnsible実行時に注意されるので、こんな風に書いた。
今回はphp php-mysql msql mysql-serverの最新版をインストールする設定。
で、インストールしたmysqldをスタートする設定。 これもyum同様にservice機能を使えと言われたのでそう記述。
mysqlにSQLを流し込んで、ユーザ作成・DB作成・権限付与。
shellに複数行書く場合は、最初のところに|を入れてスタート。
ヒアドキュメントで入れるんだけど、ansibleでやると先頭にスペースが1個入って来たんで、閉じマーク指定をクォーテーションでくくってスペース入るよと書いておいた。
iptables設定を追加。
blockinfileは、指定した位置に複数行を差し込める。
destは対象ファイル、insertafterは正規表現で差し込む直前行を指示し、contentに差し込む内容を書く。
今回は80と443オープンするための2行追記。
で、iptablesをリロードさせる。
次はphp.iniを設定、lineinfileは1行単位の書き換えが出来る。
regexp正規表現で見つけたところを、lineに書き換えるルールで、with_itemsセット分ぐるぐる回す。
short_open_tag =で始まる行を、short_open_tag = Onに書き換えるとか、タイムゾーンとか設定。
同じようにhttp.confも設定する。
FuelPHPアプリケーション用のFUEL_ENVを設定する1行追記するために、lineinfileにinsertafterで位置指定追記だけど、EOFはファイルの末尾を示すキーワード。
デプロイサーバからアプリケーションのTGZを落としてきて、展開して、所有権書き換えて、ゴミを消す。
で、アプリのDB接続情報をセットアップしたmysqlにあわせてやって、oilでマイグレーション実行してhttpd起動して終了。
で、できあがったら、
ansible-playbook -i xxx.xxx.xxx.xxx myappdeploy.yml
みたいに実行してやると実行してくれる。
FuelPHPで作ったアプリ展開が1分くらいで完了した。
うん、これなら普通にVPSでやっていける。
で、後からアプリをバージョンアップする場合には、グループ指定を作っておいてやれば増えたサーバに全部アップデートをかけられる。
/etc/ansible/hostsファイルに
[myapp-servers]
xxx.xxx.xxx.xxx
yyy.yyy.yyy.yyy
みたいに記述しておけば、hosts: myapp-serversってPlaybookで指定すると、xxx.xxx.xxx.xxxとyyy.yyy.yyy.yyyに一気に実行できる。
で、アプリのバージョンアップ用スクリプトだと、PHP設定とかいらないから・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
--- - name: Version-up MyApp hosts: myapp-servers vars: app_url: 'http://deploy.my.tld/MyApp-noconfig.tgz' my_user: mysql-user my_pass: mysql-password remote_user: root tasks: - name: Stop httpd service: name=httpd state=stopped - name: Download MyApp shell: | wget -O /tmp/myapp.tgz {{ app_url }} tar xzf /tmp/myapp.tgz -C /var/www/html chown apache:apache /var/www/html -R rm /tmp/myapp.tgz - name: Migrate shell: | cd /var/www/html FUEL_ENV=production php oil r migrate - name: Start httpd service: name=httpd state=started |
conf/productionディレクトリを外したバージョンのパッケージを作っておけば、httpd止めて、更新ファイルを展開して、oilでマイグレーション実行して、httpd起動し直しも一発OK。
うん、これならちょっとくらい台数増えても余裕だね。
環境へのインストール系とかインストール済みなら処理しないとか、諸々条件分岐を書く必要もあるだろうけど、完全に同一環境であればこの程度の物でもやっていけるだろう。
この手のスクリプトを作る場合は、VMとか用意してスナップショットで巻き戻し繰り返しながら作るのが速いのかな。
(1192)