From 2383b085729f3da5a0fea05d26504f09553451ac Mon Sep 17 00:00:00 2001 From: 3pings Date: Mon, 20 Jul 2026 15:02:58 -0400 Subject: [PATCH] Add garage 0.9.3 community pack (S3-compatible object store) Garage is a lightweight, S3-compatible distributed object store aimed at self-hosted, geo-distributed deployments. Packages the upstream Helm chart 0.9.3 (app v2.3.0) with Kubernetes-based peer discovery enabled. The README documents the manual layout assignment required post-install -- a Garage cluster has zero usable capacity and rejects all S3 operations until `layout assign` and `layout apply` are run against each node. Co-Authored-By: Claude Opus 4.8 (1M context) --- packs/garage-0.9.3/README.md | 213 +++++++++++++ packs/garage-0.9.3/charts/garage-0.9.3.tgz | Bin 0 -> 9963 bytes packs/garage-0.9.3/charts/garage/.helmignore | 23 ++ packs/garage-0.9.3/charts/garage/Chart.yaml | 18 ++ packs/garage-0.9.3/charts/garage/README.md | 100 +++++++ .../charts/garage/templates/_helpers.tpl | 98 ++++++ .../charts/garage/templates/clusterrole.yaml | 30 ++ .../charts/garage/templates/configmap.yaml | 62 ++++ .../charts/garage/templates/ingress.yaml | 129 ++++++++ .../charts/garage/templates/secret.yaml | 16 + .../garage/templates/service-headless.yaml | 22 ++ .../charts/garage/templates/service.yaml | 44 +++ .../garage/templates/serviceaccount.yaml | 12 + .../garage/templates/servicemonitor.yaml | 44 +++ .../charts/garage/templates/workload.yaml | 154 ++++++++++ packs/garage-0.9.3/charts/garage/values.yaml | 273 +++++++++++++++++ packs/garage-0.9.3/logo.png | Bin 0 -> 11871 bytes packs/garage-0.9.3/pack.json | 17 ++ packs/garage-0.9.3/values.yaml | 281 ++++++++++++++++++ 19 files changed, 1536 insertions(+) create mode 100644 packs/garage-0.9.3/README.md create mode 100644 packs/garage-0.9.3/charts/garage-0.9.3.tgz create mode 100644 packs/garage-0.9.3/charts/garage/.helmignore create mode 100644 packs/garage-0.9.3/charts/garage/Chart.yaml create mode 100644 packs/garage-0.9.3/charts/garage/README.md create mode 100644 packs/garage-0.9.3/charts/garage/templates/_helpers.tpl create mode 100644 packs/garage-0.9.3/charts/garage/templates/clusterrole.yaml create mode 100644 packs/garage-0.9.3/charts/garage/templates/configmap.yaml create mode 100644 packs/garage-0.9.3/charts/garage/templates/ingress.yaml create mode 100644 packs/garage-0.9.3/charts/garage/templates/secret.yaml create mode 100644 packs/garage-0.9.3/charts/garage/templates/service-headless.yaml create mode 100644 packs/garage-0.9.3/charts/garage/templates/service.yaml create mode 100644 packs/garage-0.9.3/charts/garage/templates/serviceaccount.yaml create mode 100644 packs/garage-0.9.3/charts/garage/templates/servicemonitor.yaml create mode 100644 packs/garage-0.9.3/charts/garage/templates/workload.yaml create mode 100644 packs/garage-0.9.3/charts/garage/values.yaml create mode 100644 packs/garage-0.9.3/logo.png create mode 100644 packs/garage-0.9.3/pack.json create mode 100644 packs/garage-0.9.3/values.yaml diff --git a/packs/garage-0.9.3/README.md b/packs/garage-0.9.3/README.md new file mode 100644 index 00000000..40ab9be7 --- /dev/null +++ b/packs/garage-0.9.3/README.md @@ -0,0 +1,213 @@ +# Garage + +[Garage](https://garagehq.deuxfleurs.fr/) is a lightweight, S3-compatible distributed object store built by [Deuxfleurs](https://deuxfleurs.fr/). It is designed for self-hosted, geo-distributed deployments running on commodity hardware — it tolerates high-latency links between nodes and does not require a dedicated storage network, which makes it a good fit for edge clusters and small on-prem footprints where Ceph or MinIO would be too heavy. + +This pack deploys Garage as a 3-replica StatefulSet using the upstream Helm chart (chart `0.9.3`, app `v2.3.0`). Nodes discover each other automatically through the built-in Kubernetes discovery mechanism, so no bootstrap peer list is needed. + +> [!IMPORTANT] +> Garage does not self-assemble into a usable cluster. After the pods are running you **must** manually assign a layout to each node before the S3 API will accept any data. See [Post-Installation](#post-installation). + + +## Prerequisites + +- A Kubernetes cluster with a default StorageClass, or an explicit `storageClass` set under `persistence` (see [Storage](#storage)). +- Permission to create cluster-scoped resources. The chart installs the `garagenodes.deuxfleurs.fr` CRD and a ClusterRole used for peer discovery. If you cannot grant cluster-scoped access, set `garage.kubernetesSkipCrd: true` and install the CRD out of band. +- At least 3 schedulable nodes if you keep the default `replicationFactor: "3"`. With fewer nodes, replicas will co-locate and you lose the durability the replication factor implies. + + +## Parameters + +| **Parameter** | **Description** | **Type** | **Default Value** | **Required** | +|---|---|---|---|---| +| `deployment.kind` | `StatefulSet` (PVC-backed) or `DaemonSet` (hostPath-backed) | String | `StatefulSet` | No | +| `deployment.replicaCount` | Number of Garage nodes | Integer | `3` | No | +| `garage.replicationFactor` | Copies of each object across the cluster | String | `"3"` | No | +| `garage.consistencyMode` | `consistent` (read-after-write), `degraded`, or `dangerous` | String | `"consistent"` | No | +| `garage.dbEngine` | Metadata engine: `lmdb` or `sqlite` | String | `"lmdb"` | No | +| `garage.blockSize` | Data block size in bytes | String | `"1048576"` | No | +| `garage.compressionLevel` | zstd level for stored blocks | String | `"1"` | No | +| `garage.metadataAutoSnapshotInterval` | Interval for automatic metadata DB snapshots, e.g. `6h`. Empty disables | String | `""` | No | +| `garage.rpcSecret` | Shared secret for inter-node RPC. Generated and stored in a Secret if left empty | String | `""` | No | +| `garage.existingRpcSecret` | Name of an existing Secret holding the RPC secret under key `rpcSecret` | String | `""` | No | +| `garage.kubernetesSkipCrd` | Skip installing the `garagenodes` CRD | Boolean | `false` | No | +| `garage.s3.api.region` | S3 region name advertised to clients | String | `"garage"` | No | +| `garage.s3.api.rootDomain` | Suffix enabling virtual-hosted bucket addressing | String | `".s3.garage.tld"` | No | +| `garage.s3.web.rootDomain` | Suffix for static website hosting from buckets | String | `".web.garage.tld"` | No | +| `garage.additionalTopLevelConfig` | Raw TOML appended to `garage.toml` | String | `""` | No | +| `garage.garageTomlString` | Full `garage.toml` template. **Overrides all other `garage.*` values** | String | `""` | No | +| `persistence.enabled` | Persist metadata and data | Boolean | `true` | No | +| `persistence.meta.size` | Metadata volume size | String | `100Mi` | **Yes — raise it** | +| `persistence.data.size` | Data volume size | String | `100Mi` | **Yes — raise it** | +| `service.type` | `ClusterIP`, `NodePort`, or `LoadBalancer` | String | `ClusterIP` | No | +| `ingress.s3.api.enabled` | Expose the S3 API through an Ingress | Boolean | `false` | No | +| `ingress.s3.web.enabled` | Expose bucket static-website serving through an Ingress | Boolean | `false` | No | +| `monitoring.metrics.enabled` | Annotate a Service for Prometheus scraping | Boolean | `false` | No | +| `monitoring.metrics.serviceMonitor.enabled` | Create a `ServiceMonitor` (requires Prometheus Operator) | Boolean | `false` | No | +| `resources` | Pod resource requests and limits | Object | `{}` | No | + +The full set of chart values is documented in [`charts/garage/README.md`](charts/garage/README.md). + + +## Storage + +The chart ships with `100Mi` volumes for both metadata and data. **These defaults are placeholders and are not usable for real workloads** — size them before the first deploy: + +```yaml +charts: + garage: + persistence: + meta: + storageClass: "fast-storage-class" # SSD-backed; LMDB is latency-sensitive + size: 5Gi + data: + storageClass: "bulk-storage-class" # Capacity matters more than latency here + size: 500Gi +``` + +Resizing after deployment is awkward: StatefulSet `volumeClaimTemplates` are immutable, so growing volumes requires orphaning the StatefulSet (`kubectl delete sts --cascade=orphan`), editing the PVCs, and letting the pack recreate the controller. Your StorageClass must have `allowVolumeExpansion: true`. Size generously up front. + +Setting `deployment.kind: DaemonSet` switches Garage to hostPath storage at `persistence.meta.hostPath` and `persistence.data.hostPath`, placing one node per host. This suits edge clusters with direct-attached disks, but the paths must exist and be writable by UID/GID `1000`. + + +## Usage + +To use this pack, create or edit an [add-on cluster profile](https://docs.spectrocloud.com/profiles/cluster-profiles/create-cluster-profiles/create-addon-profile/), search for the **garage** pack, and adjust the values. A minimal production-shaped override: + +```yaml +charts: + garage: + deployment: + replicaCount: 3 + garage: + replicationFactor: "3" + consistencyMode: "consistent" + metadataAutoSnapshotInterval: "6h" + s3: + api: + region: "us-east-1" + rootDomain: ".s3.example.com" + persistence: + meta: + storageClass: "fast-storage-class" + size: 5Gi + data: + storageClass: "bulk-storage-class" + size: 500Gi + resources: + requests: + cpu: 250m + memory: 1Gi + limits: + memory: 2Gi +``` + +The pack deploys into the `garage` namespace. + +### Exposing the S3 API + +By default the API is only reachable in-cluster at `garage.garage.svc.cluster.local:3900`. To reach it from outside, either set `service.type: LoadBalancer` or enable the Ingress. Virtual-hosted bucket addressing (`bucket.s3.example.com`) requires a wildcard host, and `garage.s3.api.rootDomain` must match: + +```yaml +charts: + garage: + ingress: + s3: + api: + enabled: true + className: "nginx" + hosts: + - host: "s3.example.com" + paths: + - path: / + pathType: Prefix + - host: "*.s3.example.com" + paths: + - path: / + pathType: Prefix + tls: + - secretName: garage-s3-tls + hosts: + - "s3.example.com" + - "*.s3.example.com" +``` + +S3 clients that only support path-style addressing (`s3.example.com/bucket`) work without the wildcard host. + + +## Post-Installation + +A freshly deployed Garage cluster has no layout, which means it has zero usable capacity and rejects all S3 operations. The `garage` CLI is bundled in the container image; run it via `kubectl exec` against any pod. + +**1. Confirm all nodes see each other.** Each pod should be listed with a node ID: + +```bash +kubectl exec -it -n garage garage-0 -- ./garage status +``` + +**2. Assign a layout role to each node.** Use the first several characters of each node ID (enough to be unique). `--zone` should reflect physical failure domains — with `replicationFactor: 3`, Garage spreads copies across distinct zones when it can. `--capacity` is the share of data the node accepts, and should track the size of its data volume: + +```bash +kubectl exec -it -n garage garage-0 -- ./garage layout assign -z dc1 -c 500G -t garage-0 +kubectl exec -it -n garage garage-0 -- ./garage layout assign -z dc2 -c 500G -t garage-1 +kubectl exec -it -n garage garage-0 -- ./garage layout assign -z dc3 -c 500G -t garage-2 +``` + +**3. Review and apply.** The version number must be exactly one greater than the current layout version — `1` for the first apply: + +```bash +kubectl exec -it -n garage garage-0 -- ./garage layout show +kubectl exec -it -n garage garage-0 -- ./garage layout apply --version 1 +``` + +**4. Create a bucket and a key, then grant access:** + +```bash +kubectl exec -it -n garage garage-0 -- ./garage bucket create my-bucket +kubectl exec -it -n garage garage-0 -- ./garage key create my-app-key +kubectl exec -it -n garage garage-0 -- ./garage bucket allow --read --write my-bucket --key my-app-key +``` + +`key create` prints the access key ID and secret access key **once** — capture them at that moment. Point any S3 client at the API endpoint using the region from `garage.s3.api.region`. + +Adding or removing nodes later repeats steps 2–3 with an incremented `--version`. Garage rebalances data automatically after the new layout is applied. + + +## Monitoring + +Garage exposes Prometheus metrics on the admin API port (`3903`). With the Prometheus Operator installed: + +```yaml +charts: + garage: + monitoring: + metrics: + enabled: true + serviceMonitor: + enabled: true + interval: 30s +``` + +The admin API is deliberately excluded from the main Service because its responses are not consistent across nodes — query a specific pod when using it directly. + + +## Uninstalling + +Removing the pack from the cluster profile deletes the workloads but leaves two things behind on purpose: + +- **PersistentVolumeClaims** are retained by the StatefulSet controller. Delete them explicitly to reclaim storage — and only once you are certain the data is not needed. +- **The `garagenodes.deuxfleurs.fr` CRD** is not removed by Helm and must be deleted manually if you are permanently retiring Garage. + + +## Kubernetes Compatibility + +Requires Kubernetes v1.19 or later (`networking.k8s.io/v1` Ingress). + + +## References + +- [Garage documentation](https://garagehq.deuxfleurs.fr/documentation/) +- [Deploying on Kubernetes](https://garagehq.deuxfleurs.fr/documentation/cookbook/kubernetes/) +- [Creating a cluster layout](https://garagehq.deuxfleurs.fr/documentation/operations/layout/) +- [Configuration reference](https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/) +- [S3 compatibility matrix](https://garagehq.deuxfleurs.fr/documentation/reference-manual/s3-compatibility/) +- [Source code](https://git.deuxfleurs.fr/Deuxfleurs/garage) diff --git a/packs/garage-0.9.3/charts/garage-0.9.3.tgz b/packs/garage-0.9.3/charts/garage-0.9.3.tgz new file mode 100644 index 0000000000000000000000000000000000000000..a14ba166bd40106e84cbc1c58d3cf9555619ca68 GIT binary patch literal 9963 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 literal 0 HcmV?d00001 diff --git a/packs/garage-0.9.3/charts/garage/.helmignore b/packs/garage-0.9.3/charts/garage/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packs/garage-0.9.3/charts/garage/Chart.yaml b/packs/garage-0.9.3/charts/garage/Chart.yaml new file mode 100644 index 00000000..110ba8c7 --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: garage +description: S3-compatible object store for small self-hosted geo-distributed deployments +type: application +version: 0.9.3 +appVersion: "v2.3.0" +home: https://garagehq.deuxfleurs.fr/ +icon: https://garagehq.deuxfleurs.fr/images/garage-logo.svg + +keywords: +- geo-distributed +- read-after-write-consistency +- s3-compatible + +sources: +- https://git.deuxfleurs.fr/Deuxfleurs/garage.git + +maintainers: [] diff --git a/packs/garage-0.9.3/charts/garage/README.md b/packs/garage-0.9.3/charts/garage/README.md new file mode 100644 index 00000000..1473e320 --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/README.md @@ -0,0 +1,100 @@ +# garage + +![Version: 0.9.3](https://img.shields.io/badge/Version-0.9.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v2.3.0](https://img.shields.io/badge/AppVersion-v2.3.0-informational?style=flat-square) + +S3-compatible object store for small self-hosted geo-distributed deployments + +**Homepage:** + +## Source Code + +* + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| commonLabels | object | `{}` | Extra labels for all resources | +| deployment.kind | string | `"StatefulSet"` | Switchable to DaemonSet | +| deployment.podManagementPolicy | string | `"OrderedReady"` | If using statefulset, allow Parallel or OrderedReady (default) | +| deployment.replicaCount | int | `3` | Number of StatefulSet replicas/garage nodes to start | +| environment | object | `{}` | | +| extraVolumeMounts | object | `{}` | | +| extraVolumes | object | `{}` | | +| fullnameOverride | string | `""` | | +| garage.blockSize | string | `"1048576"` | Defaults is 1MB An increase can result in better performance in certain scenarios https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#block_size | +| garage.bootstrapPeers | list | `[]` | This is not required if you use the integrated kubernetes discovery | +| garage.compressionLevel | string | `"1"` | zstd compression level of stored blocks https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#compression_level | +| garage.dbEngine | string | `"lmdb"` | Can be changed for better performance on certain systems https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#db_engine | +| garage.existingConfigMap | string | `""` | if not empty string, allow using an existing ConfigMap for the garage.toml, if set, ignores garage.toml | +| garage.garageTomlString | string | `""` | String Template for the garage configuration if set, ignores above values. Values can be templated, see https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/ | +| garage.kubernetesSkipCrd | bool | `false` | Set to true if you want to use k8s discovery but install the CRDs manually outside of the helm chart, for example if you operate at namespace level without cluster resources | +| garage.replicationFactor | string | `"3"` | Default to 3 replicas, see the replication_factor section at https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#replication_factor | +| garage.consistencyMode | string | `"consistent"` | Default to read-after-write consistency, see the consistency_mode section at https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#consistency_mode | +| garage.metadataAutoSnapshotInterval | string | `""` | If this value is set, Garage will automatically take a snapshot of the metadata DB file at a regular interval and save it in the metadata directory. https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#metadata_auto_snapshot_interval | +| garage.admin.apiBindAddr | string | `"[::]:3903"` | | +| garage.rpcBindAddr | string | `"[::]:3901"` | | +| garage.rpcSecret | string | `""` | If not given, a random secret will be generated and stored in a Secret object | +| garage.s3.api.bindAddr | string | `"[::]:3900"` | | +| garage.s3.api.region | string | `"garage"` | | +| garage.s3.api.rootDomain | string | `".s3.garage.tld"` | | +| garage.s3.web.index | string | `"index.html"` | | +| garage.s3.web.bindAddr | string | `"[::]:3902"` | | +| garage.s3.web.rootDomain | string | `".web.garage.tld"` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"dxflrs/amd64_garage"` | default to amd64 docker image | +| image.tag | string | `""` | set the image tag, please prefer using the chart version and not this to avoid compatibility issues | +| imagePullSecrets | list | `[]` | set if you need credentials to pull your custom image | +| ingress.s3.api.annotations | object | `{}` | Rely _either_ on the className or the annotation below but not both! If you want to use the className, set className: "nginx" and replace "nginx" by an Ingress controller name, examples [here](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers). | +| ingress.s3.api.enabled | bool | `false` | | +| ingress.s3.api.hosts[0] | object | `{"host":"s3.garage.tld","paths":[{"path":"/","pathType":"Prefix"}]}` | garage S3 API endpoint, to be used with awscli for example | +| ingress.s3.api.hosts[1] | object | `{"host":"*.s3.garage.tld","paths":[{"path":"/","pathType":"Prefix"}]}` | garage S3 API endpoint, DNS style bucket access | +| ingress.s3.api.labels | object | `{}` | | +| ingress.s3.api.tls | list | `[]` | | +| ingress.s3.web.annotations | object | `{}` | Rely _either_ on the className or the annotation below but not both! If you want to use the className, set className: "nginx" and replace "nginx" by an Ingress controller name, examples [here](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers). | +| ingress.s3.web.enabled | bool | `false` | | +| ingress.s3.web.hosts[0] | object | `{"host":"*.web.garage.tld","paths":[{"path":"/","pathType":"Prefix"}]}` | wildcard website access with bucket name prefix | +| ingress.s3.web.hosts[1] | object | `{"host":"mywebpage.example.com","paths":[{"path":"/","pathType":"Prefix"}]}` | specific bucket access with FQDN bucket | +| ingress.s3.web.labels | object | `{}` | | +| ingress.s3.web.tls | list | `[]` | | +| initImage.pullPolicy | string | `"IfNotPresent"` | | +| initImage.repository | string | `"busybox"` | | +| initImage.tag | string | `"stable"` | | +| livenessProbe | object | `{}` | Specifies a livenessProbe | +| monitoring.metrics.enabled | bool | `false` | If true, a service for monitoring is created with a prometheus.io/scrape annotation | +| monitoring.metrics.serviceMonitor.enabled | bool | `false` | If true, a ServiceMonitor CRD is created for a prometheus operator https://github.com/coreos/prometheus-operator | +| monitoring.metrics.serviceMonitor.interval | string | `"15s"` | | +| monitoring.metrics.serviceMonitor.labels | object | `{}` | | +| monitoring.metrics.serviceMonitor.path | string | `"/metrics"` | | +| monitoring.metrics.serviceMonitor.relabelings | list | `[]` | | +| monitoring.metrics.serviceMonitor.scheme | string | `"http"` | | +| monitoring.metrics.serviceMonitor.scrapeTimeout | string | `"10s"` | | +| monitoring.metrics.serviceMonitor.tlsConfig | object | `{}` | | +| monitoring.tracing.sink | string | `""` | specify a sink endpoint for OpenTelemetry Traces, eg. `http://localhost:4317` | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| persistence.data.hostPath | string | `"/var/lib/garage/data"` | | +| persistence.data.size | string | `"100Mi"` | | +| persistence.enabled | bool | `true` | | +| persistence.meta.hostPath | string | `"/var/lib/garage/meta"` | | +| persistence.meta.size | string | `"100Mi"` | | +| podAnnotations | object | `{}` | additional pod annotations | +| podSecurityContext.fsGroup | int | `1000` | | +| podSecurityContext.runAsGroup | int | `1000` | | +| podSecurityContext.runAsNonRoot | bool | `true` | | +| podSecurityContext.runAsUser | int | `1000` | | +| readinessProbe | object | `{}` | Specifies a readinessProbe | +| resources | object | `{}` | | +| securityContext.capabilities | object | `{"drop":["ALL"]}` | The default security context is heavily restricted, feel free to tune it to your requirements | +| securityContext.readOnlyRootFilesystem | bool | `true` | | +| service.s3.api.port | int | `3900` | | +| service.s3.web.port | int | `3902` | | +| service.type | string | `"ClusterIP"` | You can rely on any service to expose your cluster - ClusterIP (+ Ingress) - NodePort (+ Ingress) - LoadBalancer | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| tolerations | list | `[]` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/packs/garage-0.9.3/charts/garage/templates/_helpers.tpl b/packs/garage-0.9.3/charts/garage/templates/_helpers.tpl new file mode 100644 index 00000000..4451840f --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/templates/_helpers.tpl @@ -0,0 +1,98 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "garage.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "garage.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create the name of the rpc secret +*/}} +{{- define "garage.rpcSecretName" -}} +{{- .Values.garage.existingRpcSecret | default (printf "%s-rpc-secret" (include "garage.fullname" .)) -}} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "garage.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "garage.labels" -}} +helm.sh/chart: {{ include "garage.chart" . }} +{{ include "garage.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.commonLabels }} +{{- toYaml . | nindent 0 }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "garage.selectorLabels" -}} +app.kubernetes.io/name: {{ include "garage.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "garage.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "garage.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Extract the trailing port number from a bind address like [::]:3900 or 0.0.0.0:3900. +*/}} +{{- define "garage.portFromBindAddr" -}} +{{- regexFind "[0-9]+$" . -}} +{{- end }} + +{{/* + Returns given number of random Hex characters. + In practice, it generates up to 100 randAlphaNum strings + that are filtered from non-hex characters and augmented + to the resulting string that is finally trimmed down. +*/}} +{{- define "jupyterhub.randHex" -}} + {{- $result := "" }} + {{- range $i := until 100 }} + {{- if lt (len $result) . }} + {{- $rand_list := randAlphaNum . | splitList "" -}} + {{- $reduced_list := without $rand_list "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" }} + {{- $rand_string := join "" $reduced_list }} + {{- $result = print $result $rand_string -}} + {{- end }} + {{- end }} + {{- $result | trunc . }} +{{- end }} diff --git a/packs/garage-0.9.3/charts/garage/templates/clusterrole.yaml b/packs/garage-0.9.3/charts/garage/templates/clusterrole.yaml new file mode 100644 index 00000000..3fb81af9 --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/templates/clusterrole.yaml @@ -0,0 +1,30 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: manage-crds-{{ .Release.Namespace }}-{{ .Release.Name }} + labels: + {{- include "garage.labels" . | nindent 4 }} +rules: +{{- if eq .Values.garage.kubernetesSkipCrd false }} +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch", "create", "patch"] +{{ end }} +- apiGroups: ["deuxfleurs.fr"] + resources: ["garagenodes"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: allow-crds-for-{{ .Release.Namespace }}-{{ .Release.Name }} + labels: + {{- include "garage.labels" . | nindent 4 }} +subjects: +- kind: ServiceAccount + name: {{ include "garage.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: manage-crds-{{ .Release.Namespace }}-{{ .Release.Name }} + apiGroup: rbac.authorization.k8s.io diff --git a/packs/garage-0.9.3/charts/garage/templates/configmap.yaml b/packs/garage-0.9.3/charts/garage/templates/configmap.yaml new file mode 100644 index 00000000..420f31da --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/templates/configmap.yaml @@ -0,0 +1,62 @@ +{{- if not .Values.garage.existingConfigMap }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "garage.fullname" . }}-config +data: + garage.toml: |- + {{- if .Values.garage.garageTomlString }} + {{- tpl (index (index .Values.garage) "garageTomlString") $ | nindent 4 }} + {{- else }} + metadata_dir = "/mnt/meta" + data_dir = "/mnt/data" + + db_engine = "{{ .Values.garage.dbEngine }}" + + block_size = "{{ .Values.garage.blockSize }}" + + replication_factor = {{ .Values.garage.replicationFactor }} + consistency_mode = "{{ .Values.garage.consistencyMode }}" + + compression_level = {{ .Values.garage.compressionLevel }} + + {{- if .Values.garage.metadataAutoSnapshotInterval }} + metadata_auto_snapshot_interval = {{ .Values.garage.metadataAutoSnapshotInterval | quote }} + {{- end }} + + rpc_bind_addr = "{{ .Values.garage.rpcBindAddr }}" + # rpc_secret will be populated by the init container from a k8s secret object + rpc_secret = "__RPC_SECRET_REPLACE__" + + bootstrap_peers = [ + {{- range $index, $peer := .Values.garage.bootstrapPeers }} + {{- if $index}}, {{ end }}{{ $peer | quote }} + {{ end }} + ] + + {{- if .Values.garage.additionalTopLevelConfig }} + {{ .Values.garage.additionalTopLevelConfig | nindent 4 }} + {{- end }} + + [kubernetes_discovery] + namespace = "{{ .Release.Namespace }}" + service_name = "{{ include "garage.fullname" . }}" + skip_crd = {{ .Values.garage.kubernetesSkipCrd }} + + [s3_api] + s3_region = "{{ .Values.garage.s3.api.region }}" + api_bind_addr = "{{ .Values.garage.s3.api.bindAddr }}" + root_domain = "{{ .Values.garage.s3.api.rootDomain }}" + + [s3_web] + bind_addr = "{{ .Values.garage.s3.web.bindAddr }}" + root_domain = "{{ .Values.garage.s3.web.rootDomain }}" + index = "{{ .Values.garage.s3.web.index }}" + + [admin] + api_bind_addr = "{{ .Values.garage.admin.apiBindAddr }}" + {{- if .Values.monitoring.tracing.sink }} + trace_sink = "{{ .Values.monitoring.tracing.sink }}" + {{- end }} + {{- end }} +{{- end }} diff --git a/packs/garage-0.9.3/charts/garage/templates/ingress.yaml b/packs/garage-0.9.3/charts/garage/templates/ingress.yaml new file mode 100644 index 00000000..35225daa --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/templates/ingress.yaml @@ -0,0 +1,129 @@ +{{- if .Values.ingress.s3.api.enabled -}} +{{- $fullName := include "garage.fullname" . -}} +{{- $svcPort := .Values.service.s3.api.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.s3.api.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.s3.api.annotations "kubernetes.io/ingress.class" .Values.ingress.s3.api.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-s3-api + labels: + {{- include "garage.labels" . | nindent 4 }} + {{- with .Values.ingress.s3.api.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ingress.s3.api.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.s3.api.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.s3.api.className }} + {{- end }} + {{- if .Values.ingress.s3.api.tls }} + tls: + {{- range .Values.ingress.s3.api.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.s3.api.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +--- +{{- if .Values.ingress.s3.web.enabled -}} +{{- $fullName := include "garage.fullname" . -}} +{{- $svcPort := .Values.service.s3.web.port -}} +{{- if and .Values.ingress.s3.web.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.s3.web.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.s3.web.annotations "kubernetes.io/ingress.class" .Values.ingress.s3.web.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }}-s3-web + labels: + {{- include "garage.labels" . | nindent 4 }} + {{- with .Values.ingress.s3.web.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ingress.s3.web.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.s3.web.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.s3.web.className }} + {{- end }} + {{- if .Values.ingress.s3.web.tls }} + tls: + {{- range .Values.ingress.s3.web.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.s3.web.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/packs/garage-0.9.3/charts/garage/templates/secret.yaml b/packs/garage-0.9.3/charts/garage/templates/secret.yaml new file mode 100644 index 00000000..c0c45b93 --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/templates/secret.yaml @@ -0,0 +1,16 @@ +{{- if not .Values.garage.existingRpcSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "garage.rpcSecretName" . }} + labels: + {{- include "garage.labels" . | nindent 4 }} +type: Opaque +data: + {{/* retrieve the secret data using lookup function and when not exists, return an empty dictionary / map as result */}} + {{- $prevSecret := (lookup "v1" "Secret" .Release.Namespace (include "garage.rpcSecretName" .)) | default dict }} + {{- $prevSecretData := $prevSecret.data | default dict }} + {{- $prevRpcSecret := $prevSecretData.rpcSecret | default "" | b64dec }} + {{/* Priority is: 1. from values, 2. previous value, 3. generate random */}} + rpcSecret: {{ .Values.garage.rpcSecret | default $prevRpcSecret | default (include "jupyterhub.randHex" 64) | b64enc | quote }} +{{- end }} diff --git a/packs/garage-0.9.3/charts/garage/templates/service-headless.yaml b/packs/garage-0.9.3/charts/garage/templates/service-headless.yaml new file mode 100644 index 00000000..c6005cc3 --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/templates/service-headless.yaml @@ -0,0 +1,22 @@ +{{- if eq .Values.deployment.kind "StatefulSet" -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "garage.fullname" . }}-headless + labels: + {{- include "garage.labels" . | nindent 4 }} +spec: + type: ClusterIP + clusterIP: None + ports: + - port: {{ .Values.service.s3.api.port }} + targetPort: {{ include "garage.portFromBindAddr" .Values.garage.s3.api.bindAddr | int }} + protocol: TCP + name: s3-api + - port: {{ .Values.service.s3.web.port }} + targetPort: {{ include "garage.portFromBindAddr" .Values.garage.s3.web.bindAddr | int }} + protocol: TCP + name: s3-web + selector: + {{- include "garage.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/packs/garage-0.9.3/charts/garage/templates/service.yaml b/packs/garage-0.9.3/charts/garage/templates/service.yaml new file mode 100644 index 00000000..cb4bc386 --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/templates/service.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "garage.fullname" . }} + labels: + {{- include "garage.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.s3.api.port }} + targetPort: {{ include "garage.portFromBindAddr" .Values.garage.s3.api.bindAddr | int }} + protocol: TCP + name: s3-api + - port: {{ .Values.service.s3.web.port }} + targetPort: {{ include "garage.portFromBindAddr" .Values.garage.s3.web.bindAddr | int }} + protocol: TCP + name: s3-web + selector: + {{- include "garage.selectorLabels" . | nindent 4 }} +{{- if .Values.monitoring.metrics.enabled }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "garage.fullname" . }}-metrics + labels: + {{- include "garage.labels" . | nindent 4 }} + annotations: + prometheus.io/scrape: "true" +spec: + type: ClusterIP + clusterIP: None + ports: + - port: {{ include "garage.portFromBindAddr" .Values.garage.admin.apiBindAddr | int }} + targetPort: {{ include "garage.portFromBindAddr" .Values.garage.admin.apiBindAddr | int }} + protocol: TCP + name: metrics + selector: + {{- include "garage.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/packs/garage-0.9.3/charts/garage/templates/serviceaccount.yaml b/packs/garage-0.9.3/charts/garage/templates/serviceaccount.yaml new file mode 100644 index 00000000..a0a89a33 --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "garage.serviceAccountName" . }} + labels: + {{- include "garage.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packs/garage-0.9.3/charts/garage/templates/servicemonitor.yaml b/packs/garage-0.9.3/charts/garage/templates/servicemonitor.yaml new file mode 100644 index 00000000..6838d09f --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/templates/servicemonitor.yaml @@ -0,0 +1,44 @@ +{{- if .Values.monitoring.metrics.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "garage.fullname" . }} + {{- if .Values.monitoring.metrics.serviceMonitor.namespace }} + namespace: {{ tpl .Values.monitoring.metrics.serviceMonitor.namespace . }} + {{- else }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "garage.labels" . | nindent 4 }} + {{- with .Values.monitoring.metrics.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: metrics + {{- with .Values.monitoring.metrics.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.monitoring.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + honorLabels: true + path: {{ .Values.monitoring.metrics.serviceMonitor.path }} + scheme: {{ .Values.monitoring.metrics.serviceMonitor.scheme }} + {{- with .Values.monitoring.metrics.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.monitoring.metrics.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 6 }} + {{- end }} + jobLabel: "{{ .Release.Name }}" + selector: + matchLabels: + {{- include "garage.selectorLabels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} +{{- end }} \ No newline at end of file diff --git a/packs/garage-0.9.3/charts/garage/templates/workload.yaml b/packs/garage-0.9.3/charts/garage/templates/workload.yaml new file mode 100644 index 00000000..1283d245 --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/templates/workload.yaml @@ -0,0 +1,154 @@ +apiVersion: apps/v1 +kind: {{ .Values.deployment.kind }} +metadata: + name: {{ include "garage.fullname" . }} + labels: + {{- include "garage.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "garage.selectorLabels" . | nindent 6 }} + {{- if eq .Values.deployment.kind "StatefulSet" }} + replicas: {{ .Values.deployment.replicaCount }} + serviceName: {{ include "garage.fullname" . }}-headless + podManagementPolicy: {{ .Values.deployment.podManagementPolicy }} + {{- end }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "garage.labels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "garage.serviceAccountName" . }} + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + initContainers: + # Copies garage.toml from configmap to temporary etc volume and replaces RPC secret placeholder + - name: {{ .Chart.Name }}-init + image: "{{ .Values.initImage.repository }}:{{ .Values.initImage.tag }}" + imagePullPolicy: {{ .Values.initImage.pullPolicy }} + command: ["sh", "-c", "sed \"s/__RPC_SECRET_REPLACE__/$RPC_SECRET/\" /mnt/garage.toml > /mnt/etc/garage.toml"] + env: + - name: RPC_SECRET + valueFrom: + secretKeyRef: + name: {{ include "garage.rpcSecretName" . }} + key: rpcSecret + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + volumeMounts: + - name: configmap + mountPath: /mnt/garage.toml + subPath: garage.toml + - name: etc + mountPath: /mnt/etc + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - containerPort: {{ include "garage.portFromBindAddr" .Values.garage.s3.api.bindAddr | int }} + name: s3-api + - containerPort: {{ include "garage.portFromBindAddr" .Values.garage.s3.web.bindAddr | int }} + name: web-api + - containerPort: {{ include "garage.portFromBindAddr" .Values.garage.admin.apiBindAddr | int }} + name: admin + {{- with .Values.environment }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: meta + mountPath: /mnt/meta + - name: data + mountPath: /mnt/data + - name: etc + mountPath: /etc/garage.toml + subPath: garage.toml + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: configmap + configMap: + name: {{ if .Values.garage.existingConfigMap }}{{ .Values.garage.existingConfigMap }}{{ else }}{{ include "garage.fullname" . }}-config{{ end }} + - name: etc + emptyDir: {} + {{- if .Values.persistence.enabled }} + {{- if eq .Values.deployment.kind "DaemonSet" }} + - name: meta + hostPath: + path: {{ .Values.persistence.meta.hostPath }} + type: DirectoryOrCreate + - name: data + hostPath: + path: {{ .Values.persistence.data.hostPath }} + type: DirectoryOrCreate + {{- end }} + {{- else }} + - name: meta + emptyDir: {} + - name: data + emptyDir: {} + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if and .Values.persistence.enabled (eq .Values.deployment.kind "StatefulSet") }} + volumeClaimTemplates: + - metadata: + name: meta + spec: + accessModes: [ "ReadWriteOnce" ] + {{- if hasKey .Values.persistence.meta "storageClass" }} + storageClassName: {{ .Values.persistence.meta.storageClass | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.meta.size | quote }} + - metadata: + name: data + spec: + accessModes: [ "ReadWriteOnce" ] + {{- if hasKey .Values.persistence.data "storageClass" }} + storageClassName: {{ .Values.persistence.data.storageClass | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.data.size | quote }} + {{- end }} diff --git a/packs/garage-0.9.3/charts/garage/values.yaml b/packs/garage-0.9.3/charts/garage/values.yaml new file mode 100644 index 00000000..a74faf3f --- /dev/null +++ b/packs/garage-0.9.3/charts/garage/values.yaml @@ -0,0 +1,273 @@ +# Default values for garage. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# -- Additional labels to add to all resources created by this chart +commonLabels: {} +# app.kubernetes.io/part-of: storage +# team: platform + +# Garage configuration. These values go to garage.toml +garage: + # -- Can be changed for better performance on certain systems + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#db_engine + dbEngine: "lmdb" + + # -- Defaults is 1MB + # An increase can result in better performance in certain scenarios + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#block_size + blockSize: "1048576" + + # -- Default to 3 replicas, see the replication_factor section at + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#replication_factor + replicationFactor: "3" + + # -- By default, enable read-after-write consistency guarantees, see the consistency_mode section at + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#consistency_mode + consistencyMode: "consistent" + + # -- zstd compression level of stored blocks + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#compression_level + compressionLevel: "1" + + # -- If this value is set, Garage will automatically take a snapshot of the metadata DB file at a regular interval and save it in the metadata directory. + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#metadata_auto_snapshot_interval + metadataAutoSnapshotInterval: "" + + rpcBindAddr: "[::]:3901" + # -- If not given, a random secret will be generated and stored in a Secret object + rpcSecret: "" + # -- If you want to provide an rpcSecret within an existing k8s secret, + # specify the secret name here, and store the value under the secret key `rpcSecret` + # the default secret will not be created + existingRpcSecret: "" + # -- This is not required if you use the integrated kubernetes discovery + bootstrapPeers: [] + # -- Set to true if you want to use k8s discovery but install the CRDs manually outside + # of the helm chart, for example if you operate at namespace level without cluster resources + kubernetesSkipCrd: false + s3: + api: + bindAddr: "[::]:3900" + region: "garage" + rootDomain: ".s3.garage.tld" + web: + bindAddr: "[::]:3902" + rootDomain: ".web.garage.tld" + index: "index.html" + admin: + apiBindAddr: "[::]:3903" + + # -- Additional configuration to append to garage.toml. Use a multi-line string for custom config. + # Example: + # additionalTopLevelConfig: |- + # data_fsync = true + additionalTopLevelConfig: "" + + # -- if not empty string, allow using an existing ConfigMap for the garage.toml, + # if set, ignores garage.toml + existingConfigMap: "" + + # -- String Template for the garage configuration + # if set, ignores above values. + # Values can be templated, + # see https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/ + garageTomlString: "" + +# Data persistence +persistence: + enabled: true + meta: + # storageClass: "fast-storage-class" + size: 100Mi + # used only for daemon sets + hostPath: /var/lib/garage/meta + data: + # storageClass: "slow-storage-class" + size: 100Mi + # used only for daemon sets + hostPath: /var/lib/garage/data + +# Deployment configuration +deployment: + # -- Switchable to DaemonSet + kind: StatefulSet + # -- Number of StatefulSet replicas/garage nodes to start + replicaCount: 3 + # -- If using statefulset, allow Parallel or OrderedReady (default) + podManagementPolicy: OrderedReady + +image: + # -- default to amd64 docker image + repository: dxflrs/amd64_garage + # -- set the image tag, please prefer using the chart version and not this + # to avoid compatibility issues + tag: "" + pullPolicy: IfNotPresent + +initImage: + repository: busybox + tag: stable + pullPolicy: IfNotPresent + +# -- set if you need credentials to pull your custom image +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +# -- additional pod annotations +podAnnotations: {} + +podSecurityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + fsGroupChangePolicy: "OnRootMismatch" + runAsNonRoot: true + +securityContext: + # -- The default security context is heavily restricted, + # feel free to tune it to your requirements + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + +service: + # -- You can rely on any service to expose your cluster + # - ClusterIP (+ Ingress) + # - NodePort (+ Ingress) + # - LoadBalancer + type: ClusterIP + # -- Annotations to add to the service + annotations: {} + s3: + api: + port: 3900 + web: + port: 3902 + # NOTE: the admin API is excluded for now as it is not consistent across nodes + +ingress: + s3: + api: + enabled: false + # -- Rely _either_ on the className or the annotation below but not both! + # If you want to use the className, set + # className: "nginx" + # and replace "nginx" by an Ingress controller name, + # examples [here](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers). + annotations: {} + # kubernetes.io/ingress.class: "nginx" + # kubernetes.io/tls-acme: "true" + labels: {} + hosts: + # -- garage S3 API endpoint, to be used with awscli for example + - host: "s3.garage.tld" + paths: + - path: / + pathType: Prefix + # -- garage S3 API endpoint, DNS style bucket access + - host: "*.s3.garage.tld" + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: my-garage-cluster-tls + # hosts: + # - kubernetes.docker.internal + web: + enabled: false + # -- Rely _either_ on the className or the annotation below but not both! + # If you want to use the className, set + # className: "nginx" + # and replace "nginx" by an Ingress controller name, + # examples [here](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers). + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + hosts: + # -- wildcard website access with bucket name prefix + - host: "*.web.garage.tld" + paths: + - path: / + pathType: Prefix + # -- specific bucket access with FQDN bucket + - host: "mywebpage.example.com" + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: my-garage-cluster-tls + # hosts: + # - kubernetes.docker.internal + +resources: {} + # The following are indicative for a small-size deployment, for anything serious double them. + # limits: + # cpu: 100m + # memory: 1024Mi + # requests: + # cpu: 100m + # memory: 512Mi + +# -- Specifies a livenessProbe +livenessProbe: {} + #httpGet: + # path: /health + # port: 3903 # or the port from garage.admin.apiBindAddr + #initialDelaySeconds: 5 + #periodSeconds: 30 +# -- Specifies a readinessProbe +readinessProbe: {} + #httpGet: + # path: /health + # port: 3903 # or the port from garage.admin.apiBindAddr + #initialDelaySeconds: 5 + #periodSeconds: 30 + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +# -- Optional priority class name to assign to the pods. +# See https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ +priorityClassName: "" + +environment: {} + +extraVolumes: {} + +extraVolumeMounts: {} + +monitoring: + metrics: + # -- If true, a service for monitoring is created with a prometheus.io/scrape annotation + enabled: false + serviceMonitor: + # -- If true, a ServiceMonitor CRD is created for a prometheus operator + # https://github.com/coreos/prometheus-operator + enabled: false + path: /metrics + # namespace: monitoring (defaults to use the namespace this chart is deployed to) + labels: {} + interval: 15s + scheme: http + tlsConfig: {} + scrapeTimeout: 10s + relabelings: [] + tracing: + # -- specify a sink endpoint for OpenTelemetry Traces, eg. `http://localhost:4317` + sink: "" diff --git a/packs/garage-0.9.3/logo.png b/packs/garage-0.9.3/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2519e21913d3e85d2c7b41039968b38ebfe3bc4c GIT binary patch literal 11871 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 RusQsLq^O)orI3EW{{x4RSSJ7g literal 0 HcmV?d00001 diff --git a/packs/garage-0.9.3/pack.json b/packs/garage-0.9.3/pack.json new file mode 100644 index 00000000..84d2fef4 --- /dev/null +++ b/packs/garage-0.9.3/pack.json @@ -0,0 +1,17 @@ +{ + "addonType": "system app", + "annotations": { + "source": "community", + "contributor" : "spectrocloud" + }, + "cloudTypes": [ + "all" + ], + "displayName": "garage", + "charts": [ + "charts/garage-0.9.3.tgz" + ], + "layer":"addon", + "name": "garage", + "version": "0.9.3" + } \ No newline at end of file diff --git a/packs/garage-0.9.3/values.yaml b/packs/garage-0.9.3/values.yaml new file mode 100644 index 00000000..4a408e2a --- /dev/null +++ b/packs/garage-0.9.3/values.yaml @@ -0,0 +1,281 @@ +pack: + spectrocloud.com/display-name: garage + releaseNameOverride: + garage: garage + namespace: garage + +charts: + garage: + # Default values for garage. + # This is a YAML-formatted file. + # Declare variables to be passed into your templates. + + # -- Additional labels to add to all resources created by this chart + commonLabels: {} + # app.kubernetes.io/part-of: storage + # team: platform + + # Garage configuration. These values go to garage.toml + garage: + # -- Can be changed for better performance on certain systems + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#db_engine + dbEngine: "lmdb" + + # -- Defaults is 1MB + # An increase can result in better performance in certain scenarios + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#block_size + blockSize: "1048576" + + # -- Default to 3 replicas, see the replication_factor section at + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#replication_factor + replicationFactor: "3" + + # -- By default, enable read-after-write consistency guarantees, see the consistency_mode section at + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#consistency_mode + consistencyMode: "consistent" + + # -- zstd compression level of stored blocks + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#compression_level + compressionLevel: "1" + + # -- If this value is set, Garage will automatically take a snapshot of the metadata DB file at a regular interval and save it in the metadata directory. + # https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#metadata_auto_snapshot_interval + metadataAutoSnapshotInterval: "" + + rpcBindAddr: "[::]:3901" + # -- If not given, a random secret will be generated and stored in a Secret object + rpcSecret: "" + # -- If you want to provide an rpcSecret within an existing k8s secret, + # specify the secret name here, and store the value under the secret key `rpcSecret` + # the default secret will not be created + existingRpcSecret: "" + # -- This is not required if you use the integrated kubernetes discovery + bootstrapPeers: [] + # -- Set to true if you want to use k8s discovery but install the CRDs manually outside + # of the helm chart, for example if you operate at namespace level without cluster resources + kubernetesSkipCrd: false + s3: + api: + bindAddr: "[::]:3900" + region: "garage" + rootDomain: ".s3.garage.tld" + web: + bindAddr: "[::]:3902" + rootDomain: ".web.garage.tld" + index: "index.html" + admin: + apiBindAddr: "[::]:3903" + + # -- Additional configuration to append to garage.toml. Use a multi-line string for custom config. + # Example: + # additionalTopLevelConfig: |- + # data_fsync = true + additionalTopLevelConfig: "" + + # -- if not empty string, allow using an existing ConfigMap for the garage.toml, + # if set, ignores garage.toml + existingConfigMap: "" + + # -- String Template for the garage configuration + # if set, ignores above values. + # Values can be templated, + # see https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/ + garageTomlString: "" + + # Data persistence + persistence: + enabled: true + meta: + # storageClass: "fast-storage-class" + size: 100Mi + # used only for daemon sets + hostPath: /var/lib/garage/meta + data: + # storageClass: "slow-storage-class" + size: 100Mi + # used only for daemon sets + hostPath: /var/lib/garage/data + + # Deployment configuration + deployment: + # -- Switchable to DaemonSet + kind: StatefulSet + # -- Number of StatefulSet replicas/garage nodes to start + replicaCount: 3 + # -- If using statefulset, allow Parallel or OrderedReady (default) + podManagementPolicy: OrderedReady + + image: + # -- default to amd64 docker image + repository: dxflrs/amd64_garage + # -- set the image tag, please prefer using the chart version and not this + # to avoid compatibility issues + tag: "" + pullPolicy: IfNotPresent + + initImage: + repository: busybox + tag: stable + pullPolicy: IfNotPresent + + # -- set if you need credentials to pull your custom image + imagePullSecrets: [] + nameOverride: "" + fullnameOverride: "" + + serviceAccount: + # -- Specifies whether a service account should be created + create: true + # -- Annotations to add to the service account + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + + # -- additional pod annotations + podAnnotations: {} + + podSecurityContext: + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + fsGroupChangePolicy: "OnRootMismatch" + runAsNonRoot: true + + securityContext: + # -- The default security context is heavily restricted, + # feel free to tune it to your requirements + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + + service: + # -- You can rely on any service to expose your cluster + # - ClusterIP (+ Ingress) + # - NodePort (+ Ingress) + # - LoadBalancer + type: ClusterIP + # -- Annotations to add to the service + annotations: {} + s3: + api: + port: 3900 + web: + port: 3902 + # NOTE: the admin API is excluded for now as it is not consistent across nodes + + ingress: + s3: + api: + enabled: false + # -- Rely _either_ on the className or the annotation below but not both! + # If you want to use the className, set + # className: "nginx" + # and replace "nginx" by an Ingress controller name, + # examples [here](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers). + annotations: {} + # kubernetes.io/ingress.class: "nginx" + # kubernetes.io/tls-acme: "true" + labels: {} + hosts: + # -- garage S3 API endpoint, to be used with awscli for example + - host: "s3.garage.tld" + paths: + - path: / + pathType: Prefix + # -- garage S3 API endpoint, DNS style bucket access + - host: "*.s3.garage.tld" + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: my-garage-cluster-tls + # hosts: + # - kubernetes.docker.internal + web: + enabled: false + # -- Rely _either_ on the className or the annotation below but not both! + # If you want to use the className, set + # className: "nginx" + # and replace "nginx" by an Ingress controller name, + # examples [here](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers). + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + hosts: + # -- wildcard website access with bucket name prefix + - host: "*.web.garage.tld" + paths: + - path: / + pathType: Prefix + # -- specific bucket access with FQDN bucket + - host: "mywebpage.example.com" + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: my-garage-cluster-tls + # hosts: + # - kubernetes.docker.internal + + resources: {} + # The following are indicative for a small-size deployment, for anything serious double them. + # limits: + # cpu: 100m + # memory: 1024Mi + # requests: + # cpu: 100m + # memory: 512Mi + + # -- Specifies a livenessProbe + livenessProbe: {} + #httpGet: + # path: /health + # port: 3903 # or the port from garage.admin.apiBindAddr + #initialDelaySeconds: 5 + #periodSeconds: 30 + # -- Specifies a readinessProbe + readinessProbe: {} + #httpGet: + # path: /health + # port: 3903 # or the port from garage.admin.apiBindAddr + #initialDelaySeconds: 5 + #periodSeconds: 30 + + nodeSelector: {} + + tolerations: [] + + affinity: {} + + # -- Optional priority class name to assign to the pods. + # See https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ + priorityClassName: "" + + environment: {} + + extraVolumes: {} + + extraVolumeMounts: {} + + monitoring: + metrics: + # -- If true, a service for monitoring is created with a prometheus.io/scrape annotation + enabled: false + serviceMonitor: + # -- If true, a ServiceMonitor CRD is created for a prometheus operator + # https://github.com/coreos/prometheus-operator + enabled: false + path: /metrics + # namespace: monitoring (defaults to use the namespace this chart is deployed to) + labels: {} + interval: 15s + scheme: http + tlsConfig: {} + scrapeTimeout: 10s + relabelings: [] + tracing: + # -- specify a sink endpoint for OpenTelemetry Traces, eg. `http://localhost:4317` + sink: ""