2021-12-05 20:40:24 +01:00
|
|
|
{
|
|
|
|
config,
|
|
|
|
lib,
|
|
|
|
options,
|
|
|
|
pkgs,
|
|
|
|
...
|
|
|
|
}:
|
2014-11-23 01:27:04 +01:00
|
|
|
let
|
2014-12-11 23:32:37 +01:00
|
|
|
cfg = config.services.kubernetes;
|
2021-12-05 20:40:24 +01:00
|
|
|
opt = options.services.kubernetes;
|
2014-11-23 01:27:04 +01:00
|
|
|
|
2021-09-22 16:11:49 +02:00
|
|
|
defaultContainerdSettings = {
|
|
|
|
version = 2;
|
|
|
|
root = "/var/lib/containerd";
|
|
|
|
state = "/run/containerd";
|
|
|
|
oom_score = 0;
|
|
|
|
|
|
|
|
grpc = {
|
|
|
|
address = "/run/containerd/containerd.sock";
|
|
|
|
};
|
2021-02-25 16:00:59 +01:00
|
|
|
|
2021-09-22 16:11:49 +02:00
|
|
|
plugins."io.containerd.grpc.v1.cri" = {
|
|
|
|
sandbox_image = "pause:latest";
|
2021-02-25 16:00:59 +01:00
|
|
|
|
2021-09-22 16:11:49 +02:00
|
|
|
cni = {
|
|
|
|
bin_dir = "/opt/cni/bin";
|
|
|
|
max_conf_num = 0;
|
|
|
|
};
|
2021-02-25 16:00:59 +01:00
|
|
|
|
2021-09-22 16:11:49 +02:00
|
|
|
containerd.runtimes.runc = {
|
|
|
|
runtime_type = "io.containerd.runc.v2";
|
2021-12-18 22:18:10 +09:00
|
|
|
options.SystemdCgroup = true;
|
2021-09-22 16:11:49 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2021-02-25 16:00:59 +01:00
|
|
|
|
2018-07-22 13:14:20 +02:00
|
|
|
mkKubeConfig =
|
|
|
|
name: conf:
|
|
|
|
pkgs.writeText "${name}-kubeconfig" (
|
|
|
|
builtins.toJSON {
|
2016-11-16 16:29:35 +01:00
|
|
|
apiVersion = "v1";
|
|
|
|
kind = "Config";
|
|
|
|
clusters = [
|
|
|
|
{
|
|
|
|
name = "local";
|
2019-02-28 15:12:58 +01:00
|
|
|
cluster.certificate-authority = conf.caFile or cfg.caFile;
|
2018-07-22 13:14:20 +02:00
|
|
|
cluster.server = conf.server;
|
2016-11-16 16:29:35 +01:00
|
|
|
}
|
|
|
|
];
|
|
|
|
users = [
|
|
|
|
{
|
2018-07-22 13:14:20 +02:00
|
|
|
inherit name;
|
2016-11-16 16:29:35 +01:00
|
|
|
user = {
|
2018-07-22 13:14:20 +02:00
|
|
|
client-certificate = conf.certFile;
|
|
|
|
client-key = conf.keyFile;
|
2016-11-16 16:29:35 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
];
|
|
|
|
contexts = [
|
|
|
|
{
|
|
|
|
context = {
|
|
|
|
cluster = "local";
|
2018-07-22 13:14:20 +02:00
|
|
|
user = name;
|
2016-11-16 16:29:35 +01:00
|
|
|
};
|
2021-05-20 16:52:08 -04:00
|
|
|
name = "local";
|
2016-11-16 16:29:35 +01:00
|
|
|
}
|
|
|
|
];
|
2021-05-20 16:52:08 -04:00
|
|
|
current-context = "local";
|
2016-11-16 16:29:35 +01:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2018-07-22 13:14:20 +02:00
|
|
|
caCert = secret "ca";
|
|
|
|
|
|
|
|
etcdEndpoints = [ "https://${cfg.masterAddress}:2379" ];
|
2024-12-10 20:26:33 +01:00
|
|
|
|
2018-07-22 13:14:20 +02:00
|
|
|
mkCert =
|
|
|
|
{
|
|
|
|
name,
|
|
|
|
CN,
|
|
|
|
hosts ? [ ],
|
|
|
|
fields ? { },
|
|
|
|
action ? "",
|
2024-06-21 21:26:08 -03:00
|
|
|
privateKeyOwner ? "kubernetes",
|
|
|
|
privateKeyGroup ? "kubernetes",
|
|
|
|
}:
|
|
|
|
rec {
|
2018-07-22 13:14:20 +02:00
|
|
|
inherit
|
|
|
|
name
|
|
|
|
caCert
|
|
|
|
CN
|
|
|
|
hosts
|
|
|
|
fields
|
|
|
|
action
|
|
|
|
;
|
|
|
|
cert = secret name;
|
|
|
|
key = secret "${name}-key";
|
|
|
|
privateKeyOptions = {
|
|
|
|
owner = privateKeyOwner;
|
2024-06-21 21:26:08 -03:00
|
|
|
group = privateKeyGroup;
|
2018-07-22 13:14:20 +02:00
|
|
|
mode = "0600";
|
|
|
|
path = key;
|
2024-12-10 20:26:33 +01:00
|
|
|
};
|
2018-07-22 13:14:20 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
secret = name: "${cfg.secretsPath}/${name}.pem";
|
|
|
|
|
2017-05-30 11:26:32 +02:00
|
|
|
mkKubeConfigOptions = prefix: {
|
2024-12-08 13:18:23 +01:00
|
|
|
server = lib.mkOption {
|
2017-05-30 11:26:32 +02:00
|
|
|
description = "${prefix} kube-apiserver server address.";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.str;
|
2017-05-30 11:26:32 +02:00
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
caFile = lib.mkOption {
|
2018-06-04 15:45:25 +10:00
|
|
|
description = "${prefix} certificate authority file used to connect to kube-apiserver.";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.nullOr lib.types.path;
|
2017-05-30 11:57:52 +02:00
|
|
|
default = cfg.caFile;
|
2024-12-08 13:18:23 +01:00
|
|
|
defaultText = lib.literalExpression "config.${opt.caFile}";
|
2017-05-30 11:26:32 +02:00
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
certFile = lib.mkOption {
|
2017-05-30 11:26:32 +02:00
|
|
|
description = "${prefix} client certificate file used to connect to kube-apiserver.";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.nullOr lib.types.path;
|
2017-05-30 11:26:32 +02:00
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
keyFile = lib.mkOption {
|
2017-05-30 11:26:32 +02:00
|
|
|
description = "${prefix} client key file used to connect to kube-apiserver.";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.nullOr lib.types.path;
|
2017-05-30 11:26:32 +02:00
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
};
|
2014-11-23 01:27:04 +01:00
|
|
|
in
|
|
|
|
{
|
|
|
|
|
2019-12-10 02:51:19 +01:00
|
|
|
imports = [
|
2024-12-08 13:18:23 +01:00
|
|
|
(lib.mkRemovedOptionModule [
|
|
|
|
"services"
|
|
|
|
"kubernetes"
|
|
|
|
"addons"
|
|
|
|
"dashboard"
|
|
|
|
] "Removed due to it being an outdated version")
|
|
|
|
(lib.mkRemovedOptionModule [ "services" "kubernetes" "verbose" ] "")
|
2019-12-10 02:51:19 +01:00
|
|
|
];
|
|
|
|
|
2014-11-23 01:27:04 +01:00
|
|
|
###### interface
|
|
|
|
|
2014-12-11 23:32:37 +01:00
|
|
|
options.services.kubernetes = {
|
2024-12-08 13:18:23 +01:00
|
|
|
roles = lib.mkOption {
|
2016-11-16 16:29:35 +01:00
|
|
|
description = ''
|
|
|
|
Kubernetes role that this machine should take.
|
|
|
|
|
2018-07-22 13:14:20 +02:00
|
|
|
Master role will enable etcd, apiserver, scheduler, controller manager
|
|
|
|
addon manager, flannel and proxy services.
|
|
|
|
Node role will enable flannel, docker, kubelet and proxy services.
|
2016-11-16 16:29:35 +01:00
|
|
|
'';
|
|
|
|
default = [ ];
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.listOf (
|
|
|
|
lib.types.enum [
|
|
|
|
"master"
|
|
|
|
"node"
|
2024-12-10 20:26:33 +01:00
|
|
|
]
|
2024-12-08 13:18:23 +01:00
|
|
|
);
|
2016-11-16 16:29:35 +01:00
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
package = lib.mkPackageOption pkgs "kubernetes" { };
|
2014-11-23 01:27:04 +01:00
|
|
|
|
2018-07-22 13:14:20 +02:00
|
|
|
kubeconfig = mkKubeConfigOptions "Default kubeconfig";
|
2016-11-16 16:29:35 +01:00
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
apiserverAddress = lib.mkOption {
|
2018-07-22 13:14:20 +02:00
|
|
|
description = ''
|
|
|
|
Clusterwide accessible address for the kubernetes apiserver,
|
|
|
|
including protocol and optional port.
|
|
|
|
'';
|
|
|
|
example = "https://kubernetes-apiserver.example.com:6443";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.str;
|
2014-11-23 01:27:04 +01:00
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
caFile = lib.mkOption {
|
2017-05-30 11:57:52 +02:00
|
|
|
description = "Default kubernetes certificate authority";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.nullOr lib.types.path;
|
2017-05-30 11:57:52 +02:00
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
dataDir = lib.mkOption {
|
2014-11-23 01:27:04 +01:00
|
|
|
description = "Kubernetes root directory for managing kubelet files.";
|
|
|
|
default = "/var/lib/kubernetes";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.path;
|
2014-11-23 01:27:04 +01:00
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
easyCerts = lib.mkOption {
|
2018-07-22 13:14:20 +02:00
|
|
|
description = "Automatically setup x509 certificates and keys for the entire cluster.";
|
|
|
|
default = false;
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.bool;
|
2018-07-22 13:14:20 +02:00
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
featureGates = lib.mkOption {
|
2018-07-22 13:14:20 +02:00
|
|
|
description = "List set of feature gates.";
|
2024-07-17 09:10:17 +02:00
|
|
|
default = { };
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.attrsOf lib.types.bool;
|
2017-09-01 12:14:00 +02:00
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
masterAddress = lib.mkOption {
|
2018-07-22 13:14:20 +02:00
|
|
|
description = "Clusterwide available network address or hostname for the kubernetes master server.";
|
|
|
|
example = "master.example.com";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.str;
|
2017-04-26 22:44:38 +02:00
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
path = lib.mkOption {
|
2017-04-26 22:44:38 +02:00
|
|
|
description = "Packages added to the services' PATH environment variable. Both the bin and sbin subdirectories of each package are added.";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.listOf lib.types.package;
|
2017-04-21 15:25:05 +02:00
|
|
|
default = [ ];
|
2015-06-08 13:15:26 +02:00
|
|
|
};
|
2017-04-21 15:25:05 +02:00
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
clusterCidr = lib.mkOption {
|
2017-04-26 22:44:38 +02:00
|
|
|
description = "Kubernetes controller manager and proxy CIDR Range for Pods in cluster.";
|
2017-05-30 14:54:29 +02:00
|
|
|
default = "10.1.0.0/16";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.nullOr lib.types.str;
|
2017-04-26 22:44:38 +02:00
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
lib = lib.mkOption {
|
2018-07-22 13:14:20 +02:00
|
|
|
description = "Common functions for the kubernetes modules.";
|
|
|
|
default = {
|
|
|
|
inherit mkCert;
|
|
|
|
inherit mkKubeConfig;
|
|
|
|
inherit mkKubeConfigOptions;
|
|
|
|
};
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.attrs;
|
2017-05-26 23:21:17 +02:00
|
|
|
};
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
secretsPath = lib.mkOption {
|
2018-07-22 13:14:20 +02:00
|
|
|
description = "Default location for kubernetes secrets. Not a store location.";
|
2024-12-08 13:18:23 +01:00
|
|
|
type = lib.types.path;
|
2018-07-22 13:14:20 +02:00
|
|
|
default = cfg.dataDir + "/secrets";
|
2024-12-08 13:18:23 +01:00
|
|
|
defaultText = lib.literalExpression ''
|
2021-12-08 05:08:23 +01:00
|
|
|
config.${opt.dataDir} + "/secrets"
|
|
|
|
'';
|
2018-07-22 13:14:20 +02:00
|
|
|
};
|
2014-11-23 01:27:04 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
###### implementation
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
config = lib.mkMerge [
|
2017-09-01 12:22:12 +02:00
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
(lib.mkIf cfg.easyCerts {
|
|
|
|
services.kubernetes.pki.enable = lib.mkDefault true;
|
2018-07-22 13:14:20 +02:00
|
|
|
services.kubernetes.caFile = caCert;
|
2016-11-16 16:29:35 +01:00
|
|
|
})
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
(lib.mkIf (lib.elem "master" cfg.roles) {
|
|
|
|
services.kubernetes.apiserver.enable = lib.mkDefault true;
|
|
|
|
services.kubernetes.scheduler.enable = lib.mkDefault true;
|
|
|
|
services.kubernetes.controllerManager.enable = lib.mkDefault true;
|
|
|
|
services.kubernetes.addonManager.enable = lib.mkDefault true;
|
|
|
|
services.kubernetes.proxy.enable = lib.mkDefault true;
|
2018-07-22 13:14:20 +02:00
|
|
|
services.etcd.enable = true; # Cannot mkDefault because of flannel default options
|
2019-02-12 16:48:23 +01:00
|
|
|
services.kubernetes.kubelet = {
|
2024-12-08 13:18:23 +01:00
|
|
|
enable = lib.mkDefault true;
|
|
|
|
taints = lib.mkIf (!(lib.elem "node" cfg.roles)) {
|
2019-02-12 16:48:23 +01:00
|
|
|
master = {
|
|
|
|
key = "node-role.kubernetes.io/master";
|
|
|
|
value = "true";
|
|
|
|
effect = "NoSchedule";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2014-11-23 01:27:04 +01:00
|
|
|
})
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
(lib.mkIf (lib.all (el: el == "master") cfg.roles) {
|
2018-07-22 13:14:20 +02:00
|
|
|
# if this node is only a master make it unschedulable by default
|
2024-12-08 13:18:23 +01:00
|
|
|
services.kubernetes.kubelet.unschedulable = lib.mkDefault true;
|
2017-04-26 22:44:38 +02:00
|
|
|
})
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
(lib.mkIf (lib.elem "node" cfg.roles) {
|
|
|
|
services.kubernetes.kubelet.enable = lib.mkDefault true;
|
|
|
|
services.kubernetes.proxy.enable = lib.mkDefault true;
|
2018-07-22 13:14:20 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
# Using "services.kubernetes.roles" will automatically enable easyCerts and flannel
|
2024-12-08 13:18:23 +01:00
|
|
|
(lib.mkIf (cfg.roles != [ ]) {
|
|
|
|
services.kubernetes.flannel.enable = lib.mkDefault true;
|
|
|
|
services.flannel.etcd.endpoints = lib.mkDefault etcdEndpoints;
|
|
|
|
services.kubernetes.easyCerts = lib.mkDefault true;
|
2018-07-22 13:14:20 +02:00
|
|
|
})
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
(lib.mkIf cfg.apiserver.enable {
|
|
|
|
services.kubernetes.pki.etcClusterAdminKubeconfig = lib.mkDefault "kubernetes/cluster-admin.kubeconfig";
|
|
|
|
services.kubernetes.apiserver.etcd.servers = lib.mkDefault etcdEndpoints;
|
2018-07-22 13:14:20 +02:00
|
|
|
})
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
(lib.mkIf cfg.kubelet.enable {
|
2021-02-25 16:00:59 +01:00
|
|
|
virtualisation.containerd = {
|
2024-12-08 13:18:23 +01:00
|
|
|
enable = lib.mkDefault true;
|
|
|
|
settings = lib.mapAttrsRecursive (name: lib.mkDefault) defaultContainerdSettings;
|
2017-05-26 23:21:17 +02:00
|
|
|
};
|
2014-11-23 01:27:04 +01:00
|
|
|
})
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
(lib.mkIf (cfg.apiserver.enable || cfg.controllerManager.enable) {
|
2018-07-22 13:14:20 +02:00
|
|
|
services.kubernetes.pki.certs = {
|
|
|
|
serviceAccount = mkCert {
|
|
|
|
name = "service-account";
|
|
|
|
CN = "system:service-account-signer";
|
|
|
|
action = ''
|
2024-06-22 07:52:46 +02:00
|
|
|
systemctl restart \
|
2018-07-22 13:14:20 +02:00
|
|
|
kube-apiserver.service \
|
|
|
|
kube-controller-manager.service
|
|
|
|
'';
|
2017-04-26 22:44:38 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
})
|
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
(lib.mkIf
|
|
|
|
(
|
2014-11-23 01:27:04 +01:00
|
|
|
cfg.apiserver.enable
|
|
|
|
|| cfg.scheduler.enable
|
|
|
|
|| cfg.controllerManager.enable
|
|
|
|
|| cfg.kubelet.enable
|
2018-07-22 13:14:20 +02:00
|
|
|
|| cfg.proxy.enable
|
|
|
|
|| cfg.addonManager.enable
|
2024-12-10 20:26:33 +01:00
|
|
|
)
|
|
|
|
{
|
2019-09-14 19:51:29 +02:00
|
|
|
systemd.targets.kubernetes = {
|
2014-11-23 01:27:04 +01:00
|
|
|
description = "Kubernetes";
|
2024-12-08 13:18:23 +01:00
|
|
|
wantedBy = [ "multi-user.target" ];
|
2024-12-10 20:26:33 +01:00
|
|
|
};
|
2017-05-26 23:21:17 +02:00
|
|
|
|
2016-11-16 16:29:35 +01:00
|
|
|
systemd.tmpfiles.rules = [
|
|
|
|
"d /opt/cni/bin 0755 root root -"
|
2018-07-22 13:14:20 +02:00
|
|
|
"d /run/kubernetes 0755 kubernetes kubernetes -"
|
2024-12-08 13:18:23 +01:00
|
|
|
"d ${cfg.dataDir} 0755 kubernetes kubernetes -"
|
2024-12-10 20:26:33 +01:00
|
|
|
];
|
|
|
|
|
2018-06-30 01:58:35 +02:00
|
|
|
users.users.kubernetes = {
|
2014-11-23 01:27:04 +01:00
|
|
|
uid = config.ids.uids.kubernetes;
|
2024-12-08 13:18:23 +01:00
|
|
|
description = "Kubernetes user";
|
2014-11-23 01:27:04 +01:00
|
|
|
group = "kubernetes";
|
|
|
|
home = cfg.dataDir;
|
2024-12-08 13:18:23 +01:00
|
|
|
createHome = true;
|
2024-02-14 14:42:02 -08:00
|
|
|
homeMode = "755";
|
2024-12-10 20:26:33 +01:00
|
|
|
};
|
2024-12-08 13:18:23 +01:00
|
|
|
users.groups.kubernetes.gid = config.ids.gids.kubernetes;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
# dns addon is enabled by default
|
|
|
|
services.kubernetes.addons.dns.enable = lib.mkDefault true;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
2024-12-08 13:18:23 +01:00
|
|
|
services.kubernetes.apiserverAddress = lib.mkDefault (
|
|
|
|
"https://${
|
2018-07-22 13:14:20 +02:00
|
|
|
if cfg.apiserver.advertiseAddress != null then
|
2017-05-30 11:26:32 +02:00
|
|
|
cfg.apiserver.advertiseAddress
|
2018-07-22 13:14:20 +02:00
|
|
|
else
|
|
|
|
"${cfg.masterAddress}:${toString cfg.apiserver.securePort}"
|
|
|
|
}"
|
|
|
|
);
|
2017-05-26 23:21:17 +02:00
|
|
|
}
|
|
|
|
)
|
2014-11-23 01:27:04 +01:00
|
|
|
];
|
2022-01-08 07:10:25 +01:00
|
|
|
|
|
|
|
meta.buildDocsInSandbox = false;
|
2014-11-23 01:27:04 +01:00
|
|
|
}
|