「おじいちゃん kubernetesってなに？」「...それはコスモスじゃよ」(1)

おはこんばんにちは
zerobillbank株式会社のインフラエンジニアtomatoことtomatoです。
ちなみにtoが苗字、matoが名前になります。

今回はkubernetesについてお話ししていきたいと思います。
よくある既存のシステムと比較しつつ、kubernetesとはなんぞやという部分を
なるべくシンプルに話していきたいなと、思っております。

## kubernetes以前のコスモス

kubernetesとは何か..を話すために、既存のよくあるシステム構成と比較していきたいと思います。
kubernetesはあくまで「拡張」なので、その根本を抑えておかないと片手落ちになってしまいますので..

### 一般的な3層クライアントシステム
![スクリーンショット 2021-02-19 11.56.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274405/c8eed94a-03e7-7e9d-c40b-91a4794d2ff9.png)

上記が一般的な3層クライアントシステムの図になります。
よく教科書にも出てくるこれですが、あくまでこう分けたら整理しやすいんじゃない？っていう
概念なので、そういうものかーと思っておいてください。

例えばAmazonのショッピングサイトを上記に当てはめると、

- プレゼンテーション層が、実際にアクセスできて商品とかが見える画面
- アプリケーション層が、買い物カートとかの裏側の仕組みの部分
- データ層が、商品の価格とか在庫とかユーザ情報とかのデータの部分

まあ超おおざっぱですが、こんな感じになるかと思います。

### 冗長性
上の図だとコンピュータ（サーバ）が6台になってると思うのですが、
「え、一台のサーバにぶち込めばよくね？」って思う方もいるかなーと、
これに関しては確かに1台のサーバでも動作するんですが、その場合

- その１台のサーバが落ちたらサービスが停止する
- 更新作業で再起動や停止時間が必要な場合、サービスが停止する
- マシンのリソース（CPU,メモリ,HDD容量など）が限界を迎えた際、カタストロフィーが訪れる

などなど、現実に運用していくには色々と不都合が起こります。
もちろん商用利用せず、サービス停止しても大丈夫ーな場合とかは1台でも動作はできますよ。

そのため、実際のシステム運用ではこの冗長性というワードが避けて通れないものになってきます。
kubernetesにおいても重要なキーワードになってきます。

で、上記のように6台に分けている理由ですが

- 層ごとに分けることでメンテナンス性をあげる（部分的な更新のしやすさ）
- ある層に負荷が集中した場合の、スケールアウト（サーバの追加）やスケールアップ（サーバのアップグレード）を容易にする
- 障害が起こった際に全体に伝播することを防ぐ

などなど色々な目的があります。
ですので、実際にはこの３層を基本にさらに層を細分化したり、
サーバの台数を増やしたりして運用しています。

サーバの部分は、オンプレミス（自社サーバ）であれば物理的なコンピュータだったり、クラウドであれば仮想的に分けたコンピュータだったりします。
基本的にはスケールアウト（サーバの追加）やスケールアップ（サーバのアップグレード）を行うことで、
全体の稼働率は上がりますが、同時にコストも上がるのでこの辺りはトレードオフになります。

## サーバ型の問題点
上記がkubernetes以前のコスモスになります。
これはシンプルでわかりやすいコスモスなんですが、実際に運用していくと下記ような問題も見えてきます。

#### 1. サーバのリソース計算が難しく、コストが最適化されない

例えばプレゼンテーション層のサーバは負荷が高く、アプリケーション層のサーバは負荷が低い..なんてことはよくあります。
プレゼンテーション層のサーバ２台の平均使用率は80%だけど、アプリケーション層のサーバ2台の平均使用率は20%だ..なんて場合です。
この場合でも可用性の観点から、アプリケーション層のサーバを1台にすることは危険なため、プレゼンテーション層のサーバを3台に増やすことになります。
またどのサーバがどれだけ使われるかというのは、もちろん事前に予測を立てるわけですが、
実際にどれだけ使われるかはサービスインしてみないとわからないわけで、事前に正確な予測を立てることは難しいです。

