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