tkak's tech blog

This is my technological memo.

個人的#ChefConf2013まとめ。

f:id:keepkeptkept:20130429101710j:plain

最近日本でも何かと話題になっているconfiguration management toolのchefですが、やっぱり海外のほうがDevOpsが進んでますね。
今回のカンファレンスは、導入事例とかベストプラクティスな感じの話が多かったです。

個人的に面白かったセッションを5つ、ログとして残しておきます。

#ChefConf 2013

Scaling Configuration Management

つい最近facebookでPrivate Chefを導入したとかニュースになってましたが、
初日のメインセッションでfacebookのchef導入事例の話をしてました。

facebookのサーバ管理メンバーが、目指すところは以下な感じです。規模感がすごいですね。

  • 4 people
  • Tens of thousands of heterogeneous systems
  • Service owners own/adjust relevant settings

主にscalabilityなchefをどうやって実装するかについて話してました。

■node.save()問題

facebookでは15分ごとにconvergenceを実行してChef Serverにnode情報を送っているらしいんですが、15,000台ものnodeを管理するとなると、その通信データ量は馬鹿にならないみたいです。

そこで、

  • 簡単にできる解決方法としてはohaiのpluginを無効にする方法があるが、ohaiのdataは欲しい。
  • ただし、chef serverにnode情報はなくてもいい。
  • つまり、node.save()機能を使うけど、サーバに送信しなければおk

ということで、
解決方法 = whitelist_node_attrs
opscode-cookbooks/whitelist-node-attrs · GitHub

このcookbookを使って、node.save()機能の送信するデータを制限して、結果的にサーバに送信するデータを1kb以下になるようにしたらしいです。

■method_missing問題

nodeのメソッドを使おうとしてそのメソッドの定義がない場合、
Chefは勝手にアトリビュートを作ってそこにハッシュ値を入れてしまうようです。

node.foo('bar')
  • Ruby: "If there a method foo()?"
  • Chef: "If not, is there an attribute foo?", "If not, create; assign bar"
  • OK for...
node['foo'] = 'bar'
node.foo = bar
  • But imagine
node.has_key('foo')  # want has_key?()

そこで、以下のようなメソッドを作ったみたいです。

class Chef::Node
  def method_missing(method, *args)
    Chef::Log.warn(“FB Chef Tweak: Not assuming missing method is an attr!”)
    Object.send(:method_missing, method, args)
  end
end
■sysctlのcookbook

facebookで使っているsysctlのcookbookの例を紹介してました。

  • fb_sysctl/attributes/default.rbにすべてのdefaultのパラメータを定義
  • fb_sysctl/recipes/default.rbに、templateリソースを定義
  • fb_sysctl/templates/default/sysctl.erbは、3行
# Generated by Chef, do not edit directly!
<%­ node['fb']['fb_sysctl'].keys.sort.each do |key| %>
<%= key %> = <%= node['fb']['fb_sysctl'][key] %>
<%­ end %>

そのcookbookをさらにDBサーバのcookbookを作って、database/recipes/default.rbの中でattributeをオーバーライドして使うそうです。

node.default['fb']['fb_sysctl']['kernel.shmmax'] = 19541180416
node.default['fb']['fb_sysctl']['kernel.shmall'] = 5432001
■Open Source Chef (OSC)と Opscode Private Chef (OPC)の性能比較

OSCよりもOPCのほうが性能いいらしいです。
詳細は、スライドにグラフとか掲載しているのでそっちを参考にしてください。

OSCのほうは、カスタマイズして使っていて、scaleのために、Chef Serverのsearchとdatabags機能を使ってないらしいです。

Client監視用に取得する情報

  • Last exception seen
  • success/failure of run
  • number of resources
  • time to run
  • time since last run
  • other system info

Server sideの監視

  • stats(postgres, authz[OPC], etc)
  • Errors(nginx, erchef, etc)
  • more...

server side の監視のためのutilsをgithubに公開してます。
facebook/chef-utils · GitHub


