前回に続いて、Kubernetesのエコシステムをまとめていく。

今回はKubernetesのクラスタの構築手段について書く。

(2020/3/23更新)

Kubernetesのアーキテクチャ

とりあえず、Kubernetesのクラスタとは何かについて書く。

Kubernetesはざっくりマスタコンポーネントとノードコンポーネントに分けられる。 これらは同一または別個のマシンにデプロイできて、HTTPS通信を介して一つのクラスタを構成する。

マスタコンポーネントをデプロイしたマシン群はコントロールプレーンと呼ばれることがある。 ノードコンポーネントをデプロイした1マシンは単にノードと呼ばれるが、ワーカノードと呼ぶことも多い。 ノードは1クラスタに複数あるのが普通で、数百ノード~数千ノードという規模の構成も可能。

Kubernetesクラスタに対してアプリのリソース(e.g. コンテナとかサービスとか永続化ボリューム)を定義してやると、Kubernetesがそれに従ってリソースを準備してアプリをデプロイしてくれる。 アプリを構成する各Podをどのノード上で動かすかはコントロールプレーンが動的に決める。

  • マスタコンポーネント

    Kubernetesクラスタやその上で動くアプリケーションの構成を管理するコンポーネント群で、それぞれがGo製の単一バイナリのサーバアプリケーション。 以下の4つのコンポーネントがある。(実際にはもう一つあるけど、マネージドKubernetesを提供するクラウドプロバイダが使うやつなので普通は気にしなくていい。)

    • kube-apiserver

      HTTPSのポートを開けて、REST API(とProtocol BuffersのAPI)でアプリのリソースを定義するためのKubernetes APIを提供するサーバ。 ユーザはkubectlというコマンドラインツールや任意のHTTPクライアントを使ってこれと話し、アプリのリソース定義を投入する。

      全てのリソースがwatch operation (aka. watch list)をサポートしていて、クライアントがリソースごとの定義や状態の更新通知をリアルタイムに受けられるようになっている。 (因みにwatch APIというのもあるが、Kubernetes 1.12で非推奨になった。)

    • etcd

      kube-apiserverが受け取ったリソース定義、アプリケーションの状態、Kubernetesクラスタ内で発生したイベントなどの情報を永続化するデータベース。 データベースのアーキテクチャは分散キーバリューストア。 kube-apiserverだけが参照、更新する。

      実はKubernetesとは別のプロジェクトのもので、etcdはetcdでKubernetesとは別にクラスタを組める。

      gRPCのAPIでデータの変更をwatchできるので、Kubernetesはこれを利用してリアクティブな感じに動く。

    • kube-scheduler

      kube-apiserverのwatch operationを使ってPod定義の作成をwatchして、各Podをどのノードにデプロイするかを決める。 決めるときには、Podの要求リソースとか、ノードや他Podとの親和性(i.e. Affinity)定義を鑑みてくれる。 この、Podをデプロイするノードを決める処理をスケジューリングという。

    • kube-controller-manager

      kube-apiserverのwatch operationを使って色んなリソース定義をwatchする。 kube-controller-managerはそのプロセス内部でリソース種別毎にgoroutineでコントローラを実行し、リソース定義と実際のリソース状態を比較し、その差を埋めるように処理をするのが主な役割。

    コンポーネント間はHTTPSやgRPCで通信するので、ネットワークさえつながっていればそれぞれがどこで動いていてもいいんだけど、普通はetcd以外の3つは同一マシンで動かして、冗長化構成にするときもその単位でする。

  • ノードコンポーネント

    ノードのマシンやPodやコンテナを管理・監視するコンポーネント群で、それぞれがGo製の単一バイナリのサーバアプリケーション。 以下の2つのコンポーネントがある。

    • kubelet

      kube-apiserverのwatch operationを使ってPod定義(など?)をwatchし、定義に従ってコンテナの起動・停止をするためにコンテナランタイム(i.e. CRI実装)と話しをするのが主な仕事。 ノードの状態監視もする。

      HTTPSポートを持っていて、kube-apiserverからのREST API呼び出しを受け付けて以下のような処理もする。

      • kubectl execで指定されたコマンドをコンテナで実行する。
      • kubectl logsで指定されたコンテナのログを取得する。
      • kubectl port-forwardでローカルホストのポートをコンテナのポートに転送する。
    • kube-proxy

      Kubernetesクラスタ内でロードバランサ的な役割をするServiceと、そのバックエンド接続を表すEndpointというリソースを監視し、それらの定義に従ってiptablesやipvsのルールをいじってPod間の通信を転送したり、ノードのポートを開けて外部からPodにつなげるようにしてくれる。

