0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

1. はじめに

この記事は、前回公開した 「【第1回】ミニPCにKubernetes環境を構築するまで ~概要編~」 の続編です。
前回の記事では、Kubernetesの主要な機能やコンポーネントについて整理しました。
今回はそれを踏まえ、実際にミニPCに Kubernetes クラスターを構築していきます。

📘 まだご覧になっていない方は、こちらから:
👉 【第1回】ミニPCにKubernetes環境を構築するまで ~概要編~

2. 構成概要・事前準備

この章では、今回構築する Kubernetes クラスターの構成イメージと、事前に行っておくべき準備について紹介します。

🔧 2.1 構築する環境の概要

今回構築する Kubernetes クラスターは、以下のようなミニマルな構成を採用しています。

項目 内容
ノード数 1台構成(単一のミニPCでコントロールプレーン兼ワーカー)
OS Ubuntu 22.04 LTS
Kubernetesのインストール方法 kubeadm
CNIプラグイン Calico
コンテナランタイム containerd

1台構成の Kubernetes クラスターのイメージ図は以下になります。

この図では、各コンポーネントを役割ごとに色分けしています。

  • 🟨 黄色:コントロールプレーン(制御プレーン)に属するコンポーネント
  • 🟥 赤色:全ノード共通のコンポーネント
  • 🟦 青色:CNI プラグイン(Calico)

本来、コントロールプレーンとワーカーノードは複数のマシンに分かれて構成されるのが一般的ですが、今回は学習目的のため、1 台のミニPCに両方の役割を担わせています。
このような最小構成でも Kubernetes の仕組みを十分に体験・学習することができます。

まずはこの構成で動作を確認し、慣れてきたら複数ノード構成への拡張を検討するのも良いかと思います!

🖥 2.2 使用するミニPCについて

構築に使用するのは、以下のようなスペックのミニPCです(筆者環境)。

  • 製品名: Beelink MINI-S12 Pro
  • CPU: 4コア
  • メモリ: 16GB
  • ストレージ: 512GB SSD
  • OS: Ubuntu 22.04 LTS

このようなスペックがあれば、Kubernetes のシングルノード構築や簡単なアプリケーションのデプロイにも十分対応可能です。

📥 2.3 事前に行った準備(Ubuntu インストール)

OSとして使用する Ubuntu 22.04 LTS は、あらかじめミニPCにインストールしておきました。
インストール手順や初期設定(SSH 有効化など)については、以下の記事で詳しく紹介しています。

💻 Ubuntuインストール手順はこちら
👉 ミニPCにUbuntu 22.04をインストール
まだ OS の準備ができていない方は、先に上記記事をご参照ください。

📦 2.4 今回使用するソフトウェアとバージョン

ソフトウェア バージョン 備考
Ubuntu 22.04 LTS 事前にミニPCにインストールしておく
Kubernetes 1.30.11 kubeadm で構築。最新の安定版を使用(執筆時点)
containerd 1.7.27 Kubernetes のコンテナランタイム
kubeadm / kubelet / kubectl 1.30.11 Kubernetes コンポーネント
Calico (CNI Plugin) 3.27.0 Pod 間通信のための CNI プラグインとして使用

バージョンは執筆時点のものですので、今後の変更に合わせて適宜読み替えてください。

🔑 2.5 作業前の前提

このあと構築作業に入りますが、以下の前提条件を満たしていることを確認してください。

  • Ubuntu がインストールされ、SSH 接続が可能である
  • sudo 権限のあるユーザーで作業する
  • インターネットに接続できる状態である

次章では、いよいよ Kubernetes のインストールに取りかかっていきます!

3. Kubernetes インストール手順

3.1 Ubuntu のパッケージを最新化

まずは、システムのパッケージを最新の状態にしておきます。
古いパッケージはセキュリティ面での脆弱性がある可能性があるため、パッケージを最新化することは大切です。

sudo apt update && sudo apt upgrade -y

3.2 SWAP無効化

下記の Kubernetes 公式ドキュメントにも記載されている通り、SWAP が有効化されていると kubelet が正常に動作しない可能性があります。
👉 https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

そのため、Kubernetes を構築する際は SWAP を必ず無効化する必要があります。

また、SWAP 領域はディスク上に存在するため、物理メモリに比べて非常に低速です。
SWAP が使用されるとディスク I/O が増加し、システム全体のパフォーマンス低下の原因となる可能性もあります。