Cookbook refactoring & abstracting logic to Ruby(gems)

/etc/hostsを設定するcookbookを例に、リファクタリングの話をしていました。

最初は一般的な、attributes, recipes, templatesの構成ですが、どんどんリファクタリングをしていって、最終的にはcookbookをgemにするところまでやっててすんごいなぁと思いました。そこまでする必要があるかどうかは、賛否が分かれるところです。

1. attributes, recipes and templates
2. attributes -> data bags
2. Provider and Resources for simple
3. Libraries for speed and test
4. pure ruby (gem) for multi-environment

最終的なhostsfile cookbookは、githubに公開しています。
customink-webops/hostsfile · GitHub


Writing a Knife Plugin for your shiny new VMWarevCloud Director

VMWarevCloud Director用のknifeプラグインを作ったという話でした。
個人的にknifeのpluginよりも、中で使っているFogというMulti-Cloud Service Libraryが気になりました。
特にvmwareAPIrubyでたたけるので、まじですごいです。すんごい使えそうです。
ちなみに、vagrantのaws pluginもこのfog使ってます。

Fog - Multi-Cloud Service Library
fog - The Ruby cloud services library

opscode/knife-vcloud · GitHub

rlane/rbvmomi · GitHub


The Berkshelf Way

Berkshelf作った人が、berkshelfの話をしてくれました。
プレゼンテーションの仕方がうまくて面白くて、楽しんで聞けました。

■berkshelfの名前の由来

もともとは、bookshelfにしようと思ったけど、googleで検索しても他のものが検索されるので、berkshelfにしたらしいです。berkはアメリカで有名なネタ画像をもとにしたらしいです。

■berkshelfを使ったcookbookの使い方

roleは使わないで、cookbookをラップするcookbookを作ってroleの代わりにする使い方がいいらしいです。
roleは、バージョン管理できないし、パッケージとして配布できないし、namespaceが厳密ではないし、組織レベルのデータしか扱えないから。

■testについて

testはvagrantを使って、berkshelfのvagrant pluginがあるので、それを使ってテストしてるそうです。

How A Mouse Became a Chef - Disney

  • Chris Putonen -- Senior Manager, System Engineering at The Walt Disney Co.
  • Brian Scott -- Staff Systems Engineer at The Walt Disney Company
  • Steven Wagner -- Staff Systems Engineer at The Walt Disney Company

Disneyのchef導入事例の話です。
導入するときの話から、かなり具体的なcookbookの書き方やテストについてまで、とてもためになりました。

  • トップダウンでchefを導入していった。
  • Devsのアジャイルが進んでいって、Opsもそれについていかなくてはならない
  • Picking a tool + Changing our culture
  • start small and simple, lean start approach
  • pluginも自分たちで作っている。例、knife-servicedesk, ohai network_location
  • f5とNexusなどネットワーク機器もchefで管理
  • ChefのTest環境、Remy、Test as a Serviceを提供しようとしている。
  • ChefのTest環境は、jenkinsとvagrantとopnstackを使ってる。virtual boxよりもopnstackのほうが早い。

アフィリエイトソンに参加してきた。

Web APIを使ったECサイトを開発してアフィリエイト収入で小遣い稼ぎをしましょうというコンセプトのアフィリエイトソンなるイベントに参加して来ました。

【楽天・ヤフー・リクルート3社共催】第1回アフィリエイトソン -開発して稼ごうお小遣い!-(4/5,6) | 集客ならイベントアテンド

いやぁ、チームで開発するって楽しいですね。
日頃会社ではOps側の仕事が中心なので、Devの人と一緒に開発ができるなんてとても新鮮な経験をさせていただきました。特に今回perlで開発したんですが、perlフレームワークとか全然知らなくて、とても得るものが多かったです。

学んだこと、ちょっと残しておきます。

Perlの開発環境

今回ノープランでハッカソンに参加したので、Perlの開発環境を整えるところからスタートしました。
事前にやっておけよっていう話ですが...^^;

