blob: 6338f5ef7a00b3ee7f5f31527a192940ec554c24 [file] [log] [blame]
Sergiusz Bazanskic78cc132020-02-02 22:31:53 +01001{ config, pkgs, lib, ... }:
2
3with (( import ./defs-cluster-k0.nix ) config.networking.hostName);
4let
5 # Pin for k8s packages. This is so that upagrading the system will not upgrade the k8s control or data planes.
6 k8spkgs = import (fetchGit {
7 # Now at 1.14.3
8 name = "nixos-unstable-2019-06-17";
9 url = https://github.com/nixos/nixpkgs-channels/;
10 rev = "415e8e5820b7825fb74a6c7986bf6af725227eaa";
11 }) {};
12 # Pin for kubelet
13 k8spkgsKubelet = import (fetchGit {
Sergiusz Bazanskid7364522020-02-02 23:43:28 +010014 # Now at 1.14.3
15 name = "nixos-unstable-2019-06-17";
Sergiusz Bazanskic78cc132020-02-02 22:31:53 +010016 url = https://github.com/nixos/nixpkgs-channels/;
Sergiusz Bazanskid7364522020-02-02 23:43:28 +010017 rev = "415e8e5820b7825fb74a6c7986bf6af725227eaa";
Sergiusz Bazanskic78cc132020-02-02 22:31:53 +010018 }) {};
19
20in rec {
21 # Disable kubelet service and bring in our own override.
22 # Also nuke flannel from the orbit.
23 disabledModules = [
24 "services/cluster/kubernetes/kubelet.nix"
25 "services/cluster/kubernetes/flannel.nix"
26 ];
27
28 imports =
29 [
30 ./module-kubelet.nix
31 ];
32
33 # List services that you want to enable:
34 virtualisation.docker.enable = true;
35 virtualisation.docker.extraOptions = "--iptables=false --ip-masq=false --ip-forward=true";
36
37 # Docker 1.13 sets iptables FORWARD to DROP. Unfuck this.
38 systemd.services."docker-iptables-unfuck" = {
39 enable = true;
40 wantedBy = [ "kubernetes.target" ];
41 description = "Docker iptable Unfuck";
42 after = [ "docker.service" ];
43 requires = [ "docker.service" ];
44 path = [ pkgs.iptables ];
45 script = ''
46 iptables -P FORWARD ACCEPT
47 '';
48 serviceConfig.Type = "oneshot";
49 };
50
51 networking.firewall.enable = false;
52
53 # Point k8s apiserver address at ourselves, as every machine runs an apiserver with this cert name.
54 networking.extraHosts = ''
55 127.0.0.1 ${k8sapi}
56 '';
57
Serge Bazanski31641172020-08-23 00:58:29 +020058 security.acme.acceptTerms = true;
Sergiusz Bazanskic78cc132020-02-02 22:31:53 +010059 security.acme.certs = {
60 host = {
61 email = acmeEmail;
62 domain = fqdn;
63 webroot = services.nginx.virtualHosts.host.root;
64 };
65 };
66
67 services.nginx = {
68 enable = true;
69 virtualHosts.host = {
70 serverName = fqdn;
71 root = "/var/www/${fqdn}";
72 };
73 };
74
75 services.etcd = rec {
76 enable = true;
77 name = fqdn;
78 listenClientUrls = ["https://0.0.0.0:2379"];
79 advertiseClientUrls = ["https://${fqdn}:2379"];
80 listenPeerUrls = ["https://0.0.0.0:2380"];
81 initialAdvertisePeerUrls = ["https://${fqdn}:2380"];
82 initialCluster = (map (n: "${n.fqdn}=https://${n.fqdn}:2380") machines);
83 initialClusterState = "existing";
84
85 clientCertAuth = true;
86 trustedCaFile = pki.etcd.server.ca;
87 certFile = pki.etcd.server.cert;
88 keyFile = pki.etcd.server.key;
89
90 peerClientCertAuth = true;
91 peerTrustedCaFile = pki.etcdPeer.ca;
92 peerCertFile = pki.etcdPeer.cert;
93 peerKeyFile = pki.etcdPeer.key;
94
95 extraConf = {
96 PEER_CLIENT_CERT_AUTH = "true";
97 };
98 };
99
100 services.kubernetes = {
101 # Pin to specific k8s package.
102 package = k8spkgs.kubernetes;
103 roles = []; # We do not use any nixpkgs predefined roles for k8s. Instead,
104 # we enable k8s components manually.
105
106 caFile = pki.kube.apiserver.ca;
107 clusterCidr = "10.10.16.0/20";
108
109 path = [ pkgs.e2fsprogs ]; # kubelet wants to mkfs.ext4 when mounting pvcs
110
111 addons.dns.enable = false;
112
113 apiserver = rec {
114 enable = true;
115 insecurePort = ports.k8sAPIServerPlain;
116 securePort = ports.k8sAPIServerSecure;
117 advertiseAddress = "${machine.ipAddr}";
118
119 etcd = {
120 # https://github.com/kubernetes/kubernetes/issues/72102
121 servers = (map (n: "https://${n.fqdn}:2379") ( [ machine ] ));
122 caFile = pki.etcd.kube.ca;
123 keyFile = pki.etcd.kube.key;
124 certFile = pki.etcd.kube.cert;
125 };
126
127 tlsCertFile = pki.kube.apiserver.cert;
128 tlsKeyFile = pki.kube.apiserver.key;
129
130 clientCaFile = pki.kube.apiserver.ca;
131
132 kubeletHttps = true;
133 kubeletClientCaFile = pki.kube.apiserver.ca;
134 kubeletClientCertFile = pki.kube.apiserver.cert;
135 kubeletClientKeyFile = pki.kube.apiserver.key;
136
137 serviceAccountKeyFile = pki.kube.serviceaccounts.key;
138
139 allowPrivileged = true;
140 serviceClusterIpRange = "10.10.12.0/24";
141 runtimeConfig = "api/all,authentication.k8s.io/v1beta1";
142 authorizationMode = ["Node" "RBAC"];
143 enableAdmissionPlugins = ["NamespaceLifecycle" "NodeRestriction" "LimitRanger" "ServiceAccount" "DefaultStorageClass" "ResourceQuota" "PodSecurityPolicy"];
144 extraOpts = ''
145 --apiserver-count=5 \
146 --proxy-client-cert-file=${pki.kubeFront.apiserver.cert} \
147 --proxy-client-key-file=${pki.kubeFront.apiserver.key} \
148 --requestheader-allowed-names= \
149 --requestheader-client-ca-file=${pki.kubeFront.apiserver.ca} \
150 --requestheader-extra-headers-prefix=X-Remote-Extra- \
151 --requestheader-group-headers=X-Remote-Group \
152 --requestheader-username-headers=X-Remote-User \
153 -v=5
154 '';
155 };
156
157 controllerManager = {
158 enable = true;
159 bindAddress = "0.0.0.0";
160 insecurePort = ports.k8sControllerManagerPlain;
161 leaderElect = true;
162 serviceAccountKeyFile = pki.kube.serviceaccounts.key;
163 rootCaFile = pki.kube.ca;
164 extraOpts = ''
165 --service-cluster-ip-range=10.10.12.0/24 \
166 --use-service-account-credentials=true \
167 --secure-port=${toString ports.k8sControllerManagerSecure}\
168 '';
169 kubeconfig = pki.kube.controllermanager.config;
170 };
171
172 scheduler = {
173 enable = true;
174 address = "0.0.0.0";
175 port = 0;
176 leaderElect = true;
177 kubeconfig = pki.kube.scheduler.config;
178 };
179
180 proxy = {
181 enable = true;
182 kubeconfig = pki.kube.proxy.config;
183 extraOpts = ''
184 --hostname-override=${fqdn}\
185 --proxy-mode=iptables
186 '';
187 };
188
189 kubelet = {
190 enable = true;
191 unschedulable = false;
192 hostname = fqdn;
193 tlsCertFile = pki.kube.kubelet.cert;
194 tlsKeyFile = pki.kube.kubelet.key;
195 clientCaFile = pki.kube.kubelet.ca;
196 nodeIp = machine.ipAddr;
197 networkPlugin = "cni";
198 clusterDns = "10.10.12.254";
199 kubeconfig = pki.kube.kubelet.config;
200 extraOpts = ''
201 --read-only-port=0
202 '';
203 package = k8spkgsKubelet.kubernetes;
204 };
205
206 };
207
208 # https://github.com/NixOS/nixpkgs/issues/60687
209 systemd.services.kube-control-plane-online = {
210 preStart = pkgs.lib.mkForce "";
211 };
212 # this seems to depend on flannel
213 # TODO(q3k): file issue
214 systemd.services.kubelet-online = {
215 script = pkgs.lib.mkForce "sleep 1";
216 };
217}