プロダクト開発のための 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 の Kuberenetes クラスタのリソースを操作するためのユーティリティです。Kubernetes を操作するための標準 CLI ツールとして用意されている kubectl の機能に加え、いくつかの便利機能とサブコマンド、および権限に応じたアクセス制御の仕組みを持ちます。

知っておくと良いコマンド

操作対象のクラスタは第1引数で指定する。また、kube はカレントディレクトリから操作対象の Namespace を決定します。 なので、原則操作対象のマイクロサービスのリポジトリがあるディレクトリに移動してからコマンドを実行するのが良いでしょう。
    コマンドを実行したい: kube <env> sh <-c, -d, branch_name> COMMAND
      e.g. 今のブランチで sandbox に DB migration したい kube sandbox sh -c rails db:migrate
      e.g. 今デプロイされてる QA で Rails console を使いたい kube qa sh -d rails c
    デプロイしたい: kube <env> deploy <-c, -d, branch_name>
    環境変数をセットしたい: kube <env> dotenv set FOO=bar
    今動いている Pod 一覧が見たい: kube <env> get po
    ログが見たい: kube <env> tail
    クラスタをコピーし自分専用のものとして利用する: kube <env> fork
より詳細な使い方は kube の使い方 (internal) を参照してください。

話を聞きに行きたい

もっと知りたい

最終更新 5d ago