53
@hiboma Sqale の Puppet と Chef 2013510日金曜日

Sqale の Puppet と Chef (と テスト)

  • Upload
    hiboma

  • View
    4.409

  • Download
    4

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Sqale の Puppet と Chef (と テスト)

@hiboma

Sqale のPuppet と Chef

2013年5月10日金曜日

Page 2: Sqale の Puppet と Chef (と テスト)

• 伊藤洋也 (いとう ひろや)

• 株式会社 paperboy&co. 6年目氏

• 弟 30年目氏

• 技術基盤エンジニア

• ホスティングの開発業務に関わってる時間が多め

@hiboma

2013年5月10日金曜日

Page 3: Sqale の Puppet と Chef (と テスト)

どっちも買って下さい

2013年5月10日金曜日

Page 4: Sqale の Puppet と Chef (と テスト)

前置きの話

• レンタルサーバー / ホスティング

• 分譲マンションモデル

• リソースの切り売り

2013年5月10日金曜日

Page 5: Sqale の Puppet と Chef (と テスト)

ユーザーで共有されるリソース

システム管理者用リソース

PHP Perl Ruby Python Apache postfix sshd

user A user B user C user D

ユーザーごとのリソース (任意のタイミングで追加/削除)

レンサバ モデルレイヤ

nagios munin fluentd ldap

ftpd

resque

2013年5月10日金曜日

Page 6: Sqale の Puppet と Chef (と テスト)

Sqale

2013年5月10日金曜日

Page 7: Sqale の Puppet と Chef (と テスト)

2013年5月10日金曜日

Page 8: Sqale の Puppet と Chef (と テスト)

2013年5月10日金曜日

Page 9: Sqale の Puppet と Chef (と テスト)

http://www.slideshare.net/mizzy/inside-sqales-backend-at-sapporo-ruby-kaigi-2012

Sqaleのバックエンド諸々

2013年5月10日金曜日

Page 10: Sqale の Puppet と Chef (と テスト)

* PaaS *

2013年5月10日金曜日

Page 11: Sqale の Puppet と Chef (と テスト)

今日の話

• アプリがうごく環境

• 「コンテナ」と呼んでいます

2013年5月10日金曜日

Page 12: Sqale の Puppet と Chef (と テスト)

Sqaleのコンテナ

• Rubyコンテナ

• Nginx + Rackアプリ

• PHPコンテナ

• Apache2.4 + PHP-FPM

2013年5月10日金曜日

Page 13: Sqale の Puppet と Chef (と テスト)

コンテナの実体

• LXC ( Linux Container )

• chroot + namespace + cgroup

• 仮想化 = 隔離、分離、制限

• プロセスレベルでの仮想化

• chroot な環境を作らないといけない !

• 構成管理だ!

2013年5月10日金曜日

Page 14: Sqale の Puppet と Chef (と テスト)

構成管理

• ということで構成管理の話

2013年5月10日金曜日

Page 15: Sqale の Puppet と Chef (と テスト)

構成管理

• Sqale は 基本的に Puppet 管理

• appサーバー(Rails)とか

• gitリポジトリ管理サーバーとか

• アプリをビルドする build サーバーとか

• queueサーバー(resque) とか ... etc

• ユーザのアプリを動かすサーバーが特殊

• Puppet と Chef

2013年5月10日金曜日

Page 16: Sqale の Puppet と Chef (と テスト)

EC2 Instance

PHP Apache phpenv ruby unicorn nginx

chef-solo で chroot環境chef-solo で chroot環境

ldap munin nagios rbenv kernel cgroup

Puppet の土台

/var/rootfs/ruby/var/rootfs/php

lxc-start lxc-start lxc-start lxc-start

2013年5月10日金曜日

Page 17: Sqale の Puppet と Chef (と テスト)

Puppetのレイヤ

• LDAP とか munin とか nagios とか 何かいろいろ

• ログインしてオペできる土台

• カーネルも

• LXC を動かせる土台

2013年5月10日金曜日

Page 18: Sqale の Puppet と Chef (と テスト)

