Airbnbの事例に学ぶKubernetesとマイクロサービスのあり方 @ KubeCon Seattle 2018

# はじめに
こちらは、[ZOZOテクノロジーズアドベントカレンダー](https://qiita.com/advent-calendar/2018/zozo_tech) 20日目の記事です。
KubeConに参加したSREチーム所属のへっぽこエンジニア@inductorが、2日目のKeynoteであるAirbnbの事例をみて学んだことをまとめます。

KubeConの当日の様子は、[僕個人のブログ](https://inductor.hatenablog.com/entry/2018/12/15/210650)や、[弊社テックブログに後輩がまとめています](https://techblog.zozo.com/entry/kubecon-cloudnativecon-north-america-2018-report)ので、そちらもご覧ください。

# TL;DR
- 1年前にK8sを導入していまやサービス全体の40％のアプリケーションがK8s上で動いてる
- 多数のマイクロサービス・チームを抱えるため、Kubernetesの管理に必要なYAMLの生成を自動化している
- アプリケーション本体とインフラ構成管理を同じプロジェクトで管理することで**構成管理が腐らないように**仕組み化されている
- CIでLintやバリデーション、アプリケーションのデプロイとKubernetesのPodの立ち上げを一本のパイプラインにまとめている

[キーノートの動画](https://www.youtube.com/watch?v=ytu3aUCwlSg)が昨日ようやくアップロードされました！
全スライドは[こちら](https://kccna18.sched.com/event/GsxY/keynote-developing-kubernetes-services-at-airbnb-scale-melanie-cebula-software-engineer-airbnb?iframe=no&w=100%&sidebar=yes&bg=no)からダウンロードできます。

# Airbnbとは

世界各地のいたるところで民泊や体験をシェアするためのオンラインマーケットプレイスです

- 81,000都市
- 191ヶ国以上
- 500万戸の民泊宿

の規模で展開しているそうです！

![kubecon 2018-03.png](https://qiita-image-store.s3.amazonaws.com/0/100275/0b905857-f76a-c8c6-5fb8-35b2adc715b9.png)

# Airbnbにおけるマイクロサービス化の機運
Airbnbでは1000人を超えるエンジニアリングチームがおり、全アプリ・全環境合わせて週に20,000回を超えるデプロイが行われています。
プロダクションのデプロイは年間125,000回にまで達し、エンジニアリングの規模感と合わせながらマイクロサービス化を進めることによって、スケーラブルなCD(Continous Delivery)環境を用意する必要がありました。

![kubecon 2018-09.png](https://qiita-image-store.s3.amazonaws.com/0/100275/19e2bcea-e80f-7e7b-5e8d-321b6bfe4b89.png)

そこで、1年ほど前にKubernetesを導入し、現在は全体の40%近くのサービスがAWSのK8sクラスター上で動いているそうです。

![kubecon 2018-08.png](https://qiita-image-store.s3.amazonaws.com/0/100275/0686d274-7015-5047-f914-a362b55c0518.png)

# Why Kubernetes?

## 構成管理の進化の歴史

デプロイ作業には大きく分けて以下の3つの変革がありました

1. 完全に手動でサーバー設定を入れる方法
2. Chefでアプリケーションの設定自体を自動化する方法
3. Kubernetesによってコンテナ化されたアプリケーションの設定とオーケストレーションを自動化する方法

![kubecon 2018-12.png](https://qiita-image-store.s3.amazonaws.com/0/100275/54988947-1f24-ea3c-2f1c-a696e0325f90.png)

## Kubernetesのメリット

- 宣言的な設定項目
- 効率的なスケジューラ
- APIの拡張性

これらによって、柔軟かつ堅牢なインフラストラクチャを作ることができます。

## コンテナ化のメリット

継続的なデリバリを行う上で、主に、以下のメリットを享受できるという意味で、コンテナは非常に相性の良い選択肢の一つです。

- ポータブル(どこでも動く)
- イミュータブル
- 環境の再現が容易

## yamlによる構成管理のメリット

- 人間が読める
- 標準フォーマットであること

上記にて、Kuberentesのメリットとして宣言的にインフラストラクチャの定義ができるという話がありましたが、YAMLを使うことで一定の可読性が担保できます。

![kubecon 2018-13.png](https://qiita-image-store.s3.amazonaws.com/0/100275/c57054e1-8578-28d2-6940-ccc2e8267451.png)

# Kubernetes導入で大変だったこと
- Kubernetesに必要な設定ファイルが多すぎる問題
  - 環境によって複数のボイラープレートができる(yaml地獄)
- 複雑なツール類
  - CLIツールの学習コストが高い(1000人にどうやって教育するか)
- OSS特有の問題
  - オープンなバグへの対応など
- 既存のインフラへの導入
  - OSSをどこまで自分たちのインフラに寄せていけるか問題  
  →カスタムリソースを使う(これについてはあまり深掘りされなかったので今回は省略します)

## Kubernetesに必要な設定ファイルが多すぎる問題

各サービス、環境や様々な設定ファイルをKubernetesに用意する必要があるため、Infrastructure as Codeを管理するコストが跳ね上がってしまうという問題があります。特に、DevとProdなどに固有の情報が書かれた各設定ファイルは、細かいメタ情報を除いて共通の部分が多く、ファイルの存在自体が冗長になりがちです。

そこで、以下の内容に重きを置きつつyamlを吐き出す自動化ツール `kube-gen` を作ることで、yaml作成のコストと定常運用における自動化の両方を実現しました。

- 継承よりもテンプレート化
- レガシーなサービスを移行しやすいように
- 1000人以上のエンジニアへの再教育をしやすくする

![kubecon 2018-26.png](https://qiita-image-store.s3.amazonaws.com/0/100275/317ed3e3-3a9d-61f0-c107-4430ee5b3881.png)

`kube-gen generate`すると、既存プロジェクトに含まれるファイル群からKubernetesの設定ファイルを、**環境に応じて標準化されたネームスペースをもたせた状態で**自動生成してくれます（！）

- ボイラープレートの種類をできるだけ減らす
- そのために、環境やネームスペースといった情報は標準化する

といったことが大事だということがわかりました。

### 各サービスにおけるボイラープレートの生成について

大原則として、「サービスに関することはすべてGitで1つの場所にまとめる」ことが大事です。具体的には

- 設定を1箇所にまとめる
  - 全ての構成設定情報は、サービスのプロジェクトのリポジトリに_infraディレクトリを切って管理
  - コードも構成管理も1PRで管理
    - 新しい設定を入れやすくなった
    - プロジェクトに沿って定期的に検証が可能になった
- テンプレートでサポートするもの
  - kube-genに必要なファイル
  - アプリケーションフレームワークのボイラープレート
  - APIのボイラープレート
  - CI/CD
  - docs
  - AWSのIAMロール
  - プロジェクトのownership
  - ストレージ などなど

![kubecon 2018-34.png](https://qiita-image-store.s3.amazonaws.com/0/100275/7bf92ada-d9f4-9e6e-0d71-1706fc8a323b.png)

#### ここでのまとめ

- サービスに関することはすべてGitで1つの場所にまとめる」
- ベストプラクティスを設定自動生成の「デフォルト値」にする

## kubectlのラッパーを作成した

テンプレート自動生成によって自動化されているKubernetesの設定ファイルがあれば、Kubectlを使った定常運用の作業も自動化が可能になります

- k tool

  - `k generate`でkube-genの自動生成ファイルをKubernetesのyamlに変換
  - `k build`でプロジェクトのビルド、Dockerイメージのビルド、push(tag付き)を実行
  - `k deploy`でネームスペースの生成、kubectlでapplyしたりデプロイステータスをチェックしたりいろいろ

全部をchainで実行することも可能

![kubecon 2018-47.png](https://qiita-image-store.s3.amazonaws.com/0/100275/aa6b48c2-4f1e-0927-d9f2-408fc9af784d.png)

#### ここでのまとめ

- kubectlのラッパーコマンドを作って定常運用で使うワークフローを自動化しよう

## CI/CD

### CI

CIでは以下の項目に関して主に動かします。

- ビルドの前に、きちんとパイプラインが適切に設定されているかのバリデーション
- アプリケーションのテスト
- プロジェクトのビルド

![kubecon 2018-51.png](https://qiita-image-store.s3.amazonaws.com/0/100275/df309097-48be-7690-9048-b5d0191a6302.png)

### CD

CDでは、各ステップをDockerfileに書かれたとおりに実行させます。
下記のスクショでは先程の `k tools` を動かしていることがわかりますね(ローカルで動かすラッパーツールと同じもの)。

![kubecon 2018-52.png](https://qiita-image-store.s3.amazonaws.com/0/100275/4825e4af-d5a4-1ee0-6f7d-9f37c746616f.png)

#### ここでのまとめ

- CI/CDはエンジニアたちがローカルで叩くものと全く同じものを実行させる
- CI/CDはコンテナ内で実行させる
- パイプライン上で設定情報の検証を行う

### 実際のデプロイプロセス

各デプロイにおいては以下のようなフローで行います。

実際のデプロイ時には**設定変更とコードの変更を同時に行う**ことで、IaCで書かれた設定情報が腐らないように仕組み化されています。

![kubecon 2018-56.png](https://qiita-image-store.s3.amazonaws.com/0/100275/b4f2192a-9d3c-ed8a-e8b7-a3313aaa11b1.png)

このあとは、Kubernetesにおけるデプロイ時のプロセスのライフサイクルの話等がありましたが、今回自分が学んだこととはまた別枠なので、スライド等を御覧ください。

以上、だいたいこんな感じでした。組織拡大に起因するマイクロサービス化はなかなか大変だと思いますが、ここまでやりきってるのはすごいですねー。Airbnbはアメリカ国内と中国に開発拠点があるみたいです。

## 所感
キーノートがKubernetesや周辺OSSのアップデート中心で辟易してたところでこの話があって、衝撃を受けました。
Infrastructure as CodeやCI/CD、DevOpsなどといった言葉は、言葉こそ先行していろいろな場所で使われてますが、ユーザー向けのサービスの文脈において、ここまで体系立てて大規模なkubernetesインフラの構成を管理している事例は、あまり今までなかったものと思っています。

特に、「1000人のエンジニアの教育をできるだけさせないこと」や、「ローカルで行う作業と全く同じ作業をCI/CDで行う」といった話はなかなか分かっていてもできないことだと思っていて、素直にすごいと思ってしまいました。

インフラ構成管理を腐らせないための仕組みをコードのコミットと一緒に入れるという取り組み含め、「マイクロサービス」のあり方について自分の中でいろいろと学ぶところが多く、今回深掘りしたくなった次第です。

余談ですが、AirbnbはCIツールを自作しているみたいです。CIのスクショに見覚えがなかったのでMelanieに聞いてみたところ、「どのCIサービスも自分たちの使い方にマッチしなかったため自作した」とのことでした。しゅごい。

※余談ですがAirbnbでは、[このCIツールの開発エンジニアを募集しているらしい](https://www.airbnb.com/careers/departments/position/953250)です

あと、Airbnbではマイクロサービス化されていない当時からのメインのRailsのシステムのことをモノリシック+Railsでモノレールと呼ぶんだそうです。

Kubernetesもマイクロサービスも、モダンなインフラストラクチャ・開発体制を構築する上では知っておくべき概念の一つですが、メリット・デメリットをきちんと理解した上で技術選定にかかりたいところです。