NixOSで好きなコンテナランタイム・CNIを使用してKubernetesを構築する
2025/06/19
はじめに
NixOS は宣言的に構成を定義できるLinuxディストリビューションです。
KubernetesもNixOS上で宣言的に構築できるのですが、この方法を使用した場合、コンテナランタイムにContainerd、CNIにFlannelを使用する構成に限定されてしまいます。
デフォルトで設定されるContainerdやFlannelを明示的に無効化したり別途他のコンテナランタイムやCNIを有効化することはできますが、 Kubernetesと組み合わせて動作させることができませんでした。 (このあたりやこのあたりを見る限り、ContainerdやFlannelを使うことが前提とされているのだと思います。)
当方ではコンテナランタイムとしてCRI-O、CNIとしてCiliumを使用したかったので、NixOSでこれらを使用するKubernetesを構築しました。
NixOSのバージョンは25.05です。
一言でいうと
NixOSでの構成はKubeletやKubeadm、およびSystemd service unit fileを設定するにとどめ、クラスタ自体はKubeadmで構築する。
configuration.nix
パッケージとしてkubectlやkubernetes、cilium-cliを設定し、コマンドを使用できるようにします。
environment.systemPackages = with pkgs; [
(中略)
cri-o
kubectl
kubernetes
cilium-cli
];
コンテナランタイムであるCRI-Oを有効化します。storageDriverはお好みですが、当環境ではbtrfsを使用しています。また後ほどCiliumをインストールするため、そのインストール先となる /opt/cni/bin をCNIプラグインのパスに設定します。
virtualisation.cri-o = {
enable = true;
storageDriver = "btrfs";
settings.crio.network.plugin_dirs = [ "/opt/cni/bin" ];
};
KubeletをSystemdで起動できるようにします。以下の内容はKubeletの配布物のUnitファイルにKubeadmでセットアップする際のDrop-inを反映した内容にしています。これにより、後でKubeadmを使ってKubernetesクラスタをセットアップしたときに使用できる状態にします。
systemd.services.kubelet = {
enable = true;
description = "kubelet: The Kubernetes Node Agent";
documentation = [ "https://kubernetes.io/docs/" ];
path =
with pkgs;
[
util-linux
iproute2
ethtool
iptables
kubernetes
];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {
Environment= [
"\"KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf\""
"\"KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml\""
];
EnvironmentFile = [
"/var/lib/kubelet/kubeadm-flags.env"
];
Restart = "always";
RestartSec = "10";
ExecStart = "${pkgs.kubernetes}/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS";
};
unitConfig = {
StartLimitInterval = "0";
};
wantedBy = [ "multi-user.target" ];
};
kubeadm
あとはKubernetesのドキュメント にあるように通常通りkubeadmによってクラスターを作成します。
当方ではコンフィグファイルで作成しています。
# kubeadm init --config=kubeadm-init.yaml
設定等はお好みですが、当方ではCRI-Oを使用するためにCRIのソケットとしてCRI-Oのパスを設定しています。
$ cat kubeadm-init.yaml
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
(中略)
nodeRegistration:
criSocket: unix:///var/run/crio/crio.sock
CNIをインストールします。当方ではCiliumを使うためCiliumのCLIでインストールします。
$ cilium install
おわりに
宣言型を守れなかったよ。。。