通常 k3s を動かす場合、内蔵されている Flannel が CNI プラグインとして使用されます。ただこの仕組みだと Tailscale Operator を使用した際にクライアントから Pod へ direct connection を張れないという不具合があり、ずっと悩んでいました。最近これが既知の不具合であることを知り、
Flannel の代わりに Calico を使った上で MASQFullyRandom=false を設定すると解決できるという
ワークアラウンドを知ったので早速 NixOS 上に立てた k3s で試してみました。結論からいうと Calico をインストールしてセットアップすることはできたのですが Tailscale の問題は治りませんでした。が、Calico のセットアップまでも一波瀾あったのでまとめます。
Calico のドキュメントを確認すると k3s で使用する場合のセットアップが書かれているので、基本的にはこのドキュメント通りに作業します。まず services.k3s を以下のように設定します:
services.k3s = {
enable = true;
role = "server";
extraFlags = [
# cf. https://docs.tigera.io/calico/latest/getting-started/kubernetes/k3s/quickstart
"--flannel-backend=none"
"--cluster-cidr=10.42.0.0/16"
"--disable-network-policy"
"--disable=traefik"
];
};
ここで --cluster-cidr= を適当な値に設定することに注意してください。ホストの LAN の IP レンジと被らないことが重要です。後述する Calico の設定で同じ IP レンジを指定します[1]。
この状態で nixos-rebuild switch して k3s を立ち上げると、k3s が立ち上げようとするシステム用の Pod が ContainerCreating の状態で止まります。これは正常で、CNI プラグインが存在しないためだと思われます。そこで、
Calico のマニフェストを適用し Calico を立ち上げます。自分はマニフェストの管理に Grafana Tanka を使用しているので、以下のような Jsonnet のコードを書いてマニフェストを生成し、これを適当に 1 枚の YAML ファイルに固めて kubectl apply で適用します。Jsonnet を使う必要はなく helm template とかを実行しても同様のことが実現できると思います。
values.yaml の ipPools に k3s へ渡した CIDR を指定するようにしてください:
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='calico-system'),
k.namespace(name='tigera-operator'),
helm.template('app', '../charts/crd.projectcalico.org.v1', {
includeCrds: true,
values: {},
}),
helm.template('app', '../charts/tigera-operator', {
namespace: 'tigera-operator',
includeCrds: true,
values: {
installation: {
calicoNetwork: {
ipPools: [
{
# k3s の --cluster-cidr と同じレンジを指定する。
cidr: '10.42.0.0/16',
},
],
},
},
defaultFelixConfiguration: {
enabled: true,
# Tailscale の既知の不具合を解消するための設定。
# (ただし効果はなかった。)
featureDetectOverride: 'MASQFullyRandom=false',
},
},
}),
]
注釈
-
デフォルトだと Calico は 192.168.0.0/16 を使用します。これがホストの LAN の IP レンジとかぶると DNS による名前解決が行えなくなります(一敗)。 ↩