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