DevOpsとはなんだ

# はじめに
弊社(株式会社Works Human Intelligence)では、若手への研修として[Schoo][1]という「いろんな内容で1時間くらいの授業をしてくれる」サイトの1ヵ月見放題権利を渡しています。
そこで、せっかくですから私もこれを機に適当にやりすごしていたIt知識をしっかり学びなおそうと思いまして、手始めに見た動画が以下になります。

[DevOps -歴史から学ぶ本質とその未来-][2]

1時間ほどの動画なのですが、DevOpsというあいまいな定義を背景から説明してもらえることで、予備知識の少ない私でも理解しやすいものとなっていました。
そこで、今回はこの動画の内容を簡単に振り替えられるようにまとめなおそうというのが本記事の内容になります。

# DevOpsとは
厳密な定義などないあいまいな概念。
もともと、開発開始から顧客が使えるようになるまでのプロセスを高速に行えるようにしたいという考えの元、それを実現するためにこう考えるべきという考え方、活動の大きな枠組みを指す。

# DevOpsのメリット
DevOpsプラクティスがITパフォーマンスを改善するという前提の元、ITパフォーマンスの改善には以下のようなメリットがある。

・ITパフォーマンスの良さが競争力につながる
・30倍速くコードをデプロイできれば、200倍短いリードタイムを達成できる
・60倍障害が少なくなり、108倍速く復旧できる。

一例だが、DevOpsを実現すれば50台のAPサーバーと30台のDBサーバーを一人でメンテナンスすることが実際に可能だという。

# DevOpsが始まるまでの歴史
開発の課題として「リリースサイクル改善」というものがある。
これは「早く」「頻繁に」「安全に」エンドユーザーの元へ製品を届けるということを目的としているものだ。

#### 一般的開発　（要件定義→設計→開発→テスト）
これらを普通に順に実行していくと、開発開始から顧客への提供まで1-2年かかっていた。

#### アジャイル開発　（小さい規模で一般的開発を繰り返す）
そこで、一般的開発をもっと短いサイクルで、1-2週間に1回くらいの速度で繰り返す開発手法としてアジャイル開発というものが使われ始めた。
しかし、そう簡単なものではなく、これだけをやろうとするとせいぜい1サイクル当たり半年程度までしか短くできなかった。
これは、1-2週間で作った機能をいきなり本番環境にデプロイするのは難しく、開発の後に様々な種類のテストを繰り返したり手戻りがあったりということが発生するためだった。

#### 継続的デリバリー　 (テストと開発プロセスの並列化、テストの自動化)
アジャイル開発では開発プロセスの後にテストのタイミングが発生することで1サイクル当たりの時間が伸びるという問題があった。
そこで、Sprintという単位で開発とテストを並列でおこなうこと、そしてある程度のテストを自動化して常に実行し続けるようにすることで、その問題を解決しようとした。
しかし、これだけでもうまくいかなかった。
エンドユーザーに製品を提供するためにはもう一つ、製品をインフラに引き渡して本番環境上で動くようにしてもらうというプロセスが必要だった。
ここでもアジャイルと同じように作業や手戻りが発生し、思ったよりも長くかかってしまうことになった。
また、インフラについては物理的な資産を用意し構築するという手順が必要で、内容もほぼ手作業という状態であり、さらに根深い問題となっていた。

#### DevOpsの誕生
前述の状況を打破するため重宝されたのが以下3つの概念である。

　・アジャイル
　前述したように、アプリを早く作る考え方

　・インフラ自動化技術
　Ansibleなどの構成管理ツールを使ったインフラ作業を自動化するという考え方（Infrastructure as Code）

　・WebOperation
　クラウドの時代、サーバーなどをAWSなどをつかって仮想化するということが始まり、物理的な機器の調達などを行っていた時代からWeb上で完結する時代への変化

この3つの概念によって、「Agile Infrastructure」という考え方が提唱されることとなる。
これが後のDevOpsと呼ばれるものになっていく。

#### DevOpsの原型
ある時、1日10回デプロイするために必要な考え方として発表される。
ここで初めてDevOpsという言葉が使われることとなる。

[10+ Deploys Per Day: Dev and Ops Cooperation at Flickr][3]
・自動化されたインフラ
・共有されたバージョン管理
・ワンステップビルドとデプロイ
・フューチャーフラグ
・共有されたメトリクス
・IRCとIMボット

