ざっくりと理解するマイクロサービスアーキテクチャ / DevOps / コンテナ

#はじめに
マイクロサービスやDevOps、コンテナという言葉をよく聞いていると思います。
私自身、それぞれの意味については漠然と理解はしていたものの、「なぜマイクロサービスとDevOpsが関係するのか」、「コンテナとはどのように関係しているのか」のようなそれぞれの関係がなかなか理解できずにいました。

ここでは同じような境遇の方々に少しでも理解の一助になればと思い、ざっくりとしたそれぞれの関係性(持論)を説明しようと思います。

#マイクロサービスアーキテクチャとは
まずざっくり説明すると、マイクロサービス(アーキテクチャ)とは「複数の規模の小さな機能を組み合わせて1つの大きなアプリケーションを構成」する「ソフトウェア開発技法のひとつ」です。
マイクロサービスと対になる技法 / 考え方に「モノリシック」が挙げられます。
「モノリシック」は「依存関係のある複数の機能を組み合わせて1つの大きなアプリケーションを構成」します。
両者の決定的な差としては「それぞれのコンポーネントが独立しているか、依存関係にあるか」の違いだと私は理解しています。

マイクロサービスでは機能が独立しているので、各サービス/コンポーネント間はAPIを呼び合うだけの関係であり、互いに依存関係はありません。

この特性によるメリットとして、以下が挙げられます。

・試験的なデプロイやコードの更新が容易であり、迅速に新機能を反映できる
・各サービスを個別にスケーリングできるため、コストを抑えた対応ができる
・サービスの再利用が可能であり、共通するモジュールを多機能から移植できる

マイクロサービスのメリットを挙げるとキリがないのでひとまずこの辺かなと思います。

「マイクロサービスについてはだいたい分かった。それがどのようにDevOpsと関係するんだ！」
と思われてる方もいるでしょう。
先にざっくり説明してしまうと、DevOpsはマイクロサービスを実現するにあたっての最善手と言えます。

詳しくは次の章で説明します。
#DevOpsとは
そもそもDevOpsには、これといった厳密な定義は存在しません。人によって考え方が違うんですね。なのでググってみても人によって微妙に捉え方が違うと思いますが、大まかには以下の三パターンかなと思います。

・開発と運用の協業という組織文化のこと
・迅速かつ柔軟なサービス提供を行うための考え方及び仕組み
・自動化ツールの適用のこと

ほほぅ。結構幅広いこと言っちゃってますね。組織文化であったり、仕組みであったり、はたまたツールの適用のこと自体を指したりしちゃってますね。

まぁいきなりこの三パターンです！と言われても理解しにくいと思うので、今度はそもそもの語源から紐解いてみましょう。

何となくお察しだと思いますが、DevOpsは「Development(開発)」と「Operations(運用)」を組み合わせた造語です。

ここで少し考えてほしいことがあります。もしあなたがアプリ開発チームに所属しているとして、チームのゴールとしてはいったい何が考えられるでしょう。
きっとユーザー満足度の高いアプリをどんどん世に出していくことがゴールだと思います。
そして今度はそのアプリを運用する運用チームの気持ちに立ってみてください。
きっと彼らのゴールは満足度の高いアプリをどんどん世に出していくということよりも、とにかくバグらないように、安全に確実にアプリ運用をしていくことをゴールにしているのだと思います。
なので開発後の運用のことを気にせずじゃんじゃんアプリをリリースされてしまうと運用チームは非常に困るのです。

そうです。このように開発チームと運用チームのゴールは似て非なるものであり、各チームのゴールだけを切り抜くと利害関係が一致しません。
しかし、会社としてのゴールは一つで、満足度の高いアプリをハイスパンでリリース、そして安全かつ確実に運用をしていくということがゴールのはずです。

あ、、もうお分かりですね。
この両者の利害関係を超えてOne teamで協業するために、それにはSlackのようなコミュニケーションツールを使ってコミュニケーションを促進してみたり、更にはこれを一度だけでなく継続的に行うための仕組みやルールを作ってあげたり。。。
と、これがDevOpsということなんですね。(なんと漠然な。。)