perlbrew+perl

まずperlbrewとperlをいれます。
perlbrewは複数のバージョンのperlを切り替えるためのツールです。rubyでいうrenv+ruby-buildとかrvmとかと同様のものです。
defaultでは、~/perl5/perlbrewにインストールされます。

$ curl -kL http://install.perlbrew.pl | bash
  • .zshrc にsource ~/perl5/perlbrew/etc/bashrcを追加する。
$ source .zshrc
$ perlbrew init
$ perlbrew install perl-5.16.2 --as perl-5.16
$ perlbrew switch perl-5.16.2

この辺を参考にしました。
安定的な Perl アプリケーション運用のための perlbrew 運用テクニック - tokuhirom's blog.

cpanm+carton

次にcpanmとcartonをいれます。
cpanmは、CPAN::Shellの次世代版みたいなもので、より省メモリで動作するそうです。
cpanmについてはここを参考にしました。
perlモジュールのinstallにcpanmを使う|perl|@OMAKASE

$ perlbrew install-cpanm

cartonは、rubyでいうbundlerのようなものです。
プロジェクトごとにモジュールをわけたり、モジュールのバージョンを環境ごとにあわせたりすることができるので、便利です。
モジュールは、project/local/lib/perl5/配下にインストールされます。
cartonについてはここを参考にしました。
cpanm ってなんですか? carton ってなんですか?利点はなんですか? - tokuhirom's blog.

$ cpanm Carton
$ cat cpanfile
requires 'Plack', 0.9980;
requires 'Starman', 0.2000;
$ carton install
$ ls carton.lock ## installに成功するとできる。
$ carton exec -Ilib -- plackup -p 8080 myapp.psgi

carton でインストールされたモジュールで実行できるものは、carton exec で実行できます。
オプションは、"--"のあとに指定します。

Webサーバとフレームワーク

今回perlで開発したのでPlackとAmon2を使いました。

$ carton exec plackup app.psgi -- --port 8080 -R

memo
PSGIという仕様の実装版がPlack。
plackupでサーバを起動します。
起動するときにapp.psgiファイルを指定します。
--portでポートを指定することができます。
-Rで、実行配下のファイルの更新をチェックして、サーバの動作に反映してくれます。

フレームワークのAmon2に関してはまだあまり知らないので、後日追記します。

MongoDB

今回DBまわりは、MongoDBを使いました。
MongoDBは、クエリにJSONファイルを使えるので、テーブル設計とか意識せずにとりあえずデータをなんでも突っ込んでおけて便利です。スタートアップとかに向いてるみたいです。

セットアップはここを参考にしました。
Installing MongoDB — MongoDB Manual 2.4.1

あとがき

残念ながら、昨日一日ではサービスをリリースすることはできなかったんですが、
隙をみてなんとかリリースするところまでは持って行きたいです。
そして、お小遣い稼ぎできたらなぁなんて考えてます。

開発もできて小遣い稼ぎもできるなんてなんて素晴らしいイベントだろう。
もし次回があればまた参加したいですね!

Bash Tips

最近、短期間に大量のサーバに設定をいれるという仕事がたんまりきていて、とてもじゃないけど手作業なんてしんどいので、ちまちまと使い捨てスクリプトを書いて作業を楽にしてます。
そんな中『これは使える!』というスニペットを残しておきます。

seqコマンド

seqコマンドは順番で数字を出力するだけなんですが、使い勝手よくてちょくちょく使ってます。

$ seq 3 #1から3までの整数を出力
1
2
3

$ seq 2 5 # 2から5までの整数を出力
2
3
4
5

$ seq 4 2 8 # 4から2ずつ8まで出力
4
6
8

$ seq -w 5 100 # -wをつけると桁の幅を同じにできる
005
006
007
009
010
...
...
100

$ seq -s " " 5 # -sで区切り文字を指定できる
1 2 3 4 5

