Links

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

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

Kubernetes とは?

Kubernetes における代表的な Object の階層構造と役割(機能) を知ることが重要です。より詳しくは公式ドキュメントのKubernetesとは何か?を参照してください。

Object とは

Kubernetes の管理下にあるレイヤのリソース(Container, Network, Storage, etc…)を抽象化したものを指します。詳細は公式ドキュメントのKubernetesオブジェクトを理解するを参照してください。また、少し古いですがKubernetes道場 Advent Calendar 2018 - Qiitaの記事群も図解が多めでわかりやすいです。
Object には spec(仕様)と state(状態)が存在しています。Kubernetes の根本的なコンセプトとして Reconciliation Loop によって Object で宣言された spec(desired state) に操作対象リソースの state を近づけるというものがあります。例えば Pod を 2 つ立てておいてくださいと spec に書いている状態で Pod が 1 つになってしまった(state)ら自動的にもう一台 Pod を立てるということを勝手にやってくれます。詳細はKubernetes のしくみ やさしく学ぶ 内部構造とアーキテクチャーを参照してください。

よく聞く主な 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 の階層構造

Wantedly での Kunbernetes 構成

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

デプロイについて

Wantedly の Kubernetes クラスタ上で動いているアプリケーションは全て、Rolling update という Strategy でデプロイされます。これは動いているアプリケーション徐々に入れ替えていく方式で、古いアプリと新しいアプリが同時に動作する時間が存在することになります。 なので、Pull request を作るときには「バックエンドとフロントエンドの変更を分ける」「DB スキーマ変更とアプリケーション変更は分ける」などを意識することが重要になります。
より詳しくはリリース・デプロイ戦略の章を参照してください。

環境変数・dotenv について

The Twelve-Factor AppIII. Config で、アプリケーションの設定値はコード上に記述せず環境変数にセットすることが推奨されています。 Wantedly の Kubernetes クラスタでは Secret を利用し環境変数を管理しています。 各 Namespace に dotenv という Secret を作成し、そこに設定値を格納して環境変数に展開しています。 dotenv への環境変数の設定などは、後述する kube コマンドを介して行われます。

kube コマンド

kube は Wantedly の Kubernetes クラスタのリソースを操作するためのユーティリティです。 詳しくは kube - Wantedly Engineering Handbook を参照してください。

話を聞きに行きたい

もっと知りたい