Puppet + AWS 自動化

http://www.slideshare.net/lamanotrama/on-aws-sqale2013年5月10日金曜日

Page 19: Sqale の Puppet と Chef (と テスト)

Chefのレイヤ

• Puppet の土台の上に

• chroot 環境を chef-solo で作る

• ユーザーごとの環境も chef-solo で作る

• ユーザー追加のタイミングで作る

2013年5月10日金曜日

Page 20: Sqale の Puppet と Chef (と テスト)

Chefでchroot環境

• chroot 環境を Chef 管理

• /var/rootfs/php # PHP用

• /var/rootfs/ruby # Ruby用

• chroot してから chef-solo 流す

• レシピは mount --bind してホストOSを参照

• レシピの作り方は慣例通り

• Ruby や PHPに必要なものをガッと入れる

2013年5月10日金曜日

Page 21: Sqale の Puppet と Chef (と テスト)

Why Chef ?

• chroot するので ホスト名ベースでレシピを当てられない• なので chef-solo にした• puppet apply でもできるかも

2013年5月10日金曜日

Page 22: Sqale の Puppet と Chef (と テスト)

#レンサバあるある

2013年5月10日金曜日

Page 23: Sqale の Puppet と Chef (と テスト)

#レンサバあるある

• ユーザを追加する度に環境作成

• アカウントの追加

• ストレージ ($HOME) の作成

• mkdir したり

• uid:gid 変えたり

• パーミッション変えたり

• ミドルウェアの設定追加

• 例) httpd.conf

2013年5月10日金曜日

Page 24: Sqale の Puppet と Chef (と テスト)

#ホスティングあるある

• たんぽぽ作業

• chef-solo で作ろう

2013年5月10日金曜日

Page 25: Sqale の Puppet と Chef (と テスト)

ユーザー作成

user node.username do action :createend directory "/var/www/#{node.username}" do owner node.username group node.username action :create mode "0755"end template "/etc/httpd/conf.d/#{node.username}.conf" do notifies :restart, "service[httpd]" source "httpd.conf.erb" owner "apache" group "apache" mode "0644"end service "httpd" do action :restartend

{ "username": "sushi",}

attribute/sushi.json

2013年5月10日金曜日

Page 26: Sqale の Puppet と Chef (と テスト)

ユーザー作成

• attributeで変数を注入 *1

• ユーザー名を変えて環境複製

• べき等性 = 上書き、やり直しも簡単

(注) 任意の値を入れると死ぬので要バリデート

2013年5月10日金曜日

Page 27: Sqale の Puppet と Chef (と テスト)

ユーザー削除

• 消す時にも便利

• べき等性が効いてくる

user node.username do action :removeend directory "/var/www/#{node.username}" do action :deleteend file "/etc/httpd/conf.d/#{node.username}.conf" do notifies :restart, "service[httpd]" action :deleteend service "httpd" do action :restartend

2013年5月10日金曜日

Page 28: Sqale の Puppet と Chef (と テスト)

chef-solo -j <URL>• でも attribute ファイル作るの面倒じゃないですか ...

• chef-solo -j <URL> 便利 そう

$ sudo chef-solo -j http://chef-api.example.com/user/fuga

chef-api.example.com

ユーザ収容のサーバーs

① kick

② chef-solo

2013年5月10日金曜日

Page 29: Sqale の Puppet と Chef (と テスト)

Sqale

• sqale でも ユーザごとに attribute を作って管理

2013年5月10日金曜日

Page 30: Sqale の Puppet と Chef (と テスト)

コンテナ作成のchef-solo

{ "run_list": [ "role[create_container_ruby]" ], "sqale": { "consecutive_number": "1", "container_id": "1", "port_offset": "0", "project_name": "ruby", "role": "ruby", "username": "namahage" }}

$ sudo chef-solo -j namahage_sqale_1.json

• Resqueワーカーが chef-solo

attribute/namahage-ruby-1.json

2013年5月10日金曜日

Page 31: Sqale の Puppet と Chef (と テスト)

仕様変更

• 仕様変更したい場合も chef-solo