$ seq -f "hoge%02g.log" 3 # 他の文字列と合わせて出力
hoge01.log
hoge02.log
hoge03.log

$ for i in $(seq 3); do echo "do something"; done
do something
do something
do something

source コマンド

bashでテンプレートエンジンもどきみたいなことをしたい時とかに使います。

#!/bin/sh
string="Hello World!!"
source test.txt

test.txt

cat << EOF
<html>
<head>
This is a test.
</head>
<body>
${string}
</body>
</html>
EOF

list fileの読み込み

リストファイルを一行ずつ読んで何かにしたい時に。

$ while read line do; echo ${line}; done < list.txt

配列に要素を追加する

array=() # 配列定義
array=(${array[@]} "fuga")

文字列置換

サーバをコピーして、中の設定ファイルを書き変えたい時に。

$ sed -i "s/hoge/fuga/g" /etc/hosts

DNSからIPアドレスを取得

$ host `hostname` | cut -d" " -f4

大量のサーバに対して手作業するのには限界があるので、うまくコマンド使い回して作業を効率化して定時で帰りましょうね!(キリッ

RHEL6系/CentOS6系のファイルパーミッションのdot「.」をなくす方法

RHEL6系/CentOS6系から、selinuxの管理下にあるファイルにはファイルパーミッションにdot「.」がつくようになってます。

[root@localhost ~]# ls -ld /etc
drwxr-xr-x. 57 root root 4096 Jan  4 13:21 /etc

selinuxを無効化しても、元々あったファイルにはドットがついたままなので、
なんか気持ち悪い感じ…。

いろいろ調べたら、ファイルの拡張属性security.selinuxが残ってるのが原因っぽいです。

このdot「.」を消すためには、ファイルの拡張属性を設定するsetfattrコマンドを使います。

[root@localhost ~]# getfattr -m - /etc
getfattr: Removing leading '/' from absolute path names
# file: etc
security.selinux

[root@localhost ~]# setfattr -x security.selinux /etc
[root@localhost ~]# getfattr -m - /etc
[root@localhost ~]# ls -ld /etc
drwxr-xr-x 57 root root 4096 Jan  4 13:21 /etc

全ファイルに対して設定する場合は下記を実行します。
(再帰的にコマンドを実行するオプションがないので、findでごりっとやってます。)

# find / -exec setfattr -x security.selinux {} \; 

VagrantのBase Boxを作ってみた。CentOS6.3 x86_64編

Vagrantは、Virtual BoxのVM(仮想サーバ)管理を簡単にするためのツールです。
VMを、コマンドラインから起動、停止、削除、etcできるので、テストや開発環境作成などでかなり重宝します。


今回はそのテンプレートになるBase Boxを作ってみたので、メモを残しておきます。
VagrantのBase Box作成を自動化するVeeweeというツールもありますが、
使ってみてうまくいかなかったので、今回は自分で作ります…。

今回試した環境はこんな感じ。

OS(Mac) 10.8.2
Virtual Box 4.2.6
Vagrant 1.0.5

※Virtual BoxとかVagrantのインストールなどは、今回省略します。

VMは、CentOS6.3 x86_64です。

Virtual BoxのVM作成

まず、Virtual BoxのVMを作ります。
VMは下記のような感じで作りました。

Name: vagrant-centos6.3
Type: Linux
Version: Red Hat (64bit)
Memory size: 512MB
Hard drive: 8GB (新規作成)
Hard drive file type: VDI, Dynamically allocated (動的割り当て)
Audio: Disable
USB controller: Disable
Port Forwarding: Name: ssh, Protocol: TCP, Host Port: 2222, Guest Port: 22

起動させてOSをインストールします。
メモリが512MBしかないので、テキストモードのインストーラが起動します。(1GB以上だとGUIモード)
キーボード、言語環境を選択します。
テキストモードだと、パッケージ選択やパーティション設定などが設定できないので、
そのまま進めていけばインストーラが終わります。

VMの初期設定

次にいろいろとVMに初期設定を入れていきます。

ネットワークの有効化

そのままだとネットワークが有効になっていなかったので、有効にします。

# /bin/sed -i 's/ONBOOT="no"/ONBOOT="yes"/g' /etc/sysconfig/network-scripts/ifcfg-eth0
# /etc/init.d/networking restart
vagrantユーザの作成

sshで接続するために、vagrantユーザを作成します。

# /bin/sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication no/g' /etc/ssh/sshd_config
# /etc/init.d/sshd reload
# /usr/bin/yum -y install sudo
# /usr/sbin/groupadd vagrant
# /usr/sbin/useradd vagrant -g vagrant -G wheel
# echo "vagrant"|passwd --stdin vagrant
# echo "vagrant   ALL=(ALL)   NOPASSWD: ALL" >> /etc/sudoers
ssh 接続

ポートフォワーディング機能で、ホスト側の2222ポートをゲストの22ポートに割り当ててるので、
localhostの2222にsshします。

$ ssh localhost -l vagrant -p 2222
$ su -
# id
必要なパッケージのインストール

いろいろ入れます。

# yum -y install gcc make gcc-c++ ruby kernel-devel-`uname -r` zlib-devel openssl-devel readline-devel sqlite-devel perl

epelのリポジトリ設定ファイルを作成します。

# cat > /etc/yum.repos.d/epel.repo << EOM
[epel]
name=epel
baseurl=http://download.fedoraproject.org/pub/epel/6/\$basearch
enabled=1
gpgcheck=0
EOM

ruby-develとrubygemsをインストールします。

# yum -y install ruby-devel rubygems
# yum -y clean all
# rm -f /etc/yum.repos.d/epel.repo
chefクライアントのインストール

chefをインストールします。少し時間がかかるので、待ちます。

# gem install --no-ri --no-rdoc chef
vagrantユーザの公開鍵配置

vagrantユーザ用の公開鍵を配置します。

# mkdir /home/vagrant/.ssh
# chmod 700 /home/vagrant/.ssh
# cd /home/vagrant/.ssh
# curl -L -o authorized_keys https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub
# chown -R vagrant /home/vagrant/.ssh
VirtualBox Guest Additionsのインストール

VitualBoxゲストOS用ドライバVirtualBox Guest Additionsをインストールします。

# cd /tmp
# curl -L -o VBoxGuestAdditions_4.2.6.iso http://download.virtualbox.org/virtualbox/4.2.6/VBoxGuestAdditions_4.2.6.iso
# mount -o loop VBoxGuestAdditions_4.2.6.iso /mnt
# sh /mnt/VBoxLinuxAdditions.run
# umount /mnt
# rm VBoxGuestAdditions_4.2.6.iso
# sed -i "s/^.*requiretty/#Defaults requiretty/" /etc/sudoers
# sed -i "s/^#UseDNS yes/UseDNS no/g" /etc/ssh/sshd_config
# dd if=/dev/zero of=/tmp/clean || rm /tmp/clean

Base Boxのパッケージ化

作ったVMをBase Boxにします。

$ vagrant package --base vagrant-centos6.3

カレントディレクトリにpackage.boxというファイルができます。

あとは、Base Boxをvagrantに登録して、起動させます。

$ vagrant box add my_box package.box
$ mkdir test_environment
$ cd test_environment
$ vagrant init my_box
$ vagrant up
$ vagrant ssh

以上。

…と、まぁ、ほとんどveeweeの設定ファイルをなめただけなんですが、
とりあえず、流れが把握できたのとchefだけのBase Boxができたので、めでたしめでたし。
veeweeで失敗していたのは、ネットワーク周りが原因な気がする…。
まー、あとは、chefのcookbook作っていろいろ遊んでみよう。

Opscode Chef のトレーニングに参加してきた。

久々のblog更新。
日本Chef User会のFacebookで紹介されている
Chefのハンズオントレーニングイベントに参加してきました。
Japan Chef Users Group | Facebook

トレーニングの講師は、Opscode社のSean OMeara 氏。
全部英語でしたが、(たぶん)普段普通に話すよりゆっくり話てくれてたのと、
周りのスタッフの方々が通訳してくださって、内容は大体把握できました。
ただ、やっぱり質問は流暢な英語でしたかった(´・ω・`)

また、対象者がChefをさわった事がある方 (初級の上〜中級の下)でしたが、
なぜConfiguration Managementが必要なのか、なぜChefなのかとか、
割りと基本的な話を最初にしてくれて内容整理できてよかったです。


以下、自分が気になったところのまとめです。

cookbookのテストについて

Chef のテストについては、3つ。テストの種類によってツールを使い分ける。

1. unit test -> chef-minitest-hundler

calavera/minitest-chef-handler · GitHub
テストできるところとできないところがるので、使い方を工夫する。

2. integration test -> test-kitchin with vagrant

test-kitchen | RubyGems.org | your community gem host
chefはやっぱりvagrantとの相性がいい。開発環境やテスト環境としてvagrantとchefを組み合わせて使う。
これ使ったことがないので、今度試してみよう。

3. Behavior Test -> cucumber chef

Cucumber-chef
cucumber自体全然使ったことがないので、これも今度試す。

個人的にchefのcookbookを書いていて、テストコードどう書くのか、
ものすごーく気になってたところなんですが、
Seanが言ってたけど(たぶん)、

  • chefのテストにはカバーできない部分がある。
  • UnitTestの中でChefのResource機能の動作をテストするのは無駄。
  • why-run機能を使いなよ。

テストに関してだったり、cookbookの使い方だったり、
まだベストプラクティスっていうのはなくて、
会社ごとにポリシーとかもあるし、各自で試行錯誤するしかないっていうのが、
印象でした。

why-run機能について

ver10.14でリリースされた機能。
chefを実行したときの処理をサーバ側に反映せずに動作確認できる機能です。
この機能はchefの開発が始まった頃からチケットがあって、
何度もclose, reopenを繰り返し、議論されてきたらしい。
元々は、dry-runっていうネーミングで作ってたんだけど、今はwhy-run。
dry-runだと、実行中でシステムに変更を加えない
(ファイルを作成したり、マウントをしたりしない)ので、
real-runを実行したときと差分がでてしまう。
why-runは、実行中にシステムの内容が変わるところもカバーしている。

chef実行時のフォーマットについて

chef-client実行時に、Fオプションで出力結果を変更することができる。

$ sudo chef-client -Fdoc -lfatal --color --why-run

null, doc, minimal, minの4つが現状使用可能。

その他、開発に便利なツールについて

bento

opscode/bento · GitHub
vagrant用baseboxの作成を効率化するツールveeweeをカプセル化するもの。

test-kichin

Integration Test Tool
opscode/test-kitchen · GitHub

foodcritic

link checker, style guide
Foodcritic - A lint tool for your Opscode Chef cookbooks
これはめちゃくちゃ参考になる!色々と間違ってcookbook書いてた。

設定ファイルに設定を追加するためには

rubyで書く場合


Class: Chef::Util::FileEdit

— Documentation for chef (0.8.16)


上記クラスをruby blockの中で使う。

bashで書く場合

bushスクリプトを書いてexecuteで使う。

Chef の処理系について

  1. chef-client実行
  2. build node
  3. authenticate
  4. sync cookbooks(expanded run list)
  5. load cookbooks
  6. converge
  7. success?
  8. if yes -> run
  9. if no -> error

chefのresourceとLWRP

chefのcookbookは、Lightweight Resources and Providers (LWRP)という機能を使うことによって、
recipe内で使うresourceを簡単に定義することができます。

用意するファイルは下記になります。

resources

resourceで使うactionとattributeの定義とバリデーションをLWRPの形式で記述する。

providers

resourceの具体的なアクションを記述する。中でchefで定義しているresourceを使うことができる。