マイクロサービスでは各コンポーネント同士に依存関係がなく分断できるため、それぞれのコンポーネントごとにチームを組んであげ、開発から保守運用を一貫して担当させるといったアプローチが取りやすいです。
そうすることで開発、保守運用がOne teamになり満足度の高いサービスを短期間で、そして安全に運用するという一つの目標に集約することができますね。

DevOpsを実現するにはアジャイル開発、CI/CDツールを使って実現することが主なので、以下簡単に説明します。

##アジャイル開発
アジャイル開発を説明するのには従来型のウォーターフォール開発との比較が一番分りやすいと思います。

ウォーターフォール開発では要件定義、設計、実装、テスト、運用といったフェーズを厳密に取りまとめてから開発します。また、開発途中での変更を想定しておらず、原則後戻りはしません。(まさに滝のようですね。)

一方、アジャイル開発はというと大枠だけを決めて開発をじゃんじゃん進めます。あらかじめ失敗やエラーを想定しているので、開発途中での変更や機能追加を想定しています。兎にも角にもクイックに手を動かしていく、課題見つかる、そしてブラッシュアップするといったサイクルをぐるぐる回すことを何度もすることで開発していく手法です。

DevOpsと親和性の高い開発手法になります。

##CI/CD
CI/CD(Continuous Integration/Continuous Delivery)とは、日本語に訳すと継続的インテグレーション/継続的デリバリーです。
、、、って何？って感じですよね。(日本語訳の方が分からんみたいなこと結構多いですよね。)

簡単にいうと、ビルドやテスト等の作業を自動化し、一度のみならず継続的に実行する仕組みのことを指します。
また、冒頭DevOpsの説明であった自動化ツールのことを指しています。(企業がDevOps実践しました！という文脈の時は、このCI/CDツールの導入を指していると思います。)

そして、CIとCDの違いですが単にどこまでのプロセスをカバーしているかだけのことです。
CIはざっくりとCode,Build,Integrate,Testまでのことで
CDはCode,Build,Integrate,Testから更にRelease,Deploy,Operateまでのデリバリーまでを含められています。

CI/CDツールとして有名なのはJenkinsかなと思います。
Jenkinsの大まかな流れとしては以下です。

開発メンバーがソースコードをGitHubのようなバージョン管理サーバにコミットしたらJenkins君が動きます。このJenkinsは色んな自動化ツールを操っていて、ビルドの実行を勝手にしてくれたり、単体テストの実行や、設定によってはテスト環境へ勝手にデプロイまでしてくれます。
開発者はビルドOK、単体テストOK、デプロイOKみたいな通知を受け取って、あとはJenkins君にThank you buddyとコマンドで伝えてあげればOKです。(嘘です。)

これもまたDevOpsと親和性の高い考え方/ツールです。

#DevOpsまとめ
開発手法面でのアプローチとしては、計画から開発、テスト、運用までのプロセスを迅速に繰り返すアジャイル開発を。ツール面のアプローチとしては継続的にビルド・テスト・デリバリーを繰り返すCI/CDを。この二つによって迅速かつ柔軟なサービス提供(=DevOps)を実現するというお話でした。

開発手法もツールも、仕組みも分かった。それではもっと下層レイヤーの技術はどうすればいいんだ。起動処理遅かったり、コンポーネント毎に分けたチームで僕の環境では動くけど、あなたの環境では動かない。みたいなことが起きたら迅速かつ柔軟なサービス提供なんかできず、本末転倒じゃないか。
みたいな声が上がりますよね？(希望的観測)

鋭いご指摘ありがとうございます。そうです、今あなたが思ったことを解決してくれる技術がコンテナと呼ばれる技術です。
次の章で解説します。

#コンテナ
いきなりコンテナを理解しようとするとIT特有の横文字無理～みたいな拒否反応が起こってしまうので、一度物流業界のコンテナを考えてみましょう。