#### この時点でのDevOps
・開発とインフラが協力してソフトウェアライフライクルを改善する活動
・ソフトウェアのプラクティスをインフラ運用に応用
・具体化された内容ではなく、考え方が重要
・誰も明確な定義を持っていない

<details><summary>saito_ryの感想</summary>
このあたりで「DevOps完全に理解した」感が自分の中ですごいでましたね。
歴史から追うとめっちゃわかりやすい。
</details>

#### 現在のDevOps
ビジネス・DEV(developer)・OPS(Operater)が協力し、ソフトウェアサイクルを改善してビジネス価値の創出を改善する活動

今では経営やセキュリティ、営業などのビジネス側の人間も交えた概念となっており、以下の本がDevOpsにおけるバイブル的な存在となっている。
技術書というより小説仕立ての内容なので興味があれば気軽に読んでほしい。
[The Phoenix Project][4]

結局デプロイするのに誰かの承認を得るとか、ボトルネックとなるのは技術的部分だけではない。
様々な関係者全員で10デプロイ/Dayを実現するのだという話。

# Microsoftが考えるDevOpsの実現方法

## 悪い状況
開発者が開発したものを、インフラに乗せて問題ないかどうかもわからずインフラ運用者に丸投げする。
このような状況下では信頼関係は構築されず対立を生み、何より動かない開発物に工程の巻き戻しをされるという時限爆弾をうみかねない。

<details><summary>saito_ryの感想</summary>
めっちゃわかる。
僕はもともと製品をお客様が所有するサーバに適用に行くフィールドエンジニアだったので、開発ふざけんなと思っていたことは記憶に新しいですね。
上手くいかないと開発に問い合わせするんですけど、こっちはお客様の前でめっちゃにらまれてるのに開発の返事は一次回答すらなかなかこなくてめちゃくちゃイライラしたりとかね。
自分が製品開発側にいたときはお客様からちょくせつ問い合わせもらって直接対応するなんて言うこともしてたのであれなんですけど、現場と執務室の温度感の差がありありわかるので余計いらつくというかね。
いや、前の会社にいた時の話ですけどね。
</details>

## 重要な3要素
DevOpsを実現するためには以下の3つの要素が必要である。

・People 考え方
・Process　やり方
・Products　技術

このうち、peopleは前述の内容を把握してもらい、productsの紹介は難しいため、processについて重点的に説明する。

## Process
DevOpsは以下の手順で開発が進む。

[開発環境]
　1.計画
　2.開発とテスト
[本番環境]
　3.リリース
　4.モニタリングと学び

### なぜリリースを高速に繰り返さなければならないのか
このうち、リリースを何度も高速に行える体制を作るというのがDevOpsの原型であると話してきた。
では、なぜリリースを何度も素早く行いたいのか。
それは、戦略はあくまで仮説にすぎず、高度な柔軟性を保ちつつ臨機応変な対応が必要であるという考え方があるからである。

いままでは戦略を立てたら中長期的に継続して結果を収集していたが、そのようなやり方をしていてはもし戦略が間違っていた時に多くの時間とリソースを失ってしまう。
だからこそ、どんなに小さくともまずすぐ顧客の触れられるところに製品を出し、フィードバックを収集し、計画を立て直すというサイクルを高速に回す必要がある。

### 開発とテスト
計画部分はともかく、開発者がDevOpsにおいてしっかりとやらなければならないのがこのプロセスである。

・コードを書く
・ユニットテスト
・バージョン管理
・ビルド
・ビルドの検証

開発者はいきなり本番コードを書くのではなく、まずテストのコードを書き、それに合わせて動くように本番コードを書く。
これをTDD、テスト駆動開発（Test-Driven Development: TDD）という。
こうすることで、テストコードによる自動テストを繰り返し自動的におこなえるようにしていき、開発とテストのプロセスを並行して進めることができるようになる。
（とはいえ完全にテストから書くというより、最初に動くもの作ってなんとなく把握してから「よしテスト書いて本番書くか」で全然いいらしい）