以下のコマンドで SWAP を無効化できます。

  • swapoff -a コマンドで SWAP 領域を無効化します
  • /etc/fstab に定義された SWAP の自動マウント設定をコメントアウトし、再起動後も有効化されないようにします
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

3.3 カーネル設定

Kubernetes ではネットワーク通信を正しく行うために、以下のカーネルモジュールやネットワーク設定が必要です。

特に、br_netfilter モジュールとカーネルパラメーターの設定により、ブリッジ接続されたインターフェース間の通信(Pod 間の通信など)に対しても iptables のルールが適用されるようになります。
Kubernetes はネットワーク制御に iptables を活用しているため、これらの設定が欠けていると、Pod 間通信が正しく機能しなくなる可能性があります。

3.3.1 必要なカーネルモジュールのロード

以下のコマンドで、overlay および br_netfilter モジュールを読み込みます。

sudo modprobe overlay
sudo modprobe br_netfilter

起動時に自動でロードされるよう、設定ファイルを作成します。

sudo tee /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF

3.3.2 カーネルパラメーターの設定

次の設定を行うことで、ブリッジ接続を経由するトラフィックにも iptables のルールが適用され、また IP 転送(ルーティング)も有効になります。

sudo tee /etc/sysctl.d/kubernetes.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

設定を反映します。

sudo sysctl --system

3.4 containerd インストール

次に、コンテナランタイムである containerd のインストールを行います。

3.4.1 依存パッケージのインストール

以下のコマンドを実行し、containerd のインストールに必要なパッケージを準備します。

sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates

3.4.2 Docker リポジトリの登録

containerd は Docker の APT リポジトリで提供されています。

以下のコマンドを実行し、Docker のリポジトリを登録します。

sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

3.4.3 containerd のインストール

パッケージリストを更新し、containerd パッケージをインストールします。

sudo apt update
sudo apt install -y containerd.io

3.4.4 containerd の設定変更

Kubernetes では、CPU・メモリなどのリソース制御に Linux の cgroup を使用します。
Ubuntu のように init システムが systemd の場合は、cgroup の制御方式(cgroup ドライバー)にも systemd を使うことが推奨されています。
そのため、containerd 側でも以下のように SystemdCgroup = true に設定変更を行います。

containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml

containerd デーモンを再起動し、設定変更を反映します。
また、containerd デーモンを自動起動する設定を行います。

sudo systemctl restart containerd
sudo systemctl enable containerd

cgroup とは
cgroup(Control Group) は、プロセス単位で CPU・メモリなどのリソースを制御する Linux の機能です。
Kubernetes のノードでは、以下2種類の cgroup ドライバーのどちらかを使ってリソース管理を行います。

  • cgroupfs
  • systemd

Ubuntu などの systemd ベースのシステムでは、systemdcgroup マネージャーとして動作します。
この環境において、cgroupfs を使うと、2つの cgroup マネージャーが動作することになり、これがノードを動かすうえでよろしくない場合があります。
例えば、kubelet やコンテナランタイムで cgroupfs を、残りのプロセスに systemd を使用するようにノードが設定されていると、高負荷時に不安定になることがあります。

Kubernetes 公式ドキュメントでも、systemd が init システムとして動作している場合は SystemdCgroup = true に設定することが推奨されています。

参考:
https://kubernetes.io/ja/docs/setup/production-environment/container-runtimes/#containerd-systemd

3.5 Kubernetes APT リポジトリの追加

Ubuntu 22.04 には、デフォルトで Kubernetes 関連の APT パッケージ(kubeadmkubeletkubectl など)を提供するリポジトリが登録されていません。

そのため、以下のコマンドを実行して Kubernetes 公式の APT リポジトリを追加します。

echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

補足:リポジトリの仕様変更について
以前は apt.kubernetes.io から配布されていましたが、2024年3月以降は 新しいリポジトリ pkgs.k8s.io に移行されています。

3.6 kubelet、kubectl、kubeadm のインストール

先ほど追加した APT リポジトリを使って、以下の Kubernetes パッケージをインストールします。

  • kubelet: Kubernetes クラスターのコンポーネントの 1 つで、各ノードで Pod の起動・管理を行うエージェント
  • kubeadm: クラスターの構築・初期化・アップグレードなどを行うツール
  • kubectl: Kubernetes を操作するための CLI
sudo apt update
sudo apt install -y kubelet kubeadm kubectl

# 自動アップグレードされないようにバージョンを固定
sudo apt-mark hold kubelet kubeadm kubectl

