mirror of
https://github.com/shadoll/helm-charts.git
synced 2026-10-12 21:59:18 +00:00
Add garage helm chart wrapper
S3-compatible object store (dxflrs/garage), single-node by default with hostPath/PVC persistence, existingSecret for rpc/admin/metrics tokens, and a postStart hook that bootstraps the single-node layout automatically. Tracks upstream via dockerhub-tags-pattern for scripts/update-charts.sh. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014ZA4cJygj4VPCYVms4TDrH
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
apiVersion: v2
|
||||
name: garage
|
||||
description: A Helm chart for Garage, a lightweight S3-compatible object store
|
||||
type: application
|
||||
annotations:
|
||||
version-source: dockerhub-tags-pattern:dxflrs/garage:^v[0-9]+\.[0-9]+\.[0-9]+$
|
||||
version: 0.1.0
|
||||
appVersion: "v2.4.1"
|
||||
@@ -0,0 +1,16 @@
|
||||
Garage {{ .Chart.AppVersion }} has been deployed.
|
||||
|
||||
S3 API: http://{{ include "garage.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.s3ApiPort }}
|
||||
Admin API: http://{{ include "garage.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.adminPort }}
|
||||
{{- if .Values.garage.web.enabled }}
|
||||
Web: http://{{ include "garage.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.s3WebPort }}
|
||||
{{- end }}
|
||||
|
||||
On first install, the pod's postStart hook assigns and applies a single-node
|
||||
layout automatically. Check with:
|
||||
kubectl -n {{ .Release.Namespace }} exec deploy/{{ include "garage.fullname" . }} -- /garage status
|
||||
|
||||
Create a bucket and access key with:
|
||||
kubectl -n {{ .Release.Namespace }} exec deploy/{{ include "garage.fullname" . }} -- /garage bucket create my-bucket
|
||||
kubectl -n {{ .Release.Namespace }} exec deploy/{{ include "garage.fullname" . }} -- /garage key create my-key
|
||||
kubectl -n {{ .Release.Namespace }} exec deploy/{{ include "garage.fullname" . }} -- /garage bucket allow --read --write --key my-key my-bucket
|
||||
@@ -0,0 +1,34 @@
|
||||
{{- define "garage.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{- 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 }}
|
||||
|
||||
{{- define "garage.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{- 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 }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "garage.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "garage.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,41 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "garage.fullname" . }}
|
||||
labels:
|
||||
{{- include "garage.labels" . | nindent 4 }}
|
||||
data:
|
||||
garage.toml: |
|
||||
metadata_dir = "/var/lib/garage/meta"
|
||||
data_dir = "/var/lib/garage/data"
|
||||
db_engine = {{ .Values.garage.dbEngine | quote }}
|
||||
|
||||
replication_factor = {{ .Values.garage.replicationFactor }}
|
||||
consistency_mode = {{ .Values.garage.consistencyMode | quote }}
|
||||
|
||||
rpc_bind_addr = {{ .Values.garage.rpcBindAddr | quote }}
|
||||
{{- if .Values.garage.rpcPublicAddr }}
|
||||
rpc_public_addr = {{ .Values.garage.rpcPublicAddr | quote }}
|
||||
{{- end }}
|
||||
rpc_secret_file = "/etc/garage/secrets/rpc-secret"
|
||||
|
||||
[s3_api]
|
||||
s3_region = {{ .Values.garage.s3.region | quote }}
|
||||
api_bind_addr = "[::]:{{ .Values.service.s3ApiPort }}"
|
||||
{{- if .Values.garage.s3.rootDomain }}
|
||||
root_domain = {{ .Values.garage.s3.rootDomain | quote }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.garage.web.enabled }}
|
||||
[s3_web]
|
||||
bind_addr = "[::]:{{ .Values.service.s3WebPort }}"
|
||||
{{- if .Values.garage.web.rootDomain }}
|
||||
root_domain = {{ .Values.garage.web.rootDomain | quote }}
|
||||
{{- end }}
|
||||
index = {{ .Values.garage.web.index | quote }}
|
||||
{{- end }}
|
||||
|
||||
[admin]
|
||||
api_bind_addr = "[::]:{{ .Values.service.adminPort }}"
|
||||
admin_token_file = "/etc/garage/secrets/admin-token"
|
||||
metrics_token_file = "/etc/garage/secrets/metrics-token"
|
||||
@@ -0,0 +1,139 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "garage.fullname" . }}
|
||||
labels:
|
||||
{{- include "garage.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "garage.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "garage.selectorLabels" . | nindent 8 }}
|
||||
annotations:
|
||||
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
|
||||
spec:
|
||||
containers:
|
||||
- name: garage
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
args:
|
||||
- server
|
||||
env:
|
||||
- name: RUST_LOG
|
||||
value: garage=info
|
||||
ports:
|
||||
- name: s3-api
|
||||
containerPort: {{ .Values.service.s3ApiPort }}
|
||||
- name: rpc
|
||||
containerPort: {{ .Values.service.rpcPort }}
|
||||
{{- if .Values.garage.web.enabled }}
|
||||
- name: s3-web
|
||||
containerPort: {{ .Values.service.s3WebPort }}
|
||||
{{- end }}
|
||||
- name: admin
|
||||
containerPort: {{ .Values.service.adminPort }}
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/garage.toml
|
||||
subPath: garage.toml
|
||||
- name: secrets
|
||||
mountPath: /etc/garage/secrets
|
||||
readOnly: true
|
||||
- name: data
|
||||
mountPath: /var/lib/garage/data
|
||||
- name: meta
|
||||
mountPath: /var/lib/garage/meta
|
||||
{{- if .Values.layoutJob.enabled }}
|
||||
lifecycle:
|
||||
postStart:
|
||||
exec:
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
NODE_ID=""
|
||||
for i in $(seq 1 60); do
|
||||
NODE_ID=$(/garage node id -q 2>/dev/null | cut -d@ -f1)
|
||||
[ -n "$NODE_ID" ] && break
|
||||
sleep 2
|
||||
done
|
||||
[ -z "$NODE_ID" ] && exit 0
|
||||
if /garage layout show 2>/dev/null | grep -q "$NODE_ID"; then
|
||||
exit 0
|
||||
fi
|
||||
/garage layout assign -z {{ .Values.garage.zone }} -c {{ .Values.garage.capacity }} "$NODE_ID"
|
||||
VERSION=$(/garage layout show 2>/dev/null | grep -o 'version [0-9]*' | tail -1 | awk '{print $2+1}')
|
||||
/garage layout apply --version "${VERSION:-1}" || true
|
||||
{{- end }}
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: s3-api
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: s3-api
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: {{ include "garage.fullname" . }}
|
||||
- name: secrets
|
||||
secret:
|
||||
secretName: {{ .Values.existingSecret }}
|
||||
items:
|
||||
- key: {{ .Values.secretKeys.rpcSecret }}
|
||||
path: rpc-secret
|
||||
- key: {{ .Values.secretKeys.adminToken }}
|
||||
path: admin-token
|
||||
- key: {{ .Values.secretKeys.metricsToken }}
|
||||
path: metrics-token
|
||||
- name: data
|
||||
{{- if .Values.persistence.data.enabled }}
|
||||
{{- if eq .Values.persistence.data.type "hostPath" }}
|
||||
hostPath:
|
||||
path: {{ .Values.persistence.data.hostPath }}
|
||||
type: DirectoryOrCreate
|
||||
{{- else }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .Values.persistence.data.existingClaim | default (printf "%s-data" (include "garage.fullname" .)) }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
- name: meta
|
||||
{{- if .Values.persistence.meta.enabled }}
|
||||
{{- if eq .Values.persistence.meta.type "hostPath" }}
|
||||
hostPath:
|
||||
path: {{ .Values.persistence.meta.hostPath }}
|
||||
type: DirectoryOrCreate
|
||||
{{- else }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .Values.persistence.meta.existingClaim | default (printf "%s-meta" (include "garage.fullname" .)) }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
emptyDir: {}
|
||||
{{- 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 }}
|
||||
@@ -0,0 +1,50 @@
|
||||
{{- $fullName := include "garage.fullname" . -}}
|
||||
{{- $labels := include "garage.labels" . -}}
|
||||
{{- $kubeVersion := .Capabilities.KubeVersion.GitVersion -}}
|
||||
{{- range $key, $port := (dict "s3" .Values.service.s3ApiPort "web" .Values.service.s3WebPort "admin" .Values.service.adminPort) }}
|
||||
{{- $ing := index $.Values.ingress $key }}
|
||||
{{- if $ing.enabled }}
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}-{{ $key }}
|
||||
labels:
|
||||
{{- $labels | nindent 4 }}
|
||||
{{- with $ing.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if $ing.className }}
|
||||
ingressClassName: {{ $ing.className }}
|
||||
{{- end }}
|
||||
{{- if $ing.tls }}
|
||||
tls:
|
||||
{{- range $ing.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range $ing.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- if and .pathType (semverCompare ">=1.18-0" $kubeVersion) }}
|
||||
pathType: {{ .pathType }}
|
||||
{{- end }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $port }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,47 @@
|
||||
{{- if .Values.persistence.data.enabled }}
|
||||
{{- if eq .Values.persistence.data.type "pvc" }}
|
||||
{{- if not .Values.persistence.data.existingClaim }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "garage.fullname" . }}-data
|
||||
labels:
|
||||
{{- include "garage.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
accessModes:
|
||||
{{- toYaml .Values.persistence.data.accessModes | nindent 4 }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.persistence.data.size | quote }}
|
||||
{{- if .Values.persistence.data.storageClass }}
|
||||
storageClassName: {{ .Values.persistence.data.storageClass | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
---
|
||||
{{- if .Values.persistence.meta.enabled }}
|
||||
{{- if eq .Values.persistence.meta.type "pvc" }}
|
||||
{{- if not .Values.persistence.meta.existingClaim }}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: {{ include "garage.fullname" . }}-meta
|
||||
labels:
|
||||
{{- include "garage.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
accessModes:
|
||||
{{- toYaml .Values.persistence.meta.accessModes | nindent 4 }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.persistence.meta.size | quote }}
|
||||
{{- if .Values.persistence.meta.storageClass }}
|
||||
storageClassName: {{ .Values.persistence.meta.storageClass | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,29 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "garage.fullname" . }}
|
||||
labels:
|
||||
{{- include "garage.labels" . | nindent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
selector:
|
||||
{{- include "garage.selectorLabels" . | nindent 4 }}
|
||||
ports:
|
||||
- name: s3-api
|
||||
port: {{ .Values.service.s3ApiPort }}
|
||||
targetPort: s3-api
|
||||
protocol: TCP
|
||||
- name: rpc
|
||||
port: {{ .Values.service.rpcPort }}
|
||||
targetPort: rpc
|
||||
protocol: TCP
|
||||
{{- if .Values.garage.web.enabled }}
|
||||
- name: s3-web
|
||||
port: {{ .Values.service.s3WebPort }}
|
||||
targetPort: s3-web
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
- name: admin
|
||||
port: {{ .Values.service.adminPort }}
|
||||
targetPort: admin
|
||||
protocol: TCP
|
||||
@@ -0,0 +1,109 @@
|
||||
# Default values for garage.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: dxflrs/garage
|
||||
pullPolicy: IfNotPresent
|
||||
# Overrides the image tag whose default is the chart appVersion.
|
||||
tag: ""
|
||||
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
garage:
|
||||
replicationFactor: 1
|
||||
consistencyMode: consistent
|
||||
dbEngine: sqlite
|
||||
# Zone/capacity used by the layout job to bootstrap a single-node cluster.
|
||||
zone: dc1
|
||||
capacity: 100G
|
||||
rpcBindAddr: "[::]:3901"
|
||||
# Address other nodes would use to reach this one. Not needed for a
|
||||
# single-node (replicationFactor: 1) deployment - leave empty.
|
||||
rpcPublicAddr: ""
|
||||
s3:
|
||||
region: garage
|
||||
rootDomain: ""
|
||||
web:
|
||||
enabled: false
|
||||
rootDomain: ""
|
||||
index: index.html
|
||||
|
||||
# Secret must contain the keys named below (rpc-secret, admin-token,
|
||||
# metrics-token). Charts never create secrets - provide an existingSecret.
|
||||
existingSecret: ""
|
||||
secretKeys:
|
||||
rpcSecret: rpc-secret
|
||||
adminToken: admin-token
|
||||
metricsToken: metrics-token
|
||||
|
||||
persistence:
|
||||
data:
|
||||
enabled: true
|
||||
type: hostPath # or pvc
|
||||
hostPath: /srv/data/garage/data
|
||||
existingClaim: ""
|
||||
size: 50Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClass: ""
|
||||
meta:
|
||||
enabled: true
|
||||
type: hostPath # or pvc
|
||||
hostPath: /srv/data/garage/meta
|
||||
existingClaim: ""
|
||||
size: 5Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClass: ""
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
s3ApiPort: 3900
|
||||
rpcPort: 3901
|
||||
s3WebPort: 3902
|
||||
adminPort: 3903
|
||||
|
||||
ingress:
|
||||
s3:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
hosts:
|
||||
- host: s3.garage.lan
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
tls: []
|
||||
web:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
hosts: []
|
||||
tls: []
|
||||
admin:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
hosts: []
|
||||
tls: []
|
||||
|
||||
# One-shot Helm hook Job that assigns and applies a single-node layout on
|
||||
# first install. Safe to re-run; it exits early once a layout already exists.
|
||||
layoutJob:
|
||||
enabled: true
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 512Mi
|
||||
|
||||
nodeSelector: {}
|
||||
affinity: {}
|
||||
tolerations: []
|
||||
Reference in New Issue
Block a user