ペパボ新卒エンジニア研修 後編

#pepabo #ops

前回、ペパボ新卒エンジニア研修のアプリケーションサイドについて、2013年の振り返りに合わせて紹介した。 今回はその後編にあたるオペレーションサイドの研修について紹介しようと思う。

Ops研修

エンジニア研修オペレーションサイドの内容を説明するのはカンタンだ。

Rails Tutorialで作成したTwitter風Webアプリケーションは、これまでHerokuSqaleで動かしていた。 今度はそれを、minimalなOSの入ったサーバを用意し、環境を構築し、デプロイする。

production環境を自分で作り上げる。 自ら作り上げたサービスを自ら運営してみせるのが、この2ヶ月に渡り実施されたエンジニア研修の大目的だったと思う。

maglica

社内にはmaglicaによって構築されたinternal cloud環境がある。 社内ネットワークにVMを好きなだけ(といってもストレージに限界はあるが)立てたり壊すことが出来る。

maglicaに関しては以下の資料がある。

Maglica - A Simple Internal Cloud Tool at #techkayac from Gosuke Miyashita

Ops研修では、このmaglica環境にVMを立ち上げてサーバを構築した。

第1段階:手動でサーバ構築

ここからがオペレーションサイド研修の具体的な内容となる。

まずはじめに取り組んだのは、必要なパッケージをサーバにインストールし、とにかくRailsアプリケーションを動かせるようにすることだ。 図を以下に示す。

+------------------+
|   Nginx          |
|     |            |
|  Unicorn--MySQL  |
+------------------+

この枠は1つのサーバ (VM) である。 初めはこのような1つのサーバに対して、NginxやMySQLやUnicornといった必要なパッケージを片っ端からインストールした。

実はここで1つ失敗を犯しているのだが、それは次の段階で合わせて説明する。

第2段階:プロビジョニングツールの導入

第1段階で構築したサーバは手動で――yumやgemのinstallコマンドを直接叩いて――構築した。

さて、次はそれを自動化する。 当時はまだchef or puppetで(今はもう少しツールに選択肢がある)、ペパボは古くからpuppetを使いこなしている経緯もあってpuppetを使用した。 その時に使用した教材は栗林さん (@kentaro) の書いた入門Puppetだった。

ちなみに、その時作ったpuppetファイルはGitHubに公開している。

リポジトリ名が奇妙な上にディレクトリ構成がたいそう酷い。 当時はpuppetやserverspecの技術的位置づけや不慣れがあり、モダンなディレクトリ構成もその必要性も全く分かっていなかった。

最小構成と美的感覚

puppet化にあたり困ったことがあった。 第1段階では以下のコマンドを実行した。

$ yum groupinstall "Development Tools"

これが本当に良くなかった。 production環境に"Development Tools"という、余計なものまで大量に紛れ込んだツール群を叩き込んでしまっていたのだ。

本番環境に不要なものを入れてはいけない。

それは保守性や脆弱性や依存性であったりと、そうしたリスクめいたものも勿論だが、何より美しさに欠ける。 美醜への姿勢・感覚は重要だと思う。

重ねて、そうした美醜に対する意見を提出し、議論することが重要だと思う。 気になるが黙っているなんて態度はエンジニアらしくないと思うし、意見を出すことでチームや組織へ還元できると信じているから、美的感覚は常に研ぎ澄ましておくべきだと思っている。

話が逸れた。

ともかく本番環境は最小構成であるべきで、だからこそ"Development Tools"はpuppet化にあたって様々な面倒をもたらしてくれた。

例えばruby 2.0.0を入れようとruby-buildでビルドしようとする。 しかしビルドに最低限必要なパッケージが分からない。 手動で構築した頃には見えなかった問題がここにきて顕在化した。 最終的にはエラーログを見ながら足りないものを一個ずつ追加していく、という泥臭い方法でなんとかした。 手動構築時に必要なパッケージをメモしておけばこうはならなかっただろう。

この頃には、もたらされた恩恵をありがたく受け取るだけでは、決して成長はできないと思うようになった。

また話が逸れるが、同期のデザイナの研修では、会社のWebサービスをトレースしたと聞いた。 デザインの細部を自ら再現してみせることで、1つ1つの要素への理解を促すその内容は、どこかOps研修に通じるようだと感じた。

なお、この段階では他にも、monitによる死活監視やCapistranoによるデプロイ簡易化、セッションサーバの導入 (memcached) 等を行った。

第3段階:冗長構成

第2段階の時点でそこそこ安全なサーバになった。 他の可能性を考えるに、それは今までの構築が全て1つのサーバの中で行われていたことがあげられる。