物流業界のコンテナとは、貨物を積む規格化された箱であり、世界標準規格化されているものです。(個人的にはものというより概念だと思っていますが、。)

これにより、
じゃがいもinコンテナ＠中国、輸出
→じゃがいもinコンテナ@アメリカ、輸入
→中身をとうもろこしと入れ替えinコンテナ@アメリカ、輸出
→とうもろこしinコンテナ@ドイツ、輸入
→中身をキャベツに入れ替えinコンテナ＠ドイツ、輸出
→キャベツinコンテナ＠日本、輸入

のようにコンテナを返す必要はなく、中身を入れ替え使いまわすことができます。

また、工場からトラックinアメリカ→港について船fromアメリカ→港について鉄道from日本→仕分け場についてトラックin日本

みたいな陸海一貫輸送も実現できています。

物流業界のコンテナとは、容器を規格化することで環境(国や輸送手段)にとらわれない高可搬性を実現することを可能にしました。

IT業界のコンテナも同じような考え方です。
アプリケーションをカプセル化し、その土台(コンテナエンジン)を規格化することで環境(OS)に依存しない高可搬性を実現可能にしました。

この特性による代表的なメリット二点を挙げてみます。

まず一点目はリソース効率が良いことです。
今までのVM型仮想化では、ホストOSの上にゲストOSを立ち上げその上でアプリを起動していました。
ゲストOSにはある程度余分なリソースを割く必要があること、またアプリの起動停止に伴いゲストOSの起動停止をしなければなりません。
コンテナの場合、ホストOSの上にコンテナエンジンを立ち上げ、その土台の上でアプリを立ち上げます。
ゲストOSがないことにより、リソースを大幅に節約、またアプリの起動停止が高速ということが一点目のリソース効率の良さです。

二点目に高可搬性が挙げられます。
開発メンバーのPC上やサーバー上でコンテナエンジンをかまし、パッケージング化されたアプリ(コンテナイメージ)を動かすので、どの環境でも動きます。
これにより「僕の環境では動いた」問題が発生しません。

以上がコンテナの説明でしたが、もう少し話さなければならないことがあります。
それがKubernetesです。

もしもコンテナの数が500～1000個と増えていったら、どうしましょう。
・コンテナのスケジューリング
・ローリングアップデート
・コンテナの死活監視
・サービスディスカバリ
・データの管理 etc

上記の項目を手動で管理する必要があり、現実的ではありません。

これを自動で管理してくれるのがKubernetesのようなコンテナ・オーケストレーションツールです。
次の章で説明します。
##Kubernetesとは
コンテナ管理を自動で行ってくれるOSSであり、コンテナ・オーケストレーションのデファクトスタンダートと言われています。

Kubernetesのメリットを説明すると少し専門的な話になるので、分かりやすいメリットを挙げてみます。
まずはスケジューリングです。
あらかじめアクセスが集中すると分かっている時(例えばECサイトのセールや毎週月曜クーポン配布のような定期イベント等)、にコンテナを自動的に配置してくれます。
またコンテナは揮発性であるため、集中したその次の日とかには勝手に消えてくれるため、リソースの有効利用を実現することができます。

また、ロールアウトとロールバックもメリットとして挙げられます。
アプリケーションのアップデート時、旧バージョンのコンテナを動かしたまま、新バージョンを移植できます。
それによりサービスを止めないでアップデートすることができます。
アプデ中に新しいバージョンができた方にリクエストが飛んできた場合、自動的に新バージョンにリクエストが飛ぶようになります。
(まぁ全部CLIでいじらなきゃいけないので勉強しなきゃいけませんが、、)

#おわりに
ひとまずバッと説明してみましたがいかがだったでしょうか。
この記事は正確に書くということより、少し誤りがあっても分かりやすくということで書いてるので、有識者の人からすれば全部分かっとるしちょこちょこ間違っとるわ！と言われてしまいそうですが。。

兎にも角にも、みなさんの理解の一助になれば幸いです。
最後まで読んでいただきありがとうございました。