blog.anqou.net
rss
author
tags

NixOS + k3s に Calico を入れて動かす

通常 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.yamlipPools に 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',
      },
    },
  }),
]

注釈

  1. デフォルトだと Calico は 192.168.0.0/16 を使用します。これがホストの LAN の IP レンジとかぶると DNS による名前解決が行えなくなります(一敗)。