泥臭いサーバ運用自動化の話
こんにちは、North America事業本部のLiang Fanです。このエントリーは GREE Advent Calendar 2015 10日目の記事です。
本日は、以前所属していたインフラストラクチャ部のサーバ運用と自動化の話を少しご紹介したいと思います。
よろしくお願い致します。
はじめに
運用自動化と聞いて、みなさんは頭の中に何を浮かべますか?仮想化技術(docker、VM)、構成管理ツール(chef、puppet)やクラウドサービス(AWS、Google Cloud Platform)などの答えがたくさん出てくるかもしれません。本日はそれらの技術を使って、かっこいい運用自動化ができたという話ではなく、レガシー環境のサーバ運用を少しでも楽にするための泥臭い自動化の話を紹介したいと思います。
グリーのレガシー環境
レガシー環境と言っても、もう歩けない80歳のおじいさんではなく、たくさんの子供(プロダクト)を養っているまだまだ元気な50歳のお父さん、というのが私のイメージです。その元気さを支えているのは「整備されたパッケージ」「豊富な運用ツール」「丁寧な手順」の3本の矢です。
整備されたパッケージ
サーバを構築するとき、メインパッケージをインストールするだけで、他の必要なパッケージが依存関係により同時に入ってくれるので、とても便利です。構築したいサーバのスペックに基づいて、自動的に、パラメータの最適化やグリーの環境に特化したチューニングを行います。
豊富な運用ツール
オンプレのサーバは長く運用しているため、運用ツールが内製でたくさん作られ、ほとんどの場面に対応できます。その中には、グリー環境に特化した運用ツール(せじまくんの刺さらない話(MySQL Slave増設編))などもあり、非常に便利です。
丁寧な手順
サーバ運用の手順は過去試行錯誤しながら積み重ねられてきたノウハウを元に、非常に丁寧にまとめられています。ツールの使用例、どのようなアウトプットがあるのかはもちろん、使うときの注意事項や過去発生したオペミスなど、細かいところまで書かれています。
上記を踏まえると、非常に楽に運用できるような印象があるかもしれませんが、実際には一つの構築作業の中には複雑なステップや、結果によって対応が違うステップが多数含まれています。パッケージと運用ツールで省力化できているものの、パッケージをいれるだけで完結することは少なく、ほとんどの場合手作業がたくさんあって大変です。加えて本番環境でのサーバ操作には厳密なオペレーションを要求されるので、構築作業には時間を要します。
と言っても、私が入社した時点でグリーで最も古いインフラ環境は既に3年以上の安定運用の実績があり、当時ゲームプロダクトも安定稼働できていたため、多少不便ではありましたが、手動による構築で基本カバーできていました。
らくだの背骨を折る最後の藁
ところで、「らくだの背骨を折る最後の藁」ということばをご存じでしょうか?「限界を超えた状況では、ほんの些細なことが大事故を引き起こす原因となる」という戒めのことわざです。
ある日突然サーバの保守の関係で、半年間で数千台のサーバを構築するという作業が発生しました。もともとチーム作業の大部分を占めている構築作業が急に増え、まるで空気中の二酸化炭素が一気に増えたように、息苦しくて死にそうな状態でした。こうして、構築作業を自動化する必要性が出てきました。
レガシー環境のサーバ構築自動化
自動化には様々なやり方がありますが、現存のリソースを活用できる選択肢はそこまで多くはないです。まず、長年オンプレ環境で運用しているため、ゼロから仮想化は難しいでしょう。また新しい構成管理ツール(chefやpuppet)には、そのツール独自のDSLで、現在の設定とチューニング内容を全部探して反映しなければなりません。そうすると、時間がかかりますし、既存の運用を捨てて、新しいフレームワークに切り替えることはリスクも高いです。いろいろ悩んだ結果、現在実績のある手順をベースにして、少しづつ自動化する方法が一番現実的な選択肢でした。
1.暗黙知を形式知に
従来の手順書は綺麗に整備されていますが、「プロセスが生きていることを確認する」のような、人間しか理解できないステップが手順の中に多数存在しています。このような手順は自動化に向いていないため、機械に優しい手順を作らなければなりません。
以下はデータベースサーバを構築するステップの1つです。コマンドは1行しかないことに注目してください。
1 2 3 4 5 |
過去のスナップショット(mysqlのバックアップファイル)を新しく構築するサーバにrysncで転送する rsync --progress --bwlimit=xxx -a <standbyのhost>:/path/to/mysql_xxxx_standby-20yymmdd.tgz ./ && sudo tar zxvf mysql_xxxx_standby-20yymmdd.tgz 注意:スナップショットの転送は1台ずつ実施する |
このステップを機械で自動実行するためには、以下の問題を考えなければなりません。
- 過去のスナップショットはどこにあるのか?
- スナップショットの名前は何か?
- 転送先サーバのハードディスクの容量は足りるか?(現在ハードディスクの容量 >= スナップショットの容量+解凍するときに必要な容量)
- 複数サーバを構築する場合、どのように転送すれば一番効率がいいのか?
上記の問題を全部考慮した上でスクリプト化した結果、1行のスナップショット転送コマンドは200行を超えるrubyスクリプトになりました。
2.サーバのステータス確認を自動化
サーバ構築を行うにあたって、手順のステップごとに、構築対象となるサーバのステータスを確認しておく必要があります。従来のサーバステータス確認方法は、サーバにsshでログインして、手動でコマンドを叩いて、プロセスやミドルウェアなどの状態を確認するというものでした。しかし、確認ポイントはたくさん存在していて、全部手動で確認すると時間がかかります。確認するサーバを間違えたこともありました。このような確認をより正確かつ早く行えるよう、railsとserverspecを使って、サーバの状態を確認するシステムを作りました。手順書の確認ポイントを機械で読めるようにserverspecに書きかえて、チェックファイルを作成しました。そして、確認システムが複数のチェックファイルを組み合わせてくれるので、作業者は確認のリクエストを投げるだけで、サーバ状態をssh経由で確認することができます。
サーバのステータス確認を自動化したおかげで、従来の手順書ではカバーしきれなかったポイントもチェックできるようになりました。たとえば、kern.logのエラーやハードディスクのエラーなどの問題は、過去の手動構築ではチェックしていません。グリーの監視システムは上記の問題を検知することができますが、構築中のサーバはサービスを提供していないため、監視の対象外でした。そのため、監視を有効にした途端検知されてしまい、再構築を行わなければならないことが何回もありました。自動チェックシステムが導入された後、機械で毎回全部チェックして、怪しいサーバを本番に入れる前に検出でき、手戻りが無くなりました。
チェックファイルの一例:
1 2 3 4 5 6 7 8 |
#kern.log describe file("/var/log/kern.log") do it { should_not contain 'segfault' } it { should_not contain 'I/O error' } it { should_not contain 'filesystem read-only' } it { should_not contain 'Out of memory: kill process' } ... end |
3.手順をjenkinsで実行する
手順を実行する手段として、一番手軽かつ機能豊富なjenkinsを選びました。
jenkinsにはGUI画面が優しい、権限管理やバックアップの仕組みが完備されている、プラグインが豊富などのメリットがあります。更に、job中のステップが簡単に設定することができ、jobの結果に応じて次の行動を起こすことも簡単です。
実際の自動化のイメージはこのような感じです。jenkinsを中央コントローラーとして、ツールの操作やサーバの確認作業を手順通りで実行します。job完了もしくは予期せぬエラーで終了の場合はchatworkに通知を投げます。これで構築対象となるサーバ情報とパラメータを入れるだけで、サーバを構築することができました。めでたしめでたし。
最後に
サーバ構築自動化システム運用を開始してから半年、合計数千台のサーバを自動構築することができました。運用開始後、「運用者(業務委託・社員)ごとの権限変更機能が欲しい」「遅延実行の機能が欲しい」などの新しい運用ニーズが出てきましたが、追加実装はほとんどなく、ほぼ全部をjenkinsのプラグインで解決できました!本当に当時jenkinsを選んで良かったと思いました!現在でも運用中であり活躍しているjenkinsプラグインを最後にまとめました。同じ運用問題を抱えている方がいらしゃいましたら、ぜひ参考にしてください。
そして最後まで読んでいただき、ありがとうございました。
明日は Art グループ / Technical Artist チームの酒井 駿介 さんの Shader の話です。お楽しみに!
APPENDIX:便利なjenkins plugin
バックアップ
- 簡単にバックアップ、復旧することができる(thinBackup)
権限の管理
- 業務委託とチームメンバーの権限を分けたい(Role-based Authorization Strategy)
作業ログを綺麗に保存したい
- timestampを追加する(Timestamper)
- consoleの色を追加する(AnsiColor)
- ログから特定の文字を検索できる(log-parser)
全体制御
- 最大並列数の制限ができる(Throttle Concurrent Builds Plug-in)
- 最大実行時間を制御できる(build timeout plugin)
- ピークタイムを避けてjobを実行する(Run Condition Plugin)
- 特定の環境変数を注入する(envinject plugin)
validation
- 入力されたパラメータを正規表現で検証できる(validating-string-parameter)
- パスワードパラメータを入力できる(mask-passwords plugin)
通知