1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 top = config.services.kubernetes;
7 cfg = top.flannel;
8
9 # we want flannel to use kubernetes itself as configuration backend, not direct etcd
10 storageBackend = "kubernetes";
11in
12{
13 ###### interface
14 options.services.kubernetes.flannel = {
15 enable = mkEnableOption (lib.mdDoc "flannel networking");
16 };
17
18 ###### implementation
19 config = mkIf cfg.enable {
20 services.flannel = {
21
22 enable = mkDefault true;
23 network = mkDefault top.clusterCidr;
24 inherit storageBackend;
25 nodeName = config.services.kubernetes.kubelet.hostname;
26 };
27
28 services.kubernetes.kubelet = {
29 cni.config = mkDefault [{
30 name = "mynet";
31 type = "flannel";
32 cniVersion = "0.3.1";
33 delegate = {
34 isDefaultGateway = true;
35 bridge = "mynet";
36 };
37 }];
38 };
39
40 networking = {
41 firewall.allowedUDPPorts = [
42 8285 # flannel udp
43 8472 # flannel vxlan
44 ];
45 dhcpcd.denyInterfaces = [ "mynet*" "flannel*" ];
46 };
47
48 services.kubernetes.pki.certs = {
49 flannelClient = top.lib.mkCert {
50 name = "flannel-client";
51 CN = "flannel-client";
52 action = "systemctl restart flannel.service";
53 };
54 };
55
56 # give flannel some kubernetes rbac permissions if applicable
57 services.kubernetes.addonManager.bootstrapAddons = mkIf ((storageBackend == "kubernetes") && (elem "RBAC" top.apiserver.authorizationMode)) {
58
59 flannel-cr = {
60 apiVersion = "rbac.authorization.k8s.io/v1";
61 kind = "ClusterRole";
62 metadata = { name = "flannel"; };
63 rules = [{
64 apiGroups = [ "" ];
65 resources = [ "pods" ];
66 verbs = [ "get" ];
67 }
68 {
69 apiGroups = [ "" ];
70 resources = [ "nodes" ];
71 verbs = [ "list" "watch" ];
72 }
73 {
74 apiGroups = [ "" ];
75 resources = [ "nodes/status" ];
76 verbs = [ "patch" ];
77 }];
78 };
79
80 flannel-crb = {
81 apiVersion = "rbac.authorization.k8s.io/v1";
82 kind = "ClusterRoleBinding";
83 metadata = { name = "flannel"; };
84 roleRef = {
85 apiGroup = "rbac.authorization.k8s.io";
86 kind = "ClusterRole";
87 name = "flannel";
88 };
89 subjects = [{
90 kind = "User";
91 name = "flannel-client";
92 }];
93 };
94
95 };
96 };
97
98 meta.buildDocsInSandbox = false;
99}