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 hairpinMode = true;
45 bridge = "mynet";
46 };
47 }
48 ];
49 };
50
51 networking = {
52 firewall.allowedUDPPorts = lib.mkIf cfg.openFirewallPorts [
53 8285 # flannel udp
54 8472 # flannel vxlan
55 ];
56 dhcpcd.denyInterfaces = [
57 "mynet*"
58 "flannel*"
59 ];
60 };
61
62 services.kubernetes.pki.certs = {
63 flannelClient = top.lib.mkCert {
64 name = "flannel-client";
65 CN = "flannel-client";
66 action = "systemctl restart flannel.service";
67 };
68 };
69
70 # give flannel some kubernetes rbac permissions if applicable
71 services.kubernetes.addonManager.bootstrapAddons =
72 lib.mkIf ((storageBackend == "kubernetes") && (lib.elem "RBAC" top.apiserver.authorizationMode))
73 {
74
75 flannel-cr = {
76 apiVersion = "rbac.authorization.k8s.io/v1";
77 kind = "ClusterRole";
78 metadata = {
79 name = "flannel";
80 };
81 rules = [
82 {
83 apiGroups = [ "" ];
84 resources = [ "pods" ];
85 verbs = [ "get" ];
86 }
87 {
88 apiGroups = [ "" ];
89 resources = [ "nodes" ];
90 verbs = [
91 "list"
92 "watch"
93 ];
94 }
95 {
96 apiGroups = [ "" ];
97 resources = [ "nodes/status" ];
98 verbs = [ "patch" ];
99 }
100 ];
101 };
102
103 flannel-crb = {
104 apiVersion = "rbac.authorization.k8s.io/v1";
105 kind = "ClusterRoleBinding";
106 metadata = {
107 name = "flannel";
108 };
109 roleRef = {
110 apiGroup = "rbac.authorization.k8s.io";
111 kind = "ClusterRole";
112 name = "flannel";
113 };
114 subjects = [
115 {
116 kind = "User";
117 name = "flannel-client";
118 }
119 ];
120 };
121
122 };
123 };
124
125 meta.buildDocsInSandbox = false;
126}