特にオンプレミス（自社サーバ）で稼働している場合、サーバの調達には時間もコストもかかりますので、簡単にはできません。


#### 2. 運用が大掛かりになりコストが結構かかる

特に24時間稼働しているサービスでは、いつでも障害に対応できるように24時間365日で監視したりの対応が必要になります。
大掛かりなプロジェクトであれば、このあたりの運用監視をする部隊が社内でもしくはアウトソーシングで存在しています。
どこかのサーバのプロセス（アプリケーション）が落ちている！みたいなことになれば
深夜であろうと容赦無くアラートが鳴り響き、現場に駆けつけて障害対応しなければいけないわけです。
すぐ直ればいいですが、原因不明のエラーとかの場合、現場は阿鼻叫喚、混沌と終焉のコスモスです。
で、このサーバやプロセスの不具合は思ったより多く起こります。ﾎﾞｸﾅﾆﾓｼﾃﾅｲﾉﾆ..

あと、OS設定やアプリのバージョンなど、サーバごとに環境を揃えるのだけでも一苦労で、
大掛かりなプロジェクトはOS設定のスペシャリストや、特定のアプリのスペシャリストがいたりします。


まだまだある気がしますが、思いついたら追記のスタイルでいこうかと思います。

## kubernetesというコスモス
![スクリーンショット 2021-02-19 13.01.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274405/708554bc-6007-8b61-75fc-4e0326ec19d9.png)

突然ですが、上記のサーバモデルをkubernetesに置き換えてみました。
実際にはもうちょっと細かいんですが、まずは概念を理解するためということで、細かいところには目を瞑ってくだせえ。

ここで重要なのはサーバがnodeとpodというものに置き換わっていることです。
たったそれだけのことですが、それが革新的な違いになるんですよね..
ちなみに3層クライアントシステム自体は概念ですので、kubetenetesにおいても有効です。

### おじいちゃん nodeってなに？
nodeはサーバ（コンピュータ）だと思ってOK
ただ少し違うのは、kubernetesではnodeをサーバ群として扱っていて、
<b>ただのリソース提供元</b>だと思っていることです。
前述のサーバ型では一台一台のサーバが明確に区別されたことに比較して、
kubernetesではサーバがリソースのグループとして認識され、あまり明確に区別されていないです。
上記の図だと、3つのサーバを1つのnodeプールとして捉えていて、
例えば1台につき２GhzのCPUを搭載していたら、プール合計で6Ghz分になるじゃん！っていうイメージです。
どのサーバの1Ghz分を使います！とかは明確ではなく、空いてるところから選んで使うよーっていう感じです。

ちなみにnodeの管理に関してはkubernetesの基本機能というよりも、クラウドでのマネージドの機能という側面が強いです。

### おじいちゃん podってなに？
nodeがリソースの提供元だとすると、podはリソースの提供先になります。
例えばプレゼンテーション層の「HTMLを表示するpodくん」は、
HTMLを表示するだけに必要なリソース（CPU,メモリなど）をnodeに要求します。
nodeはその要求にしたがって、podくんにリソースを割り当てます。

こうすることによって、サーバのリソースを無駄なく使えるわけです。

podの中身はDockerコンテナという技術を使ってます。
これについて説明すると本一冊分くらいの容量になるので、細かい部分は省きますが
Dockerの中でOSの設定とアプリが定義されていて、いつでも同じ環境で動作することが可能になるシロモノだと思ってください。

### ここがすごいよkubernetesさん

上記を踏まえてkubernetesのすごいところをまとめていきたいと思います。

#### 1. 自動リソース割り当て
これは上記のnodeとpodの関係でも触れていますが、
node(サーバ)をリソースとして捉え、そのリソースをpod(アプリ側)でどう使うか
というところに思考をシフトしたところが、革新的なコスモスです。
これによってサーバの物理的な境界を意識することなく、
<b>リソースが許す限りアプリケーションを使う</b>というシンプルな挙動が可能になりました。


