Architecture研究会の予稿です.発表資料speakerdeck.comはじめにWebサービスのインフラを設計する上で、RDBやWebサーバを始めとした多くのミドルウェアは欠かせないコンポーネントの一つであり、それらの構築、運用も重要な要素である。LAMP環境が提唱された1998年頃とは異なり、同じことを実現できるミドルウェアが複数あり、Webサービス開発者はミドルウェアの選択肢の幅が広がった。2005年以降、サーバ仮想化技術の普及を始めに、クラウドベンダーによるミドルウェアのフルマネージドサービスやコンテナ技術の登場により、ミドルウェアの実行環境は多様化してきた。同一のミドルウェアでも、実行環境が変わることにより、構築、運用手法や利用可能なツールが異なることがあり、それらの違いを表現可能なアーキテクチャの議論は十分にされていない。本稿では、ソフトウェア設計で提案されているオニオンアーキテクチャ*1やクリーンアーキテクチャ*2の考え方を参考に、Webサービスにおけるインフラアーキテクチャの捉え方を再考、整理を行なっている。再考したアーキテクチャを洗練することで、多様化したミドルウェア実行環境を、Webアプリケーションの機能要件のみならず、運用も考慮した選択手法を議論する際に利用できると考えている。アーキテクチャ検討は不十分であり、発表時に提案したアーキテクチャについての議論を行ないたいと考えている。本稿の位置づけ筆者はWebサービスにおけるインフラアーキテクチャの体系化し、Webサービス毎に適切なアーキテクチャを自動的に生成する研究を個人的に取り組んでいる。本稿は、前回の発表*3で整理した課題における「既存のインフラアーキテクチャの調査と分類」の一部である。既存のインフラアーキテクチャWebサービス構築の全体的なインフラ設計をするための、汎用的で明確な命名がされているインフラアーキテクチャはほとんど存在しない。そのうちの有名なアーキテクチャとして1990年代にできた3層アーキテクチャと呼ばれるものがある。3層アーキテクチャを図1に示す。3層アーキテクチャこのアーキテクチャはWebサーバ、アプリケーションサーバ、DBサーバの3つからなるアーキテクチャである。図1に示すように、それぞれがプレゼンテーション層、アプリケーション層、データ層のレイヤーで表現される。この3層アーキテクチャを実装するためのOSSの種類としてLAMP構成と呼ばれる造語が1998年に誕生した。LAMPはサーバOSとしてLinux、WebサーバとしてApache、DBサーバのMySQL、そしてWebアプリケーション実装をPerlで行うものである。当時はミドルウェアの種類も多くなかったため、このような造語が誕生したと思われる。Webサーバ、アプリケーションサーバ、DBサーバはそれぞれワークロードが異なり、冗長化手法なども異なるため、スケーラビリティやキャパシティプランニングが容易になる。Webアプリケーションはアプリケーションサーバのみにデプロイすればよく、WebサーバやDBサーバへのアプリケーションのデプロイは不要である。3層アーキテクチャの特に重要な点は、3層というレイヤードアーキテクチャではなく、役割毎に違うサーバを分離しておくということである。3層というのは、当時のWebサービスがシンプルな動的ページを返すサービスがほとんどであり、クライアントサーバモデルの基本が3層であるという実装上の話に過ぎない。現在のWebサービスはCDNやオンメモリKVSのキャッシュサーバなどを利用されるため、3層以上のレイヤーになることや、リクエスト処理のアプリケーションとバッチ処理のアプリケーションを分離するなど、データの流れや依存は複雑化しており、単純な階層化で表現することは困難である。そこで本稿では、3層アーキテクチャからデータの流れによる階層化を除き、役割毎に別サーバに分離するアーキテクチャをロール分割アーキテクチャと呼ぶことにする。ロール分割アーキテクチャの図2に、ロール分割アーキテクチャの例を図3を示す。図2、3の赤い線はリクエスト処理の依存を表す。2007年頃からは現在Webサービスではよく利用されるRedis,Cassandra,MongoDBなどのKVSミドルウェアを始め、より高度なWebサービスを作るため、様々なミドルウェアがOSSとして実装され、多くのWebサービス事業者が利用出来るようになった。ロール分割アーキテクチャはミドルウェアを多様化にも対応可能であり、複数のミドルウェアを組み合わせや、アプリケーションの処理内容によって、複数のアプリケーションに分離した場合でも表現ができる。図3の例では、WebサーバのNginx、RDBのMySQL、アプリケーションに加え、キャッシュサーバとしてRedisを追加し、バッチ処理用のアプリケーションを別サーバに分離している。このように、ロール分割アーキテクチャはミドルウェア毎にサーバを別にするため、多数のサーバを構築、管理する必要が出てくる。Webサービスの高度化と増加するサーバ、ミドルウェアの運用コストとのバランスが重要になり、効率の良い運用、管理手法の重要度が増した。多くのサーバの構築に利用されるChefなどのプロビジョニングツールなどが登場したのもこの頃である。ミドルウェアは多様化しているものの、ミドルウェアの実行環境であるOS部分は統一可能であることが多いため、ミドルウェアの構築やアプリケーションのデプロイなどは例えばSSHを利用して自動構築、デプロイするツールを利用することで自動構築することが可能であった。監視ツールなどもミドルウェア固有のパラメータの取得はミドルウェア毎に対応が必要なものの、CPU利用率やネットワークの死活監視、プロセスの生存確認などはOSの機能やSNMPなどのプロトコルを利用して取得が可能であった。これらを言い換えると、Webサービスの提供とは直接関係のない構築、管理のためのアプリケーションやミドルウェア(例えばSSHサーバ)がミドルウェア実行環境がOS上であることが前提だったため、Webサービスのインフラ設計と、サーバ(正確に言えばOS)の構築、管理の仕組みはある程度分離して考えることが可能であったということである。上述した既存のインフラアーキテクチャの問題点は、ミドルウェアの実行環境が多様化した際にWebサービスのリクエスト処理などは考慮できるものの、ミドルウェアの構築や監視など、Webサービスを運用していく上で重要となるインフラ管理、運用を考慮しきれていないことである。現在、以下の2つの要因でミドルウェア実行環境の多様化が発生しているコンテナ技術クラウド事業者によるミドルウェアのマネージドサービス1つめはコンテナ技術である。コンテナ技術には様々な実装形態があるが、本稿ではDockerを例に説明する。Dockerでは対象のアプリケーションをコンテナ上で実行できるが、Dockerは基本的に1コンテナに1アプリケーションという設計で作られている。WebサーバであるNginxとSSHサーバであるOpenSSHを同じコンテナ上で動かすことはDockerの設計とは合わない。コンテナ上にNginxを構築するにはDockerが提供しているDockerfileという仕組みを利用して構築する。ChefなどのSSHが前提のプロビジョニングツールを利用した構築には不向きである。2つめはミドルウェアのマネージドサービスである。本稿ではAWSを例に説明をする。RDBサーバとしてMySQLを利用する場合、AWSのマネージドサービスとしてRDSとAuroraが存在する。RDSやAuroraを構築する方法は通常のOS上にMySQLを構築する方法とは大きく異なり、AWSが提供しているAPIを利用して構築する必要がある。APIに対応したTerraformなどのOSSを利用できる。SSHを利用したプロビジョニングツールの利用は基本的にはできない。これらはミドルウェアの監視にも同じことが言える。OSの機能を使った監視(例えばPSコマンドによる監視)はマネージドサービスには利用できない。コンテナ上でも一部制限があるものが多い。Lambdaなどによるサーバレス環境は特に運用、管理に注意が必要である。マイクロサービスが実行されるサーバレス環境の管理手法とコンテナ、仮想サーバの管理手法などと併せて考える必要がある。本稿ではマイクロサービスへの議論までは行わないが、サーバレスなアプリケーションはミドルウェアのマネージドサービス管理手法の応用で対応が可能であるのではないかと筆者は考えており、今後検討が必要である。DockerでNginxを動かしても、仮想マシン上でNginxを動かしてもHTTPリクエスト処理は可能であるため、Webアプリケーションの要件は満たせるが、構築、運用の要件によって使い分ける必要がある。一般的に単体で見ればコンテナ技術やマネージドサービスが効率よく構築、運用が可能であるが、一つのWebサービスでコンテナ技術やマネージドサービスと従来の仮想マシン上で実行するミドルウェアが混在する場合、バランスを取ったほうがよいケースも存在しうる。ミドルウェア実行環境の多様化により、Webサービスの機能要件だけではなく、運用管理手法も併せて選択する必要があるが、既存のインフラアーキテクチャでは表現が不十分である。現在はロール分割アーキテクチャから下層のServerを除き、ミドルウェアやクラウドサービスの依存や、リクエスト処理フロー、データフローを記載したインフラアーキテクチャ図によって表現されることが多いが、これらだけではアプリケーションの要件を満たすか議論することはできるが運用、管理を同じアーキテクチャで議論できない。別のアーキテクチャで運用、管理を表現し議論すると、アプリケーションの要件やデータフローなどの確認が難しい。そのため、アーキテクチャを見ただけでその選択により何のトレードオフが発生するかをイメージすることが難しく、識者でなければ把握することが難しい(コンテナを選択するとChefが選択できないなど)。提案手法ミドルウェア実行環境の多様化を考慮し、かつ運用、管理手法を表現できるアーキテクチャをオニオンアーキテクチャなどのソフトウェア設計手法を参考に検討する。ソフトウェア設計手法を参考にする理由を下記に示す。Webアプリケーション実装のアーキテクチャであり、Webサービスにおけるインフラ設計の問題点と関係があることが多い2000年頃からレイヤードアーキテクチャとは異なるアーキテクチャを検討しており、複数のアーキテクチャが既に提案されているソフトウェア設計手法と同じくまずは実装ベースのレイヤードアーキテクチャを考え、そこから見方を変えることで、よりアプリケーションの要件と運用、管理を考慮しやすいアーキテクチャを再考していく。ソフトウェア開発は、実装を自らが行ないその際のクラスの依存関係がシンプルになるようにするためのアーキテクチャであるのに対し、インフラ設計はミドルウェアなど既に存在する実装から選択し、その選択によるツールの依存関係を知りたい、もしくはシンプルにしたいと言うように実際には異なる点も多々ある。そのため、そのまま適用できるわけではないので、参考にしつつ取り入れられるところを取り込んでいく形となる。具体例として以下を環境を想定して話をすすめる。WebアプリケーションがRDBを利用したいので、MySQLを選択する例をとるMySQLを仮想サーバ上に構築する場合、コンテナ上に構築する場合、マネージドサービス上に構築する場合における構築ツールとの関係と監視手法との関係、Webアプリケーションとの関係を考えるコンテナを使う場合にはDockerを使うことにするAWSのMySQL互換のマネージドサービスとしてRDS、Auroraを検討する構築ツールとしてサーバにはChef、コンテナにはDockerfile、RDS,AuroraにはCloudformationを使う実装ベースの単純なレイヤードアーキテクチャ実装ベースのレイヤードアーキテクチャを図4に示す。実装ベースのレイヤードアーキテクチャこのアーキテクチャでは図4のように、上からUI、Middleware、Infrastractureとする。これはソフトウェア設計のレイヤードアーキテクチャと似た命名をしている。UIはミドルウェアが提供するAPIやプロトコルである。ソフトウェア設計と異なる点としてはUIは自分たちで設計し実装するため自由に設計できるが、ミドルウェアの場合は追加が困難なことも多い。Middleware層はミドルウェアの実装を指す。ここも自分たちで実装することも出来るが、多くの場合は既に存在するミドルウェアを選択すると考えられる。Infrastractureはミドルウェアの実行環境を指す。OSやコンテナ、マネージドサービスであったりする。ここで具体例を当てはめたのが図5である。レイヤードアーキテクチャの例UIにはMySQLプロトコル、MiddleWareにはMySQLかRDSかAuroraが、InfrastractureにはOS、コンテナ、AWS(マネージドサービス)が入る。Webアプリケーションはどの場合にもMySQLプロトコルを使って通信をする。構築ツールはChefはOSにSSH経由で、Dockerfileはコンテナへ、CloudformationはAWSへAPI経由で実行される。外部から一番下層のレイヤーに接続しており、レイヤードアーキテクチャとしては少々おかしい。構築ツールはMySQLを構築するためのものなので、実装ベースのレイヤードアーキテクチャでは再下層に接続するのは自然である。実装ベースのレイヤードアーキテクチャの問題点を以下に示す。外部からの接続で最下層レイヤーを参照しているUIやMiddleWareはミドルウェア実装を選択した時点で記載内容が決まっているミドルウェア選択の際に利用できる情報がない2つめと3つめはインフラ設計においてミドルウェアの選択が重要であるが、その選択の際に必要となる依存関係などがわからない、表現できないため既存のインフラアーキテクチャと大きく変わりはない。オニオンアーキテクチャを参考にしたインフラアーキテクチャオニオンアーキテクチャを図6に示す。オニオンアーキテクチャオニオンアーキテクチャは名前の通り、玉ねぎのように同心円状で表されるアーキテクチャである。似たようなアーキテクチャとしてヘキサゴナルアーキテクチャ*4、クリーンアーキテクチャがあげられる。Modelを中心に置き、Interface、Infrastracture、TestsをDomainから分離している。この特徴を参考にインフラアーキテクチャへ置き換えたものを図7に示す。オニオンインフラアーキテクチャ図7に示したアーキテクチャを本稿ではオニオンインフラアーキテクチャと呼ぶことにする。domainはミドルウェア実装の本来のdomainを示す。今回の例であればRDBMSということになる。実際の設計者はWebアプリケーションにおいてRDBを利用したいという要望があり、それからミドルウェアの選択に移ることが多いだろう。その次のMiddlewareでは実際のミドルウェア実装を示す。今回はMySQLなどが該当する。外枠はUI、Infrastracture、ManagedServiceである。UIとInfrastracutureは基本的にレイヤードアーキテクチャと同じものが該当する。Serviceは下層のMiddlewareに対して互換をもつ実装やマネージドサービスが該当する。実際に今回の具体例を上記のアーキテクチャに当てはめた例が図8である。オニオンインフラアーキテクチャの具体例Webアプリケーションはレイヤードアーキテクチャと同じく、MySQLプロトコルで接続する。ここでは省略しているがWebアプリケーションはそのままオニオンアーキテクチャを利用し、WebアプリケーションのInfrastractureとRDBのUIが接続している。簡易的にプロビジョニングツールは、Domainとしてprovisioningとなり、それぞれのツールがInfrastructureにつながり構築を表現する。実際にはこの他にWebサーバやKVSなど他のDomainのオニオンインフラアーキテクチャも記載し、それぞれをWebアプリケーションからの接続、Provisioningからの接続を書き記すことで、依存関係を把握することが出来る。可能な限り依存関係の接続は少ないほうが、シンプルなより良いアーキテクチャの選択となる。ProvisionigのツールとしてCloudformationでWebサーバ、KVS、RDBMSのすべての接続が可能であるならば、図のChefやDockerfileは使う必要はなく、そういった選択を出来るかUIとWebアプリケーションとの接続も併せて同じアーキテクチャ内で検討することが出来る。レイヤードアーキテクチャに比べて以下の改善点が見られるDomainを導入したことにより、ミドルウェア実装の表現が可能になった。レイヤードアーキテクチャが並べてあるよりも、Interfrastructureの選択とProvisioningツールとの関わりがわかりやすくなった。外部との接続は外郭のみとなり、レイヤードアーキテクチャよりは違和感がすくなくなった。以下の問題点が存在する。ServiceとInfrastractureにの両方と繋がっているProvisioningの規模を小さく抑えるために考慮する際に、接続箇所が2つあるのは検討がしにくいのではないかDomainの記述ではRDBMSとして同じでも実際の機能が大きく異なる点も多いがそれらを表現しきれていない依存関係の明確化と機能の明確化は異なるのでそれぞれ違うアプローチを試みるのが良いかもしれないまとめ既存のインフラアーキテクチャをミドルウェアの観点からみて問題点を考察した。ミドルウェアの実行環境の多様化による運用管理の考慮事項の増加は、昨今のインフラ設計において無視できないものであり、それらを考慮したインフラアーキテクチャをソフトウェア設計の考え方の一部を適用し、改善できないか再考した。整理や考察が足りない箇所があるが、新規性や有用性がより明確に出てくる可能性があると考えている。議論したいことアーキテクチャというよりはどちらかというとUMLのようなものに近いかも?依存の可視化を行ない、選択を容易にするという観点でもUMLのほうが近い気もする。KVSという感じにDomainを作っていきそれぞれをつなげてみるともっと見えてくるかもしれないプロビジョニングツールのような運用管理ツールはミドルウェアとは少し違う同心円状かも?プロビジョニングだけではなくモニタリングも入れたい現状上手い形が見つからずもう少し整理が必要そうなにかいい案が無いだろうかもう少し整理されると面白そうで新規性や有用性も見えてくる気がしている議論で出た内容OSのレイヤー(ハードウェア、カーネル、システムコール、システムライブラリ)や、リングプロテクションに似ているOSなど権限がはっきりし、レイヤーを明確に分離する場合にはこういった表現が使えるレイヤーをオーバして成功した例も存在する(SDNなど)現在は過渡期なので実行環境が混在しているが、最終的には全部はマネージドサービスになるのではないか今回はミドルウェアの実行環境を想定したが、下のレイヤーが変化、多様化することはいつでも発生しうるため、それらを考慮したアーキテクチャを考えることは重要UMLというのは時代と逆行してそうで筋が悪そうミドルウェアというのも既に死語になりつつあるのではないかプロビジョニングツールなどが複雑になってしまうのは、筋の悪い間違った(レイヤーをオーバーしたような)使い方をしているだけなのではないかそういった使い方が、図示したときに可視化されることによって、ユーザーがレイヤーをオーバーした使い方をしていることが分かることは重要あとがき今回は既存のWebサービスにおけるインフラアーキテクチャを調査を開始し、それらからミドルウェアの実行環境の多様化に焦点を当てて、ソフトウェア開発手法を参考に適用したものを検討した。現在は既存のものを調査、整理している段階であることもあり、予稿や資料の作成、発表をするにあたって、まだまだしっかりとした言葉の定義や検討内容が不十分であると感じた。多様化と複雑化を解決するためによりソフトウェア的な解決方法(という言い方で良いのかわからないが)をとるようになったインフラの設計手法は、複雑かつ巨大なソフトウェアを開発するために進化したソフトウェア開発手法を参考にできることがあるのではないかという考えは今回の整理でより強くなった。(WSA研)で発表したときの予稿になります。今回はWSA研の第一回ということもあり、自分自身で何をしたいのかという点を整理するための発表という形になりました。整理や調査が不十分である状態ではありますが、WSA研のような場所で現状できているところまでを報告し、色々議論できたことでよりより調査を行えるかなと思っています。このように、明確な成果でなくても発表し議論できるところがWSA研のいいところかなと思っている*1ので、興味ある人はぜひ参加を検討してみてください。https://martinfowler.com/articles/serverless.html質疑応答とかこれができたとしてその先には何があるのか。我々が仕事をしなくても良くなるのかインフラアーキテクチャは日々進化している。現状出ているインフラアーキテクチャに対する自動選択が可能になったとしても、さらなるインフラアーキテクチャが提案される可能性がある。それに追従したり、アーキテクチャの選択、構築にかける時間が少なくなることで、より高度なアーキテクチャへの挑戦や、こういった設計自動化などの研究時間が増えるのではないか。構築したはいいけどコストが非常に掛かるシステム見たことがあったり)口頭でも出た限り既存システムへの適用もしたくなるとか、あとビジネス的な要件にどのくらい追従できるかも気になりました。後者は例えばサービスがビジネスとして軌道に乗るか分からんので良いアーキテクチャで無くてもいいからスピード重視で作りたいとかあるかなーと実際には新規構築だけではなく、むしろそこから先のサービスの成長に合わせてインフラを成長させていくのが難しいと感じている。現状のサービスと、新たに機能などが追加されたサービスの差分をサービス特性として入力とし、新たなインフラアーキテクチャを出力できたりする必要がある。最初は簡単化のために新規構築を対象とするが、最終的には差分なども考慮した特性で判別出来るようにしたい。最初はMonolithicだったが、規模が大きくなってきたのでMicroserviceにするときの適正なタイミングはどこかなど、考慮するべき項目はたくさんある。アーキテクチャを体系化してインフラ構築などを加速していく、というのはある意味ソフトウェアのライブラリ化といっしょで再利用性を高めるのと似た利点を持つと感じがしました(そこを狙っているのかもしれません)*1:成果があるならもっと影響力のある場所(論文やソフトウェアの公開、カンファレンスや大きな勉強会)での発表が良いでしょう。Qiitaの17日目の記事になります。NetLinkとIPVSを解説しようと思いましたが、気がついたら当日になっていたので、本日ははてなサマーインターン2017でメンターをしたときの話をしようと思います。developer.hatenastaff.comはてなサマーインターン2017では前半の講義パートと後半の実践パートがありました。私は前半の講義パートのインフラ講義と後半の実践パートの大規模システムコースのメンターを担当しました。講義の資料作成や大規模システムコースのメンターとして気にかけたことなどを書いてみようと思います。技術系の最後の講義として2時間インフラ講義を行いました。そもそもインフラ講義を2時間してくれっていわれても何話せばいいのかよくわからなかったので色々悩んだのですが、結局インフラ設計の考え方の基礎をお話しました。最近の学生は本当に技術レベルが高く、例えばテストを書くなどのコードを書く上での常識は比較的よく知っており、実践している学生も多いです。今年のインターン生もレベルが高く、前半パートの課題も動くだけでなくよりキレイな設計になるにはどうするか、といった内容の議論をメンターの方としている場面も見かけました。一方で、学生は基本的にインフラ技術には詳しくない場合が多いです。経験することができない、インフラの課題がわからない、勉強すべき箇所がよくわからない(実は私もよくわかっていません)。いった理由から勉強するためにインターンに参加したいという学生さんも多いと思います(社会人も多いと思いますが)。そこで、インフラ講義ではこれからインフラを勉強する、インフラ技術の話を理解しやすくするために基本的なインフラ設計の考え方を話そうと決めました。個別のミドルウェアなどは例として名前を出したりすることはしましたが、説明は特にしませんでした。ミドルウェアの仕様とか使い方、利用例はネット上を検索すれば出てくる内容も多いので、考え方などを中心にしたほうがインターンの講義内容としては価値があるだろうと考え、個別のミドルウェア内容は削りました。大体大きく分けて以下の3部構成で話を作りました。インフラとはweb,app,dbの3層構成パフォーマンスの話インフラとはまず基本的な話としてインフラという単語は指すものが大きいので注意しましょうみたいな話をしました。ISP事業者、クラウド事業者、コンテンツプロバイダーがいうインフラはそれぞれが指しているレイヤーが異なることが多いので、話を聞いたりするときはどのレイヤーをインフラと言っているのか意識したほうが話が聞きやすいという感じの話です。今回の講義ではwebサービスにおけるインフラ(つまりサーバやそれらが通信するためのネットワークの話)を中心としています。webサービス事業者はサーバを資産として持っていなくてもAWSなどでサービスを提供できたりするのでインフラとはつまりAWS,GCPであるというところもあるよーという話ですね。あとは、サービスの可用性、継続性、コスト、パフォーマンスとかを気にして設計しましょうという話。ここだけで3-4時間以上は喋れる気もするけど、いきなり経験ない学生にそんなこといってもという感じもあるのでさらっと流しましたが、インフラはここが最重要ポイント(だと私は考えている)なので、喋る時は強調はしておきました。web,app,dbの3層構成web,app,dbに分けた上でさらにbatchとかbackup用のdbとかキャッシュサーバとかくっつけていくと実際動いているサービス構成みたいになるやでーという話をしました。伝統の3層構成って感じの話ではあるんですが、それだけだとあんまりおもしろくなかったので、考え方はソフトウェアと同じで全く違う世界が広がっているというわけではないのが伝わるように話しました。3層構成に分けておいたほうがスケールや管理が楽になるといきなり言われてもわからんと思うので、main関数にすべてのコードが書かれている状態を各役割と責任範囲を明確にした上で各クラスに分離したような感じなど例を出すように説明しました。サーバ自体が状態を持ったオブジェクトであるというイメージがつくと、変更時の影響の局所化のためにサーバを分離して管理しようとか、メンテナンスがしやすいように名前を付けたり不要なパッケージは入れないようにしようとか、相互に接続するためのインターフェースは統一されていたほうが良いとか、大きなシステムになれば理解するために相互の関係性をUMLのように可視化したいとか、状態を可能な限り持たせないことでより容易に並列化しようとか、そういったプログラミングと同じ課題がインフラを見た時にも見えてくるんじゃないかなーと思っています。分散トレーシング、コンテナ技術とかを見た時に解決したい課題が、イメージしやすくなるといいなーなんて考えてたりします。言え、2時間で話すのには限度があるので↑のようなところまで伝わったかはわかりませんが、サーバもどこまで分離するかとか、どう分離しようかみたいな議論は、ディレクトリ構成の分け方、クラス設計などに通じるものがあるというのがなんとなくわかったんじゃないかなーと思います。パフォーマンスの話ここは少し具体的な技術の話をしています。今まではフワッとした話だったのでちょっとおもしろ要素として入れています。2時間もフワッとした話しても飽きてしまうかもなーとおもったのでマルチプロセス、マルチスレッド、イベントなどの話や、DBのシャーディングなどのお話をちょろっといれてフィニッシュという感じです。*1に書いてあるとおり、大規模システムコースの課題はいくつかテーマを用意しておき、実際に配属されるインターン生の特性を見ながらインターン生と相談して実際に行うテーマを決定しました。今回のテーマは"次世代監視技術への挑戦"という感じでした。具体的な内容はインターン生がまとめてくれたブログをご覧ください。id:y_uukiと案を出しつついくつかの候補をインターン生に示し、一番興味がありそうなのをやってもらう感じにしました。案ではいくつかあってredis4.0などのミドルウェア検証から今回採用した次世代技術への挑戦みたいな研究に近い内容までありました。インターン生に最高の夏だった、成長したと思ってもらうことが我々メンターの目標なので大規模システムコースのテーマの決定はなかなか大変です。2週間(10営業日)で実サービスのインフラ環境を触ったことないインターン生が、インフラ技術で内外に反響がある成果を出すというのは難しいものです。大規模システムコースは他のサービスに紐付いたコースとは異なり、実サービスの機能開発という感じでは無いため、比較的自由にテーマを決定することができる反面、実際のユーザからのフィードバックなどがもらいにくいため、成功体験が得られにくいというデメリットがあります。今までの大規模システムコースも成果としては出ているものの、フィードバックが社内からしか得られにくいという点がありました。サービスに関係したインフラ改善(例えばMySQLのバージョンを上げましたとか、パフォーマンス改善とか)はタイミングが合えばインターン生にも可能な範囲でユーザからのフィードバックがもらえるものがあるのですが、10日で出来るのかというのと果たしてそれが"大規模"であるかという問題点があります。id:y_uukiが考える解決案のイメージを伝え、それをインターン生が自分たちで理解した上で自ら実装を提案し、それらの成果をOSSや技術ブログとして外部に公開するという研究に近い課題の出し方にしました。このテーマになった理由はインターン生が選んだというのもありますが、インターン生の基礎力が十分であると判断できたという点と他のテーマより圧倒的に楽しそうだったからです。id:t-k3ntaroo)は、自ら調べ考え考察する技術、研究に必要な基礎力が十分に備わっていました。彼らなら我々が考えた解決案以上のものを提案し、共に議論が出来る実力が十分にあるのでやっている我々も楽しいものになると思ったからです。実際にテーマが決まってからは、私が主にメンターを努め2人の進捗を見守りつつ議論に参加するという感じでした。メンターをやる上で気を付けた点は以下の2点ですメンター側から意見を出しすぎず、インターン生との議論に一人のエンジニアとして参加するこまめに進捗確認と議論をする1つ目の"メンター側から意見を出しすぎず、インターン生との議論に一人のエンジニアとして参加する"のは可能な限り自分たちの手法を提案してほしいからです。私はインターン生を学生ではなく一人のエンジニアとして扱っていますが、インターン生側は私が意見してしまうと「実際に働いているエンジニアが言うのだからそうなのだ」と思ってしまう可能性があるからです。1つの意見などを出しますが、インターン生で考えた実装を成果としてもらうことで、成功体験を掴んでほしいと思っていました。「これはメンターから言われたものを実装したものではなく、自分たちが考えた実装なのだ」そういうものにして欲しいのです。2つ目の"こまめに進捗確認と議論をする"のは別にインターンに限ったことではないですが、特に「普段一緒に開発しないメンバーと共に10日間で新しい技術に挑戦し、ブログとOSSとして公開する」ということをやり遂げる必要があるので、方向性が間違ったまま1日立つとそれを修正するだけで2日程度無駄にする可能性があります。出勤後,昼食後,退勤前の3回進捗と方向性の確認、困っていることと課題と感じていること、それに対する解決案を確認していました。短い時間で目的を達成するのには、Bestな選択をし続けるのは難しくても最低限Betterな選択をしていかなければなりません。本質で無いことに躓いていたり、熱中するあまり本来とは違うものを実装していないか注意する必要があります。私もメンターをしたことがないので実際のところはよくわかっていませんが、上記の2点のみを注意してやったところ10日間でインターン成果をブログとして公開し、OSSとしてgithubリポジトリを公開するところまで行けました。インターン生が優秀すぎたので特に上の2点を重視しなくても成功していた可能性が高いのですが、1に関しては意識しておいてよかったなーと思うことが多かったです。実は始める段階では可視化までは行けないだろうと思っていたので、特に何も考えずgraphvizあたりで可視化するんだろうなーみたいに考えていたのですが、「見にくいのでneo4jで試してみました」と持ってきたのでびっくりしました。上記リンクの成果を読んでもらえるとわかるかと思いますが、実装段階でいくつもの課題が出てきてそれぞれに議論を行っています。dockerでテストしてたらARPテーブル溢れてきたみたいな話から、接続の関係性のデータ保持は誰が担当するのか、クラスタを形成する時のnetstat情報はLISTEN側(サーバ側)からjoinするのかクライアント側からするのか、Gossipプロトコルを使うのは妥当か、Gossipプロトコルの通信量は問題ないか、ヘルスチェック監視に利用するものはpingでいいのか、UDPで問題ないのか、agent自体のCPU負荷はどうなのか、などなど紹介しきれていない議論もたくさんしました。議論ではネットワークなどインターン生にとって前提知識が薄いものに関しては積極的に意見を出しつつ、それ以外のものに関してはあがってくる提案手法などに対して意見を出したりしていました。最初はConsul聞いたことはあるという程度の知識だったインターン生が、1週間も立たずにGossipプロトコルの挙動やネットワーク帯域や通信頻度への言及などの議論が出来るようになったのは、単純に使うのではなく、特性を考え活用するという過程を踏んでいるからだと思います。彼らからあがってくる報告や課題は私自身も「なるほどなー確かに実用を考えると気になる点だなー」と気付かされることが多く、もしかしたら私のほうが楽しんでいたかもしれません。講義とメンターをしてみた感想インフラ講義の資料作成では、実際に自分がインフラを学んできた過程、思考、知識の整理ができたので良かったかなーと思います。インフラなどにかかわらず人にものを教えることの最大のメリットですね。結局整理した結果良くわかっていないことも多いし、インフラ知識は体系だったものはあんまりなく結局個人の経験から得たものが多いのかなという印象があります。個人の経験では体系だった教科書を作ることは難しく、多くの経験者たちと議論をする必要がありそうです。いったこともありWebSystemArchitecture研究会を発足し、広く議論することでより体系だったインフラ講義などを提供できるようになるかなとも思っています。websystemarchitecture.hatenablog.jpメンターは課題の設計から議論を考えるとかなり労力を使うなーという感じです。インフラは特に適当にやるのは簡単だけど、実力がつくインターンをするのは、会社としては工数をしっかりかけないと提供は難しそうです。逆に言えば学生はメンターがしっかりインフラのインターン内容を考えてくれそうなところに参加すれば、(学べるレイヤーの違いはあれど)しっかり実力や考え方を身に着けてインターンを終える可能性が高い(時間を無駄にした感が少ない)インターンを選ぶことが出来るんではないでしょうか?来年のインターン担当かどうかはまだわかりませんが、担当になるとしたらより体系的な講義と課題にできたら良いなと思っていますので、もし本記事を読んで興味が出てきた学生がいればぜひ応募していただけたらと思います。17:57はてなサマーインターン2017の講義とメンターをした話Tweetもっと読むコメントを書く2016-12-19LinuxのARPとL2スイッチのお話この記事は、はてなエンジニアアドベントカレンダー2016の12月19日の記事です。id:masayoshiです。2016年に入社後、基盤チームとして仮想化、ネットワーク周りを中心に見ています。この記事ではLinuxのARPの挙動とその挙動から起こった問題を紹介しようと思います。記事を読みたくない人向けに結論をまとめるとLinuxのARPはTCP通信で使われ続ける限りキャッシュが飛ばないという挙動になるので、複数のL2スイッチにまたがったセグメントや非対称ルーティングをしている場合は気をつけましょうという話が書かれています。今回紹介する事例自体は別に新規性もなく、私が入社前から社内でも知られていて対策がされている内容なのですが、ネットワークに詳しくないインフラエンジニアやアプリケーションエンジニアはあまりこういう事例や、動作が説明されている記事がなく、検索してたどり着くのが大変そうな気配がしたので、自分の勉強ついでに書いてみることにしました。keepalivedを利用しています。LVSではNAT,DR,TUN形式が利用できますが、リアルサーバ(振り分け先のサーバ)のセグメントを選ばないかつLVSに負荷がかかりにくいTUN形式を用いています。IPトンネリングでパケットをカプセル化して送ることで、送信元IPアドレスをリアルサーバに渡すことが出来ます。そのため、リアルサーバからの戻りパケットがLVSを経由することなく、送信元ホストに直接パケットを送ることが出来ます。EC2などとは違い、リソースマネージメントがめんどくさいDC環境ではネットワークを意識しなくて良いのは非常にありがたいことです。ここらへんのお話は先月OSCTokyoFallでの発表資料も参照していただければと思います。speakerdeck.com今回の記事はLVS/TUN形式で送信元ホストとLVS、リアルサーバが同じセグメントに存在し、複数のL2スイッチで構築されている環境というかなり限定された状況下で、戻りパケットがブロードキャストされるという問題です。正確に言えばLVSは直接関係ないのですが、今回のような状況が起こるのはLVSのようなロードバランサなどを利用している場合で起きやすいと感じた(実際に発生した)のでその事例を例に説明したいと思います。上記の図1-1のように、送信元ホストであるホストAがVIP宛にパケットを送信し(1)、LVSがリアルサーバA,Bに振り分け(2)、リアルサーバA,BはホストAに直接返信する(3)と環境です。実際には通信開始から5分程度経つと、下記の図1-2のように、リアルサーバBの戻りパケットがその他のホストBにも届いてしまうようになります。5分後の想定しいない通信ホストBでtcpdumpをした際に全く関係ない通信であるはずのホストAの通信が見えてしまったことで発覚しました。ホストB以外でも関係ないホストでホストAの通信が見えており、ブロードキャストされているようでした。今回発生した問題はあるホスティングサービス上で構築した際に発覚したので、L2スイッチの詳細なつなぎ方などはわからないため、図は簡略表示をしています。ブロードキャストになったのかを理解するにはL2スイッチの挙動を理解しなければいけないので、まず先にその話をします。L2スイッチの挙動についてL2スイッチ(普通のLANハブでもよい)では、MACアドレステーブルというものを持っています。これはMACアドレスと物理ポート(L4のポートではない)の対応表であり、対象のMACアドレス宛てのパケットをどの物理ポートから出せばいいのか調べる際に利用します。MACアドレステーブルに対象のMACアドレスがない場合は送出先ポートがわからないため、フラッディング(受信したポート以外にすべて送る)します。当然ですがブロードキャストアドレス(FF:FF:FF:FF:FF:FF)は常にフラッディングします。このMACアドレステーブルは受信したポートとパケットの送信元MACアドレスからひも付けを行います。先ほどの図1の通信では図2-1,2-2,2-3のようにMACアドレスと、ポート番号を覚えていきます。はじめはフラッディングしていたL2スイッチも図2-3の時点でフラッディングせずに通信が可能になります。以降の通信はMACアドレステーブルを参照し、対象のポートのみに通信していきますが、MACアドレステーブルにはエージングタイム(IEEE802.1Dでは300秒とされている)が設けられており、エージングタイム以降は再学習することになっています。細かい仕様は機器毎に違ったりしますが、大体300秒程たった後に再学習出来ないとMACアドレステーブルが更新されないため、対象のMACアドレスへの通信はフラッディングになります。MACアドレステーブルと非対称ルーティングこれまでの説明で、通信開始から5分程度でブロードキャストになるというのがMACアドレステーブルのエージングタイム(300秒)が切れたタイミングであることから、MACアドレステーブルが更新されなかったことが原因ということが予想できるのですが、なぜそうなるのか見ていきましょう。図2にL2スイッチβを追加したのが図3-1です。Requestから通信が始まります。このとき宛先MACアドレスはFF:FF:FF:FF:FF:FFでブロードキャストを使います。ブロードキャストなので当然L2スイッチβにもARPパケットが届きます。このとき送信元MACアドレス(ホストAのMACアドレス)と受信ポートからMACアドレステーブルが作成されます。これで最低でも5分程度はホストA宛のパケットはフラッディングではなく、対象のポートのみに送られます(図3-2)。図3-2の状態ですが、重要なのはホストAからの送信パケット(1)です。ホストAはVIP宛のパケットを送ります。VIPのMACアドレスはLVSのMACアドレスなのでL2スイッチαはMACアドレステーブルに従ってLVSのつながっているポートにのみパケットを送ります。LVSはサーバBにパケットを送りますが、このパケットの送信元MACアドレスはLVSのMACアドレスであり、ホストAのMACアドレスでありません(当然ですが)。最初のARPによるブロードキャスト以外はL2スイッチβにホストAからのパケットは来ないことになります。サーバBからホストA宛のパケットはMACアドレステーブルに従い、L2スイッチαにのみ送られ、その後、ホストAに届きます。そのACKパケットなどもLVSに行ってから送られるのでL2スイッチβはホストAのMACアドレスをブロードキャスト以外で知ることはできません。そのままエージングタイムが過ぎてしまうと、MACアドレステーブルからエントリが消えてフラッディングになってしまいます(図3-3)。LVS/TUNのような行きと帰りのパケットが違うルートを通るような非対称ルーティングな通信を行うときには、こういうことが発生しやすいので特に注意する必要があります。MACアドレステーブルからエントリが消えた時の挙動さて、原因っぽいのがわかったのはいいのですが、MACアドレステーブルが消えるまでにホストAがブロードキャストしてくれれば再学習ができるのでなんの問題もありません。Requestが飛ぶので問題ないような気がします。Requestが飛ばず、MACアドレステーブルが更新できないという状況になります。LinuxのARPの挙動カーネルを読み込みが甘く、自分でも追いきれていない部分もありますので、下記内容には誤り、情報が古いなどあるかも知れません。ARPテーブルのキャッシュに関する状態遷移の簡易図が図4です。実際にはNUD_INCOMPLETE,NUD_FAILEDなど、他にも状態がありますが簡略化しています。Requestが成功するとエントリが登録されNUD_REACHABLEになります。この状態では通信の際に普通にARPテーブルから対象のMACアドレスを得ることが出来ます。一定時間経つとNUD_STALEになります。NUD_STALEのエントリは参照されるとNUD_DELAYに遷移します。Requestは送らずNUD_REACHABLEに遷移します。ACKが返ってきたということはIPアドレスとMACアドレスのひも付けは正しく、再解決する必要がないとカーネルが判断します。Requestを投げることはしないという動作になります。ちなみにUDPなどではsendmsgにMSG_CONFIRMフラグをつけることによって対象がまだ生きていることを通知してNUD_REACHABLEにすることが出来るらしいです。Requestをユニキャストで送り、成功した場合はNUD_REACHABLEに遷移します。Requestが来ることがありますが、そのパケットはNUD_PROBE状態から送られています。Requestをブロードキャストで実行します。送信キューがない場合や応答が一定時間内に返ってこない場合はARPテーブルからエントリを削除します。疑問点としてはNUD_PROBEが行うユニキャストARPは送信キューに入ってなくても行うかどうかですね。Requestのブロードキャストが発生しないことになりそうです。対策としては送信元ホスト(ホストAなど)がブロードキャストをしてくれればよいということになります。簡単なのは送信元ホストでarpingなどをcronでまわしたりするのが良いかなと思います。Requestを誘発させてブロードキャストを行う方法をとっています。この方法ではLVSにcronを仕込むだけで良いので、サーバの引っ越しや設定変更で書きなおし等があまり発生しません。(LVSを構築し直すときは別ですが頻繁には行わないです。)まとめ実際におきた事例の紹介とL2スイッチの基本的な挙動、LinuxのARPの挙動について紹介しました。今回の事例ではサーバからみるといきなりブロードキャストし始めたようにみえるので、L2スイッチの挙動を知らないとサーバ側の調査ばかりしてなかなか答えにたどり着かないみたいなことになりがちです。ネットワークの問題かな?と思ったら丁寧にパケットの気持ちになってどうやって書き換えられていくのか、書き換える情報はどこから得ているのか、どこに送られていくのかを追ってみるのが大切だと改めて実感させられる事例でした。Linuxではブロードキャストしないようにかなり気を使って実装されているなぁという印象を受けました。なんかARPテーブルに登録しておいて時間がたったらもう1回解決するんでしょ?ぐらいにしか考えていなかったので勉強になりました。このエントリで少しでもネットワークに興味を持ってくれる方が増えてくれると嬉しいです。18:42LinuxのARPとL2スイッチのお話Tweetもっと読むコメントを書く2016-04-03株式会社はてなに入社しましたブログをはじめましたid:masayoshiです。2016年4月1日に株式会社はてなに新卒枠で入社しました。職種はWebオペレーションエンジニア職です。なんかサーバとかネットワークをいじる職種です。詳しく知りたい人は以下の本が全体的な雰囲気をつかめてオススメです。見る同期が優秀な人しか居なくて、インターン生だったり、既にアルバイトとして働いている方だったり、アメリカから半年前入社に成功している猫だったりで、「このままだと殺される」と感じたので、3月の下旬からアルバイトとして入って、ほとんど研修ですが、実質2週間ぐらい仕事をしていた感じです。何か長くなったので、上の方に目標でも書いておきます。試用期間中にクビにならないことWebサービスを支えられる技術を身につけること会社を支えられるようになること"会社を支えられるようになる"というのは、別に技術とかそういう話だけではなくて、社内で困っている人の相談に乗るとか、そういうのも含めてです。ココらへん目標とかは別のエントリにしっかり書きたいと思います。以下は見たい人用はてなの印象2週間でやったこと新卒力はてなの印象まぁ一日目で雰囲気ってなんだという気もしますが、↑に書いたようにアルバイト期間も含めての印象ってことで。一言でいうと「技術を大切にしている会社だな」と思いました。会話してて、アプリケーションエンジニアやWebオペレーションエンジニアは当然として、その他の方たちもエンジニアっぽく感じることが多いです。含んで"エンジニア"かなっと思った。いう意味で全員”エンジニア”な会社だなーというのが現在の印象です。会社用PCのセットアップ研修バイト期間中に研修をやっていました(今は社員用の研修をやってます)。はてな研修用教科書に沿ってPerlとかJavaScriptとか頑張るやつです。(同期は既にインターンやアルバイト期間に終了している..)github.com私は研究室でアルティメット雑なC言語やPythonのクソコードを時々書いてただけなので、Webアプリケーションや他人に見られるコードの書き方を全く知らない状態からのスタートです。すごいと感じたのがレビューで、アプリケーションエンジニアなのかWebオペレーションエンジニアなのかミニ四駆レーサーなのかわからない社員の方が、自分の仕事をこなしつつ、私のクソコードを丁寧にレビューし、初心者丸出しの質問に的確に答えつつ、定時か定時1時間以内に仕事を終わらせ、ミニ四駆やアニメ映画を見にいっていることです。あんな感じに他人のコードをさっと見てレビューしたり、サンプルコードとかパッと提示できるあたりにプロを感じた。Webオペレーションエンジニアはアプリケーションエンジニアに比べたらコーディング量は多くないものの、コーディングはするしミドルウェアのソースコードを読むことも多いので、プログラミング修行の必要性を感じられてよい。その社員の影響ということは全く無いですが、私もミニ四駆を買いました!技術的なアウトプットの準備はてなはエンジニアが技術的なアウトプットすることを非常に推していて、私もアウトプットしたいなと思ってたので、簡単な内容からちょくちょくアウトプットしていこうかと思います。インフラ系エンジニアの人はご存知の方も多いかもしれませんが、はてなのWebオペレーションエンジニアにはアウトプット魔神のような社員がいて、毎週「いつ記事を書くのか。今でしょ」的なプッシュをされるので早めにやっていきたいです。会社用PCのセットアップはてなでは、業務で使用するPCを個人で選択できます。大体MacBookが多いです。Capitan"にアップデートしたら色々疲弊したのと、有線LANが変換コネクタなど無しで使いたかったので、X260にしました。最初は業務用なので「DebianとかUbuntuでいいかな?」と思っていました。安定していたほうがいいし、情報量も多いほうがいいと考えたからです。CPUが新しいので、Linuxカーネルがほぼ最新(4.4以降)でないと動かない関係でDebianとかUbuntuにしても、結局unstableな感じになってしまう隣の社員はFreeBSDで、CTOはGentooを推してくるといった感じなので、脳みそがユルユルになり、ArchLinuxをいれることにしました。ArchLinuxを入れた理由は、普段使っているので慣れていることと、最新を追っている割には情報量が多いことです。Ubuntuは情報量が多いですが、あくまでstableの情報が多く、testやunstableの情報量はさほど多くないです。それに比べ、ArchLinuxはローリングリリースなので、ArchLinuxの情報は全て最新に近い情報が手に入ります。(X260の情報も既にあります。ArchWiki)業務用のPCなので、ディスクの暗号化とかをする必要があり、dm-cryptをCUIで操作しディスク暗号化をしたのは始めてだったので勉強になりました。上で書いたように、同期はアルバイトやインターン生だったので、私が一番フレッシュ感あふれて新卒力で殴っていけるのではないか?と考え、フレッシュ感を推してキャラ付けし、新しい会社に馴染んでいこうという計画を3月31日に思いついた。結果としては、「全然フレッシュ感が無い」と言われてしまった。研修でも振り返りは大事ということだったので、何がいけなかったのか振り返ってみる。自己紹介スライドを作らないうえに、発表内容もその場で考える初めに3分前出社。4月1日の私は「学生気分が抜けきれてなくて新卒感ある」という主張をしていたが、どう考えても緊張しながら絶対に遅刻しないように始業30分前にはいる方が新卒力が高い。私が出社した1分後に出社してきた1年前からアルバイトしている入社同期氏のほうが新卒っぽいと言われていたので、出社時刻が決定的新卒力の差ではないことがわかった。2つ目の発言はランチのときの発言。今見直すと何いってんのこいつ?感しかない。風が吹けば桶屋が儲かる理論で「一般家庭にもNASがある時代」「NASがあるとvmstatを叩く」みたいな流れで誤った推論をしまくった結果出た発言で、MySQLに詳しい社員とFreeBSD使いの社員がなにいってんのこいつ?みたいな顔してた。詳細はよくわからないが、隣の席で「人間ドックではなく人間Docker」みたいなよくわからなそうな話も出てたし許容範囲な発言の気がする。少なくても新卒力を高める感じはしない。3つ目は新入社員歓迎会のときの2分前出社同期氏との会話で出た発言。コンテキストを覚えてないから分からないが、私は素面で同期は酒が入っていたので、よった勢いという言い訳もできない。4つ目は3分ぐらいの自己紹介があるので準備しといてね的なことを言われ、中途採用の方や他の同期がスライドを用意している中、全く用意していなかったので、その場で考えて発表してしまった。2分前出社同期氏もスライドを用意していなかったが、発表時にスマホを片手にあたかも原稿があるかのように見せて発表していた。全体として、落ち着きがありすぎる(緊張感がない)ということが新卒力、フレッシュ感のなさに繋がっていそうというご意見を頂いた。これは"はてなという会社の文化"に自然に入れたからということな気がしないでもないので、結果的に良かったということにしておこう。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。