kubeadmベースのKubernetesクラスタをワンコマンドで構築するsetup-k8sを作った

12 min read

はじめに

Kubernetesクラスタを簡単に構築する方法はいくつかあります。

たとえば、k3sなら以下でインストールできます。

curl -sfL https://get.k3s.io | sh -

k0sなら以下のようにsingle node clusterを構築できます。

curl -sSf https://get.k0s.sh | sudo sh
sudo k0s install controller --single
sudo k0s start

minikubeなら以下です。

minikube start

このように、軽量Kubernetesディストリビューションやローカル開発向けツールでは、かなり簡単にKubernetes環境を作れます。

ただし、いわゆる素のKubernetes、つまりkubeadmベースのKubernetesクラスタを同じくらい簡単に作ろうとすると、意外と面倒です。

kubeadmを使う場合、公式に近い構成でKubernetesクラスタを作れます。 一方で、実際に構築するには、container runtimeの準備、swapやsysctlの設定、カーネルモジュール、kubeadm/kubelet/kubectlのインストール、kubeadm init、kubeconfig配置、worker node join、CNI導入など、いくつかの作業が必要になります。

k3sやk0sは、このあたりをかなりまとめてくれます。 single binaryや統合パッケージとして扱えるので、構築はとても簡単です。

ただ、その便利さの代わりに、コンポーネントの構成が通常のkubeadmクラスタとは少し違います。

たとえば、containerdなどのruntimeがディストリビューション側に統合されている構成では、Kubernetes本体、container runtime、CRI、kubelet、kube-proxyなどを本番と同じような粒度で差し替えたり検証したりする用途には向かない場合があります。

特に、Kata ContainersのようなRuntimeClassやcontainer runtime周りを検証したい場合、軽量Kubernetesディストリビューションよりも、kubeadmベースで構築したクラスタの方が見通しが良いことがあります。

本番環境に近いKubernetesを使いたい。 でも、構築はk3sやminikubeのように簡単にしたい。

そのために setup-k8s を作りました。

リポジトリはこちらです。 https://github.com/MuNeNiCK/setup-k8s

Docsはこちらです。 https://munenick.github.io/setup-k8s/

setup-k8sとは

setup-k8s は、kubeadmベースのKubernetesクラスタをワンコマンドで構築するためのシェルスクリプトです。

以下のコマンドでKubernetesが構築できます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- init

これで、現在のマシンをKubernetesのcontrol-plane nodeとして初期化できます。

user@ubuntu-24:~$ kubectl get node
NAME        STATUS     ROLES           AGE   VERSION
ubuntu-24   NotReady   control-plane   8s    v1.36.1
user@ubuntu-24:~$ kubectl get pod -A
NAMESPACE     NAME                                READY   STATUS    RESTARTS   AGE
kube-system   coredns-589f44dc88-kf5vj            0/1     Pending   0          1s
kube-system   coredns-589f44dc88-w7jnj            0/1     Pending   0          1s
kube-system   etcd-ubuntu-24                      0/1     Running   0          9s
kube-system   kube-apiserver-ubuntu-24            0/1     Running   0          9s
kube-system   kube-controller-manager-ubuntu-24   0/1     Running   0          9s
kube-system   kube-proxy-v2jhh                    1/1     Running   0          2s
kube-system   kube-scheduler-ubuntu-24            1/1     Running   0          9s
user@ubuntu-24:~$

大きな特徴は、マルチディストリビューション対応です。

Ubuntuであっても、Debianであっても、Rocky Linuxであっても、AlmaLinuxであっても、Fedoraであっても、openSUSEであっても、Alpine Linuxであっても、Arch Linuxであっても、同じコマンドでKubernetesクラスタを構築できます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- init

内部では、ディストリビューションを自動検出し、apt、dnf/yum、zypper、apk、pacmanなどを使い分けます。

Kubernetesの構築手順は似ていますが、OSごとの差分は意外とあります。

パッケージ管理、必要なリポジトリ、container runtime、service manager、cgroup、iptables/nftablesまわりなど、ディストリビューションごとに細かい差分があります。

setup-k8s は、その差分を吸収し、同じ入口からkubeadmベースのKubernetesクラスタを作れるようにしています。

対応ディストリビューションは以下です。

ディストリビューション バージョン
Ubuntu 24.04 LTS, 22.04 LTS
Debian 13 (Trixie), 12 (Bookworm), 11 (Bullseye)
CentOS Stream 10, 9
Rocky Linux 10, 9, 8
AlmaLinux 10, 9, 8
Oracle Linux 9
Fedora 44, 43
openSUSE Tumbleweed, Leap 16.0
Alpine Linux 3.23
Arch Linux Rolling

最新の対応状況はDocsにまとめています。

https://munenick.github.io/setup-k8s/supported-distros/

スクリプト内部では以下のようなことが行われます。

- 必要なパッケージのインストール
- container runtimeの設定
- swapの無効化
- カーネルモジュールやsysctlの設定
- kubeadm / kubelet / kubectlのインストール
- kubeadm init
- kubeconfigの配置

