blob: e594e3db96d76b190dcaeccef818dc8a86bb7283 [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
6{
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +02007 Operator: {
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +02008 local env = self,
9 local cfg = env.cfg,
10 cfg:: {
Sergiusz Bazanski71a21c72019-08-30 21:30:42 +020011 image: "rook/ceph:v1.0.5",
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020012 namespace: "rook-ceph-system",
13 },
14
15 metadata:: {
16 namespace: cfg.namespace,
17 labels: {
18 "operator": "rook",
19 "storage-backend": "ceph",
20 },
21 },
22
23 namespace: kube.Namespace(cfg.namespace),
24
Sergiusz Bazanskia01c4872019-09-05 18:00:02 +020025 policyInsecure: policies.AllowNamespaceInsecure(cfg.namespace),
26
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +020027 crds: {
28 cephclusters: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephCluster") {
29 spec+: {
30 additionalPrinterColumns: [
31 { name: "DataDirHostPath", type: "string", description: "Directory used on the K8s nodes", JSONPath: ".spec.dataDirHostPath" },
32 { name: "MonCount", type: "string", description: "Number of MONs", JSONPath: ".spec.mon.count" },
33 { name: "Age", type: "date", JSONPath: ".metadata.creationTimestamp" },
34 { name: "State", type: "string", description: "Current State", JSONPath: ".status.state" },
35 ],
36 validation: {
37 # Converted from official operator YAML
38 "openAPIV3Schema": {
39 "properties": {
40 "spec": {
41 "properties": {
42 "cephVersion": {
43 "properties": {
44 "allowUnsupported": {
45 "type": "boolean"
46 },
47 "image": {
48 "type": "string"
49 },
50 "name": {
51 "pattern": "^(luminous|mimic|nautilus)$",
52 "type": "string"
53 }
54 }
55 },
56 "dashboard": {
57 "properties": {
58 "enabled": {
59 "type": "boolean"
60 },
61 "urlPrefix": {
62 "type": "string"
63 },
64 "port": {
65 "type": "integer"
66 }
67 }
68 },
69 "dataDirHostPath": {
70 "pattern": "^/(\\S+)",
71 "type": "string"
72 },
73 "mon": {
74 "properties": {
75 "allowMultiplePerNode": {
76 "type": "boolean"
77 },
78 "count": {
79 "maximum": 9,
80 "minimum": 1,
81 "type": "integer"
82 },
83 "preferredCount": {
84 "maximum": 9,
85 "minimum": 0,
86 "type": "integer"
87 }
88 },
89 "required": [
90 "count"
91 ]
92 },
93 "network": {
94 "properties": {
95 "hostNetwork": {
96 "type": "boolean"
97 }
98 }
99 },
100 "storage": {
101 "properties": {
102 "nodes": {
103 "items": {},
104 "type": "array"
105 },
106 "useAllDevices": {},
107 "useAllNodes": {
108 "type": "boolean"
109 }
110 }
111 }
112 },
113 "required": [
114 "mon"
115 ]
116 }
117 }
118 }
119 }
120 },
121 },
122 cephfilesystems: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephFilesystem") {
123 spec+: {
124 additionalPrinterColumns: [
125 { name: "MdsCount", type: "string", description: "Number of MDs", JSONPath: ".spec.metadataServer.activeCount" },
126 { name: "Age", type: "date", JSONPath: ".metadata.creationTimestamp" },
127 ],
128 },
129 },
130 cephnfses: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephNFS") {
131 spec+: {
132 names+: {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200133 plural: "cephnfses",
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200134 shortNames: ["nfs"],
135 },
136 },
137 },
138 cephobjectstores: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephObjectStore"),
139 cephobjectstoreusers: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephObjectStoreUser"),
140 cephblockpools: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephBlockPool"),
141 volumes: kube.CustomResourceDefinition("rook.io", "v1alpha2", "Volume") {
142 spec+: {
143 names+: {
144 shortNames: ["rv"],
145 },
146 },
147 },
148 },
149
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200150 sa: kube.ServiceAccount("rook-ceph-system") {
151 metadata+: env.metadata,
152 },
153
154 crs: {
155 clusterMgmt: kube.ClusterRole("rook-ceph-cluster-mgmt") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200156 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200157 rules: [
158 {
159 apiGroups: [""],
160 resources: ["secrets", "pods", "pods/log", "services", "configmaps"],
161 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
162 },
163 {
164 apiGroups: ["apps"],
165 resources: ["deployments", "daemonsets", "replicasets"],
166 verbs: ["get", "list", "watch", "create", "update", "delete"],
167 },
168 ],
169 },
170 global: kube.ClusterRole("rook-ceph-global") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200171 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200172 rules: [
173 {
174 apiGroups: [""],
175 resources: ["pods", "nodes", "nodes/proxy"],
176 verbs: ["get", "list", "watch"],
177 },
178 {
179 apiGroups: [""],
180 resources: ["events", "persistentvolumes", "persistentvolumeclaims", "endpoints"],
181 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
182 },
183 {
184 apiGroups: ["storage.k8s.io"],
185 resources: ["storageclasses"],
186 verbs: ["get", "list", "watch", "create", "update", "delete"],
187 },
188 {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200189 apiGroups: ["batch"],
190 resources: ["jobs"],
191 verbs: ["get", "list", "watch", "create", "update", "delete"],
192 },
193 {
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200194 apiGroups: ["ceph.rook.io"],
195 resources: ["*"],
196 verbs: ["*"],
197 },
198 {
199 apiGroups: ["rook.io"],
200 resources: ["*"],
201 verbs: ["*"],
202 },
203 ],
204 },
205 mgrCluster: kube.ClusterRole("rook-ceph-mgr-cluster") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200206 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200207 rules: [
208 {
209 apiGroups: [""],
210 resources: ["configmaps", "nodes", "nodes/proxy"],
211 verbs: ["get", "list", "watch"],
212 },
213 ]
214 },
215 },
216
217 crb: kube.ClusterRoleBinding("ceph-rook-global") {
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200218 metadata+: env.metadata { namespace:: null },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200219 roleRef_: env.crs.global,
220 subjects_: [env.sa],
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200221 },
222
223 role: kube.Role("ceph-rook-system") {
224 metadata+: env.metadata,
225 rules: [
226 {
227 apiGroups: [""],
228 resources: ["pods", "configmaps"],
229 verbs: ["get", "list", "watch", "patch", "create", "update", "delete"],
230 },
231 {
232 apiGroups: ["apps"],
233 resources: ["daemonsets"],
234 verbs: ["get", "list", "watch", "create", "update", "delete"],
235 },
236 ],
237 },
238
239 rb: kube.RoleBinding("ceph-rook-system") {
240 metadata+: env.metadata,
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200241 roleRef_: env.role,
242 subjects_: [env.sa],
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200243 },
244
245 operator: kube.Deployment("rook-ceph-operator") {
246 metadata+: env.metadata,
247 spec+: {
248 template+: {
249 spec+: {
250 serviceAccountName: env.sa.metadata.name,
251 containers_: {
252 operator: kube.Container("rook-ceph-operator") {
253 image: cfg.image,
254 args: ["ceph", "operator"],
255 volumeMounts_: {
256 "rook-config": { mountPath: "/var/lib/rook" },
257 "default-config-dir": { mountPath: "/etc/ceph" },
258 },
259 env_: {
260 LIB_MODULES_DIR_PATH: "/run/current-system/kernel-modules/lib/modules/",
261 ROOK_ALLOW_MULTIPLE_FILESYSTEMS: "false",
Sergiusz Bazanski321fad92019-04-19 14:14:36 +0200262 ROOK_LOG_LEVEL: "INFO",
Sergiusz Bazanskicdfafaf2019-04-01 19:16:18 +0200263 ROOK_MON_HEALTHCHECK_INTERVAL: "45s",
264 ROOK_MON_OUT_TIMEOUT: "600s",
265 ROOK_DISCOVER_DEVICES_INTERVAL: "60m",
266 ROOK_HOSTPATH_REQUIRES_PRIVILEGED: "false",
267 ROOK_ENABLE_SELINUX_RELABELING: "true",
268 ROOK_ENABLE_FSGROUP: "true",
269 NODE_NAME: kube.FieldRef("spec.nodeName"),
270 POD_NAME: kube.FieldRef("metadata.name"),
271 POD_NAMESPACE: kube.FieldRef("metadata.namespace"),
272 },
273 },
274 },
275 volumes_: {
276 "rook-config": { emptyDir: {} },
277 "default-config-dir": { emptyDir: {} },
278 },
279 },
280 },
281 },
282 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200283 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200284
285 // Create a new Ceph cluster in a new namespace.
286 Cluster(operator, name):: {
287 local cluster = self,
288 spec:: error "please define cluster spec",
289
290
291 metadata:: {
292 namespace: name,
293 },
294
295 name(suffix):: cluster.metadata.namespace + "-" + suffix,
296
297 namespace: kube.Namespace(cluster.metadata.namespace),
298
299 sa: {
300 // service accounts need to be hardcoded, see operator source.
301 osd: kube.ServiceAccount("rook-ceph-osd") {
302 metadata+: cluster.metadata,
303 },
304 mgr: kube.ServiceAccount("rook-ceph-mgr") {
305 metadata+: cluster.metadata,
306 },
307 },
308
309 roles: {
310 osd: kube.Role(cluster.name("osd")) {
311 metadata+: cluster.metadata,
312 rules: [
313 {
314 apiGroups: [""],
315 resources: ["configmaps"],
316 verbs: ["get", "list", "watch", "create", "update", "delete"],
317 }
318 ],
319 },
320 mgr: kube.Role(cluster.name("mgr")) {
321 metadata+: cluster.metadata,
322 rules: [
323 {
324 apiGroups: [""],
325 resources: ["pods", "services"],
326 verbs: ["get", "list", "watch"],
327 },
328 {
329 apiGroups: ["batch"],
330 resources: ["jobs"],
331 verbs: ["get", "list", "watch", "create", "update", "delete"],
332 },
333 {
334 apiGroups: ["ceph.rook.io"],
335 resources: ["*"],
336 verbs: ["*"],
337 },
338 ],
339 },
340 mgrSystem: kube.ClusterRole(cluster.name("mgr-system")) {
341 metadata+: cluster.metadata { namespace:: null },
342 rules: [
343 {
344 apiGroups: [""],
345 resources: ["configmaps"],
346 verbs: ["get", "list", "watch"],
347 }
348 ],
349 },
350 },
351
352 rbs: [
353 kube.RoleBinding(cluster.name(el.name)) {
354 metadata+: cluster.metadata,
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200355 roleRef_: el.role,
356 subjects_: [el.sa],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200357 },
358 for el in [
359 // Allow Operator SA to perform Cluster Mgmt in this namespace.
360 { name: "cluster-mgmt", role: operator.crs.clusterMgmt, sa: operator.sa },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200361 { name: "osd", role: cluster.roles.osd, sa: cluster.sa.osd },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200362 { name: "mgr", role: cluster.roles.mgr, sa: cluster.sa.mgr },
363 { name: "mgr-cluster", role: operator.crs.mgrCluster, sa: cluster.sa.mgr },
364 ]
365 ],
366
367 mgrSystemRB: kube.RoleBinding(cluster.name("mgr-system")) {
368 metadata+: {
369 namespace: operator.cfg.namespace,
370 },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200371 roleRef_: cluster.roles.mgrSystem,
372 subjects_: [cluster.sa.mgr],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200373 },
374
375 cluster: kube._Object("ceph.rook.io/v1", "CephCluster", name) {
376 metadata+: cluster.metadata,
377 spec: {
378 cephVersion: {
Sergiusz Bazanskied2e6702019-04-19 13:27:20 +0200379 # https://github.com/rook/rook/issues/2945#issuecomment-483964014
380 #image: "ceph/ceph:v13.2.5-20190319",
Sergiusz Bazanski71a21c72019-08-30 21:30:42 +0200381 image: "ceph/ceph:v14.2.2-20190830",
Sergiusz Bazanskied2e6702019-04-19 13:27:20 +0200382 allowUnsupported: true,
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200383 },
Serge Bazanskic33ebcc2019-11-01 18:43:45 +0100384 dataDirHostPath: if name == "ceph-waw2" then "/var/lib/rook" else "/var/lib/rook-%s" % [name],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200385 dashboard: {
386 ssl: false,
387 enabled: true,
388 port: 8080,
389 },
390 } + cluster.spec,
391 },
392
393 dashboardService: kube.Service(cluster.name("dashboard")) {
394 metadata+: cluster.metadata,
395 spec: {
396 ports: [
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200397 { name: "dashboard", port: 80, targetPort: 8080, protocol: "TCP" },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200398 ],
399 selector: {
400 app: "rook-ceph-mgr",
401 rook_cluster: name,
402 },
403 type: "ClusterIP",
404 },
405 },
406
407 dashboardIngress: kube.Ingress(cluster.name("dashboard")) {
Piotr Dobrowolski3187c592019-04-02 14:44:04 +0200408 metadata+: cluster.metadata {
409 annotations+: {
410 "kubernetes.io/tls-acme": "true",
411 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
412 },
413 },
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200414 spec+: {
Piotr Dobrowolski3187c592019-04-02 14:44:04 +0200415 tls: [
416 {
417 hosts: ["%s.hswaw.net" % name],
418 secretName: cluster.name("dashboard"),
419 },
420 ],
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200421 rules: [
422 {
423 host: "%s.hswaw.net" % name,
424 http: {
425 paths: [
426 { path: "/", backend: cluster.dashboardService.name_port },
427 ]
428 },
429 }
430 ],
431 },
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200432 },
433
434 # Benji is a backup tool, external to rook, that we use for backing up
435 # RBDs.
436 benji: {
437 sa: kube.ServiceAccount(cluster.name("benji")) {
438 metadata+: cluster.metadata,
439 },
440
441 cr: kube.ClusterRole(cluster.name("benji")) {
442 rules: [
443 {
444 apiGroups: [""],
445 resources: [
446 "persistentvolumes",
447 "persistentvolumeclaims"
448 ],
449 verbs: ["list", "get"],
450 },
451 {
452 apiGroups: [""],
453 resources: [
454 "events",
455 ],
456 verbs: ["create", "update"],
457 },
458 ],
459 },
460
461 crb: kube.ClusterRoleBinding(cluster.name("benji")) {
462 roleRef_: cluster.benji.cr,
463 subjects_: [cluster.benji.sa],
464 },
465
466 config: kube.Secret(cluster.name("benji-config")) {
467 metadata+: cluster.metadata,
468 data_: {
469 "benji.yaml": std.manifestJson({
470 configurationVersion: '1',
471 databaseEngine: 'sqlite:////data/benji.sqlite',
472 defaultStorage: 'wasabi',
473 storages: [
474 {
475 name: "wasabi",
476 storageId: 1,
477 module: "s3",
478 configuration: cluster.spec.benji.s3Configuration {
479 activeTransforms: ["encrypt"],
480 },
481 },
482 ],
483 transforms: [
484 {
485 name: "encrypt",
486 module: "aes_256_gcm",
487 configuration: {
488 # not secret.
489 kdfSalt: "T2huZzZpcGhhaWM3QWVwaDhybzRhaDNhbzFpc2VpOWFobDNSZWVQaGVvTWV1bmVaYWVsNHRoYWg5QWVENHNoYWg0ZGFoN3Rlb3NvcHVuZzNpZXZpMm9vTG9vbmc1YWlmb0RlZXAwYmFobDlab294b2hjaG9odjRhbzFsYWkwYWk=",
490 kdfIterations: 2137,
491 password: cluster.spec.benji.encryptionPassword,
492 },
493 },
494 ],
495 ios: [
496 { name: pool, module: "rbd" }
497 for pool in cluster.spec.benji.pools
498 ],
499 }),
500 },
501 },
502
503 # Yes, Benji keeps data (backup metadata) on the ceph cluster that
504 # it backs up. However:
505 # - we add a command to benji-k8s to also copy over the sqlite
506 # database over to s3
507 # - benji can, in a pinch, restore without a database if a version
508 # is known: https://benji-backup.me/restore.html#restoring-without-a-database
509 data: kube.PersistentVolumeClaim(cluster.name("benji-data")) {
510 metadata+: cluster.metadata,
511 spec+: {
512 storageClassName: cluster.spec.benji.metadataStorageClass,
513 accessModes: [ "ReadWriteOnce" ],
514 resources: {
515 requests: {
516 storage: "1Gi",
517 },
518 },
519 },
520 },
521
522 # Extra scripts.
523 extrabins: kube.ConfigMap(cluster.name("benji-extrabins")) {
524 metadata+: cluster.metadata,
525 data: {
526 "metabackup.sh" : |||
527 # Make backups of sqlite3 metadata used by Benji.
528 # The backups live in the same bucket as backups, and the metabackups
529 # are named `metabackup-0..10`, where 0 is the newest backup. Any time
530 # this script is called, backups get shifted one way to the left (9 to 10,
531 # 8 to 9, etc). This ensures we have at least 10 backup replicas.
532
533 set -e
534
535 which s3cmd || pip install --upgrade s3cmd
536
537 AWS_ACCESS_KEY_ID=$(jq -r .storages[0].configuration.awsAccessKeyId < /etc/benji/benji.yaml)
538 AWS_SECRET_ACCESS_KEY=$(jq -r .storages[0].configuration.awsSecretAccessKey < /etc/benji/benji.yaml)
539 BUCKET=$(jq -r .storages[0].configuration.bucketName < /etc/benji/benji.yaml)
540
541 s3() {
542 s3cmd --host=s3.wasabisys.com \
543 "--host-bucket=%(bucket)s.s3.wasabisys.com" \
544 --region=eu-central-1 \
545 --access_key=$AWS_ACCESS_KEY_ID \
546 --secret_key=$AWS_SECRET_ACCESS_KEY \
547 "$@"
548 }
549
550 # Copy over old backups, if they exist.
551 for i in `seq 9 -1 0`; do
552 from="s3://$BUCKET/metabackup-$i.sqlite3"
553 to="s3://$BUCKET/metabackup-$((i+1)).sqlite3"
554
555 if [[ $(s3 ls $from | wc -l) -eq 0 ]]; then
556 echo "$from does not exist, skipping shift."
557 continue
558 fi
559 echo "Moving $from to $to..."
560 s3 mv $from $to
561 done
562
563 # Make new metabackup.
564 s3 put /data/benji.sqlite s3://$BUCKET/metabackup-0.sqlite3
565
566 |||,
567 "get-rook-creds.sh": |||
568 # Based on the Rook Toolbox /usr/local/bin/toolbox.sh script.
569 # Copyright 2016 The Rook Authors. All rights reserved.
570
571 CEPH_CONFIG="/etc/ceph/ceph.conf"
572 MON_CONFIG="/etc/rook/mon-endpoints"
573 KEYRING_FILE="/etc/ceph/keyring"
574
575 # create a ceph config file in its default location so ceph/rados tools can be used
576 # without specifying any arguments
577 write_endpoints() {
578 endpoints=$(cat ${MON_CONFIG})
579
580 # filter out the mon names
581 mon_endpoints=$(echo ${endpoints} | sed 's/[a-z]\+=//g')
582
583 # filter out the legacy mon names
584 mon_endpoints=$(echo ${mon_endpoints} | sed 's/rook-ceph-mon[0-9]\+=//g')
585
586 DATE=$(date)
587 echo "$DATE writing mon endpoints to ${CEPH_CONFIG}: ${endpoints}"
588 cat <<EOF > ${CEPH_CONFIG}
589 [global]
590 mon_host = ${mon_endpoints}
591
592 [client.admin]
593 keyring = ${KEYRING_FILE}
594 EOF
595 }
596
597 # watch the endpoints config file and update if the mon endpoints ever change
598 watch_endpoints() {
599 # get the timestamp for the target of the soft link
600 real_path=$(realpath ${MON_CONFIG})
601 initial_time=$(stat -c %Z ${real_path})
602 while true; do
603 real_path=$(realpath ${MON_CONFIG})
604 latest_time=$(stat -c %Z ${real_path})
605
606 if [[ "${latest_time}" != "${initial_time}" ]]; then
607 write_endpoints
608 initial_time=${latest_time}
609 fi
610 sleep 10
611 done
612 }
613
614 # create the keyring file
615 cat <<EOF > ${KEYRING_FILE}
616 [client.admin]
617 key = ${ROOK_ADMIN_SECRET}
618 EOF
619
620 # write the initial config file
621 write_endpoints
622
623 # continuously update the mon endpoints if they fail over
624 watch_endpoints &
625 |||
626 },
627 },
628
629 cronjob: kube.CronJob(cluster.name("benji")) {
630 metadata+: cluster.metadata,
631 spec+: { # CronJob Spec
Sergiusz Bazanski95868ee2019-09-26 23:47:14 +0200632 schedule: "42 0 * * *", # Daily at 42 minute past midnight.
Sergiusz Bazanski13bb1bf2019-08-31 16:33:29 +0200633 jobTemplate+: {
634 spec+: { # Job Spec
635 selector:: null,
636 template+: {
637 spec+: { # PodSpec
638 serviceAccountName: cluster.benji.sa.metadata.name,
639 containers_: {
640 benji: kube.Container(cluster.name("benji")) {
641 # TODO(q3k): switch back to upstream after pull/52 goes in.
642 # Currently this is being built from github.com/q3k/benji.
643 # https://github.com/elemental-lf/benji/pull/52
644 image: "registry.k0.hswaw.net/q3k/benji-k8s:20190831-1351",
645 volumeMounts_: {
646 extrabins: { mountPath: "/usr/local/extrabins" },
647 monendpoints: { mountPath: "/etc/rook" },
648 benjiconfig: { mountPath: "/etc/benji" },
649 data: { mountPath: "/data" },
650 },
651 env_: {
652 ROOK_ADMIN_SECRET: { secretKeyRef: { name: "rook-ceph-mon", key: "admin-secret" }},
653 },
654 command: [
655 "bash", "-c", |||
656 bash /usr/local/extrabins/get-rook-creds.sh
657 benji-backup-pvc
658 benji-command enforce latest3,hours48,days7,months12
659 benji-command cleanup
660 bash /usr/local/extrabins/metabackup.sh
661 |||,
662 ],
663 },
664 },
665 volumes_: {
666 data: kube.PersistentVolumeClaimVolume(cluster.benji.data),
667 benjiconfig: kube.SecretVolume(cluster.benji.config),
668 extrabins: kube.ConfigMapVolume(cluster.benji.extrabins),
669 monendpoints: {
670 configMap: {
671 name: "rook-ceph-mon-endpoints",
672 items: [
673 { key: "data", path: "mon-endpoints" },
674 ],
675 },
676 },
677 },
678 },
679 },
680 },
681 },
682 },
683 },
684 },
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +0200685 },
686
Sergiusz Bazanski36cc4fb2019-05-17 18:08:48 +0200687 ReplicatedBlockPool(cluster, name):: {
688 local pool = self,
Sergiusz Bazanskid07861b2019-08-08 17:48:25 +0200689 name:: name,
690
Sergiusz Bazanski36cc4fb2019-05-17 18:08:48 +0200691 spec:: error "spec must be specified",
692
693 pool: kube._Object("ceph.rook.io/v1", "CephBlockPool", name) {
694 metadata+: cluster.metadata,
695 spec: pool.spec,
696 },
697
698 storageClass: kube.StorageClass(name) {
699 provisioner: "ceph.rook.io/block",
700 parameters: {
701 blockPool: pool.pool.metadata.name,
702 clusterNamespace: pool.pool.metadata.namespace,
703 fstype: "ext4",
704 },
705 reclaimPolicy: "Retain",
706 },
707 },
708
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +0200709 ECBlockPool(cluster, name):: {
710 local pool = self,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200711 name:: name,
Serge Bazanskic33ebcc2019-11-01 18:43:45 +0100712 metadataReplicas:: 3,
Sergiusz Bazanski4d61d202019-07-21 16:56:41 +0200713
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +0200714 spec:: error "spec must be specified",
715
716 pool: kube._Object("ceph.rook.io/v1", "CephBlockPool", name) {
717 metadata+: cluster.metadata,
718 spec: pool.spec,
719 },
720 metapool: kube._Object("ceph.rook.io/v1", "CephBlockPool", name + "-metadata") {
721 metadata+: cluster.metadata,
722 spec: {
723 failureDomain: "host",
724 replicated: {
Serge Bazanskic33ebcc2019-11-01 18:43:45 +0100725 size: pool.metadataReplicas,
Sergiusz Bazanski65f3b1d2019-04-02 01:05:38 +0200726 },
727 },
728 },
729
730 storageClass: kube.StorageClass(name) {
731 provisioner: "ceph.rook.io/block",
732 parameters: {
733 blockPool: pool.metapool.metadata.name,
734 dataBlockPool: pool.pool.metadata.name,
735 clusterNamespace: pool.pool.metadata.namespace,
736 fstype: "ext4",
737 },
738 reclaimPolicy: "Retain",
Sergiusz Bazanskic6da1272019-04-02 00:06:13 +0200739 },
740 },
Piotr Dobrowolski5ac85c62019-04-09 21:45:32 +0200741
742 S3ObjectStore(cluster, name):: {
743 local store = self,
744 spec:: error "spec must be specified",
745 objectStore: kube._Object("ceph.rook.io/v1", "CephObjectStore", name) {
746 metadata+: cluster.metadata,
747 spec: store.spec {
748 gateway: {
749 type: "s3",
750 port: 80,
751 instances: 1,
752 allNodes: false,
753 },
754 },
755 },
756
757 objectIngress: kube.Ingress(name) {
758 metadata+: cluster.metadata {
759 annotations+: {
760 "kubernetes.io/tls-acme": "true",
761 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
762 "nginx.ingress.kubernetes.io/proxy-body-size": "0",
763 },
764 },
765 spec+: {
766 tls: [
767 {
768 hosts: ["object.%s.hswaw.net" % [cluster.metadata.namespace]],
769 secretName: "%s-tls" % [name],
770 },
771 ],
772 rules: [
773 {
774 host: "object.%s.hswaw.net" % [cluster.metadata.namespace],
775 http: {
776 paths: [
777 {
778 path: "/",
779 backend: {
780 serviceName: "rook-ceph-rgw-%s" % [name],
781 servicePort: 80,
782 },
783 },
784 ]
785 },
786 }
787 ],
788 },
789 },
790 },
Sergiusz Bazanskib7fcc672019-04-01 18:40:50 +0200791}