大規模システム構築と小規模システム構築の大きな違い
最近採用活動をしていてよく誤解されることがありましたので、昔書いた記事を紹介させていただきます。
・大規模システム構築と小規模システム構築の大きな違い(その1)
・大規模システム構築と小規模システム構築の大きな違い(その2)
最近採用活動をしていてよく誤解されることがありましたので、昔書いた記事を紹介させていただきます。
・大規模システム構築と小規模システム構築の大きな違い(その1)
・大規模システム構築と小規模システム構築の大きな違い(その2)
ここ5年ほど社内システム関連の部署に異動となっていたため、システム管理的な話題があまりなくてブログを更新できてませんでしたが、昨年9月に突然古巣のインフラ部門に異動となって戻ってきたため、ブログの更新を再開しようと思います。
あと、ずっと所属会社名を伏せていましたが、ちょっと考え方を変えて、今年から所属会社名をオープンにすることにしました。
所属会社はNHN Japan株式会社です。サービスブランドはHangame、NAVER、そしてlivedoorの3つです。社員数は多分1500人くらい、サーバ台数は数千台規模の会社となります。私は現在そこでサーバ部門の管理職を行っています。
最近はスマートフォン上で動く「LINE」というサービスが世界規模で大ブレイクしていまして、毎週100万人規模でユーザが増えています。今日時点でユーザ数が1500万人くらいです。このペースだと年内1億ユーザに到達してしまうかも、という雰囲気の中で動いています。当然サーバ増強のペースがものすごくてとてもあわただしい状況です。
最後に人材募集をさせてください。
今本気でインフラ部門の人材募集をしています。下記に該当される方は是非ご連絡ください。まずは話を聞いてみたい程度でも結構です。
●サーバ部門:Linux/Windows serverの構築・運用経験がある方。ベテランだけでなく伸び盛りな見習いの方も大募集です。
●ネットワーク部門:ISPもしくは同等規模でのネットワーク構築/運用経験がある方。L3スイッチ以上の経験者が望ましいです。
●データベース部門:Oracle/SQL Server/MySQLのDBA経験者。特にMySQLのDBAに関心がある方を大募集しております。
当社に関心を持ってもらうための売り文句を述べます。
・今年9月に渋谷ヒカリエに事務所移転します。通勤が便利です。
・億規模のインフラ投資(必要と思われるものは大抵買ってもらえる環境です)
・エンタープライズ機器大量導入(普段滅多に見られない高価な機器にたくさん触れます)
・海外に行くチャンスあり(一応グローバル企業ですので)
・福利厚生(詳しくはこちらを見てください)
・天才エンジニアが多い(天才エンジニアの開発速度は常人の常識を遙かに超えていてそれを間近に見られます。特に韓国でNHNはNo.1インターネット企業ということもあり韓国内での天才エンジニアがNHNに集まりやすい傾向があるようです。天才の定義は難しいのですが、概して韓国人天才エンジニアは全く日本語を知らない状態で来日して3ヶ月もあれば普通に日本語をマスターしてしまいます。うらやましい。。。)
・女性が多い。特にデザイナーの女性比率が結構高いみたいです。
・グローバル企業です。韓国本社、東京・福岡、アメリカ、大連などのオフィスがあります。他にもありそう(実はよく知らない)。
・(自身のキャリアアップの方向性が明確であれば)教育を受ける環境がたくさんあります。
この募集は一旦2月を締め切りとします。ご興味がちょっとでも沸いた方はとりあえずご連絡だけでもいただけたら幸いです。
よろしくお願いいたします。
※追記(2012/2/13)
予想を大幅に超えるご連絡をいただいており現在ご返答が大変遅れております。順次ご回答させておりますので今しばらくお待ちください。また、原則メールをいただいてから3日以内にご返答させていただいておりますが、もしメールが返答されてこないという場合は再度ご連絡ください。どうぞよろしくお願いいたします。
SSHクライアントソフトとして普段puttyを愛用していますが、タブモードで使えないことだけが不満でした。そこでなんとかならないかと調べてみたら、PuTTY Connection Managerを入れればよいとわかりましたのでご紹介します。
→PuTTY Connection Manager公式ページ
Downloads->Current beta versionの中にある「Standalone Executable」をダウンロードすれば、あとはそのexeファイルを実行し、putty本体の所在地を指定するだけでタブ版puttyが起動します。

携帯サイトを作っている際、全ての全角カタカナを半角カタカナに置き換えるために、全角カタカナが含まれているファイルを一気に洗い出したいと思うことがあります。しかしネット上で検索しても自分的にしっくりくる方法がみつかりませんでした。
そこで今回非常に簡単なスクリプトを作ってみました。スクリプトを見ていただければわかりますが、実現方法としてはかなり恥ずかしい部類とは言えます。が、この方法以外思いつかなかったのと、こんなスクリプトでもきっと役に立つ人がいると思い恥を忍んで公開してみます。(注:調べたいファイルの文字コードがUTF-8ならUTF-8で保存するようにしてください)
※もしスマートな解決方法をご存じな方がいらっしゃいましたらコメントいただけたら嬉しいです。
#!/bin/bashpushd /var/www/html/
grep "ア" *.html > tmp
grep "イ" *.html >> tmp
grep "ウ" *.html >> tmp
grep "エ" *.html >> tmp
grep "オ" *.html >> tmp
grep "カ" *.html >> tmp
grep "キ" *.html >> tmp
grep "ク" *.html >> tmp
grep "ケ" *.html >> tmp
grep "コ" *.html >> tmp
grep "サ" *.html >> tmp
grep "シ" *.html >> tmp
grep "ス" *.html >> tmp
grep "セ" *.html >> tmp
grep "ソ" *.html >> tmp
grep "タ" *.html >> tmp
grep "チ" *.html >> tmp
grep "ツ" *.html >> tmp
grep "テ" *.html >> tmp
grep "ト" *.html >> tmp
grep "ナ" *.html >> tmp
grep "ニ" *.html >> tmp
grep "ヌ" *.html >> tmp
grep "ネ" *.html >> tmp
grep "ノ" *.html >> tmp
grep "ハ" *.html >> tmp
grep "ヒ" *.html >> tmp
grep "フ" *.html >> tmp
grep "ヘ" *.html >> tmp
grep "ホ" *.html >> tmp
grep "マ" *.html >> tmp
grep "ミ" *.html >> tmp
grep "ム" *.html >> tmp
grep "メ" *.html >> tmp
grep "モ" *.html >> tmp
grep "ヤ" *.html >> tmp
grep "ユ" *.html >> tmp
grep "ヨ" *.html >> tmp
grep "ラ" *.html >> tmp
grep "リ" *.html >> tmp
grep "ル" *.html >> tmp
grep "レ" *.html >> tmp
grep "ロ" *.html >> tmp
grep "ワ" *.html >> tmp
grep "ヲ" *.html >> tmp
grep "ン" *.html >> tmp
grep "ー" *.html >> tmp
sort tmp | uniq > tmp2
cat tmp2
rm -f tmp
rm -f tmp2
popd
コンソール上でキー操作をしている時に突然キー入力できなくなる問題に遭遇することがあります。これは簡単に再現&解除できます。
CTRL+s : キー入力できなくなったように見える操作
CTRL+q : キー入力できなくなった状態を解除する操作
このキー操作がどのような経緯で生まれたのか等は別のWEBサイトに譲るとして、この機能自体恒久的に必要ないという大多数の方は、以下のコマンドを実行することでキー入力が受け付けられなくなる機能が無効になります。
$ stty stop undef
ログイン毎にこの入力をするのが面倒な方は.bashrcに追記しておくと良いでしょう。
Twitter内で、MySQL管理はGUIとCUIのどちらがいいのか、という論争がありました。私個人としては、断然GUI派です。CUIも一応使えますが、GUIが使える環境であれば迷わずGUIを使います。
データベースって、例えば細かい権限設定などをCUIでやろうとすると、見にくいのでどうしてもケアレスミスが発生しがちです。GUIであれば直感的な操作で対応できる場合が多いので、ケアレスミスが少なくなります。
・・・という表向きの理由がありますが、実は「privileges」という単語をどうしても覚えられなくてCUIだとつらいという状況が続いていました。MySQLのCUIって全般的に覚えにくい気がします。さすがに5年目くらいには慣れてきて今では大丈夫になりましたが。
[関連記事]
急いでいる人のためのMySQLのユーザ権限付与講座
L2~L4スイッチあたりは馴染みがある人が多いと思いますが、L1スイッチについては聞いたことすらない人も多いのではないでしょうか。L1スイッチは大規模サイトでは必須と言っても過言ではないくらい重要となります。というわけで今回はL1スイッチについて記してみます。
【L1スイッチとは?】
L1スイッチとは、物理層で切り替え(スイッチ)することのできるネットワーク機器となります。ある意味パッチパネルでの切り替えを電気的に行える機械とも言えます。かつ市販されているL1スイッチではメーカー毎に様々な機能が付加されている場合が多いです。
※余談ですが、レピータHUBもレイヤー1に該当しますが、レピータHUB自体にスイッチ機能はないのでレピータHUBがL1スイッチかと問われると微妙な気がします。
【L1スイッチのよくある使い道: ログ分析&IDS】
大規模サイトでよく使われる用途としてはログ分析&IDS監視です。大量の通信をログ分析サーバもしくはIDSサーバに流し込むために、本番系ネットワークとバックエンドネットワークの間にL1スイッチを挟みこみます。