• 1. レシピ更新

• 2. chef-solo 再度実行

• 3. コンテナのプロセスを再起動

• 4. 仕様 update !

• ユーザ名に依存しちゃうような仕様を変える際に便利

2013年5月10日金曜日

Page 32: Sqale の Puppet と Chef (と テスト)

DSL

• #{node.key.value} と埋め込むのはイマイチ

• ふつうのRubyのコードっぽくなるし ...

• 内部DSLを逸脱するので若干 BK な匂い

2013年5月10日金曜日

Page 33: Sqale の Puppet と Chef (と テスト)

DSL

• ラップするクラスを入れてキレイに

• "define" でラップするのも良いですかね

directory lxc.userfs_root "/home/sqale/current" do owner "sqale" group "sqale" mode "0755" recursive true action :createend

directory "/var/sqale/namahage/ruby/1/home/sqale/current"

after

2013年5月10日金曜日

Page 34: Sqale の Puppet と Chef (と テスト)

• puppet apply でもできそう ?

• antipopさん お願いします

2013年5月10日金曜日

Page 35: Sqale の Puppet と Chef (と テスト)

混ぜるな危険 !!!!1

• Puppet と Chef が混在 していましたが ...

• 管理しているスコープが違うのでOK

• 特殊事例

2013年5月10日金曜日

Page 36: Sqale の Puppet と Chef (と テスト)

#テスト

2013年5月10日金曜日

Page 37: Sqale の Puppet と Chef (と テスト)

#テスト

• 「Puppet, Chef」でプロビジョニング しました!!」

• 期待通り動くのかな ?

• 手作業で確認するの ?

• 変更する度に ?

2013年5月10日金曜日

Page 38: Sqale の Puppet と Chef (と テスト)

Infrastructure as Code

• コード書いたらテストですよねー

2013年5月10日金曜日

Page 39: Sqale の Puppet と Chef (と テスト)

#あるある

• パッケージの追加が怖い

• パッケージのアップデートが怖い

• パッケージの削除が怖い

• 設定追加が怖い

• 設定変更が怖い

• 設定削除が怖い

• 意図しないところで不具合

2013年5月10日金曜日

Page 40: Sqale の Puppet と Chef (と テスト)

#あるある

• 振る舞いが把握できてないとこわい

2013年5月10日金曜日

Page 41: Sqale の Puppet と Chef (と テスト)

#テスト

• 振る舞いをテスト = 動く仕様

• 「あれ、この設定なんだったかな...」

• テストで思い出す

• require "serverspec"

• Puppet, Chef のリファクタリング

• 振る舞いを保証して マニフェスト/レシピをいじる

2013年5月10日金曜日

Page 42: Sqale の Puppet と Chef (と テスト)

EC2 Instance

PHP Apache phpenv ruby unicorn nginx

Chef の chroot環境Chef の chroot環境

ldap munin nagios rbenv kernel cgroup

Puppet の土台

/var/rootfs/ruby/var/rootfs/php

lxc-start lxc-start lxc-start lxc-start

2013年5月10日金曜日

Page 43: Sqale の Puppet と Chef (と テスト)

Sqaleのテスト

• 1. chef-solo で LXCの作成/起動

• 2. LXCの外からプロセスが起動しているかテスト

• nginx, unicorn, supervisord, sshd, syslogd ...

• 3. SSHでログイン、コンテナでRSpecを実行

• 4. chef-soloで LXCの停止/削除

2013年5月10日金曜日

Page 44: Sqale の Puppet と Chef (と テスト)

RSpecの中味

• ユーザーさんの行動を模擬テスト

• SSHログインできる?

• /etc/init.d/nginx で操作できる?

• Rails動く? Sinatra動く?

• bundle install できる?

• シェルコマンド使える?

• ログ見れる?

• cron 動いてる ?

• セキュリティ制限効いてる?

• cgroupのリソース制限効いてる?

2013年5月10日金曜日

Page 45: Sqale の Puppet と Chef (と テスト)

RSpec / Railsの例

