# プロダクト開発のための Kubernetes 入門

Wantedly のバックエンドシステムは全て AWS 上に構築された [Kubernetes](https://kubernetes.io/ja/) クラスタの上で動いています。 新しいコードをデプロイしたり、開発用クラスタで `rails c` を実行したりなど日常の業務はインフラチームの助けを借りずにできるようになっています。 　 この章では、プロダクト開発に必要となる知識の説明をします。Kubernetes の基本的な概念、Wantedly における Kubernetes の構成、そしてその内製CLIである `kube` コマンドの概要を説明します。

## Kubernetes とは？

**Kubernetes における代表的な Object の階層構造と役割（機能）** を知ることが重要です。より詳しくは公式ドキュメントの[Kubernetesとは何か？](https://kubernetes.io/ja/docs/concepts/overview/what-is-kubernetes/)を参照してください。

### Object とは

Kubernetes の管理下にあるレイヤのリソース（Container, Network, Storage, etc…）を抽象化したものを指します。詳細は公式ドキュメントの[Kubernetesオブジェクトを理解する](https://kubernetes.io/ja/docs/concepts/overview/working-with-objects/kubernetes-objects/)を参照してください。また、少し古いですが[Kubernetes道場 Advent Calendar 2018 - Qiita](https://qiita.com/advent-calendar/2018/k8s-dojo)の記事群も図解が多めでわかりやすいです。

Object には spec（仕様）と state（状態）が存在しています。Kubernetes の根本的なコンセプトとして **Reconciliation Loop** によって Object で宣言された spec(desired state) に操作対象リソースの state を近づけるというものがあります。例えば Pod を 2 つ立てておいてくださいと spec に書いている状態で Pod が 1 つになってしまった（state）ら自動的にもう一台 Pod を立てるということを勝手にやってくれます。詳細は[Kubernetes のしくみ やさしく学ぶ 内部構造とアーキテクチャー](https://www.slideshare.net/ToruMakabe/kubernetes-120907020)を参照してください。

### よく聞く主な Object の役割（機能）

* Namespace
  * Kubernetes 上のリソースを分類するための名前空間
  * 操作権限の境界
  * Object のグルーピング
  * ClusterRole(Binding) とか一部の Object 以外は必ずどこかの Namespace に所属している
    * Object の作成時に Namespace を指定しなかった場合は `default` Namespace が指定される
  * Wantedly においてはマイクロサービスごとに Namespace を作っている
    * e.g. wantedly/yashima-rails リポジトリ - `yashima-rails` namespace
* Pod
  * Kubernetes におけるアプリケーションの最小構成単位
  * コンテナの集まり
    * 1 つの Pod に N 個の Container が含まれる
    * e.g. rails server などアプリケーションサーバ, nginx や envoy などの reverse proxy をひとまとめに扱う
* Node
  * VM もしくは物理マシンに対応
    * Wantedly においては AWS 上の EC2 インスタンス
  * Node 上には複数の Pod がデプロイされる
* ReplicaSet
  * Pod の管理
  * 指定した数の Pod の複製・維持
    * 例えば Pod を 2 台起動して欲しいと宣言しておくと、1 台 Pod が終了してもその直後に勝手に 1 台 Pod を起動して 2 台構成を維持してくれる
    * これを逆手にとって Pod を強制的に再起動したいときは Pod を delete することで消えた分の数の Pod が自動的に立ち上がる
      * ただこの場合 Pod の台数を維持できなくなる瞬間が存在する（Rolling Update ではないので 1 台構成とかだったらサービスダウンする）ので、複数台構成になっている前提
    * Deployment/ReplicaSet で管理された Pod を完全に削除したいという場合は Deployment/ReplicaSet を削除する
* Deployment
  * ReplicaSet の世代管理
  * Pod の Rolling Update
  * 以前の ReplicaSet までの Rollback
* CronJob
  * 指定した時刻に Job を起動する
* Job
  * Pod を起動して指定された One Shot なコマンドを実行する
* Service
  * Pod への通信を管理する
  * Pod に対する L4(TCP/IP) Load Balancer
  * Pod に対して通信しようと思ったら Service を追加しなければならない
* Ingress
  * Pod(Service) への通信を管理する
  * Pod(Service) に対する L7(HTTP) Load Balancer
    * URL 上の Path でルーティングを切り替えるとかはこのレイヤでないと出来ない
  * この Object が実際に操作するのは Cloud Provider の Load Balancer が多い(Wantedly では ALB)
    * 他にも Kubernetes 内の Object も操作できる（e.g. nginx-ingress-controller とか）

### Object の階層構造

![](/files/-MhWAMvyxzFmtVkAR7bP)

## Wantedly での Kunbernetes 構成

以下の3種類のクラスタが存在します。

* Production
  * ユーザからのアクセスを受ける、いわゆる本番環境です。
* QA
  * 本番デプロイ前の動作確認用クラスタです。
    * QAテスターチームが日常的に利用しています。社内のビジネスチームが動作確認のために利用することもあります。
  * 原則として、本番環境と同じバージョンのコードが動いている状態を保ちます。
  * モバイルアプリ・Web フロントエンドエンジニアは普段ローカルから QA につないで開発しています。
* Sandbox
  * 開発用クラスタです。
  * バックエンドエンジニアが本番に近い環境でアプリケーションを動かしたいときに利用しています。

### デプロイについて

Wantedly の Kubernetes クラスタ上で動いているアプリケーションは全て、[Rolling update](https://kubernetes.io/docs/tutorials/kubernetes-basics/update/update-intro/) という Strategy でデプロイされます。これは動いているアプリケーション徐々に入れ替えていく方式で、古いアプリと新しいアプリが同時に動作する時間が存在することになります。 なので、Pull request を作るときには「バックエンドとフロントエンドの変更を分ける」「DB スキーマ変更とアプリケーション変更は分ける」などを意識することが重要になります。

より詳しくはリリース・デプロイ戦略の章を参照してください。

### 環境変数・dotenv について

[The Twelve-Factor App](https://12factor.net) の [III. Config](https://12factor.net/config) で、アプリケーションの設定値はコード上に記述せず環境変数にセットすることが推奨されています。 Wantedly の Kubernetes クラスタでは [Secret](https://kubernetes.io/docs/concepts/configuration/secret/) を利用し環境変数を管理しています。 各 Namespace に `dotenv` という Secret を作成し、そこに設定値を格納して環境変数に展開しています。 `dotenv` への環境変数の設定などは、後述する kube コマンドを介して行われます。

## kube コマンド

`kube` は Wantedly の Kubernetes クラスタのリソースを操作するためのユーティリティです。 詳しくは [kube - Wantedly Engineering Handbook](/fields/dev-tools/kube.md) を参照してください。

#### 話を聞きに行きたい

* Slack: [#infra](https://wantedly.slack.com/archives/C010V922570), [#dx](https://wantedly.slack.com/archives/CQK61054H)

#### もっと知りたい

* [強いインフラが組織を創る / #jtf2018 - Speaker Deck](https://speakerdeck.com/koudaiii/number-jtf2018)
* [Kube - The core tool at Wantedly - Speaker Deck](https://speakerdeck.com/potsbo/kube-the-core-tool-at-wantedly)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.wantedly.dev/fields/infrastructure/kubernetes-introduction.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
