こんにちは!
ネットワークコンテンツ研究会 Nekko Cloud Teamのいるまるです。
現在、Nekko Cloud TeamではプライベートKubernetes基盤の開発に取り組んでいます。Kubernetesクラスターを構築するにあたり、様々な方法が存在し、その選択に悩みました。そこで今回は「高可用なKubernetesクラスターの構築」に焦点を当て、いくつかの構築ツールを比較したいと思います。
今回は以下のツールを比較します。
- kubespray
- k0sctl
- k3s
間違いや、アップデートによる仕様変更等ありましたら、コメントにて教えて頂けるとありがたいです。
実験する構成について
今回は、高可用なKubernetesクラスター自体の構築ツールについて比較します。
そのため、CNIやkube-apiserverのロードバランサーなどKubernetes自体以外の部分は高可用構成となっていなかったり、詳しく説明されていなかったりします。
クラスターに使用するVMをセットアップ
今回の検証では以下のVMを3台作成しました。
- OS: ubuntu server 22.04 cloudimg
- CPU: 8Core
- RAM: 8GiB
- ROM: 32GiB
- 構築場所: ProxmoxVE(弊サークルのプライベートクラウド基盤を使用)
VMでは以下の設定を行いました。
- ssh鍵の設定
本記事で公開鍵としてk8s_test
の表記があるものは、すべてここで設定したものです。 - Firewallの無効化
クラスターのIPアドレス
図のVM名 | VMのホスト名 | VMのIPv4アドレス | VMのIPv6アドレス |
---|---|---|---|
haproxy | k8s-test-lb | 192.168.16.193 | fd12::be24:11ff:fe9d:af10 |
VM-1 | k8s-test-1 | 192.168.16.189 | fd12::be24:11ff:fe56:cf79 |
VM-2 | k8s-test-2 | 192.168.16.190 | fd12::be24:11ff:fe63:5121 |
VM-3 | k8s-test-3 | 192.168.16.191 | fd12::be24:11ff:fe14:e491 |
kubespray
概要
Kubesprayは、汎用的なOSやKubernetesクラスターの構成管理タスクのためのAnsibleプレイブック、インベントリー、プロビジョニングツール、ドメインナレッジをまとめたものです。
https://kubernetes.io/ja/docs/setup/production-environment/tools/kubespray/
kubesprayはkubernetes-sigsによりメンテナンスされている、AnsibleをベースとしたKubernetes clusterの構築ツールです。
kubesprayは、クラスター構成を設定ファイルに記述して、これを元にクラスターをデプロイします。
実験環境
kubesprayのセットアップ
PC-2で実行
git clone https://github.com/kubernetes-sigs/kubespray.git
cd kubespray
git branch -a
git switch remotes/origin/release-2.21 --detach
pip install requirements.txt
git switch
で実行したいkubesprayのバージョンを選択します。
pip
を使用するため、長期的に安定動作させたい場合や環境を汚したくない場合は、devcontainerを使用すると便利です。
cluster設定をする
PC-2で実行
-
inventory/sample
をinventory/test-cluster
にコピーする - VM-1~VM-3のSSH鍵を
inventory/test-cluster/k8s-test
へコピーする -
inventory/test-cluster/inventory.ini
を以下のように編集するinventory.ini[all] node1 ansible_host=192.168.16.189 ansible_user=ncadmin ip=192.168.16.189 etcd_member_name=etcd1 node2 ansible_host=192.168.16.190 ansible_user=ncadmin ip=192.168.16.190 etcd_member_name=etcd2 node3 ansible_host=192.168.16.191 ansible_user=ncadmin ip=192.168.16.191 etcd_member_name=etcd3 [kube_control_plane] node1 node2 node3 [etcd] node1 node2 node3 [kube_node] node1 node2 node3 [calico_rr] [k8s_cluster:children] kube_control_plane kube_node calico_rr
-
inventory/test-cluster/group_vars/k8s_cluster/k8s-cluster.yml
の以下の項目をtrueに編集する
inventory/test-cluster/artifacts
でkubeconfigを取得するために必要です# Make a copy of kubeconfig on the host that runs Ansible in {{ inventory_dir }}/artifacts kubeconfig_localhost: true # Use ansible_host as external api ip when copying over kubeconfig. kubeconfig_localhost_ansible_host: true # Download kubectl onto the host that runs Ansible in {{ bin_dir }} kubectl_localhost: true
クラスターをセットアップする
ansible-playbook -i inventory/test-cluster/inventory.ini --private-key inventory/test-cluster/k8s-test --become --become-user=root cluster.yml
処理が終われば、クラスターのセットアップは完了です。
クラスターをアップグレードする
inventory/test-cluster/group_vars/k8s_cluster/k8s-cluster.yml
の.kube_version
をアップグレード後のバージョンへ変更します。
アップグレードをPC-2で実行
ansible-playbook -i inventory/test-cluster/inventory.ini --private-key inventory/test-cluster/nc-k8s-test --become --become-user=root upgrade-cluster.yml
処理が終われば、クラスターのアップグレードは完了です。
実行時間
- セットアップ時間(1.29.7): 14分30秒
- アップグレード時間(1.29.7 -> 1.30.4): 25分17秒
注意事項
cluster再作成時は、kubesprayを一度削除し再作成する必要がありました。
kubesprayをそのまま使用した場合、artifactsがキャッシュされている?のか、なぜかkubeconfigが古いクラスターのまま更新されませんでした。
k0sctl
概要
Deploy and run Kubernetes workloads at any scale on any infrastructure.
All batteries included. 100% open source & free.
https://k0sproject.io/
k0sは単一のバイナリとして提供され、コントロールプレーンやノード上でKubernetesクラスターのセットアップやアップグレードに使用されます。各ノードに対してk0sを手動で1つずつセットアップすることも可能ですが、k0sctlを利用することで、1台の端末から複数のコントロールプレーンやノードを含むKubernetesクラスターを一括でセットアップできます。
k0sおよびk0sctlはMirantisによってメンテナンスされています。
k0sctlは、kubesprayと同様に設定ファイルを用いてクラスターの構成を定義し、これに基づいてクラスターをデプロイします。
実験環境
k0sctlのセットアップ
PC-2で実行
brew install k0sproject/k0sctl
クラスターのセットアップ
PC-2で以下の設定ファイルを作成
apiVersion: k0sctl.k0sproject.io/v1beta1
kind: Cluster
metadata:
name: k0s-cluster
spec:
hosts:
- role: controller+worker
ssh:
address: 192.168.16.189
user: ncadmin
keyPath: ../k8s-test
- role: controller+worker
ssh:
address: 192.168.16.190
user: ncadmin
keyPath: ../k8s-test
- role: controller+worker
ssh:
address: 192.168.16.191
user: ncadmin
keyPath: ../k8s-test
k0s:
version: 1.31.1+k0s.0
dynamicConfig: false
config:
spec:
network:
provider: "calico"
calico:
mode: "bird"
podCIDR: "172.18.0.0/16"
serviceCIDR: "172.19.0.0/16"
dualStack:
enabled: true
IPv6podCIDR: "fd3b:15a9:3b12:2002::/108"
IPv6serviceCIDR: "fd3b:15a9:3b12:2003::/108"
api:
externalAddress: 192.168.16.193
sans:
- 192.168.16.189
- 192.168.16.190
- 192.168.16.191
PC-2で実行
k0sctl apply --config k0sctl.yaml
処理が終われば、クラスターのセットアップは完了です。
kubeconfigの取得
PC-2で実行
k0sctl kubeconfig --config k0sctl.yaml > config
アップグレード方法
k0sctl.yaml
の.spec.k0s.version
を変更します。
インストール時と同じコマンドをPC-2で実行
k0sctl apply --config k0sctl.yaml
処理が終われば、クラスターのアップグレードは完了です。
実行時間
- セットアップ時間(v1.30.5): 1分24秒
- アップグレード時間(v1.30.5 -> v1.31.1): 2分12秒
k3s
概要
The certified Kubernetes distribution built for IoT & Edge computing
https://k3s.io/
リソースが限られた環境向けに構築された、非常に軽量なKubernetesディストリビューションです。
k3sはRancherによって開発され、現在はCNCFのサンドボックスプロジェクトとして運営されています。
k3sでは、最初のノードのセットアップ時にクラスターが作成され、同時にトークンが生成されます。2台目以降のノードは、このトークンを使用してクラスターに参加する形式を採用しています。
実験環境
1台目のセットアップ
VM-1で実行
// 1台目のセットアップ
curl -sfL https://get.k3s.io | K3S_TOKEN=SECRET INSTALL_K3S_VERSION=v1.29.9+k3s1 sh -s - server \
--node-taint CriticalAddonsOnly=true:NoExecute \
--cluster-init \
--tls-san=fd12::be24:11ff:fe9d:af10
// tokenの取得
sudo cat /var/lib/rancher/k3s/server/node-token
// 結果
K1006aefec7cc45005796b2bbdf9ad8e751f9a5befd065c78727fb27e8d380ff4d3::server:SECRET
2台目以降のセットアップ
VM-2とVM-3で実行
※K3S_TOKEN=の値をVM-1で取得したtokenに書き換え
curl -sfL https://get.k3s.io | K3S_TOKEN=K1006aefec7cc45005796b2bbdf9ad8e751f9a5befd065c78727fb27e8d380ff4d3::server:SECRET INSTALL_K3S_VERSION=v1.29.9+k3s1 sh -s - server \
--node-taint CriticalAddonsOnly=true:NoExecute \
--server https://[fd12::be24:11ff:fe9d:af10]:6443
アップグレード方法
インストール時に使用したコマンドに、INSTALL_K3S_VERSION
オプションを追加する形でアップグレードします。
VM-1で実行
curl -sfL https://get.k3s.io | K3S_TOKEN=SECRET INSTALL_K3S_VERSION=v1.30.5+k3s1 sh -s - server \
--node-taint CriticalAddonsOnly=true:NoExecute \
--cluster-init \
--tls-san=fd12::be24:11ff:fe9d:af10
VM-2とVM-3で実行
curl -sfL https://get.k3s.io | K3S_TOKEN=K1006aefec7cc45005796b2bbdf9ad8e751f9a5befd065c78727fb27e8d380ff4d3::server:SECRET INSTALL_K3S_VERSION=v1.30.5+k3s1 sh -s - server \
--node-taint CriticalAddonsOnly=true:NoExecute \
--server https://[fd12::be24:11ff:fe9d:af10]:6443
実行時間
セットアップとアップグレード両方とも数秒程度で完了しました。
Podのデプロイに関して
k0sctlとk3sは、初期状態ではコントロールプレーンが設定されたノードにPodがデプロイできません。
そのため、Nodeに設定されたTaintを削除する必要があります。
Taintの削除方法
Taintの確認
kubectl describe nodes | grep Taints
Taintの削除
kubectl taint nodes k8s-test-1 CriticalAddonsOnly=true:NoExecute-
まとめ
実行時間
実行時間は以下のようになりました。
セットアップ実行時間 | アップグレード実行時間 | |
---|---|---|
kubespray | 14分30秒 | 25分17秒 |
k0sctl | 1分24秒 | 2分12秒 |
k3s | 数秒程度 | 数秒程度 |
セットアップ・アップグレード
k3sでは、クラスター内の各VMに対して直接コマンドを実行する必要がありますが、クラスター外の端末を使用しなくて済むというメリットがあります。
一方で、k0sctlとkubesprayは、どちらもクラスター外の端末から設定ファイルを元にSSHを用いて、遠隔でデプロイを行います。
そのため、デプロイ時の冪等性を重視する場合は、k0sctlやkubesprayの方が便利でしょう。
結論
結論として、弊サークルのKubernetesクラスター構築ツールは、現時点(調査時点)ではkubesprayを採用する予定です。
その理由は以下の通りです。
- クラスター構成をテスト環境と一致させる冪等性を考慮すると、k0sctlまたはkubesprayが適している
- k0sctlはエラー発生時のログが、kubesprayよりも読みづらかった
なお、これらのツールを使用して構築するクラスターは同じKubernetesであるものの、利用できる機能や構成に差異があります。そのため、構築ツールの選定にあたっては、利便性以外の要素も考慮する必要があります。
例えば、以下の要素が挙げられます。
- リソースの限られたクラスターを構築する場合はk3sが選択肢に入る
- 自動アップグレードが必要な場合はk3sが有力な候補となる
- 使用したいCNIがサポートされている構築ツールの確認が必要
- 複雑な構成のクラスターを構築する際、テストしやすいツールの選定が重要
おまけ
ProxmoxVEで今回のような検証をする場合、スナップショットを活用すると、以下のようなときに便利です。
- クラスター構築に失敗して、OSインストール直後の状態に戻したい
- 現在の状態を残して、別の検証がしたい
参考文献
https://kubespray.io/#/
https://docs.k0sproject.io/head
https://docs.k3s.io/ja/
https://www.the38.page/posts/high-availability-k3s-cluster-setup/