次に行うべきは、役割ごとにサーバを分離して冗長化を図ることだ。

構成その1 アプリケーションサーバとDBサーバの分離

まず初めに分離したのはアプリケーションとデータベースである。

単純にVMを2個用意し、それぞれに応じたpuppet rolesを作成、各サーバにてapplyした。 appサーバからdbへの接続は、RAILS\_ROOT/config/database.ymlのhostを指定し、db側ではこのような暴力的なmanifestで対応した。

教訓として、データベースのセットアップはpuppetでやる領域では無いと思う。

+-----------+
|    app    |
+ - - - - - +
| memcached |
+-----------+
      |
      | TCP/IP
      |
+-----+-----+
|    db     |
+-----------+

通信インタフェイスの選択

maglica上に立てたVMにはeth0/1の2つのネットワークが用意されている。 eth0がWAN側、eth1がLAN側に見立てたもので、さて、appとdbサーバが通信するのに適したネットワークはどちらだろう。

当然、LAN側ネットワークで通信すべきだ。 わざわざWAN側を使って世に晒すことはない。 dbサーバのWAN側はむしろ閉じておいたほうが安全だ。 しかし、そうしたことも当時は頭を捻らせていたと思うと、ほとほと自分は物を知らないと思う。

(当然と書いたが、システムは生きており、構成は都度変化するものなので、あくまで一定条件下における選択程度の意味しかない。)

構成その2 アプリケーションサーバの冗長化

appサーバからdbサーバを分離することで、各サーバの役割は整理された。 しかしappサーバが1つしかない状況は、万が一アクセス過多となった場合に危険である。

そのような負荷対策として、appサーバを2つ用意して冗長化を図る。
*ただし、この作業だけでは十分ではなく、その3の作業も合わせて冗長化と言えるだろう。

セッションサーバ

appサーバを増やした時に厄介だったのがセッション管理だ。

  1. app1とapp2サーバを用意する
  2. あるユーザがapp1にアクセスし、ユーザ登録、そしてログインする
  3. ユーザ情報はdbサーバへ保存されるため、各appサーバで利用可能な情報となる
  4. しかし、ユーザのログイン情報はapp1だけが知っており、app2はそれを知らない
  5. つまり、app1でログインしたとしても、app2のサーバではログインしたことにはならない

この問題の解決策として、各appサーバが同じセッションサーバ (memcached) を参照させることにした。 願わくばセッションサーバは独立させたかったが、実力的に難しく、app1に用意したmemcachedをapp2に参照させた。

+-----------+  +-----------+
|  app (1)  |  |  app (2)  |
+ - - - - - +  + - - - - - +
| memcached |<-|           |
+-----------+  +-----------+
     |         /
     |        /
     |       /
+-----------+
|db (master)|
+-----------+

これでapp1でログインしてもapp2でログインしても、セッション情報はapp1のいるサーバ上のmemcachedに格納されるため、どちらでログインしてもセッション情報は共有される。

構成その3 リバースプロキシサーバによる負荷分散

さて、このままでは自動的に各appサーバへのアクセス振り分けが出来ない。

そこで次はリバースプロキシサーバを導入する。 リバースプロキシサーバにはnginxを用いた。

+-----------------+
|  reverse proxy  |
+-----------------+
     |       \
     |        \
     |         \
+-----------+  +-----------+
|  app (1)  |  |  app (2)  |
+ - - - - - +  + - - - - - +
| memcached |<-|           |
+-----------+  +-----------+
     |         /
     |        /
     |       /
+-----------+
|db (master)|
+-----------+

冗長構成その4 データベースサーバのレプリケーション

さて、次はデータベースである。 こちらは思っていたより簡単な作業だった。MySQLのマスタースレーブ構成の恩恵をそのまま受けた。

+-----------------+
|  reverse proxy  |
+-----------------+
     |       \
     |        \
     |         \
+-----------+  +-----------+
|  app (1)  |  |  app (2)  |
+ - - - - - +  + - - - - - +
| memcached |<-|           |
+-----------+  +-----------+
     |         /
     |        /
     |       /
+-----------+  +-----------+
|db (master)|<-| db (slave)|
+-----------+  +-----------+

Ops研修で得たもの

反省

1ヶ月ほどのOps研修で私が挑戦した内容は、ザッとこのようなものだった。

この研修はRails Tutorialのようなゴールのある研修ではなく、作業が早く終われば次の課題が顔を出すようなやり方で、もっと先のことを出来た同期もいた。

この研修の反省点は、ロードバランサを用意出来なかったことだ。 puppetに慣れるのに結構な時間をかけてしまったことや、途中1週間ほどひどく体調が悪化し、進捗がずっと悪かったのが原因として挙げられる。 日々の体調管理がいかに重要かということも学んだ。

