blob: e9ed75bf25b38230985b52ab5b567f0af9ef67d1 [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 Bazanski2c04c842021-01-19 21:41:11 +010013 image: "rook/ceph:v1.2.7",
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
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020029 crds: {
Serge Bazanski6579e842021-09-11 14:58:46 +000030 cephclusters: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephCluster") {
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020031 spec+: {
32 additionalPrinterColumns: [
33 { name: "DataDirHostPath", type: "string", description: "Directory used on the K8s nodes", JSONPath: ".spec.dataDirHostPath" },
34 { name: "MonCount", type: "string", description: "Number of MONs", JSONPath: ".spec.mon.count" },
35 { name: "Age", type: "date", JSONPath: ".metadata.creationTimestamp" },
36 { name: "State", type: "string", description: "Current State", JSONPath: ".status.state" },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +010037 { name: "Health", type: "string", description: "Ceaph Health", JSONPath: ".status.ceph.health" },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020038 ],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +010039 validation: oa.Validation(oa.Dict {
40 spec: oa.Dict {
41 annotations: oa.Any,
42 cephVersion: oa.Dict {
43 allowUnsupported: oa.Boolean,
44 image: oa.String,
45 },
46 dashboard: oa.Dict {
47 enabled: oa.Boolean,
48 urlPrefix: oa.String,
49 port: oa.Integer { minimum: 0, maximum: 65535 },
50 ssl: oa.Boolean,
51 },
52 dataDirHostPath: oa.String { pattern: "^/(\\S+)" },
53 skipUpgradeChecks: oa.Boolean,
Serge Bazanski3b9ee5f2021-01-19 22:44:07 +010054 continueUpgradeAfterChecksEvenIfNotHealthy: oa.Boolean,
Sergiusz Bazanskid436de22020-02-21 17:10:42 +010055 mon: oa.Dict {
56 allowMultiplePerNode: oa.Boolean,
57 count: oa.Integer { minimum: 0, maximum: 9 },
58 preferredCount: oa.Integer { minimum: 0, maximum: 9 },
59 },
60 mgr: oa.Dict {
61 modules: oa.Array(oa.Dict {
62 name: oa.String,
63 enabled: oa.Boolean,
64 }),
65 },
66 network: oa.Dict {
67 hostNetwork: oa.Boolean,
68 },
69 storage: oa.Dict {
70 disruptionManagement: oa.Dict {
71 managePodBudgets: oa.Boolean,
72 osdMaintenanceTimeout: oa.Integer,
73 manageMachineDisruptionBudgets: oa.Boolean,
74 },
75 useAllNodes: oa.Boolean,
76 nodes: oa.Array(oa.Dict {
77 name: oa.String,
78 config: oa.Dict {
79 metadataDevice: oa.String,
80 storeType: oa.String { pattern: "^(filestore|bluestore)$" },
81 databaseSizeMB: oa.String,
82 walSizeMB: oa.String,
83 journalSizeMB: oa.String,
84 osdsPerDevice: oa.String,
85 encryptedDevice: oa.String { pattern: "^(true|false)$" },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020086 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +010087 useAllDevices: oa.Boolean,
88 deviceFilter: oa.Any,
89 directories: oa.Array(oa.Dict {
90 path: oa.String,
91 }),
92 devices: oa.Array(oa.Dict {
93 name: oa.String,
94 }),
95 location: oa.Any,
96 resources: oa.Any,
97 }),
98 useAllDevices: oa.Boolean,
99 deviceFilter: oa.Any,
100 location: oa.Any,
101 directories: oa.Array(oa.Dict {
102 path: oa.String,
103 }),
104 config: oa.Any,
105 topologyAware: oa.Boolean,
106 },
107 monitoring: oa.Dict {
108 enabled: oa.Boolean,
109 rulesNamespace: oa.String,
110 },
111 rbdMirroring: oa.Dict {
112 workers: oa.Integer,
113 },
114 placement: oa.Any,
115 resources: oa.Any,
116 },
117 }),
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200118 },
119 },
120 cephfilesystems: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephFilesystem") {
121 spec+: {
122 additionalPrinterColumns: [
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100123 { name: "ActiveMDS", type: "string", description: "Number of desired active MDS daemons", JSONPath: ".spec.metadataServer.activeCount" },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200124 { name: "Age", type: "date", JSONPath: ".metadata.creationTimestamp" },
125 ],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100126 validation: oa.Validation(oa.Dict {
127 spec: oa.Dict {
128 metadataServer: oa.Dict {
129 activeCount: oa.Integer,
130 activeStandby: oa.Boolean,
131 annotations: oa.Any,
132 placement: oa.Any,
133 resources: oa.Any,
134 },
135 metadataPool: oa.Dict {
136 failureDomain: oa.String,
137 replicated: oa.Dict {
138 size: oa.Integer,
139 },
140 erasureCoded: oa.Dict {
141 dataChunks: oa.Integer,
142 codingChunks: oa.Integer,
143 },
144 },
145 dataPools: oa.Array(oa.Dict {
146 failureDomain: oa.String,
147 replicated: oa.Dict {
148 site: oa.Integer,
149 erasureCoded: oa.Dict {
150 dataChunks: oa.Integer,
151 codingChunks: oa.Integer,
152 },
153 },
154 })
155 },
156 }),
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200157 },
158 },
159 cephnfses: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephNFS") {
160 spec+: {
161 names+: {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200162 plural: "cephnfses",
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200163 shortNames: ["nfs"],
164 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100165 validation: oa.Validation(oa.Dict {
166 spec: oa.Dict {
167 rados: oa.Dict {
168 pool: oa.String,
169 namespace: oa.String,
170 },
171 server: oa.Dict {
172 active: oa.Integer,
173 annotations: oa.Any,
174 placement: oa.Any,
175 resources: oa.Any,
176 },
177 },
178 }),
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200179 },
180 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100181 cephobjectstores: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephObjectStore") {
182 spec+: {
183 validation: oa.Validation(oa.Dict {
184 spec: oa.Dict {
185 gateway: oa.Dict {
186 type: oa.String,
187 sslCertificateRef: oa.Any,
188 port: oa.Integer,
189 securePort: oa.Any,
190 instances: oa.Integer,
191 annotations: oa.Any,
192 placement: oa.Any,
193 resources: oa.Any,
194 },
195 local poolDef = oa.Dict {
196 failureDomain: oa.String,
197 replicated: oa.Dict {
198 size: oa.Integer,
199 },
200 erasureCoded: oa.Dict {
201 dataChunks: oa.Integer,
202 codingChunks: oa.Integer,
203 },
204 },
205 metadataPool: poolDef,
206 dataPool: poolDef,
207 },
208 }),
209 },
210 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200211 cephobjectstoreusers: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephObjectStoreUser"),
212 cephblockpools: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephBlockPool"),
213 volumes: kube.CustomResourceDefinition("rook.io", "v1alpha2", "Volume") {
214 spec+: {
215 names+: {
216 shortNames: ["rv"],
217 },
218 },
219 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100220 objectbuckets: kube.CustomResourceDefinition("objectbucket.io", "v1alpha1", "ObjectBucket") {
221 spec+: {
222 names+: {
223 shortNames: ["ob", "obs"],
224 },
225 scope: "Cluster",
226 subresources: { status: {} },
227 },
228 },
229 objectbucketclaims: kube.CustomResourceDefinition("objectbucket.io", "v1alpha1", "ObjectBucketClaim") {
230 spec+: {
231 names+: {
232 shortNames: ["obc", "obcs"],
233 },
234 subresources: { status: {} },
235 },
236 },
Serge Bazanski2c04c842021-01-19 21:41:11 +0100237 cephclients: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephClient") {
238 spec+: {
239 validation: oa.Validation(oa.Dict {
240 spec: oa.Dict {
241 caps: oa.Any,
242 },
243 }),
244 },
245 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200246 },
247
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100248 sa: {
249 system: kube.ServiceAccount("rook-ceph-system") {
250 metadata+: env.metadata,
251 },
252 csiCephfsPlugin: kube.ServiceAccount("rook-csi-cephfs-plugin-sa") {
253 metadata+: env.metadata,
254 },
255 csiCephfsProvisioner: kube.ServiceAccount("rook-csi-cephfs-provisioner-sa") {
256 metadata+: env.metadata,
257 },
258 csiRbdPlugin: kube.ServiceAccount("rook-csi-rbd-plugin-sa") {
259 metadata+: env.metadata,
260 },
261 csiRbdProvisioner: kube.ServiceAccount("rook-csi-rbd-provisioner-sa") {
262 metadata+: env.metadata,
263 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200264 },
265
266 crs: {
267 clusterMgmt: kube.ClusterRole("rook-ceph-cluster-mgmt") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200268 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200269 rules: [
270 {
271 apiGroups: [""],
272 resources: ["secrets", "pods", "pods/log", "services", "configmaps"],
273 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
274 },
275 {
276 apiGroups: ["apps"],
277 resources: ["deployments", "daemonsets", "replicasets"],
278 verbs: ["get", "list", "watch", "create", "update", "delete"],
279 },
280 ],
281 },
282 global: kube.ClusterRole("rook-ceph-global") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200283 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200284 rules: [
285 {
286 apiGroups: [""],
287 resources: ["pods", "nodes", "nodes/proxy"],
288 verbs: ["get", "list", "watch"],
289 },
290 {
291 apiGroups: [""],
292 resources: ["events", "persistentvolumes", "persistentvolumeclaims", "endpoints"],
293 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
294 },
295 {
296 apiGroups: ["storage.k8s.io"],
297 resources: ["storageclasses"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100298 verbs: ["get", "list", "watch"],
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200299 },
300 {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200301 apiGroups: ["batch"],
302 resources: ["jobs"],
303 verbs: ["get", "list", "watch", "create", "update", "delete"],
304 },
305 {
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200306 apiGroups: ["ceph.rook.io"],
307 resources: ["*"],
308 verbs: ["*"],
309 },
310 {
311 apiGroups: ["rook.io"],
312 resources: ["*"],
313 verbs: ["*"],
314 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100315 {
316 apiGroups: ["policy", "apps"],
Serge Bazanski2c04c842021-01-19 21:41:11 +0100317 resources: ["poddisruptionbudgets", "deployments", "replicasets"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100318 verbs: ["*"],
319 },
Serge Bazanski2c04c842021-01-19 21:41:11 +0100320 {
321 apiGroups: ["healthchecking.openshift.io"],
322 resources: ["machinedisruptionbudgets"],
323 verbs: ["get", "list", "watch", "create", "update", "delete"],
324 },
325 {
326 apiGroups: ["machine.openshift.io"],
327 resources: ["machines"],
328 verbs: ["get", "list", "watch", "create", "update", "delete"],
329 },
330 {
331 apiGroups: ["storage.k8s.io"],
332 resources: ["csidrivers"],
333 verbs: ["create"],
334 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200335 ],
336 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100337
338 // Upstream rook uses split ClusterRoles, with the 'main' role (eg rook-ceph-cluster-mgmt)
339 // using aggregationRules to point to a '-rules' role (eg rook-ceph-cluster-mgmt-rules) which
340 // contains the actual role rules. This was done to permit for a bettr upgrade experience on
341 // systems that only allow for a recreation of a clusterroles (see https://github.com/rook/rook/issues/2634
342 // for more background information).
343 // We do not use this split because our update mechanism is not broken. However, it seems
344 // that Rook started to use these split rules for other reasons, too. For instance, the
345 // mgr-cluster role in upstream not only aggregates its equivalent -rules role, but also
346 // the rook-ceph-object-bucket role. As such, we split mgr-cluster as they do in upstream.
347 // In the future, we may split the rest of the roles in order to stay consisdent with upsteam.
348
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200349 mgrCluster: kube.ClusterRole("rook-ceph-mgr-cluster") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200350 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100351 aggregationRule: {
352 clusterRoleSelectors: [
353 { matchLabels: { "rbac.ceph.rook.io/aggregate-to-rook-ceph-mgr-cluster": "true" }},
354 ],
355 },
356 },
357 mgrClusterRules: kube.ClusterRole("rook-ceph-mgr-cluster-rules") {
358 metadata+: env.metadata {
359 namespace:: null,
360 labels+: {
361 "rbac.ceph.rook.io/aggregate-to-rook-ceph-mgr-cluster": "true",
362 },
363 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200364 rules: [
365 {
366 apiGroups: [""],
367 resources: ["configmaps", "nodes", "nodes/proxy"],
368 verbs: ["get", "list", "watch"],
369 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100370 {
371 apiGroups: [""],
372 resources: ["events"],
373 verbs: ["create", "patch", "list", "get", "watch"],
374 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200375 ]
376 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100377 objectBucket: kube.ClusterRole("rook-ceph-object-bucket") {
378 metadata+: env.metadata {
379 namespace:: null,
380 labels+: {
381 "rbac.ceph.rook.io/aggregate-to-rook-ceph-mgr-cluster": "true",
382 },
383 },
384 rules: [
385 {
386 apiGroups: [""],
387 resources: ["secrets", "configmaps"],
388 verbs: ["*"],
389 },
390 {
391 apiGroups: ["storage.k8s.io"],
392 resources: ["storageclasses"],
393 verbs: ["get", "list", "watch"],
394 },
395 {
396 apiGroups: ["objectbucket.io"],
397 resources: ["*"],
398 verbs: ["*"],
399 },
400 ],
401 },
402
403 cephfsCSINodeplugin: kube.ClusterRole("cephfs-csi-nodeplugin") {
404 metadata+: env.metadata { namespace:: null },
405 rules: [
406 {
407 apiGroups: [""],
408 resources: ["nodes"],
409 verbs: ["get", "list", "update"],
410 },
411 {
412 apiGroups: [""],
413 resources: ["namespaces"],
414 verbs: ["get", "list"],
415 },
416 {
417 apiGroups: [""],
418 resources: ["persistentvolumes"],
419 verbs: ["get", "list", "watch", "update"],
420 },
421 {
422 apiGroups: ["storage.k8s.io"],
423 resources: ["volumeattachments"],
424 verbs: ["get", "list", "watch", "update"],
425 },
426 {
427 apiGroups: [""],
428 resources: ["configmaps"],
429 verbs: ["get", "list"],
430 },
431 ],
432 },
433
434 cephfsExternalProvisionerRunner: kube.ClusterRole("cephfs-external-provisioner-runner") {
435 metadata+: env.metadata { namespace:: null },
436 rules: [
437 {
438 apiGroups: [""],
439 resources: ["secrets"],
440 verbs: ["get", "list"],
441 },
442 {
443 apiGroups: [""],
444 resources: ["persistentvolumes"],
445 verbs: ["get", "list", "watch", "create", "update", "delete"],
446 },
447 {
448 apiGroups: [""],
449 resources: ["persistentvolumeclaims"],
450 verbs: ["get", "list", "watch", "update"],
451 },
452 {
453 apiGroups: ["storage.k8s.io"],
454 resources: ["storageclasses"],
455 verbs: ["get", "list", "watch"],
456 },
457 {
458 apiGroups: [""],
459 resources: ["events"],
460 verbs: ["list", "watch", "create", "update", "patch"],
461 },
462 {
463 apiGroups: ["storage.k8s.io"],
464 resources: ["volumeattachments"],
465 verbs: ["get", "list", "watch", "update"],
466 },
467 {
468 apiGroups: [""],
469 resources: ["nodes"],
470 verbs: ["get", "list", "watch"],
471 },
472 ],
473 },
474
475 rbdCSINodeplugin: kube.ClusterRole("rbd-csi-nodeplugin") {
476 metadata+: env.metadata { namespace:: null },
477 rules: [
478 {
479 apiGroups: [""],
480 resources: ["secrets"],
481 verbs: ["get", "list"],
482 },
483 {
484 apiGroups: [""],
485 resources: ["nodes"],
486 verbs: ["get", "list", "update"],
487 },
488 {
489 apiGroups: [""],
490 resources: ["namespaces"],
491 verbs: ["get", "list"],
492 },
493 {
494 apiGroups: [""],
495 resources: ["persistentvolumes"],
496 verbs: ["get", "list", "watch", "update"],
497 },
498 {
499 apiGroups: ["storage.k8s.io"],
500 resources: ["volumeattachments"],
501 verbs: ["get", "list", "watch", "update"],
502 },
503 {
504 apiGroups: [""],
505 resources: ["configmaps"],
506 verbs: ["get", "list"],
507 },
508 ],
509 },
510
511 rbdExternalProvisionerRunner: kube.ClusterRole("rbd-external-provisioner-runner") {
512 metadata+: env.metadata { namespace:: null },
513 rules: [
514 {
515 apiGroups: [""],
516 resources: ["secrets"],
517 verbs: ["get", "list"],
518 },
519 {
520 apiGroups: [""],
521 resources: ["persistentvolumes"],
522 verbs: ["get", "list", "watch", "create", "update", "delete"],
523 },
524 {
525 apiGroups: [""],
526 resources: ["persistentvolumeclaims"],
527 verbs: ["get", "list", "watch", "update"],
528 },
529 {
530 apiGroups: ["storage.k8s.io"],
531 resources: ["volumeattachments"],
532 verbs: ["get", "list", "watch", "update"],
533 },
534 {
535 apiGroups: [""],
536 resources: ["nodes"],
537 verbs: ["get", "list", "watch"],
538 },
539 {
540 apiGroups: ["storage.k8s.io"],
541 resources: ["storageclasses"],
542 verbs: ["get", "list", "watch"]
543 },
544 {
545 apiGroups: [""],
546 resources: ["events"],
547 verbs: ["list", "watch", "create", "update", "patch"],
548 },
549 {
550 apiGroups: ["snapshot.storage.k8s.io"],
551 resources: ["volumesnapshotcontents"],
552 verbs: ["create", "get", "list", "watch", "update", "delete"],
553 },
554 {
555 apiGroups: ["snapshot.storage.k8s.io"],
556 resources: ["volumesnapshotclasses"],
557 verbs: ["get", "list", "watch"],
558 },
559 {
560 apiGroups: ["apiextensions.k8s.io"],
561 resources: ["customresourcedefinitions"],
562 verbs: ["create", "list", "watch", "delete", "get", "update"],
563 },
564 {
565 apiGroups: ["snapshot.storage.k8s.io"],
566 resources: ["volumesnapshots/status"],
567 verbs: ["update"],
568 },
569 ],
570 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200571 },
572
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100573 crbs: {
574 global: kube.ClusterRoleBinding("ceph-rook-global") {
575 metadata+: env.metadata { namespace:: null },
576 roleRef_: env.crs.global,
577 subjects_: [env.sa.system],
578 },
579 objectBucket: kube.ClusterRoleBinding("rook-ceph-object-bucket") {
580 metadata+: env.metadata { namespace:: null },
581 roleRef_: env.crs.objectBucket,
582 subjects_: [env.sa.system],
583 },
584 cephfsCSINodeplugin: kube.ClusterRoleBinding("cepfs-csi-nodeplugin") {
585 metadata+: env.metadata { namespace:: null },
586 roleRef_: env.crs.cephfsCSINodeplugin,
587 subjects_: [env.sa.csiCephfsPlugin],
588 },
589 cephfsCSIProvisioner: kube.ClusterRoleBinding("cephfs-csi-provisioner") {
590 metadata+: env.metadata { namespace:: null },
591 roleRef_: env.crs.cephfsExternalProvisionerRunner,
592 subjects_: [env.sa.csiCephfsProvisioner],
593 },
594 rbdCSINodeplugin: kube.ClusterRoleBinding("rbd-csi-nodeplugin") {
595 metadata+: env.metadata { namespace:: null },
596 roleRef_: env.crs.rbdCSINodeplugin,
597 subjects_: [env.sa.csiRbdPlugin],
598 },
599 rbdCSIProvisioner: kube.ClusterRoleBinding("rbd-csi-provisioner") {
600 metadata+: env.metadata { namespace:: null },
601 roleRef_: env.crs.rbdExternalProvisionerRunner,
602 subjects_: [env.sa.csiRbdProvisioner],
603 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200604 },
605
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100606 roles: {
607 system: kube.Role("ceph-rook-system") {
608 metadata+: env.metadata,
609 rules: [
610 {
611 apiGroups: [""],
612 resources: ["pods", "configmaps", "services"],
613 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
614 },
615 {
616 apiGroups: ["apps"],
617 resources: ["deployments", "statefulsets", "daemonsets"],
618 verbs: ["get", "list", "watch", "create", "update", "delete"],
619 },
620 ],
621 },
622 cephfsExternalProvisioner: kube.Role("cephfs-external-provisioner-cfg") {
623 metadata+: env.metadata,
624 rules: [
625 {
626 apiGroups: [""],
627 resources: ["endpoints"],
628 verbs: ["get", "watch", "list", "delete", "update", "create"],
629 },
630 {
631 apiGroups: [""],
632 resources: ["configmaps"],
633 verbs: ["get", "list", "create", "delete"],
634 },
635 {
636 apiGroups: ["coordination.k8s.io"],
637 resources: ["leases"],
638 verbs: ["get" ,"watch", "list", "delete", "update", "create"],
639 },
640 ],
641 },
642 rbdExternalProvisioner: kube.Role("rbd-external-provisioner-cfg") {
643 metadata+: env.metadata,
644 rules: [
645 {
646 apiGroups: [""],
647 resources: ["endpoints"],
648 verbs: ["get", "watch", "list", "delete", "update", "create"],
649 },
650 {
651 apiGroups: [""],
652 resources: ["configmaps"],
653 verbs: ["get", "list", "watch", "create", "delete"],
654 },
655 {
656 apiGroups: ["coordination.k8s.io"],
657 resources: ["leases"],
658 verbs: ["get" ,"watch", "list", "delete", "update", "create"],
659 },
660 ],
661 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200662 },
663
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100664 rbs: {
665 system: kube.RoleBinding("ceph-rook-system") {
666 metadata+: env.metadata,
667 roleRef_: env.roles.system,
668 subjects_: [env.sa.system],
669 },
670 cephfsCSIProvisioner: kube.RoleBinding("cephfs-csi-provisioner-role-cfg") {
671 metadata+: env.metadata,
672 roleRef_: env.roles.cephfsExternalProvisioner,
673 subjects_: [env.sa.csiCephfsProvisioner],
674 },
675 rbdCSIProvisioner: kube.RoleBinding("rbd-csi-provisioner-role-cfg") {
676 metadata+: env.metadata,
677 roleRef_: env.roles.rbdExternalProvisioner,
678 subjects_: [env.sa.csiRbdProvisioner],
679 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200680 },
681
682 operator: kube.Deployment("rook-ceph-operator") {
683 metadata+: env.metadata,
684 spec+: {
685 template+: {
686 spec+: {
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100687 serviceAccountName: env.sa.system.metadata.name,
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200688 containers_: {
689 operator: kube.Container("rook-ceph-operator") {
690 image: cfg.image,
691 args: ["ceph", "operator"],
692 volumeMounts_: {
693 "rook-config": { mountPath: "/var/lib/rook" },
694 "default-config-dir": { mountPath: "/etc/ceph" },
695 },
696 env_: {
697 LIB_MODULES_DIR_PATH: "/run/current-system/kernel-modules/lib/modules/",
698 ROOK_ALLOW_MULTIPLE_FILESYSTEMS: "false",
Sergiusz Bazanski321fad92019-04-19 14:14:36 +0200699 ROOK_LOG_LEVEL: "INFO",
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200700 ROOK_MON_HEALTHCHECK_INTERVAL: "45s",
701 ROOK_MON_OUT_TIMEOUT: "600s",
702 ROOK_DISCOVER_DEVICES_INTERVAL: "60m",
703 ROOK_HOSTPATH_REQUIRES_PRIVILEGED: "false",
704 ROOK_ENABLE_SELINUX_RELABELING: "true",
705 ROOK_ENABLE_FSGROUP: "true",
706 NODE_NAME: kube.FieldRef("spec.nodeName"),
707 POD_NAME: kube.FieldRef("metadata.name"),
708 POD_NAMESPACE: kube.FieldRef("metadata.namespace"),
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100709 ROOK_CSI_KUBELET_DIR_PATH: "/var/lib/kubernetes"
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200710 },
711 },
712 },
713 volumes_: {
714 "rook-config": { emptyDir: {} },
715 "default-config-dir": { emptyDir: {} },
716 },
717 },
718 },
719 },
720 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200721 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200722
723 // Create a new Ceph cluster in a new namespace.
724 Cluster(operator, name):: {
725 local cluster = self,
726 spec:: error "please define cluster spec",
727
728
729 metadata:: {
730 namespace: name,
731 },
732
733 name(suffix):: cluster.metadata.namespace + "-" + suffix,
734
735 namespace: kube.Namespace(cluster.metadata.namespace),
736
737 sa: {
738 // service accounts need to be hardcoded, see operator source.
739 osd: kube.ServiceAccount("rook-ceph-osd") {
740 metadata+: cluster.metadata,
741 },
742 mgr: kube.ServiceAccount("rook-ceph-mgr") {
743 metadata+: cluster.metadata,
744 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100745 cmdReporter: kube.ServiceAccount("rook-ceph-cmd-reporter") {
746 metadata+: cluster.metadata,
747 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200748 },
749
750 roles: {
751 osd: kube.Role(cluster.name("osd")) {
752 metadata+: cluster.metadata,
753 rules: [
754 {
755 apiGroups: [""],
756 resources: ["configmaps"],
757 verbs: ["get", "list", "watch", "create", "update", "delete"],
Serge Bazanski2c04c842021-01-19 21:41:11 +0100758 },
759 ],
760 },
761 osdCluster: kube.ClusterRole(cluster.name("osd-cluster")) {
762 metadata+: cluster.metadata { namespace:: null },
763 rules: [
764 {
765 apiGroups: [""],
766 resources: ["nodes"],
767 verbs: ["get", "list"],
768 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200769 ],
770 },
771 mgr: kube.Role(cluster.name("mgr")) {
772 metadata+: cluster.metadata,
773 rules: [
774 {
775 apiGroups: [""],
776 resources: ["pods", "services"],
777 verbs: ["get", "list", "watch"],
778 },
779 {
780 apiGroups: ["batch"],
781 resources: ["jobs"],
782 verbs: ["get", "list", "watch", "create", "update", "delete"],
783 },
784 {
785 apiGroups: ["ceph.rook.io"],
786 resources: ["*"],
787 verbs: ["*"],
788 },
789 ],
790 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100791 cmdReporter: kube.Role(cluster.name("cmd-reporter")) {
792 metadata+: cluster.metadata,
793 rules: [
794 {
795 apiGroups: [""],
796 resources: ["pods", "configmaps"],
797 verbs: ["get", "list", "watch", "create", "update", "delete"],
798 },
799 ],
800 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200801 mgrSystem: kube.ClusterRole(cluster.name("mgr-system")) {
802 metadata+: cluster.metadata { namespace:: null },
803 rules: [
804 {
805 apiGroups: [""],
806 resources: ["configmaps"],
807 verbs: ["get", "list", "watch"],
808 }
809 ],
810 },
811 },
812
813 rbs: [
814 kube.RoleBinding(cluster.name(el.name)) {
815 metadata+: cluster.metadata,
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200816 roleRef_: el.role,
817 subjects_: [el.sa],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200818 },
819 for el in [
820 // Allow Operator SA to perform Cluster Mgmt in this namespace.
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100821 { name: "cluster-mgmt", role: operator.crs.clusterMgmt, sa: operator.sa.system },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200822 { name: "osd", role: cluster.roles.osd, sa: cluster.sa.osd },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200823 { name: "mgr", role: cluster.roles.mgr, sa: cluster.sa.mgr },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100824 { name: "cmd-reporter", role: cluster.roles.cmdReporter, sa: cluster.sa.cmdReporter },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200825 { name: "mgr-cluster", role: operator.crs.mgrCluster, sa: cluster.sa.mgr },
826 ]
827 ],
828
829 mgrSystemRB: kube.RoleBinding(cluster.name("mgr-system")) {
830 metadata+: {
831 namespace: operator.cfg.namespace,
832 },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200833 roleRef_: cluster.roles.mgrSystem,
834 subjects_: [cluster.sa.mgr],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200835 },
836
Serge Bazanski2c04c842021-01-19 21:41:11 +0100837 osdClusterRB: kube.ClusterRoleBinding(cluster.name("osd-cluster")) {
838 metadata+: {
839 namespace:: null,
840 },
841 roleRef_: cluster.roles.osdCluster,
842 subjects_: [cluster.sa.osd],
843 },
844
845
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200846 cluster: kube._Object("ceph.rook.io/v1", "CephCluster", name) {
847 metadata+: cluster.metadata,
848 spec: {
849 cephVersion: {
Sergiusz Bazanskied2e6702019-04-19 13:27:20 +0200850 # https://github.com/rook/rook/issues/2945#issuecomment-483964014
Serge Bazanski3b9ee5f2021-01-19 22:44:07 +0100851 image: "ceph/ceph:v14.2.16",
Sergiusz Bazanskied2e6702019-04-19 13:27:20 +0200852 allowUnsupported: true,
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200853 },
Serge Bazanskic33ebcc2019-11-01 18:43:45 +0100854 dataDirHostPath: if name == "ceph-waw2" then "/var/lib/rook" else "/var/lib/rook-%s" % [name],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200855 dashboard: {
856 ssl: false,
857 enabled: true,
858 port: 8080,
859 },
860 } + cluster.spec,
861 },
862
863 dashboardService: kube.Service(cluster.name("dashboard")) {
864 metadata+: cluster.metadata,
865 spec: {
866 ports: [
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200867 { name: "dashboard", port: 80, targetPort: 8080, protocol: "TCP" },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200868 ],
869 selector: {
870 app: "rook-ceph-mgr",
871 rook_cluster: name,
872 },
873 type: "ClusterIP",
874 },
875 },
876
877 dashboardIngress: kube.Ingress(cluster.name("dashboard")) {
Piotr Dobrowolski3187c592019-04-02 14:44:04 +0200878 metadata+: cluster.metadata {
879 annotations+: {
880 "kubernetes.io/tls-acme": "true",
881 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
882 },
883 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200884 spec+: {
Piotr Dobrowolski3187c592019-04-02 14:44:04 +0200885 tls: [
886 {
887 hosts: ["%s.hswaw.net" % name],
888 secretName: cluster.name("dashboard"),
889 },
890 ],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200891 rules: [
892 {
893 host: "%s.hswaw.net" % name,
894 http: {
895 paths: [
896 { path: "/", backend: cluster.dashboardService.name_port },
897 ]
898 },
899 }
900 ],
901 },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200902 },
903
904 # Benji is a backup tool, external to rook, that we use for backing up
905 # RBDs.
906 benji: {
907 sa: kube.ServiceAccount(cluster.name("benji")) {
908 metadata+: cluster.metadata,
909 },
910
911 cr: kube.ClusterRole(cluster.name("benji")) {
912 rules: [
913 {
914 apiGroups: [""],
915 resources: [
916 "persistentvolumes",
917 "persistentvolumeclaims"
918 ],
919 verbs: ["list", "get"],
920 },
921 {
922 apiGroups: [""],
923 resources: [
924 "events",
925 ],
926 verbs: ["create", "update"],
927 },
928 ],
929 },
930
931 crb: kube.ClusterRoleBinding(cluster.name("benji")) {
932 roleRef_: cluster.benji.cr,
933 subjects_: [cluster.benji.sa],
934 },
935
936 config: kube.Secret(cluster.name("benji-config")) {
937 metadata+: cluster.metadata,
938 data_: {
939 "benji.yaml": std.manifestJson({
940 configurationVersion: '1',
941 databaseEngine: 'sqlite:////data/benji.sqlite',
942 defaultStorage: 'wasabi',
943 storages: [
944 {
945 name: "wasabi",
946 storageId: 1,
947 module: "s3",
948 configuration: cluster.spec.benji.s3Configuration {
949 activeTransforms: ["encrypt"],
950 },
951 },
952 ],
953 transforms: [
954 {
955 name: "encrypt",
956 module: "aes_256_gcm",
957 configuration: {
958 # not secret.
959 kdfSalt: "T2huZzZpcGhhaWM3QWVwaDhybzRhaDNhbzFpc2VpOWFobDNSZWVQaGVvTWV1bmVaYWVsNHRoYWg5QWVENHNoYWg0ZGFoN3Rlb3NvcHVuZzNpZXZpMm9vTG9vbmc1YWlmb0RlZXAwYmFobDlab294b2hjaG9odjRhbzFsYWkwYWk=",
960 kdfIterations: 2137,
961 password: cluster.spec.benji.encryptionPassword,
962 },
963 },
964 ],
965 ios: [
966 { name: pool, module: "rbd" }
967 for pool in cluster.spec.benji.pools
968 ],
969 }),
970 },
971 },
972
973 # Yes, Benji keeps data (backup metadata) on the ceph cluster that
974 # it backs up. However:
975 # - we add a command to benji-k8s to also copy over the sqlite
976 # database over to s3
977 # - benji can, in a pinch, restore without a database if a version
978 # is known: https://benji-backup.me/restore.html#restoring-without-a-database
979 data: kube.PersistentVolumeClaim(cluster.name("benji-data")) {
980 metadata+: cluster.metadata,
981 spec+: {
982 storageClassName: cluster.spec.benji.metadataStorageClass,
983 accessModes: [ "ReadWriteOnce" ],
984 resources: {
985 requests: {
986 storage: "1Gi",
987 },
988 },
989 },
990 },
991
992 # Extra scripts.
993 extrabins: kube.ConfigMap(cluster.name("benji-extrabins")) {
994 metadata+: cluster.metadata,
995 data: {
996 "metabackup.sh" : |||
997 # Make backups of sqlite3 metadata used by Benji.
998 # The backups live in the same bucket as backups, and the metabackups
999 # are named `metabackup-0..10`, where 0 is the newest backup. Any time
1000 # this script is called, backups get shifted one way to the left (9 to 10,
1001 # 8 to 9, etc). This ensures we have at least 10 backup replicas.
1002
1003 set -e
1004
1005 which s3cmd || pip install --upgrade s3cmd
1006
1007 AWS_ACCESS_KEY_ID=$(jq -r .storages[0].configuration.awsAccessKeyId < /etc/benji/benji.yaml)
1008 AWS_SECRET_ACCESS_KEY=$(jq -r .storages[0].configuration.awsSecretAccessKey < /etc/benji/benji.yaml)
1009 BUCKET=$(jq -r .storages[0].configuration.bucketName < /etc/benji/benji.yaml)
1010
1011 s3() {
1012 s3cmd --host=s3.wasabisys.com \
1013 "--host-bucket=%(bucket)s.s3.wasabisys.com" \
1014 --region=eu-central-1 \
1015 --access_key=$AWS_ACCESS_KEY_ID \
1016 --secret_key=$AWS_SECRET_ACCESS_KEY \
1017 "$@"
1018 }
1019
1020 # Copy over old backups, if they exist.
1021 for i in `seq 9 -1 0`; do
1022 from="s3://$BUCKET/metabackup-$i.sqlite3"
1023 to="s3://$BUCKET/metabackup-$((i+1)).sqlite3"
1024
1025 if [[ $(s3 ls $from | wc -l) -eq 0 ]]; then
1026 echo "$from does not exist, skipping shift."
1027 continue
1028 fi
1029 echo "Moving $from to $to..."
1030 s3 mv $from $to
1031 done
1032
1033 # Make new metabackup.
1034 s3 put /data/benji.sqlite s3://$BUCKET/metabackup-0.sqlite3
1035
1036 |||,
1037 "get-rook-creds.sh": |||
1038 # Based on the Rook Toolbox /usr/local/bin/toolbox.sh script.
1039 # Copyright 2016 The Rook Authors. All rights reserved.
1040
1041 CEPH_CONFIG="/etc/ceph/ceph.conf"
1042 MON_CONFIG="/etc/rook/mon-endpoints"
1043 KEYRING_FILE="/etc/ceph/keyring"
1044
1045 # create a ceph config file in its default location so ceph/rados tools can be used
1046 # without specifying any arguments
1047 write_endpoints() {
1048 endpoints=$(cat ${MON_CONFIG})
1049
1050 # filter out the mon names
1051 mon_endpoints=$(echo ${endpoints} | sed 's/[a-z]\+=//g')
1052
1053 # filter out the legacy mon names
1054 mon_endpoints=$(echo ${mon_endpoints} | sed 's/rook-ceph-mon[0-9]\+=//g')
1055
1056 DATE=$(date)
1057 echo "$DATE writing mon endpoints to ${CEPH_CONFIG}: ${endpoints}"
1058 cat <<EOF > ${CEPH_CONFIG}
1059 [global]
1060 mon_host = ${mon_endpoints}
1061
1062 [client.admin]
1063 keyring = ${KEYRING_FILE}
1064 EOF
1065 }
1066
1067 # watch the endpoints config file and update if the mon endpoints ever change
1068 watch_endpoints() {
1069 # get the timestamp for the target of the soft link
1070 real_path=$(realpath ${MON_CONFIG})
1071 initial_time=$(stat -c %Z ${real_path})
1072 while true; do
1073 real_path=$(realpath ${MON_CONFIG})
1074 latest_time=$(stat -c %Z ${real_path})
1075
1076 if [[ "${latest_time}" != "${initial_time}" ]]; then
1077 write_endpoints
1078 initial_time=${latest_time}
1079 fi
1080 sleep 10
1081 done
1082 }
1083
1084 # create the keyring file
1085 cat <<EOF > ${KEYRING_FILE}
1086 [client.admin]
1087 key = ${ROOK_ADMIN_SECRET}
1088 EOF
1089
1090 # write the initial config file
1091 write_endpoints
1092
1093 # continuously update the mon endpoints if they fail over
1094 watch_endpoints &
1095 |||
1096 },
1097 },
1098
1099 cronjob: kube.CronJob(cluster.name("benji")) {
1100 metadata+: cluster.metadata,
1101 spec+: { # CronJob Spec
Sergiusz Bazanski95868ee2019-09-26 23:47:14 +02001102 schedule: "42 0 * * *", # Daily at 42 minute past midnight.
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +02001103 jobTemplate+: {
1104 spec+: { # Job Spec
1105 selector:: null,
1106 template+: {
1107 spec+: { # PodSpec
1108 serviceAccountName: cluster.benji.sa.metadata.name,
1109 containers_: {
1110 benji: kube.Container(cluster.name("benji")) {
Sergiusz Bazanski0c337ac2019-12-21 23:45:07 +01001111 # TODO(q3k): switch back to upstream after pull/65 goes in.
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +02001112 # Currently this is being built from github.com/q3k/benji.
Sergiusz Bazanski0c337ac2019-12-21 23:45:07 +01001113 # https://github.com/elemental-lf/benji/pull/65
1114 image: "registry.k0.hswaw.net/q3k/benji-k8s:20191221-2336",
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +02001115 volumeMounts_: {
1116 extrabins: { mountPath: "/usr/local/extrabins" },
1117 monendpoints: { mountPath: "/etc/rook" },
1118 benjiconfig: { mountPath: "/etc/benji" },
1119 data: { mountPath: "/data" },
1120 },
1121 env_: {
1122 ROOK_ADMIN_SECRET: { secretKeyRef: { name: "rook-ceph-mon", key: "admin-secret" }},
1123 },
1124 command: [
1125 "bash", "-c", |||
1126 bash /usr/local/extrabins/get-rook-creds.sh
Sergiusz Bazanski0c337ac2019-12-21 23:45:07 +01001127 benji-backup-pvc %s
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +02001128 benji-command enforce latest3,hours48,days7,months12
1129 benji-command cleanup
1130 bash /usr/local/extrabins/metabackup.sh
Sergiusz Bazanski0c337ac2019-12-21 23:45:07 +01001131 ||| % [std.join(" ", ["--pool-filter=%s" % [p] for p in cluster.spec.benji.pools])],
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +02001132 ],
1133 },
1134 },
1135 volumes_: {
1136 data: kube.PersistentVolumeClaimVolume(cluster.benji.data),
1137 benjiconfig: kube.SecretVolume(cluster.benji.config),
1138 extrabins: kube.ConfigMapVolume(cluster.benji.extrabins),
1139 monendpoints: {
1140 configMap: {
1141 name: "rook-ceph-mon-endpoints",
1142 items: [
1143 { key: "data", path: "mon-endpoints" },
1144 ],
1145 },
1146 },
1147 },
1148 },
1149 },
1150 },
1151 },
1152 },
1153 },
1154 },
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +02001155 },
1156
Sergiusz Bazanski36cc4fb2019-05-17 18:08:48 +02001157 ReplicatedBlockPool(cluster, name):: {
1158 local pool = self,
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +02001159 name:: name,
1160
Sergiusz Bazanski36cc4fb2019-05-17 18:08:48 +02001161 spec:: error "spec must be specified",
1162
1163 pool: kube._Object("ceph.rook.io/v1", "CephBlockPool", name) {
1164 metadata+: cluster.metadata,
1165 spec: pool.spec,
1166 },
1167
1168 storageClass: kube.StorageClass(name) {
1169 provisioner: "ceph.rook.io/block",
1170 parameters: {
1171 blockPool: pool.pool.metadata.name,
1172 clusterNamespace: pool.pool.metadata.namespace,
1173 fstype: "ext4",
1174 },
1175 reclaimPolicy: "Retain",
1176 },
1177 },
1178
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +02001179 ECBlockPool(cluster, name):: {
1180 local pool = self,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +02001181 name:: name,
Serge Bazanskic33ebcc2019-11-01 18:43:45 +01001182 metadataReplicas:: 3,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +02001183
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +02001184 spec:: error "spec must be specified",
1185
1186 pool: kube._Object("ceph.rook.io/v1", "CephBlockPool", name) {
1187 metadata+: cluster.metadata,
1188 spec: pool.spec,
1189 },
1190 metapool: kube._Object("ceph.rook.io/v1", "CephBlockPool", name + "-metadata") {
1191 metadata+: cluster.metadata,
1192 spec: {
1193 failureDomain: "host",
1194 replicated: {
Serge Bazanskic33ebcc2019-11-01 18:43:45 +01001195 size: pool.metadataReplicas,
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +02001196 },
1197 },
1198 },
1199
1200 storageClass: kube.StorageClass(name) {
1201 provisioner: "ceph.rook.io/block",
1202 parameters: {
1203 blockPool: pool.metapool.metadata.name,
1204 dataBlockPool: pool.pool.metadata.name,
1205 clusterNamespace: pool.pool.metadata.namespace,
1206 fstype: "ext4",
1207 },
1208 reclaimPolicy: "Retain",
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +02001209 },
1210 },
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001211
1212 S3ObjectStore(cluster, name):: {
1213 local store = self,
1214 spec:: error "spec must be specified",
1215 objectStore: kube._Object("ceph.rook.io/v1", "CephObjectStore", name) {
1216 metadata+: cluster.metadata,
1217 spec: store.spec {
1218 gateway: {
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001219 port: 80,
1220 instances: 1,
1221 allNodes: false,
1222 },
1223 },
1224 },
1225
1226 objectIngress: kube.Ingress(name) {
1227 metadata+: cluster.metadata {
1228 annotations+: {
1229 "kubernetes.io/tls-acme": "true",
1230 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
1231 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
1232 },
1233 },
1234 spec+: {
1235 tls: [
1236 {
1237 hosts: ["object.%s.hswaw.net" % [cluster.metadata.namespace]],
1238 secretName: "%s-tls" % [name],
1239 },
1240 ],
1241 rules: [
1242 {
1243 host: "object.%s.hswaw.net" % [cluster.metadata.namespace],
1244 http: {
1245 paths: [
1246 {
1247 path: "/",
1248 backend: {
1249 serviceName: "rook-ceph-rgw-%s" % [name],
1250 servicePort: 80,
1251 },
1252 },
1253 ]
1254 },
1255 }
1256 ],
1257 },
1258 },
1259 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +02001260}