1{ config, pkgs, lib, ... }:
2
3with lib;
4
5let
6 cfg = config.services.kubernetes.addons.dashboard;
7in {
8 options.services.kubernetes.addons.dashboard = {
9 enable = mkEnableOption "kubernetes dashboard addon";
10
11 rbac = mkOption {
12 description = "Role-based access control (RBAC) options";
13 default = {};
14 type = types.submodule {
15 options = {
16 enable = mkOption {
17 description = "Whether to enable role based access control is enabled for kubernetes dashboard";
18 type = types.bool;
19 default = elem "RBAC" config.services.kubernetes.apiserver.authorizationMode;
20 };
21
22 clusterAdmin = mkOption {
23 description = "Whether to assign cluster admin rights to the kubernetes dashboard";
24 type = types.bool;
25 default = false;
26 };
27 };
28 };
29 };
30
31 version = mkOption {
32 description = "Which version of the kubernetes dashboard to deploy";
33 type = types.str;
34 default = "v1.8.3";
35 };
36
37 image = mkOption {
38 description = "Docker image to seed for the kubernetes dashboard container.";
39 type = types.attrs;
40 default = {
41 imageName = "k8s.gcr.io/kubernetes-dashboard-amd64";
42 imageDigest = "sha256:dc4026c1b595435ef5527ca598e1e9c4343076926d7d62b365c44831395adbd0";
43 finalImageTag = cfg.version;
44 sha256 = "18ajcg0q1vignfjk2sm4xj4wzphfz8wah69ps8dklqfvv0164mc8";
45 };
46 };
47 };
48
49 config = mkIf cfg.enable {
50 services.kubernetes.kubelet.seedDockerImages = [(pkgs.dockerTools.pullImage cfg.image)];
51
52 services.kubernetes.addonManager.addons = {
53 kubernetes-dashboard-deployment = {
54 kind = "Deployment";
55 apiVersion = "apps/v1";
56 metadata = {
57 labels = {
58 k8s-addon = "kubernetes-dashboard.addons.k8s.io";
59 k8s-app = "kubernetes-dashboard";
60 version = cfg.version;
61 "kubernetes.io/cluster-service" = "true";
62 "addonmanager.kubernetes.io/mode" = "Reconcile";
63 };
64 name = "kubernetes-dashboard";
65 namespace = "kube-system";
66 };
67 spec = {
68 replicas = 1;
69 revisionHistoryLimit = 10;
70 selector.matchLabels."k8s-app" = "kubernetes-dashboard";
71 template = {
72 metadata = {
73 labels = {
74 k8s-addon = "kubernetes-dashboard.addons.k8s.io";
75 k8s-app = "kubernetes-dashboard";
76 version = cfg.version;
77 "kubernetes.io/cluster-service" = "true";
78 };
79 annotations = {
80 "scheduler.alpha.kubernetes.io/critical-pod" = "";
81 };
82 };
83 spec = {
84 priorityClassName = "system-cluster-critical";
85 containers = [{
86 name = "kubernetes-dashboard";
87 image = with cfg.image; "${imageName}:${finalImageTag}";
88 ports = [{
89 containerPort = 8443;
90 protocol = "TCP";
91 }];
92 resources = {
93 limits = {
94 cpu = "100m";
95 memory = "300Mi";
96 };
97 requests = {
98 cpu = "100m";
99 memory = "100Mi";
100 };
101 };
102 args = ["--auto-generate-certificates"];
103 volumeMounts = [{
104 name = "tmp-volume";
105 mountPath = "/tmp";
106 } {
107 name = "kubernetes-dashboard-certs";
108 mountPath = "/certs";
109 }];
110 livenessProbe = {
111 httpGet = {
112 scheme = "HTTPS";
113 path = "/";
114 port = 8443;
115 };
116 initialDelaySeconds = 30;
117 timeoutSeconds = 30;
118 };
119 }];
120 volumes = [{
121 name = "kubernetes-dashboard-certs";
122 secret = {
123 secretName = "kubernetes-dashboard-certs";
124 };
125 } {
126 name = "tmp-volume";
127 emptyDir = {};
128 }];
129 serviceAccountName = "kubernetes-dashboard";
130 tolerations = [{
131 key = "node-role.kubernetes.io/master";
132 effect = "NoSchedule";
133 } {
134 key = "CriticalAddonsOnly";
135 operator = "Exists";
136 }];
137 };
138 };
139 };
140 };
141
142 kubernetes-dashboard-svc = {
143 apiVersion = "v1";
144 kind = "Service";
145 metadata = {
146 labels = {
147 k8s-addon = "kubernetes-dashboard.addons.k8s.io";
148 k8s-app = "kubernetes-dashboard";
149 "kubernetes.io/cluster-service" = "true";
150 "kubernetes.io/name" = "KubeDashboard";
151 "addonmanager.kubernetes.io/mode" = "Reconcile";
152 };
153 name = "kubernetes-dashboard";
154 namespace = "kube-system";
155 };
156 spec = {
157 ports = [{
158 port = 443;
159 targetPort = 8443;
160 }];
161 selector.k8s-app = "kubernetes-dashboard";
162 };
163 };
164
165 kubernetes-dashboard-sa = {
166 apiVersion = "v1";
167 kind = "ServiceAccount";
168 metadata = {
169 labels = {
170 k8s-app = "kubernetes-dashboard";
171 k8s-addon = "kubernetes-dashboard.addons.k8s.io";
172 "addonmanager.kubernetes.io/mode" = "Reconcile";
173 };
174 name = "kubernetes-dashboard";
175 namespace = "kube-system";
176 };
177 };
178 kubernetes-dashboard-sec-certs = {
179 apiVersion = "v1";
180 kind = "Secret";
181 metadata = {
182 labels = {
183 k8s-app = "kubernetes-dashboard";
184 # Allows editing resource and makes sure it is created first.
185 "addonmanager.kubernetes.io/mode" = "EnsureExists";
186 };
187 name = "kubernetes-dashboard-certs";
188 namespace = "kube-system";
189 };
190 type = "Opaque";
191 };
192 kubernetes-dashboard-sec-kholder = {
193 apiVersion = "v1";
194 kind = "Secret";
195 metadata = {
196 labels = {
197 k8s-app = "kubernetes-dashboard";
198 # Allows editing resource and makes sure it is created first.
199 "addonmanager.kubernetes.io/mode" = "EnsureExists";
200 };
201 name = "kubernetes-dashboard-key-holder";
202 namespace = "kube-system";
203 };
204 type = "Opaque";
205 };
206 kubernetes-dashboard-cm = {
207 apiVersion = "v1";
208 kind = "ConfigMap";
209 metadata = {
210 labels = {
211 k8s-app = "kubernetes-dashboard";
212 # Allows editing resource and makes sure it is created first.
213 "addonmanager.kubernetes.io/mode" = "EnsureExists";
214 };
215 name = "kubernetes-dashboard-settings";
216 namespace = "kube-system";
217 };
218 };
219 } // (optionalAttrs cfg.rbac.enable
220 (let
221 subjects = [{
222 kind = "ServiceAccount";
223 name = "kubernetes-dashboard";
224 namespace = "kube-system";
225 }];
226 labels = {
227 k8s-app = "kubernetes-dashboard";
228 k8s-addon = "kubernetes-dashboard.addons.k8s.io";
229 "addonmanager.kubernetes.io/mode" = "Reconcile";
230 };
231 in
232 (if cfg.rbac.clusterAdmin then {
233 kubernetes-dashboard-crb = {
234 apiVersion = "rbac.authorization.k8s.io/v1";
235 kind = "ClusterRoleBinding";
236 metadata = {
237 name = "kubernetes-dashboard";
238 inherit labels;
239 };
240 roleRef = {
241 apiGroup = "rbac.authorization.k8s.io";
242 kind = "ClusterRole";
243 name = "cluster-admin";
244 };
245 inherit subjects;
246 };
247 }
248 else
249 {
250 # Upstream role- and rolebinding as per:
251 # https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/alternative/kubernetes-dashboard.yaml
252 kubernetes-dashboard-role = {
253 apiVersion = "rbac.authorization.k8s.io/v1";
254 kind = "Role";
255 metadata = {
256 name = "kubernetes-dashboard-minimal";
257 namespace = "kube-system";
258 inherit labels;
259 };
260 rules = [
261 # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
262 {
263 apiGroups = [""];
264 resources = ["secrets"];
265 verbs = ["create"];
266 }
267 # Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
268 {
269 apiGroups = [""];
270 resources = ["configmaps"];
271 verbs = ["create"];
272 }
273 # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
274 {
275 apiGroups = [""];
276 resources = ["secrets"];
277 resourceNames = ["kubernetes-dashboard-key-holder"];
278 verbs = ["get" "update" "delete"];
279 }
280 # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
281 {
282 apiGroups = [""];
283 resources = ["configmaps"];
284 resourceNames = ["kubernetes-dashboard-settings"];
285 verbs = ["get" "update"];
286 }
287 # Allow Dashboard to get metrics from heapster.
288 {
289 apiGroups = [""];
290 resources = ["services"];
291 resourceNames = ["heapster"];
292 verbs = ["proxy"];
293 }
294 {
295 apiGroups = [""];
296 resources = ["services/proxy"];
297 resourceNames = ["heapster" "http:heapster:" "https:heapster:"];
298 verbs = ["get"];
299 }
300 ];
301 };
302
303 kubernetes-dashboard-rb = {
304 apiVersion = "rbac.authorization.k8s.io/v1";
305 kind = "RoleBinding";
306 metadata = {
307 name = "kubernetes-dashboard-minimal";
308 namespace = "kube-system";
309 inherit labels;
310 };
311 roleRef = {
312 apiGroup = "rbac.authorization.k8s.io";
313 kind = "Role";
314 name = "kubernetes-dashboard-minimal";
315 };
316 inherit subjects;
317 };
318 })
319 ));
320 };
321}