blob: 58103840b7bbcd2d16e6a9fa781eea21badb9a98 [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,
Serge Bazanski3b9ee5f2021-01-19 22:44:07 +010057 continueUpgradeAfterChecksEvenIfNotHealthy: oa.Boolean,
Sergiusz Bazanskid436de22020-02-21 17:10:42 +010058 mon: oa.Dict {
59 allowMultiplePerNode: oa.Boolean,
60 count: oa.Integer { minimum: 0, maximum: 9 },
61 preferredCount: oa.Integer { minimum: 0, maximum: 9 },
62 },
63 mgr: oa.Dict {
64 modules: oa.Array(oa.Dict {
65 name: oa.String,
66 enabled: oa.Boolean,
67 }),
68 },
69 network: oa.Dict {
70 hostNetwork: oa.Boolean,
71 },
72 storage: oa.Dict {
73 disruptionManagement: oa.Dict {
74 managePodBudgets: oa.Boolean,
75 osdMaintenanceTimeout: oa.Integer,
76 manageMachineDisruptionBudgets: oa.Boolean,
77 },
78 useAllNodes: oa.Boolean,
79 nodes: oa.Array(oa.Dict {
80 name: oa.String,
81 config: oa.Dict {
82 metadataDevice: oa.String,
83 storeType: oa.String { pattern: "^(filestore|bluestore)$" },
84 databaseSizeMB: oa.String,
85 walSizeMB: oa.String,
86 journalSizeMB: oa.String,
87 osdsPerDevice: oa.String,
88 encryptedDevice: oa.String { pattern: "^(true|false)$" },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020089 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +010090 useAllDevices: oa.Boolean,
91 deviceFilter: oa.Any,
92 directories: oa.Array(oa.Dict {
93 path: oa.String,
94 }),
95 devices: oa.Array(oa.Dict {
96 name: oa.String,
97 }),
98 location: oa.Any,
99 resources: oa.Any,
100 }),
101 useAllDevices: oa.Boolean,
102 deviceFilter: oa.Any,
103 location: oa.Any,
104 directories: oa.Array(oa.Dict {
105 path: oa.String,
106 }),
107 config: oa.Any,
108 topologyAware: oa.Boolean,
109 },
110 monitoring: oa.Dict {
111 enabled: oa.Boolean,
112 rulesNamespace: oa.String,
113 },
114 rbdMirroring: oa.Dict {
115 workers: oa.Integer,
116 },
117 placement: oa.Any,
118 resources: oa.Any,
119 },
120 }),
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200121 },
122 },
123 cephfilesystems: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephFilesystem") {
124 spec+: {
125 additionalPrinterColumns: [
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100126 { name: "ActiveMDS", type: "string", description: "Number of desired active MDS daemons", JSONPath: ".spec.metadataServer.activeCount" },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200127 { name: "Age", type: "date", JSONPath: ".metadata.creationTimestamp" },
128 ],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100129 validation: oa.Validation(oa.Dict {
130 spec: oa.Dict {
131 metadataServer: oa.Dict {
132 activeCount: oa.Integer,
133 activeStandby: oa.Boolean,
134 annotations: oa.Any,
135 placement: oa.Any,
136 resources: oa.Any,
137 },
138 metadataPool: oa.Dict {
139 failureDomain: oa.String,
140 replicated: oa.Dict {
141 size: oa.Integer,
142 },
143 erasureCoded: oa.Dict {
144 dataChunks: oa.Integer,
145 codingChunks: oa.Integer,
146 },
147 },
148 dataPools: oa.Array(oa.Dict {
149 failureDomain: oa.String,
150 replicated: oa.Dict {
151 site: oa.Integer,
152 erasureCoded: oa.Dict {
153 dataChunks: oa.Integer,
154 codingChunks: oa.Integer,
155 },
156 },
157 })
158 },
159 }),
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200160 },
161 },
162 cephnfses: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephNFS") {
163 spec+: {
164 names+: {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200165 plural: "cephnfses",
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200166 shortNames: ["nfs"],
167 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100168 validation: oa.Validation(oa.Dict {
169 spec: oa.Dict {
170 rados: oa.Dict {
171 pool: oa.String,
172 namespace: oa.String,
173 },
174 server: oa.Dict {
175 active: oa.Integer,
176 annotations: oa.Any,
177 placement: oa.Any,
178 resources: oa.Any,
179 },
180 },
181 }),
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200182 },
183 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100184 cephobjectstores: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephObjectStore") {
185 spec+: {
186 validation: oa.Validation(oa.Dict {
187 spec: oa.Dict {
188 gateway: oa.Dict {
189 type: oa.String,
190 sslCertificateRef: oa.Any,
191 port: oa.Integer,
192 securePort: oa.Any,
193 instances: oa.Integer,
194 annotations: oa.Any,
195 placement: oa.Any,
196 resources: oa.Any,
197 },
198 local poolDef = oa.Dict {
199 failureDomain: oa.String,
200 replicated: oa.Dict {
201 size: oa.Integer,
202 },
203 erasureCoded: oa.Dict {
204 dataChunks: oa.Integer,
205 codingChunks: oa.Integer,
206 },
207 },
208 metadataPool: poolDef,
209 dataPool: poolDef,
210 },
211 }),
212 },
213 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200214 cephobjectstoreusers: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephObjectStoreUser"),
215 cephblockpools: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephBlockPool"),
216 volumes: kube.CustomResourceDefinition("rook.io", "v1alpha2", "Volume") {
217 spec+: {
218 names+: {
219 shortNames: ["rv"],
220 },
221 },
222 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100223 objectbuckets: kube.CustomResourceDefinition("objectbucket.io", "v1alpha1", "ObjectBucket") {
224 spec+: {
225 names+: {
226 shortNames: ["ob", "obs"],
227 },
228 scope: "Cluster",
229 subresources: { status: {} },
230 },
231 },
232 objectbucketclaims: kube.CustomResourceDefinition("objectbucket.io", "v1alpha1", "ObjectBucketClaim") {
233 spec+: {
234 names+: {
235 shortNames: ["obc", "obcs"],
236 },
237 subresources: { status: {} },
238 },
239 },
Serge Bazanski2c04c842021-01-19 21:41:11 +0100240 cephclients: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephClient") {
241 spec+: {
242 validation: oa.Validation(oa.Dict {
243 spec: oa.Dict {
244 caps: oa.Any,
245 },
246 }),
247 },
248 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200249 },
250
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100251 sa: {
252 system: kube.ServiceAccount("rook-ceph-system") {
253 metadata+: env.metadata,
254 },
255 csiCephfsPlugin: kube.ServiceAccount("rook-csi-cephfs-plugin-sa") {
256 metadata+: env.metadata,
257 },
258 csiCephfsProvisioner: kube.ServiceAccount("rook-csi-cephfs-provisioner-sa") {
259 metadata+: env.metadata,
260 },
261 csiRbdPlugin: kube.ServiceAccount("rook-csi-rbd-plugin-sa") {
262 metadata+: env.metadata,
263 },
264 csiRbdProvisioner: kube.ServiceAccount("rook-csi-rbd-provisioner-sa") {
265 metadata+: env.metadata,
266 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200267 },
268
269 crs: {
270 clusterMgmt: kube.ClusterRole("rook-ceph-cluster-mgmt") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200271 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200272 rules: [
273 {
274 apiGroups: [""],
275 resources: ["secrets", "pods", "pods/log", "services", "configmaps"],
276 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
277 },
278 {
279 apiGroups: ["apps"],
280 resources: ["deployments", "daemonsets", "replicasets"],
281 verbs: ["get", "list", "watch", "create", "update", "delete"],
282 },
283 ],
284 },
285 global: kube.ClusterRole("rook-ceph-global") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200286 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200287 rules: [
288 {
289 apiGroups: [""],
290 resources: ["pods", "nodes", "nodes/proxy"],
291 verbs: ["get", "list", "watch"],
292 },
293 {
294 apiGroups: [""],
295 resources: ["events", "persistentvolumes", "persistentvolumeclaims", "endpoints"],
296 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
297 },
298 {
299 apiGroups: ["storage.k8s.io"],
300 resources: ["storageclasses"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100301 verbs: ["get", "list", "watch"],
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200302 },
303 {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200304 apiGroups: ["batch"],
305 resources: ["jobs"],
306 verbs: ["get", "list", "watch", "create", "update", "delete"],
307 },
308 {
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200309 apiGroups: ["ceph.rook.io"],
310 resources: ["*"],
311 verbs: ["*"],
312 },
313 {
314 apiGroups: ["rook.io"],
315 resources: ["*"],
316 verbs: ["*"],
317 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100318 {
319 apiGroups: ["policy", "apps"],
Serge Bazanski2c04c842021-01-19 21:41:11 +0100320 resources: ["poddisruptionbudgets", "deployments", "replicasets"],
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100321 verbs: ["*"],
322 },
Serge Bazanski2c04c842021-01-19 21:41:11 +0100323 {
324 apiGroups: ["healthchecking.openshift.io"],
325 resources: ["machinedisruptionbudgets"],
326 verbs: ["get", "list", "watch", "create", "update", "delete"],
327 },
328 {
329 apiGroups: ["machine.openshift.io"],
330 resources: ["machines"],
331 verbs: ["get", "list", "watch", "create", "update", "delete"],
332 },
333 {
334 apiGroups: ["storage.k8s.io"],
335 resources: ["csidrivers"],
336 verbs: ["create"],
337 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200338 ],
339 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100340
341 // Upstream rook uses split ClusterRoles, with the 'main' role (eg rook-ceph-cluster-mgmt)
342 // using aggregationRules to point to a '-rules' role (eg rook-ceph-cluster-mgmt-rules) which
343 // contains the actual role rules. This was done to permit for a bettr upgrade experience on
344 // systems that only allow for a recreation of a clusterroles (see https://github.com/rook/rook/issues/2634
345 // for more background information).
346 // We do not use this split because our update mechanism is not broken. However, it seems
347 // that Rook started to use these split rules for other reasons, too. For instance, the
348 // mgr-cluster role in upstream not only aggregates its equivalent -rules role, but also
349 // the rook-ceph-object-bucket role. As such, we split mgr-cluster as they do in upstream.
350 // In the future, we may split the rest of the roles in order to stay consisdent with upsteam.
351
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200352 mgrCluster: kube.ClusterRole("rook-ceph-mgr-cluster") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200353 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100354 aggregationRule: {
355 clusterRoleSelectors: [
356 { matchLabels: { "rbac.ceph.rook.io/aggregate-to-rook-ceph-mgr-cluster": "true" }},
357 ],
358 },
359 },
360 mgrClusterRules: kube.ClusterRole("rook-ceph-mgr-cluster-rules") {
361 metadata+: env.metadata {
362 namespace:: null,
363 labels+: {
364 "rbac.ceph.rook.io/aggregate-to-rook-ceph-mgr-cluster": "true",
365 },
366 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200367 rules: [
368 {
369 apiGroups: [""],
370 resources: ["configmaps", "nodes", "nodes/proxy"],
371 verbs: ["get", "list", "watch"],
372 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100373 {
374 apiGroups: [""],
375 resources: ["events"],
376 verbs: ["create", "patch", "list", "get", "watch"],
377 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200378 ]
379 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100380 objectBucket: kube.ClusterRole("rook-ceph-object-bucket") {
381 metadata+: env.metadata {
382 namespace:: null,
383 labels+: {
384 "rbac.ceph.rook.io/aggregate-to-rook-ceph-mgr-cluster": "true",
385 },
386 },
387 rules: [
388 {
389 apiGroups: [""],
390 resources: ["secrets", "configmaps"],
391 verbs: ["*"],
392 },
393 {
394 apiGroups: ["storage.k8s.io"],
395 resources: ["storageclasses"],
396 verbs: ["get", "list", "watch"],
397 },
398 {
399 apiGroups: ["objectbucket.io"],
400 resources: ["*"],
401 verbs: ["*"],
402 },
403 ],
404 },
405
406 cephfsCSINodeplugin: kube.ClusterRole("cephfs-csi-nodeplugin") {
407 metadata+: env.metadata { namespace:: null },
408 rules: [
409 {
410 apiGroups: [""],
411 resources: ["nodes"],
412 verbs: ["get", "list", "update"],
413 },
414 {
415 apiGroups: [""],
416 resources: ["namespaces"],
417 verbs: ["get", "list"],
418 },
419 {
420 apiGroups: [""],
421 resources: ["persistentvolumes"],
422 verbs: ["get", "list", "watch", "update"],
423 },
424 {
425 apiGroups: ["storage.k8s.io"],
426 resources: ["volumeattachments"],
427 verbs: ["get", "list", "watch", "update"],
428 },
429 {
430 apiGroups: [""],
431 resources: ["configmaps"],
432 verbs: ["get", "list"],
433 },
434 ],
435 },
436
437 cephfsExternalProvisionerRunner: kube.ClusterRole("cephfs-external-provisioner-runner") {
438 metadata+: env.metadata { namespace:: null },
439 rules: [
440 {
441 apiGroups: [""],
442 resources: ["secrets"],
443 verbs: ["get", "list"],
444 },
445 {
446 apiGroups: [""],
447 resources: ["persistentvolumes"],
448 verbs: ["get", "list", "watch", "create", "update", "delete"],
449 },
450 {
451 apiGroups: [""],
452 resources: ["persistentvolumeclaims"],
453 verbs: ["get", "list", "watch", "update"],
454 },
455 {
456 apiGroups: ["storage.k8s.io"],
457 resources: ["storageclasses"],
458 verbs: ["get", "list", "watch"],
459 },
460 {
461 apiGroups: [""],
462 resources: ["events"],
463 verbs: ["list", "watch", "create", "update", "patch"],
464 },
465 {
466 apiGroups: ["storage.k8s.io"],
467 resources: ["volumeattachments"],
468 verbs: ["get", "list", "watch", "update"],
469 },
470 {
471 apiGroups: [""],
472 resources: ["nodes"],
473 verbs: ["get", "list", "watch"],
474 },
475 ],
476 },
477
478 rbdCSINodeplugin: kube.ClusterRole("rbd-csi-nodeplugin") {
479 metadata+: env.metadata { namespace:: null },
480 rules: [
481 {
482 apiGroups: [""],
483 resources: ["secrets"],
484 verbs: ["get", "list"],
485 },
486 {
487 apiGroups: [""],
488 resources: ["nodes"],
489 verbs: ["get", "list", "update"],
490 },
491 {
492 apiGroups: [""],
493 resources: ["namespaces"],
494 verbs: ["get", "list"],
495 },
496 {
497 apiGroups: [""],
498 resources: ["persistentvolumes"],
499 verbs: ["get", "list", "watch", "update"],
500 },
501 {
502 apiGroups: ["storage.k8s.io"],
503 resources: ["volumeattachments"],
504 verbs: ["get", "list", "watch", "update"],
505 },
506 {
507 apiGroups: [""],
508 resources: ["configmaps"],
509 verbs: ["get", "list"],
510 },
511 ],
512 },
513
514 rbdExternalProvisionerRunner: kube.ClusterRole("rbd-external-provisioner-runner") {
515 metadata+: env.metadata { namespace:: null },
516 rules: [
517 {
518 apiGroups: [""],
519 resources: ["secrets"],
520 verbs: ["get", "list"],
521 },
522 {
523 apiGroups: [""],
524 resources: ["persistentvolumes"],
525 verbs: ["get", "list", "watch", "create", "update", "delete"],
526 },
527 {
528 apiGroups: [""],
529 resources: ["persistentvolumeclaims"],
530 verbs: ["get", "list", "watch", "update"],
531 },
532 {
533 apiGroups: ["storage.k8s.io"],
534 resources: ["volumeattachments"],
535 verbs: ["get", "list", "watch", "update"],
536 },
537 {
538 apiGroups: [""],
539 resources: ["nodes"],
540 verbs: ["get", "list", "watch"],
541 },
542 {
543 apiGroups: ["storage.k8s.io"],
544 resources: ["storageclasses"],
545 verbs: ["get", "list", "watch"]
546 },
547 {
548 apiGroups: [""],
549 resources: ["events"],
550 verbs: ["list", "watch", "create", "update", "patch"],
551 },
552 {
553 apiGroups: ["snapshot.storage.k8s.io"],
554 resources: ["volumesnapshotcontents"],
555 verbs: ["create", "get", "list", "watch", "update", "delete"],
556 },
557 {
558 apiGroups: ["snapshot.storage.k8s.io"],
559 resources: ["volumesnapshotclasses"],
560 verbs: ["get", "list", "watch"],
561 },
562 {
563 apiGroups: ["apiextensions.k8s.io"],
564 resources: ["customresourcedefinitions"],
565 verbs: ["create", "list", "watch", "delete", "get", "update"],
566 },
567 {
568 apiGroups: ["snapshot.storage.k8s.io"],
569 resources: ["volumesnapshots/status"],
570 verbs: ["update"],
571 },
572 ],
573 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200574 },
575
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100576 crbs: {
577 global: kube.ClusterRoleBinding("ceph-rook-global") {
578 metadata+: env.metadata { namespace:: null },
579 roleRef_: env.crs.global,
580 subjects_: [env.sa.system],
581 },
582 objectBucket: kube.ClusterRoleBinding("rook-ceph-object-bucket") {
583 metadata+: env.metadata { namespace:: null },
584 roleRef_: env.crs.objectBucket,
585 subjects_: [env.sa.system],
586 },
587 cephfsCSINodeplugin: kube.ClusterRoleBinding("cepfs-csi-nodeplugin") {
588 metadata+: env.metadata { namespace:: null },
589 roleRef_: env.crs.cephfsCSINodeplugin,
590 subjects_: [env.sa.csiCephfsPlugin],
591 },
592 cephfsCSIProvisioner: kube.ClusterRoleBinding("cephfs-csi-provisioner") {
593 metadata+: env.metadata { namespace:: null },
594 roleRef_: env.crs.cephfsExternalProvisionerRunner,
595 subjects_: [env.sa.csiCephfsProvisioner],
596 },
597 rbdCSINodeplugin: kube.ClusterRoleBinding("rbd-csi-nodeplugin") {
598 metadata+: env.metadata { namespace:: null },
599 roleRef_: env.crs.rbdCSINodeplugin,
600 subjects_: [env.sa.csiRbdPlugin],
601 },
602 rbdCSIProvisioner: kube.ClusterRoleBinding("rbd-csi-provisioner") {
603 metadata+: env.metadata { namespace:: null },
604 roleRef_: env.crs.rbdExternalProvisionerRunner,
605 subjects_: [env.sa.csiRbdProvisioner],
606 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200607 },
608
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100609 roles: {
610 system: kube.Role("ceph-rook-system") {
611 metadata+: env.metadata,
612 rules: [
613 {
614 apiGroups: [""],
615 resources: ["pods", "configmaps", "services"],
616 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
617 },
618 {
619 apiGroups: ["apps"],
620 resources: ["deployments", "statefulsets", "daemonsets"],
621 verbs: ["get", "list", "watch", "create", "update", "delete"],
622 },
623 ],
624 },
625 cephfsExternalProvisioner: kube.Role("cephfs-external-provisioner-cfg") {
626 metadata+: env.metadata,
627 rules: [
628 {
629 apiGroups: [""],
630 resources: ["endpoints"],
631 verbs: ["get", "watch", "list", "delete", "update", "create"],
632 },
633 {
634 apiGroups: [""],
635 resources: ["configmaps"],
636 verbs: ["get", "list", "create", "delete"],
637 },
638 {
639 apiGroups: ["coordination.k8s.io"],
640 resources: ["leases"],
641 verbs: ["get" ,"watch", "list", "delete", "update", "create"],
642 },
643 ],
644 },
645 rbdExternalProvisioner: kube.Role("rbd-external-provisioner-cfg") {
646 metadata+: env.metadata,
647 rules: [
648 {
649 apiGroups: [""],
650 resources: ["endpoints"],
651 verbs: ["get", "watch", "list", "delete", "update", "create"],
652 },
653 {
654 apiGroups: [""],
655 resources: ["configmaps"],
656 verbs: ["get", "list", "watch", "create", "delete"],
657 },
658 {
659 apiGroups: ["coordination.k8s.io"],
660 resources: ["leases"],
661 verbs: ["get" ,"watch", "list", "delete", "update", "create"],
662 },
663 ],
664 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200665 },
666
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100667 rbs: {
668 system: kube.RoleBinding("ceph-rook-system") {
669 metadata+: env.metadata,
670 roleRef_: env.roles.system,
671 subjects_: [env.sa.system],
672 },
673 cephfsCSIProvisioner: kube.RoleBinding("cephfs-csi-provisioner-role-cfg") {
674 metadata+: env.metadata,
675 roleRef_: env.roles.cephfsExternalProvisioner,
676 subjects_: [env.sa.csiCephfsProvisioner],
677 },
678 rbdCSIProvisioner: kube.RoleBinding("rbd-csi-provisioner-role-cfg") {
679 metadata+: env.metadata,
680 roleRef_: env.roles.rbdExternalProvisioner,
681 subjects_: [env.sa.csiRbdProvisioner],
682 },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200683 },
684
685 operator: kube.Deployment("rook-ceph-operator") {
686 metadata+: env.metadata,
687 spec+: {
688 template+: {
689 spec+: {
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100690 serviceAccountName: env.sa.system.metadata.name,
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200691 containers_: {
692 operator: kube.Container("rook-ceph-operator") {
693 image: cfg.image,
694 args: ["ceph", "operator"],
695 volumeMounts_: {
696 "rook-config": { mountPath: "/var/lib/rook" },
697 "default-config-dir": { mountPath: "/etc/ceph" },
698 },
699 env_: {
700 LIB_MODULES_DIR_PATH: "/run/current-system/kernel-modules/lib/modules/",
701 ROOK_ALLOW_MULTIPLE_FILESYSTEMS: "false",
Sergiusz Bazanski321fad92019-04-19 14:14:36 +0200702 ROOK_LOG_LEVEL: "INFO",
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200703 ROOK_MON_HEALTHCHECK_INTERVAL: "45s",
704 ROOK_MON_OUT_TIMEOUT: "600s",
705 ROOK_DISCOVER_DEVICES_INTERVAL: "60m",
706 ROOK_HOSTPATH_REQUIRES_PRIVILEGED: "false",
707 ROOK_ENABLE_SELINUX_RELABELING: "true",
708 ROOK_ENABLE_FSGROUP: "true",
709 NODE_NAME: kube.FieldRef("spec.nodeName"),
710 POD_NAME: kube.FieldRef("metadata.name"),
711 POD_NAMESPACE: kube.FieldRef("metadata.namespace"),
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100712 ROOK_CSI_KUBELET_DIR_PATH: "/var/lib/kubernetes"
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200713 },
714 },
715 },
716 volumes_: {
717 "rook-config": { emptyDir: {} },
718 "default-config-dir": { emptyDir: {} },
719 },
720 },
721 },
722 },
723 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200724 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200725
726 // Create a new Ceph cluster in a new namespace.
727 Cluster(operator, name):: {
728 local cluster = self,
729 spec:: error "please define cluster spec",
730
731
732 metadata:: {
733 namespace: name,
734 },
735
736 name(suffix):: cluster.metadata.namespace + "-" + suffix,
737
738 namespace: kube.Namespace(cluster.metadata.namespace),
739
740 sa: {
741 // service accounts need to be hardcoded, see operator source.
742 osd: kube.ServiceAccount("rook-ceph-osd") {
743 metadata+: cluster.metadata,
744 },
745 mgr: kube.ServiceAccount("rook-ceph-mgr") {
746 metadata+: cluster.metadata,
747 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100748 cmdReporter: kube.ServiceAccount("rook-ceph-cmd-reporter") {
749 metadata+: cluster.metadata,
750 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200751 },
752
753 roles: {
754 osd: kube.Role(cluster.name("osd")) {
755 metadata+: cluster.metadata,
756 rules: [
757 {
758 apiGroups: [""],
759 resources: ["configmaps"],
760 verbs: ["get", "list", "watch", "create", "update", "delete"],
Serge Bazanski2c04c842021-01-19 21:41:11 +0100761 },
762 ],
763 },
764 osdCluster: kube.ClusterRole(cluster.name("osd-cluster")) {
765 metadata+: cluster.metadata { namespace:: null },
766 rules: [
767 {
768 apiGroups: [""],
769 resources: ["nodes"],
770 verbs: ["get", "list"],
771 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200772 ],
773 },
774 mgr: kube.Role(cluster.name("mgr")) {
775 metadata+: cluster.metadata,
776 rules: [
777 {
778 apiGroups: [""],
779 resources: ["pods", "services"],
780 verbs: ["get", "list", "watch"],
781 },
782 {
783 apiGroups: ["batch"],
784 resources: ["jobs"],
785 verbs: ["get", "list", "watch", "create", "update", "delete"],
786 },
787 {
788 apiGroups: ["ceph.rook.io"],
789 resources: ["*"],
790 verbs: ["*"],
791 },
792 ],
793 },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100794 cmdReporter: kube.Role(cluster.name("cmd-reporter")) {
795 metadata+: cluster.metadata,
796 rules: [
797 {
798 apiGroups: [""],
799 resources: ["pods", "configmaps"],
800 verbs: ["get", "list", "watch", "create", "update", "delete"],
801 },
802 ],
803 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200804 mgrSystem: kube.ClusterRole(cluster.name("mgr-system")) {
805 metadata+: cluster.metadata { namespace:: null },
806 rules: [
807 {
808 apiGroups: [""],
809 resources: ["configmaps"],
810 verbs: ["get", "list", "watch"],
811 }
812 ],
813 },
814 },
815
816 rbs: [
817 kube.RoleBinding(cluster.name(el.name)) {
818 metadata+: cluster.metadata,
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200819 roleRef_: el.role,
820 subjects_: [el.sa],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200821 },
822 for el in [
823 // Allow Operator SA to perform Cluster Mgmt in this namespace.
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100824 { name: "cluster-mgmt", role: operator.crs.clusterMgmt, sa: operator.sa.system },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200825 { name: "osd", role: cluster.roles.osd, sa: cluster.sa.osd },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200826 { name: "mgr", role: cluster.roles.mgr, sa: cluster.sa.mgr },
Sergiusz Bazanskid436de22020-02-21 17:10:42 +0100827 { name: "cmd-reporter", role: cluster.roles.cmdReporter, sa: cluster.sa.cmdReporter },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200828 { name: "mgr-cluster", role: operator.crs.mgrCluster, sa: cluster.sa.mgr },
829 ]
830 ],
831
832 mgrSystemRB: kube.RoleBinding(cluster.name("mgr-system")) {
833 metadata+: {
834 namespace: operator.cfg.namespace,
835 },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200836 roleRef_: cluster.roles.mgrSystem,
837 subjects_: [cluster.sa.mgr],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200838 },
839
Serge Bazanski2c04c842021-01-19 21:41:11 +0100840 osdClusterRB: kube.ClusterRoleBinding(cluster.name("osd-cluster")) {
841 metadata+: {
842 namespace:: null,
843 },
844 roleRef_: cluster.roles.osdCluster,
845 subjects_: [cluster.sa.osd],
846 },
847
848
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200849 cluster: kube._Object("ceph.rook.io/v1", "CephCluster", name) {
850 metadata+: cluster.metadata,
851 spec: {
852 cephVersion: {
Sergiusz Bazanskied2e6702019-04-19 13:27:20 +0200853 # https://github.com/rook/rook/issues/2945#issuecomment-483964014
Serge Bazanski3b9ee5f2021-01-19 22:44:07 +0100854 image: "ceph/ceph:v14.2.16",
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: {
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +02001222 port: 80,
1223 instances: 1,
1224 allNodes: false,
1225 },
1226 },
1227 },
1228
1229 objectIngress: kube.Ingress(name) {
1230 metadata+: cluster.metadata {
1231 annotations+: {
1232 "kubernetes.io/tls-acme": "true",
1233 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
1234 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
1235 },
1236 },
1237 spec+: {
1238 tls: [
1239 {
1240 hosts: ["object.%s.hswaw.net" % [cluster.metadata.namespace]],
1241 secretName: "%s-tls" % [name],
1242 },
1243 ],
1244 rules: [
1245 {
1246 host: "object.%s.hswaw.net" % [cluster.metadata.namespace],
1247 http: {
1248 paths: [
1249 {
1250 path: "/",
1251 backend: {
1252 serviceName: "rook-ceph-rgw-%s" % [name],
1253 servicePort: 80,
1254 },
1255 },
1256 ]
1257 },
1258 }
1259 ],
1260 },
1261 },
1262 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +02001263}