describe "rubyコンテナでRailsをUnicornで動かす" do

before(:all) do system("/etc/init.d/rails stop") end it "アプリケーション /home/sqale/current に配置することができること" do

system("tar xfz /home/sqale/rspec/misc/rails_app.tar.gz").should be_true system("rm -rf /home/sqale/current").should be_true system("mv rails_app /home/sqale/current").should be_true

end it "Railsを /etc/init.d/rails で 起動することができる" do

system("/etc/init.d/rails start").should be_true end it "HTTPリクエストを出して200が返ってくること" do

response = http_get response.code.should == "200" response.body.should == "hello,world" end end

2013年5月10日金曜日

Page 46: Sqale の Puppet と Chef (と テスト)

RSpec / rbenvの例

%w{ 2.0.0-p0 2.0.0-preview1 1.9.3-p327 1.9.3-p286 1.9.3-p194 }.each do |version| context "rbenv で #{version} に切り替える場合に" do

it "バージョン切り替えできていること" do

rbenv_global(version) end it "rubyのパスが通っていること" do

system("which ruby >/dev/null").should be_true end it "irbのパスが通っていること" do

system("which irb >/dev/null").should be_true end it "gemsのパスが通っていること" do

system("which gem >/dev/null").should be_true end it "bundlerのバージョンが #{@bundler_version} であること" do

`bundle -v`.split[2].should == @bundler_version end end

2013年5月10日金曜日

Page 47: Sqale の Puppet と Chef (と テスト)

RSpec / PHP Pearの例

describe "phpコンテナのpear" do

it "pearでライブラリをインストールできること" do

system("pear install Numbers_Roman").should be_true end it "pearでインストールしたライブラリを読み込めること" do

File.write("numbers_roman.php", <<'....')<?php require_once 'Numbers/Roman.php'; $roman = new Numbers_Roman();echo $roman->toNumeral(1);.... `php numbers_roman.php`.chomp.should == "I" end end

2013年5月10日金曜日

Page 48: Sqale の Puppet と Chef (と テスト)

#お問い合わせあるある

• 「○○コマンドは使えますか?」

• 「○○ライブラリは使えますか?」

• 確認作業 => テストで残しておく

• サポートした仕様がデグレードしないようにする

2013年5月10日金曜日

Page 49: Sqale の Puppet と Chef (と テスト)

#テスト

• 「○○できない」こともテスト

• su, sudo できないとか

• LXC を reboot できないとか

• forkbomb 対策できてるかとか

• されると困るアクションをテスト

2013年5月10日金曜日

Page 50: Sqale の Puppet と Chef (と テスト)

Rspec / ○○できない it "/var/log/messagesを読み込めないこと" do expect { File.read("/var/log/messages") }.to raise_error(Errno::EACCES) end it "/var/log/secureを読み込めないこと" do expect { File.read("/var/log/messages") }.to raise_error(Errno::EACCES) end

it "cgroup の fork.remaing で fork bomb対策が施されている" do

# forkbomb するワンライナー system "perl -e 'for(0..255){$i = fork;exit 255 unless defined $i;$i == 0 && sleep 1 && exit 0; }'" $?.success?.should be_false end

context "カーネルの制限で sqaleユーザーはポートをbindできない" do

it "httpdの予約ポート 8000 ~ 10000 をbindできない" do (8000..10000).each do |port| expect { TCPServer.open(port) }.to raise_error(Errno::EACCES) end end

2013年5月10日金曜日

Page 51: Sqale の Puppet と Chef (と テスト)

#テスト

• 手続きをRSpec化

• 一般ユーザ権限で実行 = ユーザーの取れる行動

• パッケージの有無とかは見てない

• ホスティングだと価値高いテスト

2013年5月10日金曜日

Page 52: Sqale の Puppet と Chef (と テスト)

SqaleのJenkins

• Jenkins で毎日 LXC のテスト

• yum も毎回 update

• RSpecが通る = 振る舞い保証

2013年5月10日金曜日

Page 53: Sqale の Puppet と Chef (と テスト)

終わり

2013年5月10日金曜日