つまり、kubeadmでKubernetesクラスタを作るための定型作業をまとめて実行しています。

まずは単一ノードクラスタを作る

検証用で一番よく使うのは、単一ノードのKubernetesクラスタだと思います。

VMや物理マシンを1台用意して、以下を実行します。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- init

これでcontrol-plane nodeが初期化されます。

初期化後、CNI pluginをインストールします。 たとえばCalicoを使う場合は以下です。

kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

単一ノードクラスタとして使う場合は、control-plane node上でもPodを動かせるようにtaintを外します。

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

状態を確認します。

kubectl get nodes
kubectl get pods -A

これで、kubeadmベースの単一ノードKubernetesクラスタとして使えます。

worker nodeを追加する

複数ノードクラスタにしたい場合は、worker nodeをjoinします。

まず、control-plane node側でjoin commandの情報を確認します。

kubeadm token create --print-join-command

worker node側では、以下のように join を実行します。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  join \
  --join-token <token> \
  --join-address <address> \
  --discovery-token-hash <hash>

worker node側でも、必要なパッケージやcontainer runtimeをセットアップしたうえで、kubeadm join を実行します。

control-plane nodeだけでなく、worker node側の準備も同じスクリプトでできます。

複数ノードクラスタもワンコマンドで作る

1台ずつSSHしてセットアップするのも面倒です。

そこで、setup-k8s には deploy サブコマンドを用意しています。

deploy を使うと、作業端末やCI runnerなどの端末からSSHで各ノードへ接続し、複数ノードのKubernetesクラスタを一括構築できます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sh -s -- \
  deploy \
  --control-planes root@192.168.1.10 \
  --workers root@192.168.1.11,root@192.168.1.12 \
  --ssh-key ~/.ssh/id_rsa

リモートノードへSSH接続でき、リモート側でsudoできれば構築できます。

内部的には、各ノードへ自己完結したbundleを転送し、最初のcontrol-plane nodeを初期化し、その後worker nodeをjoinします。

複数ノードの検証環境を作る場合は、この使い方を推奨します。

HA control planeも作れる

control-plane nodeを複数台にしたHA構成にも対応しています。

kube-vipを使ってVIPを持たせる場合は、--ha-vip を指定します。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sh -s -- \
  deploy \
  --control-planes root@192.168.1.10,root@192.168.1.11,root@192.168.1.12 \
  --workers root@192.168.1.20 \
  --ha-vip 192.168.1.100 \
  --ssh-key ~/.ssh/id_rsa

--ha-vip を指定すると、kube-vipを使ったHA control plane構成になります。

外部ロードバランサを別途用意せずに、VIPベースのkubeadm HA構成を作れます。

containerd / CRI-Oを選べる

container runtimeは、デフォルトではcontainerdを使います。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- init

CRI-Oを使いたい場合は、--cri crio を指定します。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  init \
  --cri crio

worker nodeや追加control-plane nodeをjoinする場合は、既存クラスタと同じCRIを指定してください。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  join \
  --cri crio \
  --join-token <token> \
  --join-address <address> \
  --discovery-token-hash <hash>

Kubernetesバージョンを指定する

Kubernetesのバージョンは --kubernetes-version で指定できます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  init \
  --kubernetes-version 1.33.2

minor versionだけを指定することもできます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  init \
  --kubernetes-version 1.33

検証環境では、特定バージョンのKubernetesを素早く作りたいことがあります。

たとえば、CNI、CSI、Ingress Controller、Operator、RuntimeClassなどの互換性を確認したい場合です。 その場合に、バージョンを指定してクラスタを作れるようにしています。

kube-proxy modeを選べる

setup-k8s では、kube-proxy modeとして iptablesipvsnftables を選択できます。

デフォルトは iptables です。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  init \
  --proxy-mode iptables

IPVSを使う場合は以下です。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  init \
  --proxy-mode ipvs

nftablesを使う場合は以下です。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  init \
  --proxy-mode nftables \
  --kubernetes-version 1.31

新しくクラスタを作るだけなら、まずはデフォルトのiptablesで良いと思います。

IPVSやnftablesは、既存環境との互換性や検証目的がある場合に使う想定です。 特にnftablesはKubernetesやカーネル側の要件があるため、利用前にDocsを確認してください。

IPv4 / IPv6 / dual-stack

Pod CIDRとService CIDRも指定できます。

IPv4の場合は以下です。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  init \
  --pod-network-cidr 192.168.0.0/16 \
  --service-cidr 10.96.0.0/12

dual-stackの場合は、IPv4とIPv6のCIDRをカンマ区切りで指定します。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  init \
  --pod-network-cidr 10.244.0.0/16,fd00:10:244::/48 \
  --service-cidr 10.96.0.0/12,fd00:20::/108

IPv6 single-stackも指定できます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  init \
  --pod-network-cidr fd00:10:244::/48 \
  --service-cidr fd00:20::/108

実際に利用するには、CNI plugin側もそのaddress familyに対応している必要があります。