<details><summary>saito_ryの感想</summary>
私はどちらかというとインフラ運用側になる、まぁインフラ名乗れるほど精通していないのでSRE、クラウドエンジニアということになると思うのですが、私たちは正直TDDではないですね。
普通に動くもの作って、自分でテストして、レビュアにコード見てもらったらマージ後即デプロイします。
なんでかというとエンドユーザーが自分だからなのかなと思います。
自分で使うインフラ作業自動化コードをデプロイしたとして、問題があったら自分で調査して修正できますからね。
とはいえ製品側になるとそうもいかないと思うので、DevOpsという枠組みの中にいたとしてもここは自分の立場によって多少変わる部分なのかなと勝手に解釈してます。
</details>

#### 継続的インテグレーション（Practice）
さきほどユニットテスト用のコードを書いておくという話をしたが、これはこのために書いているものになる。
継続的インテグレーションとは、コード（リポジトリ）に対して変更があった場合、自動的にビルドして先ほどのテストを実行してくれるという仕組みのことである。
これにより、もしも変なコードを書いたとしてもすぐに用意されたテストが実行され、そもそも動かないという変更を加えることを早い段階で防止してくれる。

### リリース
実際に本番環境に適用されるまでに、多くの環境を経由して様々なテストが行われる。

・テスト環境（開発者個人レベルのテスト）
・統合テスト環境（Sprint単位の修正を交えたテスト）
・プリプロダクション環境（クラウド負荷テスト）
・ステージング環境（顧客のデータと連携したテスト）
・本番環境

#### 継続的デプロイメント（practice）
先ほどの継続的インテグレーションが成功すると、こんどはそれを別の環境にデプロイして自動的に
Sprint単位でのテストを行ったり、それらの修正をもっと上の環境に自動的に適用したりということを行う。
これくらいテストが勝手に通るようになると、ある程度安心して本番環境に適用できるようになる。

<details><summary>saito_ryの感想</summary>
インフラ作業自動化のためによくjenkinsってツールを使うんですけど、これが良くCI/CDツールっていわれるんですよね。
そうでなくてもCI/CDって単語はよく使われるんですけど、これがつまり継続的インテグレーションと継続的デプロイメントをまとめて指した単語になります。
はえーなるほどってなりますよね。
こういう概念はDevOpsというよりはアジャイルくらいのころからあったようなんですけど、僕はそもそもアジャイル開発とDevOpsって別物として認識してたんですよ。
組織の運営手法と開発チーム単位での運用手法でしょみたいな雰囲気だったんですけど、こうして歴史的経緯を踏まえてDevOpsを知ると全然印象変わりますし、CI/CDってなんやねんみたいな話とかがここまで学んできた知識と一気に紐づいていく感覚すごいいいですよね。
</details>

#### Infrastructure as Code（practice）
設定ファイルみたいなものを書くと各種サーバーに対して自動的にファイル配置や設定などのインフラ作業を行ってくれる。
これを行うときのポイントとして、設定ファイルを書いたらかならずgitなどでバージョニングしておくこと。

<details><summary>saito_ryの感想</summary>
弊社はyamlという形式で設定ファイルを書いて、JenkinsでansibleというyamlをもとにIaCを実現してくれる構成管理ツールを使ってこれを行っています。
もちろんサーバーはAWSを使って仮想化してあり、いうなればインフラの調達からセットアップまでをansibleですべて自動的に終わらせているという感じです。
さらに製品を適用する作業もjenkinsとansibleで自動化されていますし、その他細かい作業も全部自動化してます。
僕はもともとフィールドエンジニアだったので、このあたりが全くない完全手動で製品適用をするという仕事をしていたので、このチームに入ってAnsibleとCloudに触れたときは感動しました。
反面、こういう作業を全部自動でやるからこそサーバー内での作業っていうのが苦手になるんですよね。
手動でやる手順がどうなってるかわからなかったり、そもそも機器を自分で調達していたりするからこそ把握しているインフラの基礎的な知識が不足したりだとか、トラブルシューティングになると顕在化しやすいんですけど、そういう懸念点があったりします。
だから私はインフラを名乗れない、やっていることは近いようで、必要とされる知識がまるで違うんですよね。
んでこれねー、確かにコードっぽいものはかくんですけど、結構簡単なものなんですよね。
まぁ開発経験が薄い僕がなんとかやっていけているくらいなので本当にそんなものなんですが、要するに開発とも言い切れないんですよね。
アプリケーションエンジニアってもっとアルゴリズムとか数学的知識が強く生きる難しい実装をされているかと思うんですけど、構成管理ツールとかJenkinsのpiplineだとかを書くっていうのはそこまで難しいものをやるわけではないんです。
クラウドエンジニアとかSREとか格好いいし、開発・インフラどっちも触れますというと聞こえはいいんですが、どっちも本職レベルではないというか、AWSとかクラウド周りに多少詳しいというのがバリューにはなるけど、開発者としてもインフラとしても満足はできないという難しい立ち位置になります。
なので、それぞれの本職からめっちゃ優秀な人が集まりやすい反面、アプリやりたい人とかは離職率も高くなるなーという印象があるというのも面白いところでしょうか。
何の感想だこれは。
</details>