補足:kubeadm とは?
kubeadm は Kubernetes クラスターの構築や初期化、アップグレードを簡単に行うための公式ツールです。
個別にコンポーネントを設定・起動するよりもはるかに手軽に、標準的なクラスター構成を立ち上げることができます。

補足:kubectl とは?
kubectl は Kubernetes クラスターと対話するためのコマンドラインツールです。
Pod の作成・削除・ログ取得・設定変更など、あらゆる操作を Kubernetes API 経由で行うことができます。

3.7 Kubernetes の初期化

これまでの作業を経て、Kubernetes を構築する準備ができました。
kubeadm コマンドを使って、Kubernetes クラスターの初期化を行います。
これにより、下図の赤枠部分が構築されます。

3.7.1 kubeadm による Kubernetes クラスターの初期化

以下のコマンドを実行し、Kubernetes クラスターの初期化を行います。

sudo kubeadm init

以下は上記コマンドの実行ログです。
kube-apiserverkube-controller-manager 等のコントロールプレーンのコンポーネントが動く Pod マニフェストが作成されたり、CoreDNSkube-proxy が作成されていることが分かります。

user1@kubenode:~$ sudo kubeadm init
I0418 23:07:58.068217    2397 version.go:256] remote version is much newer: v1.32.3; falling back to: stable-1.30
[init] Using Kubernetes version: v1.30.11
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
W0418 23:07:58.650321    2397 checks.go:844] detected that the sandbox image "registry.k8s.io/pause:3.8" of the container runtime is inconsistent with that used by kubeadm.It is recommended to use "registry.k8s.io/pause:3.9" as the CRI sandbox image.
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubenode kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.3.17]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [kubenode localhost] and IPs [192.168.3.17 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [kubenode localhost] and IPs [192.168.3.17 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "super-admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests"
[kubelet-check] Waiting for a healthy kubelet at http://127.0.0.1:10248/healthz. This can take up to 4m0s
[kubelet-check] The kubelet is healthy after 502.208458ms
[api-check] Waiting for a healthy API server. This can take up to 4m0s
[api-check] The API server is healthy after 6.002051973s
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node kubenode as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node kubenode as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
[bootstrap-token] Using token: m3i4yj.yvlwrvpq5o4jpdll
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.3.17:6443 --token m3i4yj.yvlwrvpq5o4jpdll \
        --discovery-token-ca-cert-hash sha256:e97391516c8f47e94867cfeee0329f8986a5b03a507cfbd4cf7046f7ef5887be
user1@kubenode:

↑のメッセージにも記載されていますが、初期化完了後、一般ユーザーで以下のコマンドを実行する必要があります。

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

kubectl では、コマンドを実行する際、$HOME/.kube/config ファイルを参照し、その情報を使って Kubernetes の API サーバーと通信します。
また、管理者権限で実行するのに必要な config ファイルは以下です。

/etc/kubernetes/admin.conf

コントロールプレーンにおいて、現在利用している OS ユーザーで管理者権限で kubectl を実行できるようにするために、以下のコマンドを実行します。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

kubeconfig ファイルとは?
Kubernetes API にアクセスするための認証・接続情報を記述した設定ファイルです。
デフォルトでは $HOME/.kube/config に配置することで、kubectl コマンドが自動で使用します。

3.7.2 ノードステータスの確認

Kubernetes クラスター初期化後、以下のコマンドでノードの状態を確認します。

kubectl get nodes

この時点では、ノードのステータスが「NotReady」となっているはずです。
これは、Pod 間通信を担うネットワーク機能(CNI)がまだ有効化されていないためです。

3.8 CNI プラグインのインストール

Kubernetes では、Pod 同士の通信を行うために、CNI(Container Network Interface)プラグインが必要です。
今回は、代表的な CNI プラグインの 1 つである Calico を使用します。

以下のコマンドを実行し、Calico をインストールします。

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml

インストールが完了すると、Calico によって Pod 間のネットワークが構成され、ノードのステータスが「Ready」に変わります。

kubectl get nodes

ノードが「Ready」となっていれば、Kubernetes クラスターの基盤が正常に稼働し始めたことを意味します。

補足:CNI プラグインとは
CNI(Container Network Interface)は、コンテナにネットワーク機能を付与するための仕様です。
Calico の他に Flannel、Cilium など複数の実装がありますが、いずれも Pod に IP アドレスを割り当て、ネットワーク通信を可能にします。

3.9 コントロールプレーンノードの Taints 削除

コントロールプレーンノードは、デフォルトでは Pod(コントロールプレーンのコンポーネントの Pod を除く) をスケジューリングできないようになっています。
これは、コントロールプレーンノードはあくまで Kubernetes クラスター全体を管理する役割を担っており、本来ワークロード Pod を動かすのはワーカーノードの役割だからです。

今回の Kubernetes クラスターは 1 台構成であり、このノードはコントロールプレーン兼ワーカーノードとなり、このノードにワークロード Pod を配置するので、以下のコマンドを実行して、ノードにこれらの Pod を配置できるようにします。
 ノードから node-role.kubernetes.io/control-plane Taints を削除します。

kubectl taint nodes --all node-role.kubernetes.io/control-plane-

補足:Taints/Tolerations とは
Taints (汚染) とは Kubernetes の機能の 1 つであり、特定のノードに特定の Pod を配置できないようにするための仕組みです。
例えば、このノードには本番環境用の Pod 以外は配置しない、といった制御をこの機能で行うことができます。

一方、Tolerations(許容)とは、Pod 側に設定するプロパティで、「この Pod は特定の Taints を持ったノードにもスケジュールされてよい」と明示的に許可するためのものです。
つまり、Taints があるノードに Pod をスケジュールするには、Pod 側に対応する Tolerations が設定されている必要があります。

たとえば、コントロールプレーンノードには node-role.kubernetes.io/control-plane:NoSchedule という Taints がデフォルトで付与されており、通常の Pod はこれに Tolerations を持たないため、そのノードにスケジュールされません。

これは、重要なコントロールプレーンノードに誤ってワークロードを配置し、リソースを圧迫してしまうことを防ぐために、こうした仕組みを設けていると考えられます。

補足:node-role.kubernetes.io/control-plane とは
kubeadm がコントロールプレーンノードに適用する Taints で、Pod の配置を制限し、特定の Pod のみにスケジュールを許可します。
この Taints が適用されていることで、コントロールプレーンノードではクリティカルなワークロードの Pod のみがスケジュールされるようになります( kube-apiserverkube-scheduler 等の Pod )。

補足:なぜコントロールプレーンノードでは kube-apiserver 等のコントロールプレーンを構成するコンポーネントの Pod を起動できるのか?
コントロールプレーンノードでは、上記の Taints が設定されているため、この Taints に対応する Tolerations を Pod に設定しない限り、このノードでは Pod を起動することはできません。

一方で、コントロールプレーンノードでは kube-apiserver 等のコントロールプレーンを構成するコンポーネントの Pod がいくつか起動しています。
これらの Pod の YAML には Tolerations が設定されておらず、Taints の仕組みだけを考えると、本来は起動できないのでは?と疑問に思う方もいるかもしれません。

これはどういうことかというと、これらの Pod は Static Pod だからです。
Static Pod は、kube-scheduler を介さず kubelet が直接管理・起動するため、Kubernetes API によるスケジューリング制御(Taints/Tolerations を含む)を受けない特殊な Pod です。
Taints はあくまでスケジューリング時に考慮されるものであり、Static Pod は kube-scheduler を経由せず、kubelet 自身が起動するので、Taints/Tolerations の仕組みの影響を受けません。

これらの Pod の YAML は以下のディレクトリに存在しますが、kubelet ではこのパスにある Pod を Static Pod として起動させます。

/etc/kubernetes/manifests

ちなみに、コントロールプレーンノード上の kubelet の構成設定ファイルは以下になります。

/var/lib/kubelet/config.yaml

このファイル内の staticPodPath が Static Pod の YAML 配置先ディレクトリを指しており、コントロールプレーンで起動する kubelet では /etc/kubernetes/manifests が指定されています。
この設定により、上記ディレクトリにある Pod はすべて Static Pod として自動的に起動されます。

staticPodPath: /etc/kubernetes/manifests

4. サンプル Pod の起動

Kubernetes の構築はこれで完了です。
試しに、Nginx コンテナを Pod として起動し、クラスターが正しく動作しているか確認してみます。

kubectl run nginx --image=nginx --port=80

Pod が正常に作成されたかどうか、以下のコマンドでステータスを確認します。

kubectl get pods

Pod のステータスが「Running」となっていれば、Kubernetes クラスターは正常に動作しています 🎉

5. おわりに

ミニPCで Kubernetes を構築することで、手元で自由に試せる学習環境が手に入りました。
今後はこの環境を使って、アプリケーションのデプロイや監視、CI/CD の検証などにも挑戦していきます!

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?