preflightで事前確認する

いきなりクラスタを作るのが不安な場合は、preflight を実行できます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- preflight

join前提で確認したい場合は、--mode join を指定します。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  preflight \
  --mode join

initjoin を実行する前に、必要な条件を満たしているか確認できます。

statusで状態を確認する

クラスタやノードの状態を確認したい場合は、status を使います。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sh -s -- status

より詳細に確認する場合は --output wide を指定します。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sh -s -- status --output wide

kubeletやcontainer runtimeの状態、Kubernetesコンポーネントのバージョン、kubectlが使える場合はnodeやpodの状態などを確認します。

cleanupで消す

検証が終わったら、cleanup でKubernetes関連の設定を削除できます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- cleanup --force

worker nodeをクラスタから外す場合は、先にcontrol-plane側でdrainとdeleteを行います。

kubectl drain <worker-node-name> --ignore-daemonsets
kubectl delete node <worker-node-name>

その後、worker node側でcleanupを実行します。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- cleanup --force

control-plane nodeでcleanupを実行すると、クラスタ自体を壊す操作になります。 実行対象は必ず確認してください。

upgrade / backup / restore / renewもできる

setup-k8s は、クラスタ構築だけでなく、いくつかの運用操作にも対応しています。

ただ、この記事の主題はワンコマンドで簡単にkubeadmクラスタを作ることなので、ここでは概要だけ紹介します。

Kubernetesをアップグレードする場合は upgrade を使います。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  upgrade \
  --kubernetes-version 1.33.2 \
  --first-control-plane

etcd snapshotを取得する場合は backup を使います。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- backup

snapshotから復元する場合は restore を使います。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  restore \
  --snapshot-path /path/to/snapshot.db

kubeadm証明書を確認・更新する場合は renew を使います。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- \
  renew \
  --check-only
curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- renew

どういう時に使うか

setup-k8s は、主に以下のような場面を想定しています。

kubeadmクラスタを簡単に作りたい

k3sやk0sやminikubeのように簡単に、でもkubeadmベースのKubernetesクラスタを作りたい場合に使えます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sudo sh -s -- init

このコマンドだけでcontrol-plane nodeを初期化できます。

違うディストリビューションで同じように構築したい

Ubuntu、Debian、Rocky Linux、AlmaLinux、Fedora、openSUSE、Alpine Linux、Arch Linuxなどで、同じコマンドからKubernetesクラスタを構築できます。

ディストリビューションごとにパッケージ管理や前提設定が違うため、手作業でやると地味に面倒です。

setup-k8s ではそこを自動検出し、できるだけ同じ体験で構築できるようにしています。

本番に近いKubernetesを検証したい

軽量Kubernetesディストリビューションではなく、実際のLinux node上でkubelet、container runtime、CNI、kube-proxyを動かしたい場合に使えます。

containerdやCRI-Oを明示的に選びたい場合、RuntimeClassやKata Containersを試したい場合、kube-proxy modeを変えたい場合などは、kubeadmベースの構成の方が扱いやすいです。

複数ノードクラスタを簡単に作りたい

deploy を使えば、SSH経由で複数ノードクラスタをまとめて構築できます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sh -s -- \
  deploy \
  --control-planes root@192.168.1.10 \
  --workers root@192.168.1.11,root@192.168.1.12

1台ずつ手でjoinするよりも楽です。

HA control planeを試したい

kube-vipを使ったHA control plane構成も作れます。

curl -fsSL https://github.com/MuNeNiCK/setup-k8s/raw/main/setup-k8s.sh | sh -s -- \
  deploy \
  --control-planes root@192.168.1.10,root@192.168.1.11,root@192.168.1.12 \
  --workers root@192.168.1.20 \
  --ha-vip 192.168.1.100

注意点

setup-k8s ではCNIを提供していません。

init 後には、利用するCNI pluginを別途インストールしてください。

kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

また、initjoincleanupupgradebackuprestorerenew など、ノードを変更する操作は基本的にroot権限が必要です。

remote deployの場合、作業端末側にroot権限は不要ですが、リモートノード側にはSSH接続とsudo権限が必要です。

cleanupやrestoreは破壊的な操作です。 実行対象を間違えないようにしてください。

おわりに

Kubernetesを簡単に構築する方法はすでにあります。

k3s、k0s、minikubeはとても便利です。 軽く試すだけなら、それらを使うのが一番簡単だと思います。

ただ、kubeadmベースのKubernetesクラスタを、本番に近い構成で、でも簡単に作りたいことがあります。

container runtimeを明示的に選びたい。 CRI-Oを使いたい。 Kata Containersを試したい。 kube-proxy modeを変えたい。 HA control planeをkubeadmで試したい。 複数ディストリビューションでKubernetesを検証したい。

そういう時に、毎回kubeadmのセットアップ手順を手で実行するのは面倒です。

setup-k8s は、その面倒な部分をまとめて、kubeadmベースのKubernetesクラスタをできるだけ簡単に構築できるようにするためのツールです。

興味があれば試してみてください。