本番系ネットワークのL2スイッチにポートミラーリング設定をほどこし、L2スイッチ上を流れる全てのフレーム(※念のため注:L2なのでパケットではなくてフレーム)をL1スイッチ側に流れるようにすれば、結果的に本番系ネットワークの全てのフレームがL1スイッチを経由してバックエンドネットワークに流れ込むことになります。
そして、その流れ込まれたフレーム(というかL1なので信号かな?)をログ分析サーバもしくはIDSサーバが拾い、分析を行います。
ところでL1スイッチによっては、流れ込まれた信号をロードバランサーのように各サーバに割り振る機能を持つ場合があります。この場合負荷が増えてきた場合に分析サーバのスケールアウトが可能になります。
【L1スイッチを製造しているメーカー】
L1スイッチを製造しているメーカーはそんなに多くありません。例えば著者が調べた限り、以下の4社がありました。
・APCON社(INTELLAPATCH Family)
・Gigamon社(GigaVUE)
・日本ダイレックス株式会社(eL1 SWS)
・Glimmerglass社
【おまけ(宣伝)】
私が監修させていただいた「これだけは知っておきたい ネットワークの常識」技術評論社(共著。監修担当)にも用語集にL1のことをばっちり(?!)載せています。
MySQLの出力結果を棒グラフで表示できたらいいなぁと思っていろいろ実験していたらうまくいってしまったのでご紹介してみます。
【普通の場合】
普通は以下のようになりますよね。出力結果だけ見てもどうもよくわかりません。
■SQL文
mysql> select date_format(regdate, "%Y/%m/%d %H") date, count(*) count from usert group by date order by date asc;
■出力結果
+---------------+-------+
| date | count |
+---------------+-------+
| 2010/11/01 00 | 405 |
| 2010/11/01 01 | 276 |
| 2010/11/01 02 | 188 |
| 2010/11/01 03 | 148 |
| 2010/11/01 04 | 96 |
| 2010/11/01 05 | 63 |
| 2010/11/01 06 | 85 |
| 2010/11/01 07 | 142 |
| 2010/11/01 08 | 164 |
| 2010/11/01 09 | 137 |
| 2010/11/01 10 | 177 |
| 2010/11/01 11 | 177 |
| 2010/11/01 12 | 248 |
| 2010/11/01 13 | 178 |
| 2010/11/01 14 | 148 |
| 2010/11/01 15 | 158 |
| 2010/11/01 16 | 195 |
| 2010/11/01 17 | 213 |
| 2010/11/01 18 | 243 |
| 2010/11/01 19 | 236 |
| 2010/11/01 20 | 274 |
| 2010/11/01 21 | 310 |
| 2010/11/01 22 | 309 |
| 2010/11/01 23 | 280 |
+---------------+-------+
【棒グラフの場合】
そして今度は出力結果を棒グラフにした場合の例になります。ものすごくわかりやすくなりました。
■SQL文
mysql> select date_format(regdate, "%Y/%m/%d %H") date, REPEAT("#", count(*)/10) graph from usert group by date order by date asc;
■出力結果
+---------------+-------------------------------------------+
| date | graph |
+---------------+-------------------------------------------+
| 2010/11/01 00 | ######################################### |
| 2010/11/01 01 | ############################ |
| 2010/11/01 02 | ################### |
| 2010/11/01 03 | ############### |
| 2010/11/01 04 | ########## |
| 2010/11/01 05 | ###### |
| 2010/11/01 06 | ######### |
| 2010/11/01 07 | ############## |
| 2010/11/01 08 | ################ |
| 2010/11/01 09 | ############## |
| 2010/11/01 10 | ################## |
| 2010/11/01 11 | ################## |
| 2010/11/01 12 | ######################### |
| 2010/11/01 13 | ################## |
| 2010/11/01 14 | ############### |
| 2010/11/01 15 | ################ |
| 2010/11/01 16 | #################### |
| 2010/11/01 17 | ##################### |
| 2010/11/01 18 | ######################## |
| 2010/11/01 19 | ######################## |
| 2010/11/01 20 | ########################### |
| 2010/11/01 21 | ############################### |
| 2010/11/01 22 | ############################### |
| 2010/11/01 23 | ############################ |
+---------------+-------------------------------------------+
ログが溜まってくると、必要な情報を探しにくくなるので古いログを別のところに移動させたいと思うようになります。今回はそんな場合のためのcron設定を記してみます。
【cron設定】
いろいろな方法があるかと思いますが、今回はシンプルにいきます。
5 3 * * * /usr/bin/find /home/user/logs/*log -maxdepth 1 -type f -mtime +6 -exec /bin/mv {} /home/user/oldlogs/ \; 1> /dev/null
細かいオプションの意味は以下の通りです。
・「-maxdepth 1」・・・検索対象のディレクトリを1階層に制限する。
・「-type f」・・・検索対象をファイルに限定する。
・「-mtime +6」・・・データが修正された時間が7日以前のもの。+6とは7日(144時間)前~過去を指す。(+7でない点に注意)
・「-exec ~ \;」・・・「~」の部分のコマンドを実行する。
・「{}・・・ここにfindされたファイルのファイル名が入る。
【注意事項】
この方法で古いファイルを移動させる際、ログを吐き出す元アプリケーションを再起動しないとその後のログを吐き出さなくなる場合があります。その場合はrotatelogsかlogrotateを組み合わせるなどで回避する方法もあります。
apache生ログをWEB上から見たいという要望を受けて簡単にPHPで作ってみましたのでご紹介致します。突っ込みどころ満載かと思いますが、その場合はコメントに記載いただけましたら幸いです。改善的コメント大歓迎です。
※重大な警告:この手のスクリプトは重大なセキュリティホールを招く場合がありますので、もし実利用される場合は十分ご注意ください。
【プログラムの概要】
今回作成したプログラムでは、特定ディレクトリ内のファイルリストを取得して一覧を出します。そして一覧の中から特定ファイルをクリックするとそのファイルの最後10行(もしくは指定行数)を表示するというものです。例えばこんな感じです。
web1 top>
access_log 38543
access_log 5435
access_log 23533
error_log 10206
error_log 236
error_log 1256
【プログラム】
これを実現するプログラムは以下の通りです。特に難しいことはやってないので容易に理解できるかと思います。(赤字の部分を直して使ってください)
■logview.php
<?php
$scripturl = "http://www.example.com/admin/logview.php";
$basedir = "/var/log/httpd";global $f_cmd;
global $f_filename;
$f_numlist = 10;
if (isset($_GET["c"])) $f_cmd = htmlspecialchars(@$_GET["c"], ENT_QUOTES);
if (isset($_GET["f"])) $f_filename = htmlspecialchars(@$_GET["f"], ENT_QUOTES);
if (isset($_GET["n"])) $f_numlist = htmlspecialchars(@$_GET["n"], ENT_QUOTES);if (strpos($f_filename, "..") !== FALSE) {
print "You can't use '..'.";
exit;
}print `/bin/hostname` . "<a href='$scripturl'>top></a><br />";
?><form method="GET" action="viewlog.php">
<input type="hidden" name="c" value="<?=$f_cmd?>" />
<input type="hidden" name="f" value="<?=$f_filename?>" />
tail -<input type="text" name="n" size=3 value="<?=$f_numlist?>" />
<input type="submit" />
</form><pre>
<?php
//--------------------
//ログ一覧表示
//--------------------
if ($f_cmd == "") {
$lists = `ls -lb $basedir/*log* |awk '{print $9,$5}'`;
$arr_lists = split("\n", $lists);
foreach ($arr_lists as $list) {
$list = str_replace($basedir."/", "", $list);
$arr_list = split(" ", $list);
if ($arr_list[1] != 0) {
$arr_list_new = str_replace("error", "<font color=red>error</font>", $arr_list[0]);
print "<a href='$scripturl?c=p&f=$arr_list[0]'>$arr_list_new</a> $arr_list[1]<br />";
}
}
}//--------------------
//ログ表示
//--------------------
if ($f_cmd == "p" && !empty($f_filename)) {
system("tail -$f_numlist $basedir/$f_filename");
}
?>
</pre>
</html>
サーバ台数が増えてくると、例えば同じ種類のサーバをスケールアウトしているとき、1台だけ設定ミスがあったとしてもなかなか気付きづらくなります。サービスの安定稼動のためにはこういった些細なミスは完全に潰しておく必要があります。そこで今回はサーバ間の設定ファイル差異を比較するスクリプトを作りましたのでご紹介してみます。
【前準備】
まずはこちらでも記したような方法で、パスワードなしで各サーバにSSH接続できるようにしておいてください。
【サーバ間の設定ファイル差異を比較するスクリプト】
下記スクリプトをどこかに保存してください。ファイル名は便宜上「filediff.sh」とでもしておきます。そして、今回比較するファイル名を羅列し、かつサーバ番号(下記の例だと10.0.0.1の設定ファイルを10.0.0.2~10の設定ファイルと比較しています)を書き換えてください。
$ cat > filediff.sh
~スクリプトの内容をペースト後、Ctrl+C~
$ chmod gou+x filediff.sh
$ vim filediff.sh
■filediff.sh
#!/bin/bash
FILES[0]="/etc/httpd/conf/httpd.conf"
FILES[1]="/etc/php.ini"
FILES[2]="/etc/my.cnf"
SVR_FROM=2 # サーバ番号始まり
SVR_TO=10 # サーバ番号終り
#
for file in ${FILES[@]};do
echo "**************************************************"
echo $file
echo "**************************************************"
scp 10.0.0.1:${file} /tmp/_a
for i in `seq ${SVR_FROM} ${SVR_TO}`;
do
echo "[10.0.0.${i}]"
scp 10.0.0.${i}:${file} /tmp/_b
diff /tmp/_a /tmp/_b
rm -f /tmp/_b
done
rm -f /tmp/_a
done
# 後処理
unset SVR_FROM
unset SVR_TO
unset FILES
【実行方法】
以下のように実行します。
$ filediff.sh
差異があると下記のように表示されます。
[10.105.4.33]
103c103
< ServerName web1:80
---
> ServerName web2:80
※緊急お知らせ
今週4~6名くらいで技術者交流会という名の飲み会を行なうことになったのですが、メンバーが全然集まっていません。当然面識がなくても構いませんのでどなたか飲みませんか? 参加可能な方は調整さんにエントリーお願い致します!・・・ということで大変ありがとうございます。4名集まりましたので、10/27(水) 19:00 JR五反田駅改札を出たところ集合でいきましょう。多少であれば飛び入り参加もきっと大丈夫ですのでよろしくお願いいたしまーす。・・・ということで開催してきました。とても盛り上がって楽しかったですね。それにしても皆さん経験豊富だなあ、頑張らないとなあと思いました。またやりましょうね。
●開催趣旨:居酒屋土間土間で1時間525円飲み放題らしいので、たくさん飲みましょうというただそれだけになります。^^
各サーバ群にソースコードを配信するためにrsyncを使っているところも多いと思います。この操作をWEB上から行えるようになれば、例えばデザイナーがちょっとした画像データを配信するといった場面などで便利そうです。そこで今回はrsyncをWEB上から実行する方法について記してみたいと思います。
【ハマりどころ確認】
WEB上からrsyncを実行するのって、簡単に見えて実はちょっと難しいのです。ハマりどころは2つあります。それは
(1) rsyncを実行するユーザがパスワードなしで配信先サーバにSSH接続できるようにしておかなければならない。
(2) 配信先サーバでは、rsyncを実行するユーザと同じ名前のユーザで、該当ファイルやディレクトリの書き込み/編集権限を持っていなければならない。
というものです。
(1)については、こちらでも記したような方法で、パスワードなしで他のサーバにSSH接続できるようにしておかなければなりません。ただ厄介なのは、CentOSでyumを使ってapacheをインストールした場合、初期状態のままだとapacheユーザがnologinユーザ(すなわちログインできないユーザ)として登録されているので、これをログインできるユーザに直すところからはじめなければなりません。(注:もしくはapache起動ユーザを変えるという手もあります)
(2)については、配信先サーバ側でもapacheユーザとして該当ファイルやディレクトリに書き込みしに行きますので、パーミッション設定を行わなければなりません。方法としては、ファイルやディレクトリの所有者をapacheユーザにするか、もしくはファイルやディレクトリの所属グループをapacheにした上で、グループの書き込み権限を「w」にする方法があります。今回は後者の方法を採用しました。
ということを踏まえて、以降具体的な設定方法を記していきます。手順は面倒ですが、ほぼコピー&ペーストでいけるので作業自体はそんなに大変ではないかもしれません。
【配信元サーバ側の作業】
OSのapacheユーザがnologinになっているので、通常はapacheユーザでログインできませんが、今回は特別にapacheユーザでもログインできるようにします。(/etc/passwdのapacheユーザの最後の/sbin/nologinを/bin/bashにします)
# sed -i "s/apache:x:48:48:Apache:\/var\/www:\/sbin\/nologin/apache:x:48:48:
Apache:\/var\/www:\/bin\/bash/" /etc/passwd
apacheユーザの秘密鍵と公開鍵を置く場所を作ります。
# mkdir /var/www/.ssh
# chmod 700 /var/www/.ssh
# chown apache.apache /var/www/.ssh
apacheユーザの秘密鍵と公開鍵を作ります。
# su - apache
$ ssh-keygen -t rsa (とりあえず全部Enterで)
すると、秘密鍵(id_rsa)と公開鍵(id.rsa.pub)が生成されるので、公開鍵(id_rsa.pub)の中身をメモ帳などにコピーしておきます。(あとでペーストします。)
$ cat ~apache/.ssh/id_rsa.pub
【各配信先サーバ側の作業】
先程コピーした公開鍵をペーストしつつ、下記のスクリプトを実行します。特に一番最後の行がとても重要です。wwwディレクトリ配下をapacheユーザでも更新できるようにグループ変更を行っています。
# sed -i "s/apache:x:48:48:Apache:\/var
\/www:\/sbin\/nologin/apache:x:48:48:Apache:\/var\/www:\/bin\/bash/" /etc/passwd
# mkdir /var/www/.ssh
# chmod 700 /var/www/.ssh
# chown apache.apache /var/www/.ssh
# echo "ssh-rsa ABCDB3NzaC1yc2EAAAABIwAAAQEAuN0ZaKuttD5/XZna/B2vMKBe1VhuWu/mBqGoYncjkVM
qaWMBRyK1qI6sE4+2k2HGdJa3/RFQu5TMo1f3nxHpvM90wUMoyuTpu2b88WeWZ+ZZxjtS8E
ML5OGsnPBXJ0FMGhuIwQekIBWXiQ7VdfBEIMITngNqzhu+X3dZJgutaJudWyM0j4FZA0b9+
tVsTJw2Kz28r4HwR6Gkcl4vXAo4e4HS8Y7WlabTVXJIkKwN1VqfC/jMohXqUS3SkzMxpS0C
gII0Nmj0PNl+F7zPhJEpsVZbBP9vIYeOKzsKVnD3HWHeeW/QAwVguW8DG1xv4edTR5bwTHS
He3u4UVazwxaSFG== apache@web1" >> /var/www/authorized_keys
# chown apache.apache /var/www/.ssh/authorized_keys
# chmod 600 /var/www/.ssh/authorized_keys
# chgrp -R apache /var/www/html ←超重要!
【rsync用スクリプトの準備】
細かくは説明しませんが、例えば以下のようなrsync用スクリプトを用意しておきます。
#!/bin/sh
servers[0]=10.0.0.1
servers[1]=10.0.0.2
servers[2]=10.0.0.3
for server in ${servers[@]};
rsync -avz /var/www/html ${server}:/var/www/
done
【phpプログラムの準備】
そして最後に以下のようなphpプログラムを用意すれば、やっとWEB上からrsyncを実行できるようになります。
<?php
if (@$_GET["c"], ENT_QUOTES == "r") {
system("/home/miracle/bin/myrsync.sh");
}
?>
<a href="rsync.php?c=r">[rsync]</a>
サーバ台数が増えてくると、サーバ間移動のたびにパスワード入力が求められるのが手間になってきます。これは何とかしたいところです。そこで今回はパスワードなしで他のサーバにSSH接続する方法を記していきます。
※今回、他のサーバにログインしようとするサーバを「admin」、ログインされるサーバを「web1」、対象ユーザを「user」としておきます。
【admin側の作業】
まずは秘密鍵と公開鍵を作ります。
$ su - user
$ ssh-keygen -t rsa (とりあえず全部Enterで)
すると、秘密鍵(id_rsa)と公開鍵(id.rsa.pub)が生成されるので、公開鍵(id_rsa.pub)だけを「web1」にコピーします。
$ scp /home/user/.ssh/id_rsa.pub user@web1:/home/user/.ssh/id_rsa.pub_admin
【web1側の作業】
adminからコピーされてきた公開鍵を「authorized_keys」というファイルに追加します。
$ su - user
$ cd .ssh
$ cat id_rsa.pub_admin >> authorized_keys
$ chmod 600 authorized_keys
すると、adminからweb1にパスワードなしでSSH接続できるようになります。
[user@admin ~] $ ssh web1Last login: Sat Oct 23 00:42:19 2010 from admin
[user@web1 ~] $
ただ、この方法だとadminからログインされる全てのサーバにadminの公開鍵を配布するのが面倒なので、私は以下のようなスクリプトをログインされる側のサーバ上で実行して済ませています。
$ echo "ssh-rsa ABCDB3NzaC5yc2EAAAABIwAAAIEA0AIDjalANyx09R5KoWCBRheartsNMNmli95CBQ1eBhzZGEQRdHqyS4I9v/5qgKMsrgruhNMBlGUUrop19ALwodHB852vWvAZG3gReu2c3CbP9qGlA0mTG7nYUCWU0ggFwq1b+HAA5wF/BqkSvWXlTe+9G0/8nmgqZMzKr81fL2u8= user@web1" > /home/user/.ssh/id_rsa.pub_admin
$ chown user.user /home/user/.ssh/id_rsa.pub_admin
$ cat /home/user/.ssh/id_rsa.pub_admin >> /home/user/.ssh/authorized_keys
$ chmod 600 /home/user/.ssh/id_rsa.pub_admin
$ chmod 600 /home/user/.ssh/authorized_keys
サーバリソース監視をする際、MTRG、Cacti、Nagiosなどを使う場合が多いですが、SNMPベースのツールは設定が面倒です。
そこで今回はSNMPを使わないお手軽サーバリソース監視ツールとしてmuninを手軽に導入する方法について記してみたいと思います。自動インストールスクリプト付きです。
【muninを使う前に最低限知っておいたほうが良いこと】
muninでは、監視用WEBサーバに入れるパッケージ「munin」と監視対象の各ノードに入れる「munin-node」があります。ただし監視用WEBサーバには「munin」だけでなく「munin-node」も入れなければなりません。
【監視用WEBサーバでの設定】
監視用WEBサーバ上では以下のスクリプトをroot権限で実行してみてください。(myhostnameのところだけそのサーバのホスト名に直した方がよいでしょう)
cd /root/Packages rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpmecho "[dag]" > /etc/yum.repos.d/dag.repo
echo "name=Dag RPM Repository for Red Hat Enterprise Linux" >> /etc/yum.repos.d/dag.repo
echo "baseurl=http://ftp.riken.jp/Linux/dag/redhat/el4/en/\$basearch/dag/" >> /etc/yum.repos.d/dag.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/dag.repo
echo "gpgkey=http://dag.wieers.com/rpm/packages/RPM-GPG-KEY.dag.txt" >> /etc/yum.repos.d/dag.repo
echo "enabled=1" >> /etc/yum.repos.d/dag.repo
yum -y --enablerepo=dag install munin
yum -y --enablerepo=dag install munin-nodesed -i 's/enabled=1/enabled=0/' /etc/yum.repos.d/dag.repo
mkdir /var/www/munin
mkdir /var/www/munin/htmldirchown munin.munin /var/www/munin/htmldir
chmod 755 /var/www/munin/htmldir# munin.conf htmldir変更(9行目)
sed -i 's/# htmldir/htmldir/' /etc/munin/munin.conf# munin.conf ホスト名に変更(60行目)
sed -i 's/localhost/myhostname/' /etc/munin/munin.conf# munin-node.conf ホスト名指定(29行目)
sed -i 's/#host_name x86-19.phx2.fedoraproject.org/host_name myhostname/' /etc/munin/munin-node.confservice munin-node start
chkconfig munin-node on
【各ノードでの設定】
各ノードでは以下のスクリプトをroot権限で実行してみてください。(myhostnameのところをそのサーバのホスト名に直すことと、監視サーバのIP指定部分だけ変更します)
cd /root/Packages rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpmecho "[dag]" > /etc/yum.repos.d/dag.repo
echo "name=Dag RPM Repository for Red Hat Enterprise Linux" >> /etc/yum.repos.d/dag.repo
echo "baseurl=http://ftp.riken.jp/Linux/dag/redhat/el4/en/\$basearch/dag/" >> /etc/yum.repos.d/dag.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/dag.repo
echo "gpgkey=http://dag.wieers.com/rpm/packages/RPM-GPG-KEY.dag.txt" >> /etc/yum.repos.d/dag.repo
echo "enabled=1" >> /etc/yum.repos.d/dag.repo
yum -y --enablerepo=dag install munin-node
sed -i 's/enabled=1/enabled=0/' /etc/yum.repos.d/dag.repo
# munin-node.conf ホスト名指定(29行目)
sed -i 's/#host_name x86-19.phx2.fedoraproject.org/myhostname/' /etc/munin/munin-node.conf# munin-node.conf 監視サーバからのアクセス許可(36行目)
sed -i 's/127\\.0\\.0\\.1\$/192\\.168\\.0\\.11\$/' /etc/munin/munin-node.confservice munin-node start
chkconfig munin-node on
【動作確認】
WEBブラウザー上で以下のようなURLを開いてみてください。
http://monitoring.example.com/munin/
うまくいけば以下のような画面にたどり着きます。うまくいかなかった場合はapacheの設定を見直してみてください。

【監視項目の追加削除を行なう】
muninには監視項目をプラグインで追加削除できます。プラグイン追加といってもリンクを張るだけです。ここでは試しにApacheとMySQLを監視項目に加え、かつsendmailとntpを監視項目から外してみます。各ノード側で以下のスクリプトを実行してみてください。
ln -s /usr/share/munin/plugins/apache_accesses /etc/munin/plugins/apache_accessesln -s /usr/share/munin/plugins/apache_processes /etc/munin/plugins/apache_processes
ln -s /usr/share/munin/plugins/apache_volume /etc/munin/plugins/apache_volume
ln -s /usr/share/munin/plugins/mysql_bytes /etc/munin/plugins/mysql_bytes
ln -s /usr/share/munin/plugins/mysql_queries /etc/munin/plugins/mysql_queries
ln -s /usr/share/munin/plugins/mysql_threads /etc/munin/plugins/mysql_threads
rm -f /etc/munin/plugins/sendmail*
rm -f /etc/munin/plugins/ntp*
ただしこのままだと各ノードのApacheが必要な情報(server-status)を吐き出してくれないので、Apacheにも設定追加を行ないます。
echo "" >> /etc/httpd/conf/httpd.conf echo "ExtendedStatus On" >> /etc/httpd/conf/httpd.confecho "
" >> /etc/httpd/conf/httpd.conf echo "SetHandler server-status" >> /etc/httpd/conf/httpd.conf
echo "order deny,allow" >> /etc/httpd/conf/httpd.conf
echo "deny from all" >> /etc/httpd/conf/httpd.conf
echo "allow from 127.0.0.1" >> /etc/httpd/conf/httpd.conf
echo "" >> /etc/httpd/conf/httpd.conf
sed -i 's/#LoadModule status_module modules\/mod_status.so/LoadModule status_module modules\/mod_status.so/' /etc/httpd/conf/httpd.conf
service httpd graceful
【最後に】
以上のように、muninの導入は手軽なので非常に便利ですが、かゆいところに手が届かない気がするのも事実です。ただ本家のFAQは英語だけど割と親切なので一度目を通してみることをお勧めします。例えば集計間隔を5分以外に変える場合は /etc/cron.d/munin を編集してね、みたいなことが書いてあります。
MySQLでは細かいレベルの権限付与が可能ですが、大抵の場合そこまで細かいレベルの権限付与は必要ないですよね? マニュアルを読まないか、もしくはちょっとしたメモ書きを見る程度でおおよそ使い方が理解できるくらいならいいのに、といつも思います。
そこで今回は、MySQLのユーザ権限付与の中でも、とりわけよく行われる手順だけを簡単にまとめてみました。
【まず知っておいたほうが良いこと】
ユーザはmysqlデータベース内のuserテーブルに作られます。
次に例えば以下のユーザの情報を見てみると「_priv」系のカラム値が全部「Y」であることがわかります。この場合はグローバルレベル権限として全部「Y」なので、全てのテーブルに対して接続が可能となります。
mysql> select * from user where User='adminuser' \G
*************************** 1. row ***************************
Host: %
User: adminuser
Password: 136b4c537575b6f1
Select_priv: Y ←
Insert_priv: Y ←
Update_priv: Y ←
~~~中略~~~
Create_routine_priv: Y ←
Alter_routine_priv: Y ←
Create_user_priv: Y ←
ssl_type:
ssl_cipher:
x509_issuer:
x509_subject:
max_questions: 0
max_updates: 0
max_connections: 0
max_user_connections: 0
1 row in set (0.00 sec)
一方、以下のユーザの情報を見てみると「_priv」系のカラム値が全部「N」であることがわかります。
mysql> select * from user where User='testuser' \G
*************************** 1. row ***************************
Host: localhost
User: testuser
Password: 136b4c537575b6f1
Select_priv: N ←
Insert_priv: N ←
Update_priv: N ←
~~~中略~~~
Create_routine_priv: N ←
Alter_routine_priv: N ←
Create_user_priv: N ←
ssl_type:
ssl_cipher:
x509_issuer:
x509_subject:
max_questions: 0
max_updates: 0
max_connections: 0
max_user_connections: 0
1 row in set (0.00 sec)
この場合は、別途ユーザが接続するデータベースを「db」テーブルに設定します。
mysql> select * from db where User='testuser' \G
*************************** 1. row ***************************
Host: localhost
Db: testdatabase
User: testuser
Select_priv: Y
Insert_priv: Y
Update_priv: Y
~~~中略~~~
Create_routine_priv: Y
Alter_routine_priv: Y
Execute_priv: Y
1 row in set (0.00 sec)
普段意識すべきはこのあたりまでだと思いますが、さらに細かい設定を検討する場合は以下もご参照下さい。
※参照:mysqlデータベース内のテーブル一覧
| データベース名 | 説明 |
| user | グローバルレベルの権限とパスワードを管理するテーブル |
| db | データベースレベルの権限を管理するテーブル |
| host(今回は考えない) | dbテーブルにホスト名が指定されていない場合に適用される権限を管理するためのテーブル |
| tables_priv(今回は考えない) | テーブルレベルの権限を管理するテーブル。テーブル内のすべてのフィールドに適用される権限について格納。 |
| columns_priv(今回は考えない) | フィールドレベルの権限を管理するテーブル。テーブル内の一つのフィールドに適用される権限について格納。 |
これをふまえて。
【1.管理者用ユーザを作りたい】
いわゆる何でもできる管理者用ユーザは以下の要領で作ります。
GRANT ALL ON *.* TO adminuser@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;
※MySQLにはGRANT権限というものがあります。GRANT権限とは、他のユーザに対して権限を付与することができる権限のことです。当然のことながらGRANT権限は通常管理者用ユーザにか付与しません。
IP制限をかける場合は以下の要領です。
GRANT ALL ON *.* TO adminuser@'172.16.0.0/255.255.255.0' IDENTIFIED BY 'password' WITH GRANT OPTION;
【2.一般ユーザを作りたい】
全てのデータベースにアクセスできる一般ユーザは以下の要領で作ります(WITH GRANT OPTIONがないのに注目)。ただし全てのデータベースにアクセスできる一般ユーザをGRANT ALL ON *.*で作ると、SUPER権限がつくのでinit_connectが無視されるなどの副作用があるそうです。(sh2さんご指摘ありがとうございました)
GRANT ALL ON *.* TO testuser@'%' IDENTIFIED BY 'password';
特定のデータベースにアクセスできる一般ユーザは以下の要領で作ります。
GRANT ALL ON testdatabase.* TO testuser@'%' IDENTIFIED BY 'password';
SELECT,INSERT,UPDATE,DELETEしかできない一般ユーザは以下の要領で作ります。
GRANT SELECT,INSERT,UPDATE,DELETE ON testdatabase.* TO testuser@'%' IDENTIFIED BY 'password';
【3.レプリケーション用ユーザを作りたい】
MySQLの大きな特徴であるレプリケーションを行う場合、MASTER DBに以下の要領でユーザを作ります。
GRANT REPLICATION SLAVE ON testdatabase.* TO repl@'172.16.0.0/255.255.255.0' IDENTIFIED BY 'password';
【最後に】
柔軟な権限設定ができるシステムは多いですが、概してどれも設定が複雑になるんですよね。しかし前提知識として今回の内容程度を押さえておけば、日常運用程度ではなんとかなるし、応用も利くようになるのではないでしょうか。
今回は、いわゆるMySQLでレプリケーションを行う方法を記してみます。非常に今更感がありますが、自分にとってかゆいところに手が届く文献がなかったので、自分でも一度まとめてみようと思いました。
【MySQLにおけるレプリケーションとは】
MySQLにおけるレプリケーションとは、マスターサーバでの更新情報がほぼリアルタイムにスレーブサーバに同期化される仕組みのことを指します。
マスターサーバ上で更新が起こると、バイナリログ(更新ログとも呼ばれる)に更新情報が記録されていきます。スレーブサーバは随時マスターサーバ上の更新情報を追いかけることでマスターサーバ上のデータをスレーブサーバ上で再現していきます。
レプリケーションにはシングルマスタ構成とマルチマスタ構成があり、通常はシングルマスタ構成を使います。シングルマスタ構成は1台のマスターサーバの下に複数台のスレーブサーバがぶらさがっているイメージです。selectなどの参照系SQLコマンドはマスターサーバでもスレーブサーバでも受け付けることができますが、insert、update、deleteといった更新系SQLコマンドはマスターサーバ上で行う必要があります。万が一更新系SQLコマンドをスレーブサーバで実行するとそのスレーブサーバにデータ不整合が起きます。
一方マルチマスタ構成は、各サーバがマスタとスレーブを兼ねるというもので、どのサーバで更新系SQLコマンドを実行しても大丈夫という仕組みです。これだけ聞くとマルチマスタ構成のほうが使い勝手が良さそうですが、シングルマスタ構成と比較すると動作が不安定とのことであまり推奨されていないようです。ですので今回はマルチマスタ構成は無視し、シングルマスタ構成についてのみ記していきます。
【レプリケーションを行う手順】
MySQLでレプリケーションを行う手順はちょっと面倒くさいです。
(1) マスタサーバ上でレプリケーションを許可するスレーブサーバの権限を付与する。
(2) マスタサーバ上でバイナリログを書き出す設定を行う。
(3) マスタサーバのテーブルへの書き込みを止め、現在のバイナリログのファイル名や位置を記録する。
(4) スレーブサーバ上で、マスターサーバを参照する設定を行う。
(5) マスタサーバのデータを、新しく構築するスレーブサーバにコピーする。
(6) スレーブサーバ上で、現在のバイナリログのファイル名や位置を先ほどコピーしたデータと合わせる。
(7) マスタサーバのテーブルへの書き込みを再開する。
(8) スレーブサーバを有効にする。
といった作業が必要になります。
ところで(2)と(3)はマスターサーバからデータや位置情報を持ってきてもいいですが、他のスレーブサーバから持ってきても良いです。稼働中のマスターサーバを止めるのは大変ですが、他のスレーブサーバであれば少しは気が楽です。
【マスターサーバからデータをコピーしてくる場合の手順】
(1) マスタサーバ上でレプリケーションを許可するスレーブサーバの権限を付与する。
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%' IDENTIFIED BY '';
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'192.168.0.0/255.255.255.0' IDENTIFIED BY '';
(2) マスタサーバ上でバイナリログを書き出す設定を行う。
/etc/my.cnfファイルに下記を追記します。
[mysqld]
log-bin
server-id=1
(3) マスタサーバを止め(もしくはテーブルへの書き込みを止めるだけでもOK)、現在のバイナリログのファイル名や位置を記録する。
mysql> FLUSH TABLES WITH READ LOCK;
mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000039 | 17510192 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
(4) スレーブサーバ上で、マスターサーバを参照する設定を行う。
スレーブサーバの/etc/my.cnfファイルに下記を追記します。(※server-idは他のマスター、スレーブで設定した数とは異なった数にする必要があります。1以上の整数が有効となります)
[mysqld]
server-id=2
(5) マスタサーバのデータを、新しく構築するスレーブサーバにコピーし、スレーブサーバ上で展開する。
マスターサーバ上で以下の手順を行う。
# cd /var/lib/
# tar cvf /tmp/mysql.tar mysql
# scp /tmp/mysql.tar username@slave.example.com:/tmp/
# rm -f /tmp/mysql.tar
そしてスレーブサーバ上で以下の手順を行う。
# service mysqld stop
# cd /var/lib
# mv mysql mysql_old
# tar xvf /tmp/mysql.tar
# rm -f /tmp/mysql.tar
# service mysqld start
(6) スレーブサーバ上で、スレーブサーバのステータスを確認します。
mysql> show slave status \G*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 10.0.0.1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000039
Read_Master_Log_Pos: 17510192
Relay_Log_File: mysqld-relay-bin.000024
Relay_Log_Pos: 80878039
Relay_Master_Log_File: mysql-bin.000039
Slave_IO_Running: No
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 17510192
Relay_Log_Space: 80878039
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
この中の特に以下の内容が(3)でメモした内容と一致しているか確認します。
Master_Log_File: mysql-bin.000039
Read_Master_Log_Pos: 17510192
一致していなければ、現在のバイナリログのファイル名や位置を先ほどコピーしたデータと合わせます。
mysql> CHANGE MASTER TO
MASTER_HOST='10.0.0.1',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000039',
MASTER_LOG_POS=17510192;
エラーが出たら適切に対応します。
ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log
mysql> reset slave;
の後、「CHANGE MASTER TO~」を再度実行する。
(7) マスタサーバのテーブルへの書き込みを再開する。
mysq> UNLOCK TABLES;
(8) スレーブサーバを有効にする。
mysql> START SLAVE;
そしてスレーブサーバの動作を確認します。
mysql> show slave status \G~中略~
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
~中略~
【スレーブサーバからデータをコピーしてくる場合の手順】
さて、次はスレーブサーバからデータをコピーしてくる場合の手順を記します。この手順が他のホームページやブログにはなかなか載ってなかったのです。とは言っても手順はほぼ同じです。違うところだけ記していきます。
(1) マスタサーバ上でレプリケーションを許可するスレーブサーバの権限を付与する。
同じ
(2) マスタサーバ上でバイナリログを書き出す設定を行う。
同じ
(3) 他のスレーブサーバを止め、現在のバイナリログのファイル名や位置を記録する。
mysql> stop slave;
mysql> show slave status;~中略~
Master_Log_File: mysql-bin.000039
Read_Master_Log_Pos: 17510192
~中略~
(4) スレーブサーバ上で、マスターサーバを参照する設定を行う。
同じ
(5) 他のスレーブサーバのデータを、新しく構築するスレーブサーバにコピーし、スレーブサーバ上で展開する。
他のスレーブサーバ上で以下の手順を行う。
# service mysqld stop
# cd /var/lib/
# tar cvf /tmp/mysql.tar mysql
# scp /tmp/mysql.tar username@slave.example.com:/tmp/
# rm -f /tmp/mysql.tar
# service mysqld start
そしてスレーブサーバ上で以下の手順を行う。
# service mysqld stop
# cd /var/lib
# mv mysql mysql_old
# tar xvf /tmp/mysql.tar
# rm -f /tmp/mysql.tar
# service mysqld start
(6) スレーブサーバ上で、現在のバイナリログのファイル名や位置を先ほどコピーしたデータと合わせる。
同じ。ただ多分この作業は必要ないです。
(7)は必要なし
(8) スレーブサーバを有効にする。
同じ
【余談】
多くのサイトではマスターサーバ1台+スレーブサーバ1台の2台構成となっていると思います。しかし予備のスレーブサーバを1台足して3台構成としておくと便利です。
もし予備のスレーブサーバあると、スレーブサーバを増強しようとしたときに、本稼働中のスレーブサーバを止めずとも増強を行うことが可能となります。またバックアップや集計といったサービスとは関係ないけれども重いDB処理を行いたいときには重宝します。
最近「ソーシャルアプリをやることになって、コンテンツは作れるけどインフラ周りが全然わからないので助けて欲しい」という相談をよく受けるので、よい機会ですので数回に分けてノウハウを記していこうと思います。というわけで今回はソーシャルアプリのサービスを行う際に考えておくべきことを記してみたいと思います。
【初期サーバ台数を多めにしておく】
「お金が無いので最初は少ないサーバ台数でサービスインをして、ユーザ動向を見ながらサーバを増やしていきたい」と思う人も多いと思います。
しかしソーシャルアプリの場合、サービスイン直後に大量のユーザが押し寄せてサーバダウンしてしまう場合が多々あることや、サービスイン直後に慌ててサーバ増強が必要となってもそれができる余裕がない場合も多いと思うので、初期サーバ台数を多めに準備しておき、ユーザ動向を見て事後にサーバ台数を調整するのが良いと思います。
【大量のテストデータを用意する】
よく聞く事例として「テストデータがほとんどない開発サーバ上でさくさく動いていてもいざ本番サービスに投入してみるとすぐに高負荷になって落ちてしまう」というものがあります。
DBテーブルのIndex貼り忘れ程度であれば早期に対応できますが、アプリケーションの構造に関するものであればすぐに対応できずサービスダウンが頻発して苦しむことになります。本番サービスに投入する前にかならず大量のテストデータ(数百万件とか)がある環境で負荷テストしてみましょう。
【極力早めに本番サーバに載せてテストする】
本番サーバを利用すると費用が発生してしまうので、サービスイン直前ぎりぎりまで本番サーバを用意しない会社も多いと思います。しかし実際にやってみると本番サーバの設定に思ったより時間が取られる、開発環境でうまく動いていても本番環境だと何故かうまく動かず原因究明に手間取る、また本番環境にしか必要でなくて準備をすっかり忘れているものがあって慌てて準備することが出てくる(ドメイン取得、DNS登録、SSL証明書取得などなど)といったことが起こり、結果としてかなり慌ただしい状態でサービスインを迎えることなります。
サービスイン直前はいろいろなタスクが集中するので、多少お金がかかったとしても事前にできることは事前に準備しておいたほうが良いと思います。
【スケールアウトできるようにアプリケーションを開発する】
開発中は1台の開発サーバ上で開発する場合が多いでしょうから、開発中はなかなかスケールアウト構成を意識することはないかもしれません。しかしソーシャルアプリの場合、サービスイン直後にいきなり高負荷になるケースがあり、その場合サーバ増強することですぐに負荷分散できるようにしておかないととても追いつきません。
スケールアウトできるようにアプリケーションを開発しておくことはもちろんのこと、サービスインの前に本当にスケールアウトできるかテストも行っておきましょう。
【マルチプラットフォームに対応できるようにシステムを構成する】
オープン当初は特定プラットフォーム上だけでサービスを行うこと前提だったとして、ビジネス判断として急遽他のプラットフォーム上でもサービスを行うことになるかもしれません。
そのようなときのために、まずアプリケーション側ではコンテンツ部分とプラットフォーム依存部分を完全に切り離しておくことで、プラットフォームを変える場合その部分だけを入れ替えることでプラットフォームを変えられる設計にしておくことが重要となります。
またシステム側では、プラットフォームごとにサーバを別に立てられれば理想的ですが、費用面でそれが叶わない場合同じサーバに同居せざるを得ないことがあるかもしれません。そんな場面を想定して予めそのようなことができるシステム構成を考えておきましょう。
【まとめ】
今回記したことは、つまり常に先の先を考えて事前に準備しておくということに尽きるのではないかと思います。多分今回記したことは「そんなの当たり前じゃないか」と思われる方も多いと思います。しかし実際やってみると、その当たり前のことが目の前のタスクに忙殺されて当たり前でなくなってしまうということが本当によくあります。
つまり「先にできることは先にやっておく」というのが最大のノウハウなのかもしれません。
先日本屋の中でぶらぶらしていたら、なかなか良い本を見つけたのでご紹介してみます。オープンソースソフトウェアがどのように作られていて、またどのように作れば良いか具体的に説明されていて結構面白かったです。オープンソースってプログラミング力以前にどういうルールで作ればいいのかという段階でつまずくことがありますが、この本があればそのレベルは軽くクリアできます。
こういう実践的な情報はWEB上でもなかなか見つからないので貴重です。内容が結構良いのに無名(だと思う)なのはもったいないです。
以下引用。
「システム管理者もオープンソース開発者も必読の1冊!
OSSのブラックボックスを丸ごと解説!!
本書は、Linuxが「どのように構成されているのか」「その構成要素はどのよう
にして作られているのか」についてを平易に解説、UNIX系OSを裏側から支える
数々の仕組みを理解できます。Linuxを日常的に利用しているシステム管理者は
もちろん、オープンソース・ソフトウェアを開発しようとする開発者や、オープ
ンソース・ソフトウェアの開発に何らかの貢献をしたいと考えているユーザ
は必読、今までブラックボックスにしていたLinuxソフトウェアの裏側も、この1
冊でわかります。
コンパイルやリンク、ビルドはもちろんパッチやマニュアル、RPMまで、UNIX系OSを裏側から支える数々の仕組みを解説。Linuxを利用しているシステム管理者やLinuxについての知識を深めたい方はもちろん、オープンソースソフトウェアの開発/貢献を考えている方は必読の1冊。」
過去にHDD障害によるデータ消失を何度も経験しているため、バックアップには多少神経質になっているところがあります。かといって面倒くさいのはもっと嫌。そこで考えたのは、Linuxが動いているマシンにUSBメモリを突っ込んでそこにバックアップデータを流し込む方法です。こうしておけばいざHDDが壊れてもUSBメモリだけ引っこ抜き他のマシンにマウントするだけですぐにデータを移行できるので楽ちんです。
今回はそんなテーマで記してみます。(root権限でお試しください)
![]()
【USBメモリをマウントする方法】
まずはUSBメモリをマウントさせなければなりません。USBメモリをマシンに突っ込み、「# dmesg」とすると、「sdb1」のような感じのものが出てくると思います。これを覚えておき
# mkdir /mnt/extdisk
# mount -t vfat /dev/sdb1 /mnt/extdisk
とするとUSBメモリが見えるようになります。(# ls /mnt/extdisk等)
ただし一時的にマウントしただけだとリブートしたら消えてしまいますので/etc/fstabに下記を追加します。
/dev/sdb1 /mnt/extdisk vfat defaults 0 0
これでUSBメモリの準備はOKです。
【バックアップ用のスクリプトを作る】
次にバックアップ用のスクリプトを作ります。今回は/var/www/html配下のファイルとMySQL上にあるデータベースをバックアップ対象とします。
下記のスクリプトを仮に/root/bin/backup.shという名前で保存したとします。
#!/bin/sh#-------------------
# backup script
#-------------------TARGET_DIR=/var/www/html
SAVE_NAME=www_backup`date +%Y%m%d_%H%M`
BACKUP_DIR=/mnt/extdisk
SAVE_DIR=$BACKUP_DIR/$SAVE_NAMETMP_DIR=/tmp
TMP_SAVE_DIR=$TMP_DIR/$SAVE_NAMEmkdir $TMP_SAVE_DIR
# sources
cp -r $TARGET_DIR $TMP_SAVE_DIR# database
/usr/bin/mysqldump -R --skip-lock-tables -uUSERNAME -p'PASSWORD' DATABASE_NAME > $TMP_SAVE_DIR/dbdump.sql# compress
cd $TMP_DIR
tar -cf $SAVE_NAME.tar $SAVE_NAMErm -rf $TMP_SAVE_DIR
gzip $SAVE_NAME.tar
mv $SAVE_NAME.tar.gz $SAVE_DIR.tar.gz
そして「# crontab -e」でcrontabに登録します。
0 2 * * * /root/bin/backup.sh 1 > /dev/null
【最後に】
USBメモリの値段が劇的に下がっている現在、皆なんでこの方法でバックアップを取らないのだろうと思うくらい非常に手軽です。ぜひ皆さんもお試しください。
※追記(2010/6/20)
古いバックアップデータを自動削除するようにしたいというリクエストをいただきました。これは以下のような記述を追加すれば実現可能です。
find /mnt/extdisk -maxdepth 1 -type f *.tar.gz -atime +6 -exec rm -f {} \;
iPhoneアプリやソーシャルアプリ市場の登場によって、小人数でもそれなりの収益が得られる環境が整い起業に走る人が増えてきたように思います。しかし実際にやってみるとサーバ費用が結構かかり、あわてて資金調達をせざるを得なくなったという話しをよく聞きます。しかし融資と投資を混同する人が多いようで、資金調達の場においてこの違いを混同しているような素振りを見せたらその時点でアウトです。
そこで今回は資金調達の基本、特に融資と投資の違いについて述べてみたいと思います。
【融資とは】
融資とは、銀行や政府系金融機関などからお金を借りることを指します。借りたお金は後日利息をつけて返さなければなりません。融資というのは利息で稼ぐビジネスモデルなので貸し倒れリスクを最も嫌います。よって普通は実績のない創業したばかりの会社にはお金を貸してもらえないです。
ただし、担保があるか、もしくは公的機関がベンチャー支援として保証人になってくれるような場合はよろこんでお金を貸してくれるでしょう。
【投資とは】
一方投資とは、投資家から会社に出資してもらう代わりに会社の株券を渡さなければなりません。出資してもらったお金は返す必要はありません。株券はすでに発行されているものを渡すか、新株を発行して割り当てる方法(第三者割当)があります。
投資というのは、投資先が上場して高値で株券を売るか、株券を他社に高く買い取ってもらうか、もしくは利益が出たらその中から配当金として受け取るというものです。特に投資先が上場すると出資額に対して数十倍~数百倍というレベルでの利益が得られるため、投資家はいろいろなところに投資します。100社に投資して1社でも上場してくれれば十分儲かるので投資の場合はある程度リスクがある場合でも将来性があれば投資してくれることでしょう。
ただし投資と引き換えに株券を渡すということは、株券を渡せば渡すほど経営権が投資家に握られてしまうことになります。特に株式比率を51%以上とられてしまうとその会社は完全に投資家のものになってしまいます。
投資を受ける際重要な考え方はバリュエーション、すなわち会社の価値をどのくらいと判断するかです。バリュエーションの高い会社、すなわち儲かっているかもしくは資産をたくさん持っている会社には高い株価で投資を受けることが出来ます。言い換えると儲かっているときは儲かってないときより少ない株券で同額の出資を受けることができます。つまり儲かってないときに投資を受けるよりもある程度儲かった段階で投資を受けるほうがトクということですね。
【創業直後のベンチャー企業の資金調達はどちらが良いか】
これは究極の問いです。これぞ経営者のセンスの見せどころば部分と言えます。強いて言えば公的機関のベンチャー支援は低利息で担保不要だったりするので、最初はそういうところで運転資金を調達しておき、ある程度利益が出てバリュエーションが上がってきたらそのとき改めて投資を受けるというのが良いかもしれません。
【融資を受ける戦略】
融資の場合、融資先が気にすることは「確実に返してもらえるか」です。数年間安定的な利益が出ていたり、もしくは万が一貸し倒れても担保や保証人から確実に回収できるような場合は喜んで融資してもらえます。
しかし創業直後のベンチャー企業は利益なんてないし担保なんてない場合も多いでしょう。ということは先程も書きましたが、公的機関によるベンチャー支援として保証人になってくれそうなところを探してなんとかそこの審査をパスするということをまずは目指すのが良いでしょう。
【投資を受ける戦略】
一方投資の場合、投資先が気にすることは「将来性がありそうか」です。現在全く利益がなくても論理立てて将来おそらく儲かるという根拠を示せれば大丈夫です。また経営者がどういう人物かということも非常に重視されます。信頼でき、かつ熱い情熱でビジョンを本当に実現できそうか、ということが非常に重視されます。
よくある勘違いは、必ずしも斬新なビジネスモデルでなくてもよいです。極端な話し喫茶店やたい焼き屋といったありふれた商売でも、将来性があることが証明できれば問題ないです。
投資を受ける際意識すべきは、投資家というのは会社が上場するか他社に株券を高く売れないと利益が出ないということです。つまり投資を受けるということは、会社を上場させるくらいの覚悟が本当にありますか?ということと等しいです。このあたりの覚悟もないのに銀行から融資を受けるのと同じ気持ちで投資家に接する人がもしいるとしたらものすごく失礼だし恥ずかしい話しです。
【最後に】
今回のテーマは本が数冊書けるくらいものすごく深いテーマなので、本当にさわりだけを説明した程度に捉えてください。
他の人から頼まれたので、ソーシャルアプリ専用ホスティングサービスをざっと調べてみました。せっかく調べたのでブログでも公開してみます(注:今回は単なるクラウドや普通のホスティングなどのサービスは対象外)。
※他にもあったらぜひ教えてください
■GMO「GMOアプリクラウド」
ソーシャルアプリに必要なものがパッケージ化されていて大変便利。個人的に一番のおすすめ。
・初期費用無料
・準備期間完全無料、さらに公開後も4日間20台無料
・アクセス解析ツール無料
・ロードバランサー無料
・WEBコントロールパネルからサーバの増減が可能
・最短2日でサーバやインフラ用意可能
■ライブドア「DATAHOTEL for Social」
単なるホスティングだけでなく日常運用・監視まで対応してくれるので、インフラ担当エンジニアが全くいない会社には便利かも。
・初期費用無料
・月額課金開始はアプリのサービスインから(引渡し日1ヶ月以内)
・最短1日でサーバやインフラ用意可能
・有償コンサルティグサービスあり
・参考月額費用90万円(フルマネージドサービス付き)
■ライブドア「DATAHOTEL P.O.I for Social」
ライブドア「DATAHOTEL for Social」の安価版。よくわかりませんが、どうもWEBサーバは仮想化サーバ、DBサーバは実サーバにすることで安くしているような気がします。
・初期費用無料
・月額課金開始はアプリのサービスインから(引渡し日1ヶ月以内)
・最短1日でサーバやインフラ用意可能
・有償コンサルティグサービスあり
・参考月額費用30万円(サーバ5台、フルマネージドサービス付き)
■KLab「DSAS Hosting for Social」
・レベニューシェア型(初期費用無料)と従量課金型(初期費用あり)の2種類
■トリグラフ・インフラストラクチャー「Social Application Stock」
・レベニューシェア型(初期費用無料)と従量課金型(初期費用あり)の2種類
■ビットアイル(GMO系)「ソーシャルアプリケーションパッケージ」
・初期費用無料
・最短2週間でサーバやインフラ用意可能、追加サーバは3営業日
・基本パッケージの最低利用期間は3ヶ月
・基本パッケージにはシングル構成と冗長構成がある
・参考月額費用100万円(シングル構成、サーバ10台+FW+NW機器)
■アイ・ティー・コンサルティング「ソーシャルアプリ向けホスティングサービス」
・初期費用無料
・最短2週間でサーバやインフラ用意可能、追加サーバは3営業日
・最低利用期間は2ヶ月
・参考月額費用70万円(サーバ10台+FW+NW機器)
■ハートレイルズ「OpenSocial Host」
・フリープランとビジネスプランがある。
・フリープランでは広告表示が義務付けられる他、転送容量制限等がある。
・ビジネスプランではデータベース使用量、API使用回数、ファイル使用量、およびファイル転送量の従量課金。
※以下お願いというか宣伝というか。
最近たまに私個人宛にソーシャルアプリのインフラ関連でご相談をいただくのですが、結構手間がかかりますので今後有償でお引き受けすることにしました。(私or私の責任で別の人が対応)
1回5万円
(メールやチャットで要件整理~業者選定~申請書類作成代行~サーバ初期設定~サービス開始まで)
前回のエントリーからの続きです。今回は大規模システムと小規模システムでの負荷対策に対する考え方の違いについて述べてみたいと思います。
【小規模システムではパフォーマンスチューニング力が重要】
小規模システムではハードウェアリソースの追加が費用面で難しいので、負荷対策においては限られたハードウェアリソースを最大限活かす方向で頑張ることになります。つまりアクセスが増えてきた場合はパフォーマンスチューニングすることで乗り切ることとなります。
例えば1台のサーバ上にApacheとJAVAとTomcatとMySQLを入れた環境があったとします。最初の頃は特に問題がなくても、徐々にアクセス数が増えてだんだん応答速度が落ちてきたときは、ソースコードを改良したり、オープンソースの各パラメータを調整したり、もしくはmemcachedを入れて繰り返し問い合せられるものをメモリ上にキャッシュさせたりといった、パフォーマンスチューニングに労力を注ぐことになります。
【大規模システムではスケーラビリティの高いシステム設計が重要】
一方、大規模システムではアクセス数増大をパフォーマンスチューニングだけで乗り切るのが不可能な場合がほとんどなので、負荷対策においてはハードウェアリソースを増強することで対処することになります。つまりシステム設計の上で、ハードウェアリソースを増強することで容易にシステムキャパシティを増やすスケーラビリティの高いシステム設計が重要となります。
例えばWEBサーバ10台でアクセスをさばいている環境があったとします。ある日TV広告を打つことになりました。TV広告を打った直後アクセスが確実に100倍以上になることが予想されたときは、早急にハードウェアリソースを増やして乗り越えなければなりません。サーバを追加する、アクセス数が多すぎてキャパシティを超えた時のことを考えてSorryサーバに飛ぶようにネットワークを調整する、画像などの静的コンテンツはCDNなどを利用する、もしくはこの機会にクラウド環境に切り替えるなどなど、矢継ぎ早に作戦を練って対処していかなければなりません。
【結論】
同じインフラエンジニアであっても大規模システムを扱うか小規模システムを扱うかでこれだけ負荷対策が異なることがおわかりいただけたかと思います。
前回のエントリーでも書きましたが、大規模システムを扱う場合は技術力云々よりもとにかく次々と意思決定していくことがとても重要となります。次々と意思決定するためには幅広い技術的知識や経験がとても重要となります。インフラエンジニアを志したからにはそれらを身に付けつつ、是非ともいつかは大規模システムに挑戦してみていただければと思います。
「小規模システムの構築」と比べて「大規模システムの構築」はなんだかものすごく高度で難しい印象を持つかもしれません。しかしどちらが高度で難しいかと問われればそれぞれ作業内容が大きく異なりどちらとも言えない気がします。そこで今回は両者どのように作業内容が違うためどちらが高度で難しいと言い切れないのかを考えてみたいと思います。
【小規模システムは全てを自分でやらないといけないので難しい】
小規模サイトの場合は担当者が自分一人しかいないということがよくあります。しかし例え小規模であっても押さえなければならないポイントは大規模サイトのそれとは大きく差がないと言えるため、実は広く深い知識と経験が必要なのが小規模システムの構築と言えそうです。
例えばいわゆる一般的な2階層式(=WEB+DB)WEBサイトをリリースするとします。この場合に必要な知識は例えばサーバ、OS、WEBサーバ、セキュリティ、ネットワーク、SSL、メールなどなど。これらを一人だけで一通りこなすというのはある意味高度で難しいと言えます。
【大規模システムは全体の構成を考えるのが難しい】
一方、大規模サイトの場合は担当者が数名でかつ予算がそれなりに用意されている場合が多いです。この場合自分はある特定の部分だけ担当すればよいので気が楽です。また手厚いベンダーのサポートを受ける予算があるので、何か問題に突き当たったときにいちいち検索して調べなくてもベンダーに連絡しておけばすぐに回答が帰ってきます。このことは実は自分自身が高度な技術を持っていなくてもある程度なんとかなってしまうことを意味します。
ただし大規模システムの場合、システムを構成する要素が多くて何をどう組み合わせるのか設計するのが難しいと言えます。また小規模システムと比べて購入するハードウェアが非常に高価な場合が多いので、何を購入するかの選定が非常に難しいです。例えばネットワーク機器を購入する場合、メーカー毎にどのような違いがあり、どのような機能差があり、パフォーマンスはどうで、実績はどうで、拡張性はどうで・・・等々、気にすべき要素が多くて非常に悩みます。
【結論】
思うに、小規模システムの構築は職人技の世界なのに対して大規模システムの構築は意思決定の世界な気がします。つまり、小規模システムの構築では担当者の知識と経験が全てなのに対して、大規模システムの構築では担当者を誰にしてどのベンダーを選定してどの機器を採用して等々、大半の時間を選ぶという作業に費やすことになります。
この機会にインフラエンジニアである皆さんがどちらの世界を目指そうとしているのかをちょっと考えてみても良いかもしれません。
献本いただきましたので書評を書かせていただこうと思います。
まずは、なんといっても10年分の記事ですからものすごいボリュームです。昔読んだ記事がちらほら見られとても懐かしい気持ちで一杯になりました。これだけのボリュームがわずか2000円ちょっとですからすごい時代ですよね。HDDの中にDVDの中身を全てコピーしておくだけでもリッチな気持ちになれそうです。^^
ドッグイヤーで進化するIT業界の10年分ですからある意味情報の博物館みたいな感覚を覚えます。ベテランの方にとっては懐かしい歴史の振り返り、若い方にとってはIT業界の技術やトピックの進化を順を追ってたどっていけそうです。
編集者の方曰く刷った部数が少なくて増刷の予定も特にないそうですので、買えるうちに買っておいたほうがよいかもしれません。
無線LANとWi-Fiを混同して使ってましたが、別物だということを今日知りました。orz
Wikipediaなどから抜粋してみます。
【無線LAN】
無線通信を利用してデータの送受信を行うLANシステムのこと。
【Wi-Fi】
IEEE 802.11機器に関する業界団体である Wi-Fi Alliance による相互接続性の認定の名称のこと。
要は、無線を使ったLANであれば何でも無線LANと呼ぶのに対して、業界団体の規格にpassしたものをWi-Fiと呼ぶという違いなんですね。
最近のIT系雑誌やIT系書籍では安い機器を組み合わせてITインフラを構築する記事ばかり。高品質な機器を使ってITインフラ構築する技が書かれた記事を全然見なくなった気がします。私が大学生のときとは時代が変わったということなのでしょう。当時UNIXと言えばEnterprise UNIXの代表格であるSolarisが皆のあこがれで、当時システム一式が数十万円とか100万円とかしていました。無論Linuxもありましたが当時のLinuxは今のように手軽に扱えるディストリビューションがあったわけでもなく、そこそこマニアックな存在でした。
高品質で高価な機器を扱う場合は緊張度や真剣味が全然違います。パーソナルLinuxのように手軽に扱えるものばかり扱うのと違い、高品質で高価な機器を扱う場合は設定事例などを検索にかけてもまず出てきませんので、どうしても自分で周辺知識をきちんと勉強した上でもろもろ自分で判断して設定に落とし込んでいく必要があります。こういった習慣は奥の深いインフラ系エンジニア育成にとても有効だったと思うのですが、最近はなかなかそういう機会や環境が与えられることが少なくなってしまい残念なことです。
ちょっと行き詰まったらひたすら検索して答えだけを探す風潮や、「マニュアルやRFCを読みなさい」と言うとすぐに「英語読めません」という答えが返ってくる風潮はなんとかならないのかなぁと思ってしまいます。
ちょっと思いついたんですが、砂漠にデータセンターを作るのはどうだろう。
通常データセンターで問題になりそうなのは
・土地代の問題
・電力確保の問題
・冷却対策
・安定したネットワーク回線の問題
などがありそうなんですが、砂漠だったらこれらを全て解消できるのではないかとちょっと思いました。個別に見てみます。
【土地代の問題】
土地がいくらでもある砂漠なので、まずはこの問題はクリアですね。
【電力確保の問題】
太陽エネルギーをいくらでも活用できる砂漠であれば電力問題もクリアできそうです。
【冷却対策】
太陽エネルギーをいくらでも活用できるので、強力な冷却装置を設置することで冷却対策もなんとかなりそうな気がします。通常冷却を強くすれば排熱がすごくなりますが、砂漠なのでいくら排熱を出そうが大きな問題にはならない気がします。
【ネットワーク回線の問題】
砂漠にネットワークを引き回すのは大変かもしれないですが、海底ケーブルみたいなことが実現できたんだから、砂漠ケーブルも実現できるに違いない。
という感じですが、無論素人意見なのでいろいろ問題があるんでしょうね。どんな問題がありそうかこのあたり詳しいかたのご意見をいただけましたら幸いです。
フロントエンドWEBサーバには安い1UのIAサーバでもいいけど、DBにはEnterprise UNIXサーバを使いたいものです。Enterprise UNIXサーバの可用性の高さを一度経験してしまうとIAサーバでDBを構築するのが本当に怖くなります。
とにかく強く主張したいのは、本当に大切なものにはきちんとお金かけようよということ。MySQLクラスタ構築みたいなものに時間をかけるのもいいけど、いいサーバを買えばそれで済んでしまうので他の本質的なことに時間がかけられるようになると言えます。
無論ビジネス規模の問題で予算的にEnterprise UNIXサーバを入れられない場合が大多数なのもよくわかります。だからと言って最初から候補から外すのではなくて、最低限Enterprise UNIXサーバとはどういうものなのか詳細に調べてみてほしいのです。もっと言うと最新のメインフレーム(大型汎用機)についてまで調べてみたら目から鱗な新発見も多いと思います。
(この手の意見って、サーバが悲鳴をあげるくらいのアクセスやH/Wが毎日のように壊れる現場を経験したことがない人にはあまり実感を持ってもらえなそうですが)
Recent Comments