blog.anqou.net
rss
author
tags

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

通常 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,
    },
  }),
]