k8s-arch.png

上記の通りKubernetesクラスタは結構複雑で、構築するとなると色んなコンポーネントをインストールして、HTTPS通信のためのサーバ・クライアント証明書を作って、設定ファイルを沢山作って、コンテナランタイムをインストールしたりとかなり大変。 なので、Kubernetesコミュニティ内外でこの問題に対する様々な取り組みがある。

Kubernetesクラスタ構築ツール

Kubernetesクラスタを自動で構築するツールがいくつかある。 それらを利用して、プロダクション向けのクラスタを自分の環境に作ることができる。

kubeadm

kubeadmはKubernetesコミュニティ製の本家本元ツール。 Kubernetes 1.4とともにリリースされ、GAに達したのは割と最近でKubernetes 1.13 (2018年12月)。

Goで書かれた単一バイナリで、マスタのマシンとノードのマシンでシンプルなコマンドを実行するとクラスタが作れるけど、コンテナランタイムとかkubeletとかは事前にインストールしておく必要があり、ちょっと面倒

kops

kopsもKubernetesコミュニティ製。

KubernetesクラスタをAWSとかGCEに構築できる。 (前者はAWS公式によるサポート。)

Goで書かれた単一バイナリで、コマンドを実行するとVMのインスタンスを作ったりネットワークや権限周りの設定をしてくれたりしたうえでKubernetesクラスタを構築してくれる。

kubespray

kubesprayもKubernetesコミュニティ製。 プレーンな(ベアメタルな)マシンのほか、AWS、GCE、Azure、OpenStack、vSphereなどの環境にKubernetesクラスタを構築できる。

Ansibleのプレイブックになっているところが特徴で、それゆえ中の処理が追いやすくてカスタマイズもしやすい。

Juju、JAAS

JujuはUbuntuの開発元であるCanonical社が提供するGo製のツール。 JAASはそのSaaS版。

Kubernetesに特化しているわけではなく、汎用的な分散システムをモデリングするためのツールで、AWS、GCE、Azureなどの環境にVMや関連リソースや任意のアプリケーションをデプロイして管理できる。 Jujuはアプリケーションとそのセットアップ処理をCharmという形でパッケージングして、Charm Storeで共有できるようにしている。 Charm StoreにKubernetesのCharmがあって、これでKubernetesクラスタを構築できる。

ansible-k8s、packer-k8s

拙作のツール。 ansible-k8sが任意のマシンにKubernetesクラスタを構築するAnsibleプレイブック。 packer-k8sは、VirtualBoxかESXiでVMを作ってansible-k8sでKubernetesクラスタを構築するPackerのテンプレート。

GitHubに挙げているものはシングルノード構成しか対応してないけど、職場ではマルチノード構成(とHyper-V)に対応させたものを使ってる。

kind

kindはKubernetesコミュニティによるツール。 kindというコマンドを一回実行するだけで、Dockerコンテナとして動くKubernetesクラスタを手軽に構築できる。 マルチノードクラスタも作れるけど、あくまでテスト用途向けのツール。

Kubernetes自身のテストに使われている。

Breeze

BreezeはGUIでオンプレミス環境にプロダクションレディなKubernetesクラスタを構築できるツール。 コアはAnsibleのPlaybookで、kubesprayと似てる。 特徴的なのは、クラスタ構築に必要なKubernetesコンポーネント(のコンテナイメージ)、Docker、Dockerレジストリ(Harbor)、YUMリポジトリサーバ、aptリポジトリサーバを同梱していることで、オフラインでもクラスタ構築できること。 Breeze自体がDockerコンテナとして動くので、実行も簡単。

kublr