#### 仮設駆動開発
NetFlixとかが使っている手法だが、わざと本番環境でテストしたり問題を起こしたりする。
もし環境がエラー対処も含むインフラ作業が自動化されているのなら問題ないはずだから、やったっていいのだ。
こんなことができてしまうのがDevOpsのすごいところだ。

<details><summary>saito_ryの感想</summary>
BtoCならいいけどBtoBはさすがにできない説。うちはできない。
とはいえ、私も故意にぶっ壊された環境復旧をやりなさいといきなり訓練で飛んできて対応した経験がありますけどね。さすがに本番環境じゃやらないですね。
</details>

## DevOpsプラクティスのリスト
詳細な解説は省くが、メジャーなプラクティスの一覧を置いておくので参考にしてほしい。

・Infrastructure as Code
・継続的インテグレーション
・継続的デプロイメント
・自動化されたテスト
・リリースマネジメント
・アプリケーションパフォーマンス・モニタリング
・負荷テストとオートスケール
・可用性のモニタリング
・変更/構成管理
・フューチャーフラグ
・自動化されたデプロビジョニング
・セルフサービス環境
・オートリカバリー
・仮設駆動開発

<details><summary>saito_ryの感想</summary>
いわれてみるとうちだと以下は意識したことがありますね。
なんとなくどんなことやってるかはわかります。
それ以外はあるような内容な...というものもあれば、製品側用の話だなというのもあればという感じでしょうか。

・Infrastructure as Code
・継続的インテグレーション
・継続的デプロイメント
・自動化されたテスト
・アプリケーションパフォーマンス・モニタリング
・オートスケール
・変更/構成管理
・オートリカバリー

意外と知っているようで知らなかったDevOps、面白かったです。
</details>

##　おすすめ勉強対象
自分の立ち位置に合わせて調べてみよう。

Dev
テスト駆動開発
継続的インテグレーション
継続的デリバリー

Ops
Infrastructure as Code
無駄の特定と可視化（コスト削減）
運用改善と自動化

Manager
The Phoenix Project
上位マネジメントへの請求
推進WG設置
パートナー選定試行

<details><summary>saito_ryの感想</summary>
私はこの中ではOpsの人間だと思いますが、うちは余裕でOpsは継続的インテグレーション、デリバリーの部分もカバーしていますね。（チーム内で担当はわかれていますが）
それを加えればOpsの勉強範囲も十分かなと思います。
ちなみに僕は「運用の改善と自動化」にかなり特化している人間ですね。
Infrastructure as Codeで学んだことを生かして運用を自動化していくってことしかむしろしてないです。
自分でここ面倒だなっていうところを見つけて上司に報告して、自分で自動化して自分が楽をするという、自分の仕事を楽にして評価される素晴らしい働き方をさせてもらってます。
なのでもし自分がDevOpsで働くとなった時、これらすべてを理解していなければならないというわけではないと思います。
だからあまり気負わずに、とりあえずそれぞれのポジションについたら1つ目の奴だけ勉強しておいて、あとは自分の立場に合わせてキャッチアップでいいだろうなとは思いました。
</details>

[1]:http://corp.schoo.jp/service/
[2]:http://schoo.jp/class/2834/room
[3]:https://www.slideshare.net/jallspaw/10-deploys-per-day-dev-and-ops-cooperation-at-flickr
[4]:https://www.amazon.co.jp/dp/B00MGGW9MI/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1