summary refs log tree commit diff
path: root/nixos/modules/services/networking/flannel.nix
blob: 4c040112d28d473374e1c022c3e10afd1832b66d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
{ config, lib, pkgs, ... }:

with lib;

let
  cfg = config.services.flannel;

  networkConfig = filterAttrs (n: v: v != null) {
    Network = cfg.network;
    SubnetLen = cfg.subnetLen;
    SubnetMin = cfg.subnetMin;
    SubnetMax = cfg.subnetMax;
    Backend = cfg.backend;
  };
in {
  options.services.flannel = {
    enable = mkEnableOption "flannel";

    package = mkOption {
      description = "Package to use for flannel";
      type = types.package;
      default = pkgs.flannel;
      defaultText = "pkgs.flannel";
    };

    publicIp = mkOption {
      description = ''
        IP accessible by other nodes for inter-host communication.
        Defaults to the IP of the interface being used for communication.
      '';
      type = types.nullOr types.str;
      default = null;
    };

    iface = mkOption {
      description = ''
        Interface to use (IP or name) for inter-host communication.
        Defaults to the interface for the default route on the machine.
      '';
      type = types.nullOr types.str;
      default = null;
    };

    etcd = {
      endpoints = mkOption {
        description = "Etcd endpoints";
        type = types.listOf types.str;
        default = ["http://127.0.0.1:2379"];
      };

      prefix = mkOption {
        description = "Etcd key prefix";
        type = types.str;
        default = "/coreos.com/network";
      };

      caFile = mkOption {
        description = "Etcd certificate authority file";
        type = types.nullOr types.path;
        default = null;
      };

      certFile = mkOption {
        description = "Etcd cert file";
        type = types.nullOr types.path;
        default = null;
      };

      keyFile = mkOption {
        description = "Etcd key file";
        type = types.nullOr types.path;
        default = null;
      };
    };

    kubeconfig = mkOption {
      description = ''
        Path to kubeconfig to use for storing flannel config using the
        Kubernetes API
      '';
      type = types.nullOr types.path;
      default = null;
    };

    network = mkOption {
      description = " IPv4 network in CIDR format to use for the entire flannel network.";
      type = types.str;
    };

    nodeName = mkOption {
      description = ''
        Needed when running with Kubernetes as backend as this cannot be auto-detected";
      '';
      type = types.nullOr types.str;
      default = with config.networking; (hostName + optionalString (domain != null) ".${domain}");
      example = "node1.example.com";
    };

    storageBackend = mkOption {
      description = "Determines where flannel stores its configuration at runtime";
      type = types.enum ["etcd" "kubernetes"];
      default = "etcd";
    };

    subnetLen = mkOption {
      description = ''
        The size of the subnet allocated to each host. Defaults to 24 (i.e. /24)
        unless the Network was configured to be smaller than a /24 in which case
        it is one less than the network.
      '';
      type = types.int;
      default = 24;
    };

    subnetMin = mkOption {
      description = ''
        The beginning of IP range which the subnet allocation should start with.
        Defaults to the first subnet of Network.
      '';
      type = types.nullOr types.str;
      default = null;
    };

    subnetMax = mkOption {
      description = ''
        The end of IP range which the subnet allocation should start with.
        Defaults to the last subnet of Network.
      '';
      type = types.nullOr types.str;
      default = null;
    };

    backend = mkOption {
      description = "Type of backend to use and specific configurations for that backend.";
      type = types.attrs;
      default = {
        Type = "vxlan";
      };
    };
  };

  config = mkIf cfg.enable {
    systemd.services.flannel = {
      description = "Flannel Service";
      wantedBy = [ "multi-user.target" ];
      after = [ "network.target" ];
      environment = {
        FLANNELD_PUBLIC_IP = cfg.publicIp;
        FLANNELD_IFACE = cfg.iface;
      } // optionalAttrs (cfg.storageBackend == "etcd") {
        FLANNELD_ETCD_ENDPOINTS = concatStringsSep "," cfg.etcd.endpoints;
        FLANNELD_ETCD_KEYFILE = cfg.etcd.keyFile;
        FLANNELD_ETCD_CERTFILE = cfg.etcd.certFile;
        FLANNELD_ETCD_CAFILE = cfg.etcd.caFile;
        ETCDCTL_CERT_FILE = cfg.etcd.certFile;
        ETCDCTL_KEY_FILE = cfg.etcd.keyFile;
        ETCDCTL_CA_FILE = cfg.etcd.caFile;
        ETCDCTL_PEERS = concatStringsSep "," cfg.etcd.endpoints;
      } // optionalAttrs (cfg.storageBackend == "kubernetes") {
        FLANNELD_KUBE_SUBNET_MGR = "true";
        FLANNELD_KUBECONFIG_FILE = cfg.kubeconfig;
        NODE_NAME = cfg.nodeName;
      };
      path = [ pkgs.iptables ];
      preStart = ''
        mkdir -p /run/flannel
        touch /run/flannel/docker
      '' + optionalString (cfg.storageBackend == "etcd") ''
        echo "setting network configuration"
        until ${pkgs.etcdctl}/bin/etcdctl set /coreos.com/network/config '${builtins.toJSON networkConfig}'
        do
          echo "setting network configuration, retry"
          sleep 1
        done
      '';
      serviceConfig = {
        ExecStart = "${cfg.package}/bin/flannel";
        Restart = "always";
        RestartSec = "10s";
      };
    };

    services.etcd.enable = mkDefault (cfg.storageBackend == "etcd" && cfg.etcd.endpoints == ["http://127.0.0.1:2379"]);

    # for some reason, flannel doesn't let you configure this path
    # see: https://github.com/coreos/flannel/blob/master/Documentation/configuration.md#configuration
    environment.etc."kube-flannel/net-conf.json" = mkIf (cfg.storageBackend == "kubernetes") {
      source = pkgs.writeText "net-conf.json" (builtins.toJSON networkConfig);
    };
  };
}