😊

kubeadmで初めてkubernetesクラスタを構築する自分に贈る、大まかな仕組みと内部コンポーネントについて

2023/12/13に公開

概要

一般のご家庭なのでkubernetesクラスタを構築しようと思ったのですが、最初にk8sのドキュメントを読んでも各コンポーネントがどのような役割を果たしているのか理解しておらず内容が全くわかりませんでした。
その時の自分を想定読者に、k8sの構築を行う前に知っておきたい大まかなk8sの概要とをk8sを構成するコンポーネントについてまとめました。

間違っている点もあるかと思いますが、その点はご容赦とともにご指摘いただければと思います。

そもそもkubernete等のコンテナオーケストレーションは何がやりたいのか

コンテナが便利なのでたくさん動かしたいと言うのが根底にあるのではないかと思います

ただ各ノードで個別にコンテナのデプロイ作業を行うのは大変です。
そこでコンテナの構成情報を管理するマスターを用意し、各ノードへこの情報を取得しコンテナエンジンへデプロイ操作を行うエージェントをインストールすれば便利そうです。
さらに、一部のノードがダウンしたとしても別のノードで動作させるコンテナを増やすことができれば耐障害性も確保できて便利そうです。

そして、このクラスターを適切に管理・運用する必要があるので、設定を投入したり稼働状況を確認したりするコマンドを用意したほうが良さそうです。
すべてのノードはマスターを参照して動作するので、このコマンドはマスターと通信をしてコンフィグを書き込んだりステータスを取得したりすることでクラスターの管理を行えるようにすれば大丈夫そうです。

k8sではエージェントをkubelet、クラスターを管理するコマンドをkubectlと呼んでいます。
またこのマスターのこともコントロールプレーンと呼ぶことが多いようです。

kubernetesのコンポーネントについて

k8sのコンポーネントについて、先程より少し詳しく見ていければと思います。
参考: https://kubernetes.io/ja/docs/concepts/overview/components/#kube-proxy

(ワーカー)ノードのコンポーネントについて

kubelet

前の章で説明した通り、コントロールプレーンからコンテナの設定情報を取得してワーカーノードのコンテナエンジンへコンテナのデプロイを行います。

kube-proxy

kubeletのコンテナ用ネットワーク版といったところかなと思います。
コンテナも通信を行うわけですが、ワーカーノードのネットワーク設定をコントロールプレーンの指示どおりに行います。
これとCNIというネットワークプラグインを組み合わせてk8sクラスタ内のコンテナ間・外部ネットワークとの通信が実現されます。

コントロールプレーンノードのコンポーネントについて

etcd

key-value形式のデータストアで、k8sでは設定情報の保存場所として使用されます。
https://etcd.io/

kube-apiserver

etcdのラッパーのように動作するコンポーネントです。
他のすべてのコンポーネントがetcdへデータの書き込み・読み取りを行う場合はこのコンポーネントを介してデータのやり取りを行います。

kube-controller-manager/kube-scheduler

ユーザーが登録したmanifestにかかれていないが、実際にNodeでPodを起動するには必要な設定をetcd上へ追加します。
具体的にはPodをどのNodeで動かすかの指定とか(kube-scheduler)、ServiceAccountの作成とか(kube-controller-manager)をやります。

例えば特定のDockerイメージのPod(≒コンテナ)を3台立ち上げる設定ファイルを作成し、コントロールプレーンへ登録したとしても、どのノードに何台立ち上げるかはクラスタ内で決定する必要があります。
これらの決定と、決定した内容を(kube-apiserverを介して)etcdに書き込むのがこれらのコンポーネントの役割になります

kubeadmはどこまでやってくれるのか

今回の最終目的はk8sクラスタを構築することです。
構築ツールの代表的なものにkubeadmがあります。
ただこのkubeadmなのですが、クラスタ構築のすべての作業を行ってくれる訳ではありません。

コントロールプレーンの冗長化

コントロールプレーンを複数のノードで構築することで冗長性を確保することができます。
内部で利用するetcdの仕様上、3台/5台/7台 といった奇数台で構築することが推奨されています。

etcdは複数台でクラスタを構成しますし、kube-controller-manager/kube-schedulerもリー台選出の仕組みを備えます。
ただコントロールプレーンの冗長化には1つ地味に大きな課題があります。それはkube-apiserverのエンドポイントの冗長化です。

kube-apiserver自体は(多分)ステートを持たない(加えてetcdはクラスタ化されているのでどのノードのetcdを読み書きしても良い)ので基本的に複数台あるノードのうちのどのノードへリクエストを投げても問題はありません。
ただしコントロールプレーンを構築するコントロールプレーンノードはそれぞれ個別のIPアドレスを持つ事になるのに対し、ワーカーノードが参照するコントロールプレーンのIPアドレスもしくはドメインは1つのみになります。
そのため、何らかの仕組みを用いて、ワーカーノードが参照するアドレスは常に正常に動作するコントロールプレーンノードを示すようにする必要があります。

公式ドキュメントの例ではロードバランサをkube-apiserverの前段に用意しています。

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/ha-topology/#stacked-etcd-topology より

そのため、コントロールプレーンの冗長化を行う場合は何らかの方法でコントロールプレーンノード共通で使用できるVIPやドメイン名を用意する必要があります。(逆に冗長化をおこわない場合はこれらの用意は不要です)

kubeadm init/join

一番最初にクラスタに参加させるコントロールプレーンノードでkubeadm initを実行し、以降に参加させるコントロールプレーンノード/ワーカーノードではkubeadm joinを実行してクラスタへ参加させるのが、kubeadmを使用したクラスタの構築手順になります。

このときkubeadmが設定を行ってくれるのは基本的に下記の図の赤枠で囲った範囲のみになります。
そのため、実際にk8sクラスタを構築するときには、kubelet/kubectlのほかコンテナエンジンのインストールはkubeadm以外の方法で行う必要があります。
その他にこの図ではkube-apiserverの冗長化の方法としてkube-vipを用いていますが、これもkubeadmの外で設定を行う必要があります。

参考:
https://qiita.com/FY0323/items/6a3b3270888c96ba13d3

最後に

大まかにk8sとそのコンポーネントの仕組み、kubeadmが何をやってくれるのかについて説明ができたかなと思います。(もし誤りがあればご指摘いただければと思います)

また次の記事等で、より詳しいクラスタの構築手順等を説明できればと思っております。

Discussion