135 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{ config, lib, pkgs, ... }:
 | 
						|
 | 
						|
with lib;
 | 
						|
 | 
						|
let
 | 
						|
  top = config.services.kubernetes;
 | 
						|
  cfg = top.flannel;
 | 
						|
 | 
						|
  # we want flannel to use kubernetes itself as configuration backend, not direct etcd
 | 
						|
  storageBackend = "kubernetes";
 | 
						|
 | 
						|
  # needed for flannel to pass options to docker
 | 
						|
  mkDockerOpts = pkgs.runCommand "mk-docker-opts" {
 | 
						|
    buildInputs = [ pkgs.makeWrapper ];
 | 
						|
  } ''
 | 
						|
    mkdir -p $out
 | 
						|
 | 
						|
    # bashInteractive needed for `compgen`
 | 
						|
    makeWrapper ${pkgs.bashInteractive}/bin/bash $out/mk-docker-opts --add-flags "${pkgs.kubernetes}/bin/mk-docker-opts.sh"
 | 
						|
  '';
 | 
						|
in
 | 
						|
{
 | 
						|
  ###### interface
 | 
						|
  options.services.kubernetes.flannel = {
 | 
						|
    enable = mkEnableOption "enable flannel networking";
 | 
						|
  };
 | 
						|
 | 
						|
  ###### implementation
 | 
						|
  config = mkIf cfg.enable {
 | 
						|
    services.flannel = {
 | 
						|
 | 
						|
      enable = mkDefault true;
 | 
						|
      network = mkDefault top.clusterCidr;
 | 
						|
      inherit storageBackend;
 | 
						|
      nodeName = config.services.kubernetes.kubelet.hostname;
 | 
						|
    };
 | 
						|
 | 
						|
    services.kubernetes.kubelet = {
 | 
						|
      networkPlugin = mkDefault "cni";
 | 
						|
      cni.config = mkDefault [{
 | 
						|
        name = "mynet";
 | 
						|
        type = "flannel";
 | 
						|
        cniVersion = "0.3.1";
 | 
						|
        delegate = {
 | 
						|
          isDefaultGateway = true;
 | 
						|
          bridge = "docker0";
 | 
						|
        };
 | 
						|
      }];
 | 
						|
    };
 | 
						|
 | 
						|
    systemd.services.mk-docker-opts = {
 | 
						|
      description = "Pre-Docker Actions";
 | 
						|
      path = with pkgs; [ gawk gnugrep ];
 | 
						|
      script = ''
 | 
						|
        ${mkDockerOpts}/mk-docker-opts -d /run/flannel/docker
 | 
						|
        systemctl restart docker
 | 
						|
      '';
 | 
						|
      serviceConfig.Type = "oneshot";
 | 
						|
    };
 | 
						|
 | 
						|
    systemd.paths.flannel-subnet-env = {
 | 
						|
      wantedBy = [ "flannel.service" ];
 | 
						|
      pathConfig = {
 | 
						|
        PathModified = "/run/flannel/subnet.env";
 | 
						|
        Unit = "mk-docker-opts.service";
 | 
						|
      };
 | 
						|
    };
 | 
						|
 | 
						|
    systemd.services.docker = {
 | 
						|
      environment.DOCKER_OPTS = "-b none";
 | 
						|
      serviceConfig.EnvironmentFile = "-/run/flannel/docker";
 | 
						|
    };
 | 
						|
 | 
						|
    # read environment variables generated by mk-docker-opts
 | 
						|
    virtualisation.docker.extraOptions = "$DOCKER_OPTS";
 | 
						|
 | 
						|
    networking = {
 | 
						|
      firewall.allowedUDPPorts = [
 | 
						|
        8285  # flannel udp
 | 
						|
        8472  # flannel vxlan
 | 
						|
      ];
 | 
						|
      dhcpcd.denyInterfaces = [ "docker*" "flannel*" ];
 | 
						|
    };
 | 
						|
 | 
						|
    services.kubernetes.pki.certs = {
 | 
						|
      flannelClient = top.lib.mkCert {
 | 
						|
        name = "flannel-client";
 | 
						|
        CN = "flannel-client";
 | 
						|
        action = "systemctl restart flannel.service";
 | 
						|
      };
 | 
						|
    };
 | 
						|
 | 
						|
    # give flannel som kubernetes rbac permissions if applicable
 | 
						|
    services.kubernetes.addonManager.bootstrapAddons = mkIf ((storageBackend == "kubernetes") && (elem "RBAC" top.apiserver.authorizationMode)) {
 | 
						|
 | 
						|
      flannel-cr = {
 | 
						|
        apiVersion = "rbac.authorization.k8s.io/v1beta1";
 | 
						|
        kind = "ClusterRole";
 | 
						|
        metadata = { name = "flannel"; };
 | 
						|
        rules = [{
 | 
						|
          apiGroups = [ "" ];
 | 
						|
          resources = [ "pods" ];
 | 
						|
          verbs = [ "get" ];
 | 
						|
        }
 | 
						|
        {
 | 
						|
          apiGroups = [ "" ];
 | 
						|
          resources = [ "nodes" ];
 | 
						|
          verbs = [ "list" "watch" ];
 | 
						|
        }
 | 
						|
        {
 | 
						|
          apiGroups = [ "" ];
 | 
						|
          resources = [ "nodes/status" ];
 | 
						|
          verbs = [ "patch" ];
 | 
						|
        }];
 | 
						|
      };
 | 
						|
 | 
						|
      flannel-crb = {
 | 
						|
        apiVersion = "rbac.authorization.k8s.io/v1beta1";
 | 
						|
        kind = "ClusterRoleBinding";
 | 
						|
        metadata = { name = "flannel"; };
 | 
						|
        roleRef = {
 | 
						|
          apiGroup = "rbac.authorization.k8s.io";
 | 
						|
          kind = "ClusterRole";
 | 
						|
          name = "flannel";
 | 
						|
        };
 | 
						|
        subjects = [{
 | 
						|
          kind = "User";
 | 
						|
          name = "flannel-client";
 | 
						|
        }];
 | 
						|
      };
 | 
						|
 | 
						|
    };
 | 
						|
  };
 | 
						|
}
 |