さらなる冗長化とその必要性

当たり前の話だが、冗長化はすればするほど良いわけではない。

サーバ台数の増加に応じて増大する運用コスト、あるいはスペックを持て余すような使い方もまたコスト…冗長化は費用対効果との戦いだと思う。

次への提案

社内の先輩にも何度か話している内容なのだが、この研修ではVM環境が豊かだったこともあり、物理サーバの組み立てやRAID構成の実践はしなかった。 個人で経験済みかもしれないが、仕事で使うものの内部構造を知ることは非常に重要だと思う。

例えばRAID構成を考えるうえで、それが画像や動画データを格納するサーバであればどれを採用すべきか、といったことを考えるキッカケになると思う。

(もちろんRAIDを組んだからといって明確な答えを導き出せるわけではないが、経験というものは閃きへのトリガーになり得るので、そういう意味でオススメしたい。)

オペレーションサイドの座学

研修前半にも座学はあったが、オペレーションサイドに研修が移ってもそれは続いた。

内容はOpsらしいというか、ミドルレイヤを含めたバックエンド技術やサーバ(あるいはデータセンタ)の金銭的な話であったり、多岐に渡る貴重な話をたくさん聞かせていただいた。

  • nagiosやmuninの監視周りについて
  • AWSやCDNといったクラウド環境について
  • データセンタ見学や費用
  • インフラエンジニアの1日
  • インフラの各種レイヤーの冗長化について

他にもMySQLやNoSQL、全文検索エンジン、あるいはターミナルマルチプレクサといったものまで教えていただいた。すべてを紹介するには数が多すぎるため、紹介は一部に留める。

研修を経て、目指すべきところについて考える

研修の話は以上で、ここからは独り言として書いておこうと思う。

技術者の冷静が支えるモノ

今、インフラエンジニアとしてOJTを受けていても思うのは、オペレーションは日々を定常に構成を丁重に、連綿として維持することが重要だということだ。

例えば落ち着くこと。 技術を支える人が焦るのは良くない。 これはパニックを呼びかねない。

社内の技術者を見るに、実力に裏付けられた人であればあるほど冷静であると思う。

彼らは焦らない。 そのように意識しているのか、自然とそうであるのかは分からないが、彼らはめったに苛立ちを表にしない。

ペパボには技術基盤チームという、言うなれば社内最高戦力のみで構成されたチームがある。 彼らはどこかのサービスや部署に所属せず、社内全サービスに関わる技術基盤の整備を行っている。

新卒エンジニア研修では技術基盤チームの皆さんの元で学び、多くを教えていただいた。 その時気づいたのは、彼らは一度も怒らなかった。 覚えの悪い自分に対しても、苛立ちを見せることもなく、丁寧に教えてくれた。

技術者としての圧倒的実力に裏付けられたこの冷静さに憧憬を抱いた。 ペパボを支えているのはソースコードやデザイン、あるいはビジネス戦略なのかもしれないが、私にはこの冷静さこそが真の基盤であるように思えた。

技術者と冷静は不可分なものだと思う。

自然と、自らもそうありたいと願うようになった。

憧れからはじめる

新卒エンジニア研修の教育担当をしていただいた、技術基盤チームの伊藤さん (@hiboma) への憧れから、kernelのソースコードをなんとなく読み始めて、社内で起こったバグを解決することが出来た。

これがもし社会人2年目の出来事であれば、こうも興奮することはなかったかもしれない。 これがもし新卒社員として採用していただいた会社でなければ、こうも喜ぶことはなかったかもしれない。

ほんの小さな出来事だったかもしれないが、そうありたいという願いに、一歩近づけたように思う。

2014年、私はペパボのエンジニアとして2年目を迎える。 1年周期の目標は特に立てていないが、先にも書いたとおり、願いを叶えるべく行動していこうと思う。

憧れからはじめたkernelソースコードリーディングも、今は最も楽しく感じている。 エンジニアとして解決したい領域はここだと思うようになった。 まだまだ世間知らずだが、信頼し、尊敬できる師を見つけられたことは、この人生の中で最高の財産であると思っている。

すぐに人生とか言い出すのがいかにも青二才かもしれないが、本当にそう感じている。

終わりに

前後編合わせて長いエントリとなったが、ここで2013年度に行われたペパボ新卒エンジニア研修の話は終わりとなる。 書ききれない思いもたくさんあるし、もしかしたらとんでもなく誤解させる表現をしているかもしれないので、何かあれば連絡していただけると幸いである。

ここまで付き合っていただいた皆様へ、本当にありがとうございました。