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 "flannel networking";
16
17 openFirewallPorts = mkOption {
18 description = ''
19 Whether to open the Flannel UDP ports in the firewall on all interfaces.'';
20 type = types.bool;
21 default = true;
22 };
23 };
24
25 ###### implementation
26 config = mkIf cfg.enable {
27 services.flannel = {
28
29 enable = mkDefault true;
30 network = mkDefault top.clusterCidr;
31 inherit storageBackend;
32 nodeName = config.services.kubernetes.kubelet.hostname;
33 };
34
35 services.kubernetes.kubelet = {
36 cni.config = mkDefault [{
37 name = "mynet";
38 type = "flannel";
39 cniVersion = "0.3.1";
40 delegate = {
41 isDefaultGateway = true;
42 bridge = "mynet";
43 };
44 }];
45 };
46
47 networking = {
48 firewall.allowedUDPPorts = mkIf cfg.openFirewallPorts [
49 8285 # flannel udp
50 8472 # flannel vxlan
51 ];
52 dhcpcd.denyInterfaces = [ "mynet*" "flannel*" ];
53 };
54
55 services.kubernetes.pki.certs = {
56 flannelClient = top.lib.mkCert {
57 name = "flannel-client";
58 CN = "flannel-client";
59 action = "systemctl restart flannel.service";
60 };
61 };
62
63 # give flannel some kubernetes rbac permissions if applicable
64 services.kubernetes.addonManager.bootstrapAddons = mkIf ((storageBackend == "kubernetes") && (elem "RBAC" top.apiserver.authorizationMode)) {
65
66 flannel-cr = {
67 apiVersion = "rbac.authorization.k8s.io/v1";
68 kind = "ClusterRole";
69 metadata = { name = "flannel"; };
70 rules = [{
71 apiGroups = [ "" ];
72 resources = [ "pods" ];
73 verbs = [ "get" ];
74 }
75 {
76 apiGroups = [ "" ];
77 resources = [ "nodes" ];
78 verbs = [ "list" "watch" ];
79 }
80 {
81 apiGroups = [ "" ];
82 resources = [ "nodes/status" ];
83 verbs = [ "patch" ];
84 }];
85 };
86
87 flannel-crb = {
88 apiVersion = "rbac.authorization.k8s.io/v1";
89 kind = "ClusterRoleBinding";
90 metadata = { name = "flannel"; };
91 roleRef = {
92 apiGroup = "rbac.authorization.k8s.io";
93 kind = "ClusterRole";
94 name = "flannel";
95 };
96 subjects = [{
97 kind = "User";
98 name = "flannel-client";
99 }];
100 };
101
102 };
103 };
104
105 meta.buildDocsInSandbox = false;
106}