kublrは、サーバアプリケーションとして動き、そのGUIでAWS、Azure、GCPかオンプレのマシンにKubernetesクラスタを構築して管理できるツール。

出来合いKubernetesクラスタ

ツールを使って構築するのもそれなりの学習コストと作業が発生して簡単ではないので、出来合いのものを使う手もある。 プロダクション用のものはなく、開発用ばかり。

Minikube

MinikubeはKubernetesコミュニティ製の本家本元ツール。

minikubeというGo製のコマンドを実行すると、Kubernetesセットアップ済みのVMイメージをダウンロードして、ホストOSから使えるようにしてくれる。 Kubernetesに特化したVagrantみたいな感じ。

VMを動かす仮想環境としてはVirtualBox、KVM、Hyper-V、hyperkitがサポートされている。

Docker for Windows、Docker for Mac

Docker for WindowsDocker for Macは、それぞれOSネイティブなハイパバイザでLinuxのVMを立ち上げてDockerを使えるようにしてくれるもの。 (前者は近いうちにハイパバイザからWSL2に変わる。)

Docker for Windowsは2018年1月末、Docker for Macは2018年1月頭からKubernetesを同梱するようになり、Minikubeと同じようなことができるようになった。

Minikubeに比べてKubernetesクラスタの設定はあまりいじれないけど、こっちのほうがセットアップは簡単。

KatacodaのKubernetesコース

KatacodaはオンラインでIT技術を触って学べるサービス。 そのKubernetesコースでは、ブラウザ上でkubectlを実行してKubernetesクラスタを触ることができる。

できることは限られているが、ちょっとkubectlを触ってみたいくらいの時にはいいかも。

Play with Kubernetes

Play with KubernetesはDocker社が提供するKubernetesお試し環境。 なぜかkubeadmでクラスタを作るところからやらされて地味にめんどくさい。

今試そうとしたらなんだか繋がりにくいし、セッションがすぐ切れてクラスタを作るところまで進めなかった。 過負荷なのかな。

因みにPlay with Dockerもある。

マネージドKubernetesクラスタ

プロダクション用にKubernetes使いたいけど、自分でインフラ構築するのは面倒だし運用も楽したいという人向けに、マネージドなKubernetesを提供するサービスがクラウドベンダ各社から出ている。

Google Kubernetes Engine (GKE)

GKEはGoogle CloudのマネージドKubernetesサービス。 Kubernetesの開発の大本であるGoogleがやっているだけあって機能的には最高。

KubernetesマスタはSaaSで提供されて、KubernetesのノードはGoogle Compute Engineのインスタンスとして見えて、ノードのインスタンスだけが課金対象。 つまりマスタはタダで動かしてくれる。

Azure Kubernetes Service (AKS)

AKSはMicrosoft Azureのやつ。 GKEより3年ほど後発で機能は劣るが、2016年半ばからKubernetesのco-founderであるBrendan Burnsがリードしているので先は明るそう。

他のマネージドKubernetesに勝る点として、virtual-kubeletを利用してAzure Container Instances (ACI)と連携し、マシンレスでPodをデプロイできるところは特筆すべきところ。 けどまだ出たてだし、DaemonSetでPodを作れないなどの制限があるので、基本的にはAzure Virtual Machinesのインスタンスをノードに使う形になり、そこが課金対象になる。 AKSもマスタはタダ。

Amazon EKS

Amazon EKSはAWSのやつ。 他のと同様にKubernetesマスタがSaaSで提供される。 現時点ではノードはEC2インスタンスでそこの課金が結構大きいけど、近いうちにFargateにPodをデプロイできるようになってマシンレスになる気配が感じられる。

後発のKubernetesサービスで、結構機能的には劣るけど、AWSのブランド力でマスタにも課金してくる。

CNIプラグインとして独自のAmazon VPC CNI pluginを提供している、というかこれしかサポートしていないのが特徴。 これのせいで1ノードにデプロイできるPod数がEC2インスタンスのENI数の制限を受ける。

IBM Cloud Kubernetes Service (IKS)

IKSは名前の通りIBM Cloudのやつ。 これもマスタはタダ。 ワーカノードにベアメタルマシンを使えるのが特徴のひとつ。

使用例を聞いたことが無い…