blob: 4acf80d9f59977ea0f152cc5fe1528288f223034 [file] [log] [blame]
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +02001# Deploy Rook/Ceph Operator
2
3local kube = import "../../../kube/kube.libsonnet";
Sergiusz Bazanskia01c4872019-09-05 18:00:02 +02004local policies = import "../../../kube/policies.libsonnet";
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +02005
Sergiusz Bazanskid436de22020-02-21 17:10:42 +01006local oa = kube.OpenAPI;
7
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +02008{
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +02009 Operator: {
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020010 local env = self,
11 local cfg = env.cfg,
12 cfg:: {
Serge Bazanski464fb042021-09-11 20:24:27 +000013 image: "rook/ceph:v1.6.9",
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020014 namespace: "rook-ceph-system",
15 },
16
17 metadata:: {
18 namespace: cfg.namespace,
19 labels: {
20 "operator": "rook",
21 "storage-backend": "ceph",
22 },
23 },
24
25 namespace: kube.Namespace(cfg.namespace),
26
Sergiusz Bazanskia01c4872019-09-05 18:00:02 +020027 policyInsecure: policies.AllowNamespaceInsecure(cfg.namespace),
28
Serge Bazanski464fb042021-09-11 20:24:27 +000029 // Grab CRDs from upstream YAML.
30 //
31 // We use a bit of jsonnet to remove some fields that kubebuilder (used
32 // upstream) added and to override preserveUnknownFIelds (as some older
33 // deployment apparently set it to true, which doesn't work for new
34 // CRDs that have default values).
35 crds: [
36 (el {
37 metadata+: {
38 annotations:: null,
39 creationTimestamp:: null,
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020040 },
Serge Bazanski464fb042021-09-11 20:24:27 +000041 status:: null,
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020042 spec+: {
Serge Bazanski464fb042021-09-11 20:24:27 +000043 preserveUnknownFields: false,
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020044 },
Serge Bazanski464fb042021-09-11 20:24:27 +000045 })
46 for el in (std.native("parseYaml")(importstr "rook-crds.yaml")) if el != null
47 ],
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020048
Sergiusz Bazanskid436de22020-02-21 17:10:42 +010049 sa: {
50 system: kube.ServiceAccount("rook-ceph-system") {
51 metadata+: env.metadata,
52 },
53 csiCephfsPlugin: kube.ServiceAccount("rook-csi-cephfs-plugin-sa") {
54 metadata+: env.metadata,
55 },
56 csiCephfsProvisioner: kube.ServiceAccount("rook-csi-cephfs-provisioner-sa") {
57 metadata+: env.metadata,
58 },
59 csiRbdPlugin: kube.ServiceAccount("rook-csi-rbd-plugin-sa") {
60 metadata+: env.metadata,
61 },
62 csiRbdProvisioner: kube.ServiceAccount("rook-csi-rbd-provisioner-sa") {
63 metadata+: env.metadata,
64 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +020065 },
66
67 crs: {
68 clusterMgmt: kube.ClusterRole("rook-ceph-cluster-mgmt") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +020069 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +020070 rules: [
71 {
Serge Bazanski464fb042021-09-11 20:24:27 +000072 apiGroups: ["", "apps", "extensions"],
73 resources: ["secrets", "pods", "pods/log", "services", "configmaps", "deployments", "daemonsets"],
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +020074 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
75 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +020076 ],
77 },
78 global: kube.ClusterRole("rook-ceph-global") {
Serge Bazanski464fb042021-09-11 20:24:27 +000079 metadata+: env.metadata {
80 namespace:: null,
81 labels+: {
82 "rbac.ceph.rook.io/aggregate-to-rook-ceph-global": "true",
83 },
84 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +020085 rules: [
86 {
87 apiGroups: [""],
Serge Bazanski464fb042021-09-11 20:24:27 +000088 resources: ["pods", "nodes", "nodes/proxy", "services"],
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +020089 verbs: ["get", "list", "watch"],
90 },
91 {
92 apiGroups: [""],
93 resources: ["events", "persistentvolumes", "persistentvolumeclaims", "endpoints"],
94 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
95 },
96 {
97 apiGroups: ["storage.k8s.io"],
98 resources: ["storageclasses"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +010099 verbs: ["get", "list", "watch"],
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200100 },
101 {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200102 apiGroups: ["batch"],
Serge Bazanski464fb042021-09-11 20:24:27 +0000103 resources: ["jobs", "cronjobs"],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200104 verbs: ["get", "list", "watch", "create", "update", "delete"],
105 },
106 {
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200107 apiGroups: ["ceph.rook.io"],
108 resources: ["*"],
109 verbs: ["*"],
110 },
111 {
112 apiGroups: ["rook.io"],
113 resources: ["*"],
114 verbs: ["*"],
115 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100116 {
Serge Bazanski464fb042021-09-11 20:24:27 +0000117 apiGroups: ["policy", "apps", "extensions"],
Serge Bazanski2c04c842021-01-19 21:41:11 +0100118 resources: ["poddisruptionbudgets", "deployments", "replicasets"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100119 verbs: ["*"],
120 },
Serge Bazanski2c04c842021-01-19 21:41:11 +0100121 {
122 apiGroups: ["healthchecking.openshift.io"],
123 resources: ["machinedisruptionbudgets"],
124 verbs: ["get", "list", "watch", "create", "update", "delete"],
125 },
126 {
127 apiGroups: ["machine.openshift.io"],
128 resources: ["machines"],
129 verbs: ["get", "list", "watch", "create", "update", "delete"],
130 },
131 {
132 apiGroups: ["storage.k8s.io"],
133 resources: ["csidrivers"],
Serge Bazanski464fb042021-09-11 20:24:27 +0000134 verbs: ["create", "delete", "get", "update"],
135 },
136 {
137 apiGroups: ["k8s.cni.cncf.io"],
138 resources: ["network-attachment-definitions"],
139 verbs: ["get"],
Serge Bazanski2c04c842021-01-19 21:41:11 +0100140 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200141 ],
142 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100143
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200144 mgrCluster: kube.ClusterRole("rook-ceph-mgr-cluster") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200145 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200146 rules: [
147 {
148 apiGroups: [""],
149 resources: ["configmaps", "nodes", "nodes/proxy"],
150 verbs: ["get", "list", "watch"],
151 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100152 {
153 apiGroups: [""],
154 resources: ["events"],
155 verbs: ["create", "patch", "list", "get", "watch"],
156 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200157 ]
158 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100159 objectBucket: kube.ClusterRole("rook-ceph-object-bucket") {
160 metadata+: env.metadata {
161 namespace:: null,
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100162 },
163 rules: [
164 {
165 apiGroups: [""],
166 resources: ["secrets", "configmaps"],
167 verbs: ["*"],
168 },
169 {
170 apiGroups: ["storage.k8s.io"],
171 resources: ["storageclasses"],
172 verbs: ["get", "list", "watch"],
173 },
174 {
175 apiGroups: ["objectbucket.io"],
176 resources: ["*"],
177 verbs: ["*"],
178 },
179 ],
180 },
181
182 cephfsCSINodeplugin: kube.ClusterRole("cephfs-csi-nodeplugin") {
183 metadata+: env.metadata { namespace:: null },
184 rules: [
185 {
186 apiGroups: [""],
187 resources: ["nodes"],
188 verbs: ["get", "list", "update"],
189 },
190 {
191 apiGroups: [""],
192 resources: ["namespaces"],
193 verbs: ["get", "list"],
194 },
195 {
196 apiGroups: [""],
197 resources: ["persistentvolumes"],
198 verbs: ["get", "list", "watch", "update"],
199 },
200 {
201 apiGroups: ["storage.k8s.io"],
202 resources: ["volumeattachments"],
203 verbs: ["get", "list", "watch", "update"],
204 },
205 {
206 apiGroups: [""],
207 resources: ["configmaps"],
208 verbs: ["get", "list"],
209 },
210 ],
211 },
212
213 cephfsExternalProvisionerRunner: kube.ClusterRole("cephfs-external-provisioner-runner") {
Serge Bazanski464fb042021-09-11 20:24:27 +0000214 metadata+: env.metadata {
215 namespace:: null,
216 labels+: {
217 "rbac.ceph.rook.io/aggregate-to-cephfs-external-provisioner-runner": "true",
218 },
219 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100220 rules: [
221 {
222 apiGroups: [""],
223 resources: ["secrets"],
224 verbs: ["get", "list"],
225 },
226 {
227 apiGroups: [""],
228 resources: ["persistentvolumes"],
Serge Bazanski464fb042021-09-11 20:24:27 +0000229 verbs: ["get", "list", "watch", "create", "delete", "update", "patch"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100230 },
231 {
232 apiGroups: [""],
233 resources: ["persistentvolumeclaims"],
234 verbs: ["get", "list", "watch", "update"],
235 },
236 {
237 apiGroups: ["storage.k8s.io"],
238 resources: ["storageclasses"],
239 verbs: ["get", "list", "watch"],
240 },
241 {
242 apiGroups: [""],
243 resources: ["events"],
244 verbs: ["list", "watch", "create", "update", "patch"],
245 },
246 {
Serge Bazanski464fb042021-09-11 20:24:27 +0000247 apiGroups: ["snapshot.storage.k8s.io"],
248 resources: ["volumesnapshots"],
249 verbs: ["get", "list", "watch", "update"],
250 },
251 {
252 apiGroups: ["snapshot.storage.k8s.io"],
253 resources: ["volumesnapshotcontents"],
254 verbs: ["create", "get", "list", "watch", "update", "delete"],
255 },
256 {
257 apiGroups: ["snapshot.storage.k8s.io"],
258 resources: ["volumesnapshotclasses"],
259 verbs: ["get", "list", "watch"],
260 },
261 {
262 apiGroups: ["snapshot.storage.k8s.io"],
263 resources: ["volumesnapshotcontents/status"],
264 verbs: ["update"],
265 },
266 {
267 apiGroups: ["apiextensions.k8s.io"],
268 resources: ["customresourcedefinitions"],
269 verbs: ["create", "list", "watch", "delete", "get", "update"],
270 },
271 {
272 apiGroups: ["snapshot.storage.k8s.io"],
273 resources: ["volumesnapshots/status"],
274 verbs: ["update"],
275 },
276 {
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100277 apiGroups: ["storage.k8s.io"],
278 resources: ["volumeattachments"],
Serge Bazanski464fb042021-09-11 20:24:27 +0000279 verbs: ["get", "list", "watch", "update", "patch"],
280 },
281 {
282 apiGroups: ["storage.k8s.io"],
283 resources: ["volumeattachments/status"],
284 verbs: ["patch"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100285 },
286 {
287 apiGroups: [""],
288 resources: ["nodes"],
289 verbs: ["get", "list", "watch"],
290 },
Serge Bazanski464fb042021-09-11 20:24:27 +0000291 {
292 apiGroups: [""],
293 resources: ["persistentvolumeclaims/status"],
294 verbs: ["update", "patch"],
295 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100296 ],
297 },
298
299 rbdCSINodeplugin: kube.ClusterRole("rbd-csi-nodeplugin") {
300 metadata+: env.metadata { namespace:: null },
301 rules: [
302 {
303 apiGroups: [""],
304 resources: ["secrets"],
305 verbs: ["get", "list"],
306 },
307 {
308 apiGroups: [""],
309 resources: ["nodes"],
310 verbs: ["get", "list", "update"],
311 },
312 {
313 apiGroups: [""],
314 resources: ["namespaces"],
315 verbs: ["get", "list"],
316 },
317 {
318 apiGroups: [""],
319 resources: ["persistentvolumes"],
320 verbs: ["get", "list", "watch", "update"],
321 },
322 {
323 apiGroups: ["storage.k8s.io"],
324 resources: ["volumeattachments"],
325 verbs: ["get", "list", "watch", "update"],
326 },
327 {
328 apiGroups: [""],
329 resources: ["configmaps"],
330 verbs: ["get", "list"],
331 },
332 ],
333 },
334
335 rbdExternalProvisionerRunner: kube.ClusterRole("rbd-external-provisioner-runner") {
Serge Bazanski464fb042021-09-11 20:24:27 +0000336 metadata+: env.metadata {
337 namespace:: null,
338 labels+: {
339 "rbac.ceph.rook.io/aggregate-to-rbd-external-provisioner-runner": "true",
340 },
341 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100342 rules: [
343 {
344 apiGroups: [""],
345 resources: ["secrets"],
Serge Bazanski464fb042021-09-11 20:24:27 +0000346 verbs: ["get", "list", "watch"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100347 },
348 {
349 apiGroups: [""],
350 resources: ["persistentvolumes"],
Serge Bazanski464fb042021-09-11 20:24:27 +0000351 verbs: ["get", "list", "watch", "create", "delete", "update", "patch"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100352 },
353 {
354 apiGroups: [""],
355 resources: ["persistentvolumeclaims"],
356 verbs: ["get", "list", "watch", "update"],
357 },
358 {
359 apiGroups: ["storage.k8s.io"],
360 resources: ["volumeattachments"],
Serge Bazanski464fb042021-09-11 20:24:27 +0000361 verbs: ["get", "list", "watch", "update", "patch"],
362 },
363 {
364 apiGroups: ["storage.k8s.io"],
365 resources: ["volumeattachments/status"],
366 verbs: ["patch"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100367 },
368 {
369 apiGroups: [""],
370 resources: ["nodes"],
371 verbs: ["get", "list", "watch"],
372 },
373 {
374 apiGroups: ["storage.k8s.io"],
375 resources: ["storageclasses"],
376 verbs: ["get", "list", "watch"]
377 },
378 {
379 apiGroups: [""],
380 resources: ["events"],
381 verbs: ["list", "watch", "create", "update", "patch"],
382 },
383 {
384 apiGroups: ["snapshot.storage.k8s.io"],
Serge Bazanski464fb042021-09-11 20:24:27 +0000385 resources: ["volumesnapshots"],
386 verbs: ["get", "list", "watch", "update"],
387 },
388 {
389 apiGroups: ["snapshot.storage.k8s.io"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100390 resources: ["volumesnapshotcontents"],
391 verbs: ["create", "get", "list", "watch", "update", "delete"],
392 },
393 {
394 apiGroups: ["snapshot.storage.k8s.io"],
395 resources: ["volumesnapshotclasses"],
396 verbs: ["get", "list", "watch"],
397 },
398 {
Serge Bazanski464fb042021-09-11 20:24:27 +0000399 apiGroups: ["snapshot.storage.k8s.io"],
400 resources: ["volumesnapshotcontents/status"],
401 verbs: ["update"],
402 },
403 {
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100404 apiGroups: ["apiextensions.k8s.io"],
405 resources: ["customresourcedefinitions"],
406 verbs: ["create", "list", "watch", "delete", "get", "update"],
407 },
408 {
409 apiGroups: ["snapshot.storage.k8s.io"],
410 resources: ["volumesnapshots/status"],
411 verbs: ["update"],
412 },
Serge Bazanski464fb042021-09-11 20:24:27 +0000413 {
414 apiGroups: [""],
415 resources: ["persistentvolumeclaims/status"],
416 verbs: ["update", "patch"],
417 },
418 {
419 apiGroups: [""],
420 resources: ["configmaps"],
421 verbs: ["get"],
422 },
423 {
424 apiGroups: ["replication.storage.openshift.io"],
425 resources: ["volumereplications", "volumereplicationclasses"],
426 verbs: ["create", "delete", "get", "list", "patch", "update", "watch"],
427 },
428 {
429 apiGroups: ["replication.storage.openshift.io"],
430 resources: ["volumereplications/finalizers"],
431 verbs: ["update"],
432 },
433 {
434 apiGroups: ["replication.storage.openshift.io"],
435 resources: ["volumereplications/status"],
436 verbs: ["get", "patch", "update"],
437 },
438 {
439 apiGroups: ["replication.storage.openshift.io"],
440 resources: ["volumereplicationclasses/status"],
441 verbs: ["get"],
442 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100443 ],
444 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200445 },
446
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100447 crbs: {
448 global: kube.ClusterRoleBinding("ceph-rook-global") {
449 metadata+: env.metadata { namespace:: null },
450 roleRef_: env.crs.global,
451 subjects_: [env.sa.system],
452 },
453 objectBucket: kube.ClusterRoleBinding("rook-ceph-object-bucket") {
454 metadata+: env.metadata { namespace:: null },
455 roleRef_: env.crs.objectBucket,
456 subjects_: [env.sa.system],
457 },
Serge Bazanski464fb042021-09-11 20:24:27 +0000458 cephfsCSINodeplugin: kube.ClusterRoleBinding("cephfs-csi-nodeplugin") {
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100459 metadata+: env.metadata { namespace:: null },
460 roleRef_: env.crs.cephfsCSINodeplugin,
461 subjects_: [env.sa.csiCephfsPlugin],
462 },
463 cephfsCSIProvisioner: kube.ClusterRoleBinding("cephfs-csi-provisioner") {
464 metadata+: env.metadata { namespace:: null },
465 roleRef_: env.crs.cephfsExternalProvisionerRunner,
466 subjects_: [env.sa.csiCephfsProvisioner],
467 },
468 rbdCSINodeplugin: kube.ClusterRoleBinding("rbd-csi-nodeplugin") {
469 metadata+: env.metadata { namespace:: null },
470 roleRef_: env.crs.rbdCSINodeplugin,
471 subjects_: [env.sa.csiRbdPlugin],
472 },
473 rbdCSIProvisioner: kube.ClusterRoleBinding("rbd-csi-provisioner") {
474 metadata+: env.metadata { namespace:: null },
475 roleRef_: env.crs.rbdExternalProvisionerRunner,
476 subjects_: [env.sa.csiRbdProvisioner],
477 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200478 },
479
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100480 roles: {
481 system: kube.Role("ceph-rook-system") {
482 metadata+: env.metadata,
483 rules: [
484 {
485 apiGroups: [""],
486 resources: ["pods", "configmaps", "services"],
487 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
488 },
489 {
490 apiGroups: ["apps"],
Serge Bazanski464fb042021-09-11 20:24:27 +0000491 resources: ["daemonsets", "statefulsets", "deployments"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100492 verbs: ["get", "list", "watch", "create", "update", "delete"],
493 },
Serge Bazanski464fb042021-09-11 20:24:27 +0000494 {
495 apiGroups: ["k8s.cni.cncf.io"],
496 resources: ["network-attachment-definitions"],
497 verbs: ["get"],
498 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100499 ],
500 },
501 cephfsExternalProvisioner: kube.Role("cephfs-external-provisioner-cfg") {
502 metadata+: env.metadata,
503 rules: [
504 {
505 apiGroups: [""],
506 resources: ["endpoints"],
507 verbs: ["get", "watch", "list", "delete", "update", "create"],
508 },
509 {
510 apiGroups: [""],
511 resources: ["configmaps"],
512 verbs: ["get", "list", "create", "delete"],
513 },
514 {
515 apiGroups: ["coordination.k8s.io"],
516 resources: ["leases"],
517 verbs: ["get" ,"watch", "list", "delete", "update", "create"],
518 },
519 ],
520 },
521 rbdExternalProvisioner: kube.Role("rbd-external-provisioner-cfg") {
522 metadata+: env.metadata,
523 rules: [
524 {
525 apiGroups: [""],
526 resources: ["endpoints"],
527 verbs: ["get", "watch", "list", "delete", "update", "create"],
528 },
529 {
530 apiGroups: [""],
531 resources: ["configmaps"],
Serge Bazanski464fb042021-09-11 20:24:27 +0000532 verbs: ["get", "list", "watch", "create", "delete", "update"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100533 },
534 {
535 apiGroups: ["coordination.k8s.io"],
536 resources: ["leases"],
537 verbs: ["get" ,"watch", "list", "delete", "update", "create"],
538 },
539 ],
540 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200541 },
542
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100543 rbs: {
544 system: kube.RoleBinding("ceph-rook-system") {
545 metadata+: env.metadata,
546 roleRef_: env.roles.system,
547 subjects_: [env.sa.system],
548 },
549 cephfsCSIProvisioner: kube.RoleBinding("cephfs-csi-provisioner-role-cfg") {
550 metadata+: env.metadata,
551 roleRef_: env.roles.cephfsExternalProvisioner,
552 subjects_: [env.sa.csiCephfsProvisioner],
553 },
554 rbdCSIProvisioner: kube.RoleBinding("rbd-csi-provisioner-role-cfg") {
555 metadata+: env.metadata,
556 roleRef_: env.roles.rbdExternalProvisioner,
557 subjects_: [env.sa.csiRbdProvisioner],
558 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200559 },
560
561 operator: kube.Deployment("rook-ceph-operator") {
562 metadata+: env.metadata,
563 spec+: {
564 template+: {
565 spec+: {
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100566 serviceAccountName: env.sa.system.metadata.name,
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200567 containers_: {
568 operator: kube.Container("rook-ceph-operator") {
569 image: cfg.image,
570 args: ["ceph", "operator"],
571 volumeMounts_: {
572 "rook-config": { mountPath: "/var/lib/rook" },
573 "default-config-dir": { mountPath: "/etc/ceph" },
574 },
575 env_: {
576 LIB_MODULES_DIR_PATH: "/run/current-system/kernel-modules/lib/modules/",
577 ROOK_ALLOW_MULTIPLE_FILESYSTEMS: "false",
Sergiusz Bazanski321fad92019-04-19 14:14:36 +0200578 ROOK_LOG_LEVEL: "INFO",
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200579 ROOK_MON_HEALTHCHECK_INTERVAL: "45s",
580 ROOK_MON_OUT_TIMEOUT: "600s",
581 ROOK_DISCOVER_DEVICES_INTERVAL: "60m",
582 ROOK_HOSTPATH_REQUIRES_PRIVILEGED: "false",
583 ROOK_ENABLE_SELINUX_RELABELING: "true",
584 ROOK_ENABLE_FSGROUP: "true",
585 NODE_NAME: kube.FieldRef("spec.nodeName"),
586 POD_NAME: kube.FieldRef("metadata.name"),
587 POD_NAMESPACE: kube.FieldRef("metadata.namespace"),
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100588 ROOK_CSI_KUBELET_DIR_PATH: "/var/lib/kubernetes"
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200589 },
590 },
591 },
592 volumes_: {
593 "rook-config": { emptyDir: {} },
594 "default-config-dir": { emptyDir: {} },
595 },
596 },
597 },
598 },
599 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200600 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200601
602 // Create a new Ceph cluster in a new namespace.
603 Cluster(operator, name):: {
604 local cluster = self,
605 spec:: error "please define cluster spec",
606
607
608 metadata:: {
609 namespace: name,
610 },
611
612 name(suffix):: cluster.metadata.namespace + "-" + suffix,
613
614 namespace: kube.Namespace(cluster.metadata.namespace),
615
616 sa: {
617 // service accounts need to be hardcoded, see operator source.
618 osd: kube.ServiceAccount("rook-ceph-osd") {
619 metadata+: cluster.metadata,
620 },
621 mgr: kube.ServiceAccount("rook-ceph-mgr") {
622 metadata+: cluster.metadata,
623 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100624 cmdReporter: kube.ServiceAccount("rook-ceph-cmd-reporter") {
625 metadata+: cluster.metadata,
626 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200627 },
628
629 roles: {
630 osd: kube.Role(cluster.name("osd")) {
631 metadata+: cluster.metadata,
632 rules: [
633 {
634 apiGroups: [""],
635 resources: ["configmaps"],
636 verbs: ["get", "list", "watch", "create", "update", "delete"],
Serge Bazanski2c04c842021-01-19 21:41:11 +0100637 },
638 ],
639 },
640 osdCluster: kube.ClusterRole(cluster.name("osd-cluster")) {
641 metadata+: cluster.metadata { namespace:: null },
642 rules: [
643 {
644 apiGroups: [""],
645 resources: ["nodes"],
646 verbs: ["get", "list"],
647 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200648 ],
649 },
650 mgr: kube.Role(cluster.name("mgr")) {
651 metadata+: cluster.metadata,
652 rules: [
653 {
654 apiGroups: [""],
655 resources: ["pods", "services"],
656 verbs: ["get", "list", "watch"],
657 },
658 {
659 apiGroups: ["batch"],
660 resources: ["jobs"],
661 verbs: ["get", "list", "watch", "create", "update", "delete"],
662 },
663 {
664 apiGroups: ["ceph.rook.io"],
665 resources: ["*"],
666 verbs: ["*"],
667 },
668 ],
669 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100670 cmdReporter: kube.Role(cluster.name("cmd-reporter")) {
671 metadata+: cluster.metadata,
672 rules: [
673 {
674 apiGroups: [""],
675 resources: ["pods", "configmaps"],
676 verbs: ["get", "list", "watch", "create", "update", "delete"],
677 },
678 ],
679 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200680 mgrSystem: kube.ClusterRole(cluster.name("mgr-system")) {
681 metadata+: cluster.metadata { namespace:: null },
682 rules: [
683 {
684 apiGroups: [""],
685 resources: ["configmaps"],
686 verbs: ["get", "list", "watch"],
687 }
688 ],
689 },
690 },
691
692 rbs: [
693 kube.RoleBinding(cluster.name(el.name)) {
694 metadata+: cluster.metadata,
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200695 roleRef_: el.role,
696 subjects_: [el.sa],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200697 },
698 for el in [
699 // Allow Operator SA to perform Cluster Mgmt in this namespace.
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100700 { name: "cluster-mgmt", role: operator.crs.clusterMgmt, sa: operator.sa.system },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200701 { name: "osd", role: cluster.roles.osd, sa: cluster.sa.osd },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200702 { name: "mgr", role: cluster.roles.mgr, sa: cluster.sa.mgr },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100703 { name: "cmd-reporter", role: cluster.roles.cmdReporter, sa: cluster.sa.cmdReporter },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200704 { name: "mgr-cluster", role: operator.crs.mgrCluster, sa: cluster.sa.mgr },
705 ]
706 ],
707
708 mgrSystemRB: kube.RoleBinding(cluster.name("mgr-system")) {
709 metadata+: {
710 namespace: operator.cfg.namespace,
711 },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200712 roleRef_: cluster.roles.mgrSystem,
713 subjects_: [cluster.sa.mgr],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200714 },
715
Serge Bazanski2c04c842021-01-19 21:41:11 +0100716 osdClusterRB: kube.ClusterRoleBinding(cluster.name("osd-cluster")) {
717 metadata+: {
718 namespace:: null,
719 },
720 roleRef_: cluster.roles.osdCluster,
721 subjects_: [cluster.sa.osd],
722 },
723
724
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200725 cluster: kube._Object("ceph.rook.io/v1", "CephCluster", name) {
726 metadata+: cluster.metadata,
727 spec: {
728 cephVersion: {
Serge Bazanski085a8ff2021-09-12 22:08:16 +0000729 image: "quay.io/ceph/ceph:v16.2.5",
Sergiusz Bazanskied2e6702019-04-19 13:27:20 +0200730 allowUnsupported: true,
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200731 },
Serge Bazanskic33ebcc2019-11-01 18:43:45 +0100732 dataDirHostPath: if name == "ceph-waw2" then "/var/lib/rook" else "/var/lib/rook-%s" % [name],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200733 dashboard: {
734 ssl: false,
735 enabled: true,
736 port: 8080,
737 },
738 } + cluster.spec,
739 },
740
741 dashboardService: kube.Service(cluster.name("dashboard")) {
742 metadata+: cluster.metadata,
743 spec: {
744 ports: [
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200745 { name: "dashboard", port: 80, targetPort: 8080, protocol: "TCP" },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200746 ],
747 selector: {
748 app: "rook-ceph-mgr",
749 rook_cluster: name,
750 },
751 type: "ClusterIP",
752 },
753 },
754
755 dashboardIngress: kube.Ingress(cluster.name("dashboard")) {
Piotr Dobrowolski3187c592019-04-02 14:44:04 +0200756 metadata+: cluster.metadata {
757 annotations+: {
758 "kubernetes.io/tls-acme": "true",
759 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
760 },
761 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200762 spec+: {
Piotr Dobrowolski3187c592019-04-02 14:44:04 +0200763 tls: [
764 {
765 hosts: ["%s.hswaw.net" % name],
766 secretName: cluster.name("dashboard"),
767 },
768 ],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200769 rules: [
770 {
771 host: "%s.hswaw.net" % name,
772 http: {
773 paths: [
774 { path: "/", backend: cluster.dashboardService.name_port },
775 ]
776 },
777 }
778 ],
779 },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200780 },
781
782 # Benji is a backup tool, external to rook, that we use for backing up
783 # RBDs.
784 benji: {
785 sa: kube.ServiceAccount(cluster.name("benji")) {
786 metadata+: cluster.metadata,
787 },
788
789 cr: kube.ClusterRole(cluster.name("benji")) {
790 rules: [
791 {
792 apiGroups: [""],
793 resources: [
794 "persistentvolumes",
795 "persistentvolumeclaims"
796 ],
797 verbs: ["list", "get"],
798 },
799 {
800 apiGroups: [""],
801 resources: [
802 "events",
803 ],
804 verbs: ["create", "update"],
805 },
806 ],
807 },
808
809 crb: kube.ClusterRoleBinding(cluster.name("benji")) {
810 roleRef_: cluster.benji.cr,
811 subjects_: [cluster.benji.sa],
812 },
813
814 config: kube.Secret(cluster.name("benji-config")) {
815 metadata+: cluster.metadata,
816 data_: {
817 "benji.yaml": std.manifestJson({
818 configurationVersion: '1',
819 databaseEngine: 'sqlite:////data/benji.sqlite',
820 defaultStorage: 'wasabi',
821 storages: [
822 {
823 name: "wasabi",
824 storageId: 1,
825 module: "s3",
826 configuration: cluster.spec.benji.s3Configuration {
827 activeTransforms: ["encrypt"],
828 },
829 },
830 ],
831 transforms: [
832 {
833 name: "encrypt",
834 module: "aes_256_gcm",
835 configuration: {
836 # not secret.
837 kdfSalt: "T2huZzZpcGhhaWM3QWVwaDhybzRhaDNhbzFpc2VpOWFobDNSZWVQaGVvTWV1bmVaYWVsNHRoYWg5QWVENHNoYWg0ZGFoN3Rlb3NvcHVuZzNpZXZpMm9vTG9vbmc1YWlmb0RlZXAwYmFobDlab294b2hjaG9odjRhbzFsYWkwYWk=",
838 kdfIterations: 2137,
839 password: cluster.spec.benji.encryptionPassword,
840 },
841 },
842 ],
843 ios: [
844 { name: pool, module: "rbd" }
845 for pool in cluster.spec.benji.pools
846 ],
847 }),
848 },
849 },
850
851 # Yes, Benji keeps data (backup metadata) on the ceph cluster that
852 # it backs up. However:
853 # - we add a command to benji-k8s to also copy over the sqlite
854 # database over to s3
855 # - benji can, in a pinch, restore without a database if a version
856 # is known: https://benji-backup.me/restore.html#restoring-without-a-database
857 data: kube.PersistentVolumeClaim(cluster.name("benji-data")) {
858 metadata+: cluster.metadata,
859 spec+: {
860 storageClassName: cluster.spec.benji.metadataStorageClass,
861 accessModes: [ "ReadWriteOnce" ],
862 resources: {
863 requests: {
864 storage: "1Gi",
865 },
866 },
867 },
868 },
869
870 # Extra scripts.
871 extrabins: kube.ConfigMap(cluster.name("benji-extrabins")) {
872 metadata+: cluster.metadata,
873 data: {
874 "metabackup.sh" : |||
875 # Make backups of sqlite3 metadata used by Benji.
876 # The backups live in the same bucket as backups, and the metabackups
877 # are named `metabackup-0..10`, where 0 is the newest backup. Any time
878 # this script is called, backups get shifted one way to the left (9 to 10,
879 # 8 to 9, etc). This ensures we have at least 10 backup replicas.
880
881 set -e
882
883 which s3cmd || pip install --upgrade s3cmd
884
885 AWS_ACCESS_KEY_ID=$(jq -r .storages[0].configuration.awsAccessKeyId < /etc/benji/benji.yaml)
886 AWS_SECRET_ACCESS_KEY=$(jq -r .storages[0].configuration.awsSecretAccessKey < /etc/benji/benji.yaml)
887 BUCKET=$(jq -r .storages[0].configuration.bucketName < /etc/benji/benji.yaml)
888
889 s3() {
890 s3cmd --host=s3.wasabisys.com \
891 "--host-bucket=%(bucket)s.s3.wasabisys.com" \
892 --region=eu-central-1 \
893 --access_key=$AWS_ACCESS_KEY_ID \
894 --secret_key=$AWS_SECRET_ACCESS_KEY \
895 "$@"
896 }
897
898 # Copy over old backups, if they exist.
899 for i in `seq 9 -1 0`; do
900 from="s3://$BUCKET/metabackup-$i.sqlite3"
901 to="s3://$BUCKET/metabackup-$((i+1)).sqlite3"
902
903 if [[ $(s3 ls $from | wc -l) -eq 0 ]]; then
904 echo "$from does not exist, skipping shift."
905 continue
906 fi
907 echo "Moving $from to $to..."
908 s3 mv $from $to
909 done
910
911 # Make new metabackup.
912 s3 put /data/benji.sqlite s3://$BUCKET/metabackup-0.sqlite3
913
914 |||,
915 "get-rook-creds.sh": |||
916 # Based on the Rook Toolbox /usr/local/bin/toolbox.sh script.
917 # Copyright 2016 The Rook Authors. All rights reserved.
918
919 CEPH_CONFIG="/etc/ceph/ceph.conf"
920 MON_CONFIG="/etc/rook/mon-endpoints"
921 KEYRING_FILE="/etc/ceph/keyring"
922
923 # create a ceph config file in its default location so ceph/rados tools can be used
924 # without specifying any arguments
925 write_endpoints() {
926 endpoints=$(cat ${MON_CONFIG})
927
928 # filter out the mon names
929 mon_endpoints=$(echo ${endpoints} | sed 's/[a-z]\+=//g')
930
931 # filter out the legacy mon names
932 mon_endpoints=$(echo ${mon_endpoints} | sed 's/rook-ceph-mon[0-9]\+=//g')
933
934 DATE=$(date)
935 echo "$DATE writing mon endpoints to ${CEPH_CONFIG}: ${endpoints}"
936 cat <<EOF > ${CEPH_CONFIG}
937 [global]
938 mon_host = ${mon_endpoints}
939
940 [client.admin]
941 keyring = ${KEYRING_FILE}
942 EOF
943 }
944
945 # watch the endpoints config file and update if the mon endpoints ever change
946 watch_endpoints() {
947 # get the timestamp for the target of the soft link
948 real_path=$(realpath ${MON_CONFIG})
949 initial_time=$(stat -c %Z ${real_path})
950 while true; do
951 real_path=$(realpath ${MON_CONFIG})
952 latest_time=$(stat -c %Z ${real_path})
953
954 if [[ "${latest_time}" != "${initial_time}" ]]; then
955 write_endpoints
956 initial_time=${latest_time}
957 fi
958 sleep 10
959 done
960 }
961
962 # create the keyring file
963 cat <<EOF > ${KEYRING_FILE}
964 [client.admin]
965 key = ${ROOK_ADMIN_SECRET}
966 EOF
967
968 # write the initial config file
969 write_endpoints
970
971 # continuously update the mon endpoints if they fail over
972 watch_endpoints &
973 |||
974 },
975 },
976
977 cronjob: kube.CronJob(cluster.name("benji")) {
978 metadata+: cluster.metadata,
979 spec+: { # CronJob Spec
Sergiusz Bazanski95868ee2019-09-26 23:47:14 +0200980 schedule: "42 0 * * *", # Daily at 42 minute past midnight.
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200981 jobTemplate+: {
982 spec+: { # Job Spec
983 selector:: null,
984 template+: {
985 spec+: { # PodSpec
986 serviceAccountName: cluster.benji.sa.metadata.name,
987 containers_: {
988 benji: kube.Container(cluster.name("benji")) {
Sergiusz Bazanski0c337ac2019-12-21 23:45:07 +0100989 # TODO(q3k): switch back to upstream after pull/65 goes in.
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200990 # Currently this is being built from github.com/q3k/benji.
Sergiusz Bazanski0c337ac2019-12-21 23:45:07 +0100991 # https://github.com/elemental-lf/benji/pull/65
992 image: "registry.k0.hswaw.net/q3k/benji-k8s:20191221-2336",
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200993 volumeMounts_: {
994 extrabins: { mountPath: "/usr/local/extrabins" },
995 monendpoints: { mountPath: "/etc/rook" },
996 benjiconfig: { mountPath: "/etc/benji" },
997 data: { mountPath: "/data" },
998 },
999 env_: {
1000 ROOK_ADMIN_SECRET: { secretKeyRef: { name: "rook-ceph-mon", key: "admin-secret" }},
1001 },
1002 command: [
1003 "bash", "-c", |||
1004 bash /usr/local/extrabins/get-rook-creds.sh
Sergiusz Bazanski0c337ac2019-12-21 23:45:07 +01001005 benji-backup-pvc %s
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +02001006 benji-command enforce latest3,hours48,days7,months12
1007 benji-command cleanup
1008 bash /usr/local/extrabins/metabackup.sh
Sergiusz Bazanski0c337ac2019-12-21 23:45:07 +01001009 ||| % [std.join(" ", ["--pool-filter=%s" % [p] for p in cluster.spec.benji.pools])],
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +02001010 ],
1011 },
1012 },
1013 volumes_: {
1014 data: kube.PersistentVolumeClaimVolume(cluster.benji.data),
1015 benjiconfig: kube.SecretVolume(cluster.benji.config),
1016 extrabins: kube.ConfigMapVolume(cluster.benji.extrabins),
1017 monendpoints: {
1018 configMap: {
1019 name: "rook-ceph-mon-endpoints",
1020 items: [
1021 { key: "data", path: "mon-endpoints" },
1022 ],
1023 },
1024 },
1025 },
1026 },
1027 },
1028 },
1029 },
1030 },
1031 },
1032 },
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +02001033 },
1034
Sergiusz Bazanski36cc4fb2019-05-17 18:08:48 +02001035 ReplicatedBlockPool(cluster, name):: {
1036 local pool = self,
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +02001037 name:: name,
1038
Sergiusz Bazanski36cc4fb2019-05-17 18:08:48 +02001039 spec:: error "spec must be specified",
1040
1041 pool: kube._Object("ceph.rook.io/v1", "CephBlockPool", name) {
1042 metadata+: cluster.metadata,
1043 spec: pool.spec,
1044 },
1045
1046 storageClass: kube.StorageClass(name) {
1047 provisioner: "ceph.rook.io/block",
1048 parameters: {
1049 blockPool: pool.pool.metadata.name,
1050 clusterNamespace: pool.pool.metadata.namespace,
1051 fstype: "ext4",
1052 },
1053 reclaimPolicy: "Retain",
1054 },
1055 },
1056
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +02001057 ECBlockPool(cluster, name):: {
1058 local pool = self,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +02001059 name:: name,
Serge Bazanskic33ebcc2019-11-01 18:43:45 +01001060 metadataReplicas:: 3,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +02001061
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +02001062 spec:: error "spec must be specified",
1063
1064 pool: kube._Object("ceph.rook.io/v1", "CephBlockPool", name) {
1065 metadata+: cluster.metadata,
1066 spec: pool.spec,
1067 },
1068 metapool: kube._Object("ceph.rook.io/v1", "CephBlockPool", name + "-metadata") {
1069 metadata+: cluster.metadata,
1070 spec: {
1071 failureDomain: "host",
1072 replicated: {
Serge Bazanskic33ebcc2019-11-01 18:43:45 +01001073 size: pool.metadataReplicas,
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +02001074 },
1075 },
1076 },
1077
1078 storageClass: kube.StorageClass(name) {
1079 provisioner: "ceph.rook.io/block",
1080 parameters: {
1081 blockPool: pool.metapool.metadata.name,
1082 dataBlockPool: pool.pool.metadata.name,
1083 clusterNamespace: pool.pool.metadata.namespace,
1084 fstype: "ext4",
1085 },
1086 reclaimPolicy: "Retain",
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +02001087 },
1088 },
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001089
Serge Bazanski38f72fe2021-09-13 23:43:47 +00001090 // This is a rook CephObjectRealm which corresponds to a radosgw realm.
1091 //
1092 // A realm is a 'world' of radosgw user-facing metadata, like credentials,
1093 // buckets, and underlying structures like zones and zonegroups. A realm
1094 // contains zonegroups and zones, but a single Ceph cluster can actually
1095 // serve multiple realms, by running multiple radosgw instances.
1096 S3ObjectRealm(cluster, name):: {
1097 cluster:: cluster,
1098 realm: kube._Object("ceph.rook.io/v1", "CephObjectRealm", name) {
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001099 metadata+: cluster.metadata,
Serge Bazanski38f72fe2021-09-13 23:43:47 +00001100 },
1101 },
1102
1103 // This is a rook CephObjectZoneGroup which corresponds to a radosgw
1104 // zonegroup.
1105 //
1106 // A zonegroup contains zones, and zones within a zonegroup will serve a
1107 // concise view of objects in buckets, and will sync between eachother to
1108 // eventually contain the same data.
1109 //
1110 // A single zonegroup within a realm must be a 'master' zonegroup, and will
1111 // then hold and replicate the metadata of this realm. All realm operations
1112 // via radosgw-admin must be performed within the master zonegroup.
1113 S3ObjectZoneGroup(realm, name):: {
1114 realm:: realm,
1115 zonegroup: kube._Object("ceph.rook.io/v1", "CephObjectZoneGroup", name) {
1116 metadata+: realm.cluster.metadata,
1117 spec+: {
1118 realm: realm.realm.metadata.name,
1119 },
1120 },
1121 },
1122
1123 // This is a CephObjectZone but also a CephObjectStore.
1124 //
1125 // Rook attempts to hide away Ceph's radosgw multisite structures
1126 // (realm/zonegroup/zone) by presenting a single CRD named
1127 // 'CephObjectStore'. When such a resource is created, Rook will create a
1128 // realm, zonegroup and zone under the hood, as a radosgw zone is required
1129 // to serve data, and a radosgw zone cannot exist without a zonegroup, and
1130 // a radosgw zonegroup cannot exist without a realm.
1131 //
1132 // However, rook also exposes the lower-level API by letting the user
1133 // specify 'zone' in the ObjectStore's spec, which should point to a
1134 // CephObjectZone. Then, an entirely different reconciliation codepath is
1135 // taken and instead users are expected to manage
1136 // CephObject{Realm,ZoneGroup,Zone} manually at Ceph's native abstraction
1137 // level.
1138 //
1139 // CephObjectStore not only represents a Ceph zone (and possibly
1140 // zonegroup/realm), but also pods and services that are required to servev
1141 // radosgw data publicly. That's why S3ObjectStore takes parameters like
1142 // 'public port' and 'instance number'.
1143 //
1144 // To add to the confusion, our S3ObjectStore wrapper also sprinkles in an
1145 // Ingress with TLS to terminate the above service, and automatically
1146 // creates a CephObjectZone.
1147 //
1148 // This whole jsonent abstraction basically forces users to manually create
1149 // realms and zonegroups, but makes it very easy to do so. By forcing these
1150 // to be explicitly created by rook objects, only the 'multi-site'
1151 // reconciliation codepath is taken in rook, making things a bit more
1152 // predictable.
1153 S3ObjectStore(zonegroup, name):: {
1154 local store = self,
1155 spec:: {
1156 dataPool: error "spec.dataPool must be specified",
1157 metadataPool: error "spec.metadataPool must be specified",
1158 },
1159
1160 cfg:: {
1161 // We want to have each rgw run under a domain corresponding to the
1162 // zone it's running in, but also to the zonegroup it's running in.
1163 // This will allow us to DNS loadbalance a zonegroup to be backed
1164 // by multiple zone ingresses.
1165 domainParts: [
1166 zonegroup.zone.metadata.name,
1167 zonegroup.zonegroup.metadata.name,
1168 ],
1169 domains: [
1170 "object.ceph-%s.hswaw.net" % [part]
1171 for part in cfg.domainParts
1172 ],
1173 },
1174 local cfg = self.cfg,
1175
1176 zone: kube._Object("ceph.rook.io/v1", "CephObjectZone", name) {
1177 metadata+: zonegroup.realm.cluster.metadata,
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001178 spec: store.spec {
Serge Bazanski38f72fe2021-09-13 23:43:47 +00001179 zoneGroup: zonegroup.zonegroup.metadata.name,
1180 },
1181 },
1182
1183 objectStore: kube._Object("ceph.rook.io/v1", "CephObjectStore", name) {
1184 metadata+: zonegroup.realm.cluster.metadata,
1185 spec: {
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001186 gateway: {
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001187 port: 80,
1188 instances: 1,
1189 allNodes: false,
1190 },
Serge Bazanski38f72fe2021-09-13 23:43:47 +00001191 zone: {
1192 name: name,
1193 },
1194 preservePoolsOnDelete: true,
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001195 },
1196 },
1197
1198 objectIngress: kube.Ingress(name) {
Serge Bazanski38f72fe2021-09-13 23:43:47 +00001199 metadata+: zonegroup.realm.cluster.metadata {
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001200 annotations+: {
1201 "kubernetes.io/tls-acme": "true",
1202 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
1203 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
1204 },
1205 },
Serge Bazanski38f72fe2021-09-13 23:43:47 +00001206
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001207 spec+: {
1208 tls: [
1209 {
Serge Bazanski38f72fe2021-09-13 23:43:47 +00001210 hosts: cfg.domains,
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001211 secretName: "%s-tls" % [name],
1212 },
1213 ],
1214 rules: [
1215 {
Serge Bazanski38f72fe2021-09-13 23:43:47 +00001216 host: domain,
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001217 http: {
1218 paths: [
1219 {
1220 path: "/",
1221 backend: {
1222 serviceName: "rook-ceph-rgw-%s" % [name],
1223 servicePort: 80,
1224 },
1225 },
1226 ]
1227 },
1228 }
Serge Bazanski38f72fe2021-09-13 23:43:47 +00001229 for domain in cfg.domains
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001230 ],
1231 },
1232 },
1233 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +02001234}