通常 k3s を動かす場合、内蔵されている Flannel が CNI プラグインとして使用されます。 Flannel の代わりに Cilium を使うような構成を NixOS 上に立ち上げた k3s で試してみました。モチベーションは昨日の記事と同じなのでそちらを参照してください。
Cilium のドキュメントを見ると k3s でセットアップするための方法が記載されています。そのため基本的にはこのまま実行すれば良いのですが、NixOS ならではのハマりポイントがいくつかありました。
まず services.k3s の設定は以下のようにしておきます。ここは(ドキュメントとは異なりますが)特に注意すべき点はありません。--disable 系は一部不要かもしれませんが、せっかく Cilium を使うので全部無効化しておきます:
services.k3s = {
enable = true;
role = "server";
extraFlags = [
"--flannel-backend=none"
"--disable-kube-proxy"
"--disable-network-policy"
"--disable=servicelb"
"--disable=traefik"
"--cluster-cidr=10.42.0.0/16"
"--service-cidr=10.43.0.0/16"
];
};
続いて networking.firewall の設定を変更します。ここがハマったポイントで、以下のようにする必要があります:
networking.firewall = {
enable = true;
checkReversePath = "loose"; # ⭐1
trustedInterfaces = ["cilium+" "lxc+"]; # ⭐2
};
まず ⭐1 のように rp_filter を loose に設定する必要があります。これを設定しないと Pod から外部への通信が i/o timeout で失敗し、CoreDNS から以下のようなエラーが出続けます:
[ERROR] plugin/errors: 2 2532755807340784672.2812310023070862898. HINFO: read udp 10.42.0.210:47894->192.168.1.1:53: i/o timeout
次に ⭐2 のように cilium または lxc をプレフィックスに持つ NIC の通信を許可します。これを設定しないと Pod から Kubernetes API サーバへの通信ができず、CoreDNS から以下のようなエラーが出続けます:
[INFO] plugin/ready: Plugins not ready: "kubernetes"
以上を設定した後 k3s を起動し、Cilium のマニフェストを apply します。以下のような Grafana Tanka のコードで生成されたマニフェストを使用しました:
local k = import '../lib/k.libsonnet';
local tanka = import 'github.com/grafana/jsonnet-libs/tanka-util/main.libsonnet';
local helm = tanka.helm.new(std.thisFile);
[
# k.namespace() は想像どおりの Namespace リソースを作ってくれるユーティリティー関数。
k.namespace(name='cilium-system'),
helm.template('app', '../charts/cilium', {
namespace: 'cilium-system',
includeCrds: true,
values: {
operator: {
replicas: 1,
},
hubble: {
enabled: false,
},
envoy: {
enabled: false,
},
ipam: {
operator: {
clusterPoolIPv4PodCIDRList: [
'10.42.0.0/16',
],
},
},
k8sServiceHost: '192.168.1.171', # ノードの IP アドレス
k8sServicePort: 6443,
kubeProxyReplacement: true,
},
}),
]