#### 2. 自動増殖
kubernetesの目玉機能といえばこれじゃないでしょうか。
上記のnodeとpodは利用状況に応じて、アメーバの如く<b>自動的に増減</b>します。
例えば、プレゼンテーション層の「HTMLを表示するpodくん」の負荷が高くなれば、
自動的にpodの数を増やしてスケールアウトします。
podの数が増えすぎてリソースが足りなくなれば、nodeが自動的にスケールアウトされます。（クラウドなどのマネージド側の機能）

ですので、何かのニュースに取り上げられて瞬間的にアクセスが上がった！とか、
繁忙期と閑散期でアクセス数に差があるんだよなぁといった場合でも、
nodeやpodの数を自動でいい感じに調整してくれるので、運用が非常に楽です。
もちろんnodeが増えすぎてしまうと、その分コストがかかるので、
nodeやpodを幾つの間で増減させるかは、設定が可能です。うーん控えめに言って神コスモス。

#### 3. 自己修復機能
これはDockerの特性とも取れますが、アプリに何か異常があった場合
kubernetesではそのpodを終了させ、新しいpodを立ち上げなおします。
これによって、podは常に指定されたあるべき姿でコスモスに凛然と輝き続けるわけです。
同時にシステム運用の手間を大幅に削減してくれます。うーん控えめに言って神コスモス。

## サーバ型の問題点をkubernetesに当てはめてみる
最後に前述のサーバ型のモデルの問題点をkubernetesに当てはめてみます。

#### 1. サーバのリソース計算が難しく、コストが最適化されない
これについてはkubernetesによって解決されると言って良いでしょう。
前項の通り、node(サーバ)をリソースとして捉え、そのリソースをpod(アプリ側)で使うという設計ですので、
リソースに応じてアプリケーションを展開することが可能です。
そのため全体のサーバ数を縮小することが可能です。
状況にもよりますが、サーバ10台前後のシステムであれば、kubernetesだと3-4ノードくらいで実現できるのではないでしょうか。
もっともAWSやAzureなどのマネージドのkubernetesであればnodeの自動増減が可能ですので、
このあたりはあまり気にする必要もないかもしれません。

#### 2. 運用が大掛かりになりコストが結構かかる
ここについてはkubernetesを導入しても完全にカットすることはできません。
kubernetesを導入していても、システム障害が起こる可能性がある以上、運用監視は必要だからです。

とはいえ、運用監視の手間は大幅に減らすことができます。
podのスケールも自動でやってくれるし、podが再起動されることで防げる障害であれば自己修復してくれるからです。
弊社でもkubernetsを導入して1年以上経ちますが、kubernetsのシステム由来の障害はほぼ起きていません。

またサーバのOSの設定とアプリについては、dockerファイルで定義しておくことで不要になります。
この辺りの設定は思いのほか工数がかかるので、削減効果は大きいです。

### kubernetesのデメリットについて
ここまで、基本いいことばかり書いてきましたが、もちろんデメリットもあります。
代表的なものは学習コストでしょうか。
kubernetesは概念そのものが従来のサーバ型と異なるため、どうしても理解に時間がかかります。
kubernetes自体もまだまだ成熟途上のため、エンジニアが少ないです。

とはいえデメリットは学習コストと移行コストくらいの気がしますねー..
あとサーバ1,2台で運用できるような小規模なシステムであれば、
わざわざkubernetesで組む必要はないかもですね。どちらかといえば大規模システム向けなので。

## さいごに
というわけで第一回は、kubernetesの概念的なものを中心に書いてみました。
次回は、実際のデプロイについてお話しできたらなと思います。

ではまた🙋‍♂️

ZEROBILLBANKでは一緒に働く仲間を募集中です。
なんとかjsとか、ブロックチェーンとか、kubernetesとかでいろんなAPIを作るお仕事。
今のところエンジニアは5人くらい。スタートアップだけど、結構ホワイトで働きやすいです。

[ZEROBILLBANK JAPAN Inc.](https://zerobillbank.com)