From af1a99c4dc6f7d0f2d9e748b17fd0489342ce170 Mon Sep 17 00:00:00 2001 From: Jack Henschel Date: Wed, 4 Mar 2026 08:28:29 +0100 Subject: [PATCH] feat: add Helm chart for versitygw --- .github/workflows/helm-chart.yml | 33 ++++ README.md | 10 ++ chart/.helmignore | 23 +++ chart/Chart.yaml | 15 ++ chart/README.md | 60 +++++++ chart/templates/_helpers.tpl | 96 +++++++++++ chart/templates/certificate.yaml | 19 +++ chart/templates/deployment.yaml | 211 +++++++++++++++++++++++ chart/templates/ingress.yaml | 35 ++++ chart/templates/networkpolicy.yaml | 24 +++ chart/templates/pvc.yaml | 17 ++ chart/templates/secret.yaml | 12 ++ chart/templates/service.yaml | 27 +++ chart/templates/serviceaccount.yaml | 12 ++ chart/values.yaml | 253 ++++++++++++++++++++++++++++ 15 files changed, 847 insertions(+) create mode 100644 .github/workflows/helm-chart.yml create mode 100644 chart/.helmignore create mode 100644 chart/Chart.yaml create mode 100644 chart/README.md create mode 100644 chart/templates/_helpers.tpl create mode 100644 chart/templates/certificate.yaml create mode 100644 chart/templates/deployment.yaml create mode 100644 chart/templates/ingress.yaml create mode 100644 chart/templates/networkpolicy.yaml create mode 100644 chart/templates/pvc.yaml create mode 100644 chart/templates/secret.yaml create mode 100644 chart/templates/service.yaml create mode 100644 chart/templates/serviceaccount.yaml create mode 100644 chart/values.yaml diff --git a/.github/workflows/helm-chart.yml b/.github/workflows/helm-chart.yml new file mode 100644 index 00000000..ecac0feb --- /dev/null +++ b/.github/workflows/helm-chart.yml @@ -0,0 +1,33 @@ +name: Release Helm Chart + +on: + push: + branches: + - main + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + packages: write + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + # https://github.com/marketplace/actions/helm-oci-charts-releaser + - name: Run chart-releaser + uses: bitdeps/helm-oci-charts-releaser@v0.1.5 + with: + oci_registry: ghcr.io/versity/versitygw/charts + oci_username: versity + oci_password: ${{ secrets.GITHUB_TOKEN }} + github_token: ${{ secrets.GITHUB_TOKEN }} + charts_dir: "." diff --git a/README.md b/README.md index f346a361..a38b8ed7 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,16 @@ docker run --rm versity/versitygw:latest --version See [Docker](https://github.com/versity/versitygw/wiki/Docker) for more documentation for running within Docker. +### Run on Kubernetes + +A Helm chart is provided to easily run Versity in Kubernetes environments: + +```sh +helm install versitygw oci://ghcr.io/versity/versitygw/charts/versity:latest +``` + +Please refer to the [chart's README](./chart/README.md) for more information and configuration parameters. + *** #### Versity gives you clarity and control over your archival storage, so you can allocate more resources to your core mission. diff --git a/chart/.helmignore b/chart/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/chart/.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/chart/Chart.yaml b/chart/Chart.yaml new file mode 100644 index 00000000..99efa99b --- /dev/null +++ b/chart/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +name: versitygw +description: A Helm chart for deploying the Versity S3 Gateway on Kubernetes +type: application +version: 0.1.0 +sources: + - https://github.com/versity/versitygw +icon: https://raw.githubusercontent.com/versity/versitygw/main/webui/web/assets/images/Versity-logo-blue-horizontal.png +keywords: + - s3 + - gateway + - object-storage + - posix + - s3-compatible + - versity diff --git a/chart/README.md b/chart/README.md new file mode 100644 index 00000000..5810a0d4 --- /dev/null +++ b/chart/README.md @@ -0,0 +1,60 @@ +# versitygw Helm Chart + +Versity is an S3-compatible storage gateway that proxies S3 API requests to a variety of backend storage systems. + +## Overview + +[versitygw](https://github.com/versity/versitygw) is an S3-compatible gateway that fronts POSIX filesystems, ScoutFS, S3, Azure Blob Storage, or custom plugin backends. This chart deploys versitygw on Kubernetes as a Deployment and Service, with optional support for TLS termination, Ingress, certificate provisioning (via `cert-manager` CRDs), IAM, an Admin API, a browser-based WebUI, persistent storage, and NetworkPolicy. + +## Prerequisites + +- Kubernetes **1.19+** +- Helm **3.8+** (OCI registry support) +- optional: [cert-manager](https://cert-manager.io/) (only required if `certificate.create=true`) + +## Installation + +Basic installation (single user mode) with [posix backend](https://github.com/versity/versitygw/wiki/POSIX-Backend): + +```bash +helm install my-versitygw oci://ghcr.io/versity/versitygw/charts/versitygw \ + --set auth.accessKey=myaccesskey \ + --set auth.secretKey=mysecretkey \ + --set gateway.backend.type=posix \ + --set persistence.enabled=true +``` + +> **Production note:** Passing credentials via `--set` stores them in Helm's release history. For production deployments, create a Kubernetes Secret in advance and reference it with `auth.existingSecret=`. The Secret must contain the keys `rootAccessKeyId` and `rootSecretAccessKey`. + +## Backend Storage + +The `gateway.backend.type` value selects the storage backend. Use `gateway.backend.args` to pass backend-specific arguments. + +| Backend | Description | Example `gateway.backend.args` | +|---------|-------------|-------------------------------| +| `posix` | POSIX-compatible local or network filesystem (default) | `/mnt/data` | +| `scoutfs` | [ScoutFS](https://scoutfs.org/) high-performance filesystem | `/mnt/scoutfs` | +| `s3` | Proxy to an existing S3-compatible object store | `--access KEY --secret SECRET --endpoint https://s3.example.com` | +| `azure` | Azure Blob Storage | `--account myaccount --key mykey` | +| `plugin` | Custom backend via shared library plugin | `/path/to/plugin.so` | + +## Optional Features + +| Feature | Key values | +|---------|-----------| +| **TLS** | `tls.enabled=true` — serve HTTPS; supply a TLS Secret via `certificate.secretName` or let cert-manager provision one | +| **cert-manager** | `certificate.create=true`, `certificate.issuerRef`, `certificate.dnsNames` | +| **Ingress** | `ingress.enabled=true`, `ingress.className`, `ingress.hosts`, `ingress.tls` | +| **Admin API** | `admin.enabled=true` — exposes a separate management API on `admin.port` (default `7071`) | +| **WebUI** | `webui.enabled=true` — browser-based management UI on `webui.port` (default `8080`); set `webui.apiGateways` and `webui.adminGateways` to your externally reachable endpoints | +| **IAM** | `iam.enabled=true` — flat-file identity and access management stored alongside backend data | +| **Persistence** | `persistence.enabled=true` — provisions a PVC for backend data and IAM storage; defaults to `10Gi` | +| **NetworkPolicy** | `networkPolicy.enabled=true` — restricts ingress to selected pods/namespaces; allows all egress | + +## Multi-Replica Deployments + +When setting `replicaCount` greater than 1, the underlying storage must support concurrent access. Set `persistence.accessMode=ReadWriteMany` and use a storage class that supports it (e.g. NFS, CephFS, or a cloud-managed `RWX` provisioner). + +## Configuration + +See [`values.yaml`](./values.yaml) for the full list of parameters and their defaults. diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl new file mode 100644 index 00000000..fd23a2c1 --- /dev/null +++ b/chart/templates/_helpers.tpl @@ -0,0 +1,96 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "versitygw.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 "versitygw.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 chart name and version as used by the chart label. +*/}} +{{- define "versitygw.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "versitygw.labels" -}} +helm.sh/chart: {{ include "versitygw.chart" . }} +{{ include "versitygw.selectorLabels" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +These are the stable labels used in Service selectors and Deployment matchLabels. +They intentionally exclude helm.sh/chart (which includes the version) to prevent +broken selectors during helm upgrades. +*/}} +{{- define "versitygw.selectorLabels" -}} +app.kubernetes.io/name: {{ include "versitygw.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "versitygw.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "versitygw.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +The name of the Secret holding the root S3 credentials. +Uses auth.existingSecret if set, otherwise derives a name from the release fullname. +*/}} +{{- define "versitygw.credentialsSecretName" -}} +{{- if .Values.auth.existingSecret }} +{{- printf "%s" .Values.auth.existingSecret }} +{{- else }} +{{- printf "%s-credentials" (include "versitygw.fullname" .) }} +{{- end }} +{{- end }} + +{{/* +The name of the PVC to use for persistence. +Returns empty string if persistence is disabled. +*/}} +{{- define "versitygw.pvcName" -}} +{{- if .Values.persistence.enabled }} +{{- default (printf "%s-data" (include "versitygw.fullname" .)) .Values.persistence.claimName }} +{{- end }} +{{- end }} + +{{/* +The name of the TLS Secret used for HTTPS. +Uses certificate.secretName if set, otherwise derives a name from the release fullname. +*/}} +{{- define "versitygw.certificateSecretName" -}} +{{- if .Values.certificate.secretName }} +{{- printf "%s" .Values.certificate.secretName }} +{{- else }} +{{- printf "%s-cert" (include "versitygw.fullname" .) }} +{{- end }} +{{- end }} diff --git a/chart/templates/certificate.yaml b/chart/templates/certificate.yaml new file mode 100644 index 00000000..b51f3ee2 --- /dev/null +++ b/chart/templates/certificate.yaml @@ -0,0 +1,19 @@ +{{- if .Values.certificate.create }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "versitygw.certificateSecretName" . }} + labels: + {{- include "versitygw.labels" . | nindent 4 }} +spec: + dnsNames: + {{- toYaml .Values.certificate.dnsNames | nindent 4 }} + issuerRef: + {{- toYaml .Values.certificate.issuerRef | nindent 4 }} + privateKey: + algorithm: ECDSA + size: 256 + secretName: {{ include "versitygw.certificateSecretName" . }} + usages: + - server auth +{{- end }} diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml new file mode 100644 index 00000000..ca06cffc --- /dev/null +++ b/chart/templates/deployment.yaml @@ -0,0 +1,211 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "versitygw.fullname" . }} + labels: + {{- include "versitygw.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "versitygw.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- if not .Values.auth.existingSecret }} + checksum/credentials: {{ cat .Release.Name .Values.auth.accessKey .Values.auth.secretKey | sha256sum | trunc 12 }} + {{- end }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "versitygw.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.image.pullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "versitygw.serviceAccountName" . }} + automountServiceAccountToken: false + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + # Backend selection — consumed by docker-entrypoint.sh + - name: VGW_BACKEND + value: {{ .Values.gateway.backend.type | quote }} + - name: VGW_BACKEND_ARGS + value: {{ .Values.gateway.backend.args | quote }} + # Root credentials — sourced from a Kubernetes Secret + - name: ROOT_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ include "versitygw.credentialsSecretName" . }} + key: rootAccessKeyId + - name: ROOT_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ include "versitygw.credentialsSecretName" . }} + key: rootSecretAccessKey + # Gateway server settings + - name: VGW_PORT + value: ":{{ .Values.gateway.port }}" + - name: VGW_REGION + value: {{ .Values.gateway.region | quote }} + - name: VGW_HEALTH + value: "/_/health" + {{- if .Values.gateway.virtualDomain }} + - name: VGW_VIRTUAL_DOMAIN + value: {{ .Values.gateway.virtualDomain | quote }} + {{- end }} + {{- if .Values.gateway.readOnly }} + - name: VGW_READ_ONLY + value: "true" + {{- end }} + {{- if .Values.gateway.quiet }} + - name: VGW_QUIET + value: "true" + {{- end }} + {{- if .Values.gateway.debug }} + - name: VGW_DEBUG + value: "true" + {{- end }} + {{- if .Values.gateway.accessLog }} + - name: VGW_ACCESS_LOG + value: {{ .Values.gateway.accessLog | quote }} + {{- end }} + {{- if .Values.gateway.corsAllowOrigin }} + - name: VGW_CORS_ALLOW_ORIGIN + value: {{ .Values.gateway.corsAllowOrigin | quote }} + {{- end }} + {{- if .Values.gateway.disableStrictBucketNames }} + - name: VGW_DISABLE_STRICT_BUCKET_NAMES + value: "true" + {{- end }} + # Admin API server + {{- if .Values.admin.enabled }} + - name: VGW_ADMIN_PORT + value: ":{{ .Values.admin.port }}" + - name: VGW_ADMIN_MAX_CONNECTIONS + value: {{ .Values.admin.maxConnections | quote }} + - name: VGW_ADMIN_MAX_REQUESTS + value: {{ .Values.admin.maxRequests | quote }} + {{- end }} + # WebUI + {{- if .Values.webui.enabled }} + - name: VGW_WEBUI_PORT + value: ":{{ .Values.webui.port }}" + {{- if .Values.webui.noTls }} + - name: VGW_WEBUI_NO_TLS + value: "true" + {{- end }} + {{- if .Values.webui.apiGateways }} + - name: VGW_WEBUI_GATEWAYS + value: {{ .Values.webui.apiGateways | join "," | quote }} + {{- end }} + {{- if .Values.webui.adminGateways }} + - name: VGW_WEBUI_ADMIN_GATEWAYS + value: {{ .Values.webui.adminGateways | join "," | quote }} + {{- end }} + {{- end }} + {{- if .Values.iam.enabled }} + # IAM settings + {{- if eq .Values.iam.type "internal" }} + - name: VGW_IAM_DIR + value: "/mnt/iam" + {{- end }} + {{- if .Values.iam.cacheDisable }} + - name: VGW_IAM_CACHE_DISABLE + value: "true" + {{- end }} + - name: VGW_IAM_CACHE_TTL + value: {{ .Values.iam.cacheTtl | quote }} + - name: VGW_IAM_CACHE_PRUNE + value: {{ .Values.iam.cachePrune | quote }} + {{- if .Values.iam.debug }} + - name: VGW_IAM_DEBUG + value: "true" + {{- end }} + {{- end }} + # TLS + {{- if .Values.tls.enabled }} + - name: VGW_CERT + value: /certs/tls.crt + - name: VGW_KEY + value: /certs/tls.key + {{- end }} + # Extra user-provided environment variables + {{- with .Values.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: s3-api + containerPort: {{ .Values.gateway.port }} + protocol: TCP + {{- if .Values.admin.enabled }} + - name: admin + containerPort: {{ .Values.admin.port }} + protocol: TCP + {{- end }} + {{- if .Values.webui.enabled }} + - name: webui + containerPort: {{ .Values.webui.port }} + protocol: TCP + {{- end }} + readinessProbe: + httpGet: + path: "/_/health" + port: s3-api + initialDelaySeconds: 5 + periodSeconds: 15 + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - name: data + mountPath: /mnt/data + subPath: data + readOnly: false + - name: data + mountPath: /mnt/iam + subPath: iam + readOnly: false + {{- if .Values.tls.enabled }} + - name: certificates + mountPath: /certs + readOnly: true + {{- end }} + volumes: + - name: data + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ include "versitygw.pvcName" . }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certificates + secret: + secretName: {{ include "versitygw.certificateSecretName" . }} + {{- 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 }} diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml new file mode 100644 index 00000000..6249bed9 --- /dev/null +++ b/chart/templates/ingress.yaml @@ -0,0 +1,35 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "versitygw.fullname" . }} + labels: + {{- include "versitygw.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className | quote }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- toYaml .Values.ingress.tls | nindent 4 }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "versitygw.fullname" $ }} + port: + name: {{ .servicePort | default "s3-api" }} + {{- end }} + {{- end }} +{{- end }} diff --git a/chart/templates/networkpolicy.yaml b/chart/templates/networkpolicy.yaml new file mode 100644 index 00000000..8cdd073e --- /dev/null +++ b/chart/templates/networkpolicy.yaml @@ -0,0 +1,24 @@ +{{- if .Values.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "versitygw.fullname" . }} +spec: + podSelector: + matchLabels: + {{- include "versitygw.selectorLabels" . | nindent 6 }} + # Permit ingress traffic only from the specified namespaces and pods + ingress: + - from: + namespaceSelector: + matchLabels: {{- toYaml .Values.networkPolicy.allowIngressFromNamespaces | nindent 10 }} + podSelector: {{- toYaml .Values.networkPolicy.allowIngressFromPods | nindent 10 }} + # By omitting the ports specification we apply this NetworkPolicy to all ports + ports: [] + # All egress traffic is allowed + egress: + - {} + policyTypes: + - Ingress + - Egress +{{- end }} diff --git a/chart/templates/pvc.yaml b/chart/templates/pvc.yaml new file mode 100644 index 00000000..76df1533 --- /dev/null +++ b/chart/templates/pvc.yaml @@ -0,0 +1,17 @@ +{{- if .Values.persistence.enabled -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "versitygw.pvcName" . }} + labels: + {{- include "versitygw.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.persistence.accessMode | quote }} + resources: + requests: + storage: {{ .Values.persistence.size }} + {{- if .Values.persistence.storageClassName }} + storageClassName: {{ .Values.persistence.storageClassName | quote }} + {{- end }} +{{- end }} diff --git a/chart/templates/secret.yaml b/chart/templates/secret.yaml new file mode 100644 index 00000000..62108619 --- /dev/null +++ b/chart/templates/secret.yaml @@ -0,0 +1,12 @@ +{{- if not .Values.auth.existingSecret -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "versitygw.credentialsSecretName" . }} + labels: + {{- include "versitygw.labels" . | nindent 4 }} +type: Opaque +stringData: + rootAccessKeyId: {{ required "auth.accessKey is required when auth.existingSecret is not set" .Values.auth.accessKey | quote }} + rootSecretAccessKey: {{ required "auth.secretKey is required when auth.existingSecret is not set" .Values.auth.secretKey | quote }} +{{- end }} diff --git a/chart/templates/service.yaml b/chart/templates/service.yaml new file mode 100644 index 00000000..c9b70532 --- /dev/null +++ b/chart/templates/service.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "versitygw.fullname" . }} + labels: + {{- include "versitygw.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.gateway.port }} + targetPort: s3-api + protocol: TCP + name: s3-api + {{- if .Values.admin.enabled }} + - port: {{ .Values.admin.port }} + targetPort: admin + protocol: TCP + name: admin + {{- end }} + {{- if .Values.webui.enabled }} + - port: {{ .Values.webui.port }} + targetPort: webui + protocol: TCP + name: webui + {{- end }} + selector: + {{- include "versitygw.selectorLabels" . | nindent 4 }} diff --git a/chart/templates/serviceaccount.yaml b/chart/templates/serviceaccount.yaml new file mode 100644 index 00000000..f1465c1f --- /dev/null +++ b/chart/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "versitygw.serviceAccountName" . }} + labels: + {{- include "versitygw.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/chart/values.yaml b/chart/values.yaml new file mode 100644 index 00000000..0dfad8e7 --- /dev/null +++ b/chart/values.yaml @@ -0,0 +1,253 @@ +# Default values for versitygw. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +# Standard Helm chart settings +nameOverride: "" +fullnameOverride: "" + +# Number of pod replicas for the deployment +# Note that when using the "posix" backend with a PVC, +# you can only increase the number of replicas if you have a "ReadWriteMany" volume! +replicaCount: 1 + +# This section defines which image to use and how to pull it. +# Find all available tags / releases at: https://github.com/versity/versitygw/pkgs/container/versitygw +image: + repository: ghcr.io/versity/versitygw + tag: "latest" + pullPolicy: IfNotPresent + pullSecrets: [] + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account (e.g. for IRSA / Workload Identity) + annotations: {} + # Name of the service account to use. If empty, a name is generated using the fullname template. + name: "" + +# Additional annotations for the pod +podAnnotations: {} +# Additional labels for the pod +podLabels: {} + +# Security settings for the Deployment Pod and its containers. +# The settings below are the recommended, least-privilege values. +# For more details refer to https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +podSecurityContext: + fsGroup: 1000 + +securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + +# The Kubernetes Service that exposes the versitygw server. +# To make the server available outside the cluster, the type should be changed to `NodePort` or `LoadBalancer`. +service: + type: ClusterIP + +# --- Ingress --- +# Expose the S3 API via a Kubernetes Ingress resource. +# Requires an ingress controller (e.g. nginx, traefik) to be installed in the cluster. +ingress: + enabled: false + # IngressClass to use (maps to spec.ingressClassName). + # Leave empty to use the cluster default. + className: "" + # Annotations applied to the Ingress resource. + # Use these to configure controller-specific behaviour, e.g.: + # nginx.ingress.kubernetes.io/proxy-body-size: "0" + # nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + # nginx.ingress.kubernetes.io/ssl-redirect: "true" + annotations: {} + # List of host rules. Each host can expose one or more paths. + # The `servicePort` field on each path selects which named Service port to route to. + # Supported values: s3-api (default), admin, webui. + hosts: + - host: s3.example.com + paths: + - path: / + pathType: Prefix + # servicePort: s3-api # default — routes to the S3 API port + # TLS configuration. Each entry maps a secret name to one or more hosts. + # The secret must contain tls.crt and tls.key. + # Example: + # tls: + # - secretName: versitygw-tls + # hosts: + # - s3.example.com + tls: [] + +# --- Root credentials --- +# The root S3 access credentials. These are required for the gateway to start. +# IMPORTANT: For production use, set auth.existingSecret instead of storing +# credentials in this values file. +auth: + # If set, use this existing Kubernetes Secret for credentials instead of creating one. + # The secret must contain the keys: rootAccessKeyId and rootSecretAccessKey + existingSecret: "" + # Root access key ID (used when existingSecret is empty) + accessKey: "" + # Root secret access key (used when existingSecret is empty) + secretKey: "" + +# --- Versity Gateway server configuration --- +gateway: + # -- Backend configuration -- + backend: + # The storage backend to use. Supported values: posix, scoutfs, s3, azure, plugin + # This maps to the VGW_BACKEND environment variable used by the container entrypoint. + type: posix + # Additional arguments passed to the backend + args: "/mnt/data" + # for s3 backend: + # args: "--access 0123456 --secret 0xdeadbeef --endpoint http://s3.example.com" + # for azure backend: + # args: ""--account 0123456 --access-key 0xdeadbeef" + + # The port versitygw listens on for S3 API requests. + port: 7070 + # The AWS region string returned to clients. + region: us-east-1 + # Enable virtual-host-style bucket addressing (e.g. bucket.example.com). + # Set to your domain (e.g. "example.com") to enable. + virtualDomain: "" + # Allow only read (GET/HEAD) operations. Prevents any writes. + readOnly: false + # Silence stdout request logging (useful when using a dedicated access log). + quiet: false + # Enable verbose debug output. + debug: false + # Access log file path for S3 requests (AWS log format). Empty = disabled. + accessLog: "" + # Default CORS allowed origin. Empty = CORS disabled. + corsAllowOrigin: "" + # Disable strict S3 bucket naming validation. + disableStrictBucketNames: false + +# --- Admin API server --- +admin: + # Enable a separate admin API server on a dedicated port. + enabled: false + # The port for the admin API server. Must differ from gateway.port. + port: 7071 + # Maximum concurrent connections for the admin server. + maxConnections: 250000 + # Maximum in-flight requests for the admin server. + maxRequests: 100000 + +# --- WebUI --- +webui: + # Enable the built-in browser-based management WebUI. + enabled: false + # The port the WebUI listens on. + port: 8080 + # Disable TLS for the WebUI even when gateway TLS is enabled. + noTls: false + # List of S3 endpoints used by the Versity Web UI + # The list that is auto-generated by Versity GW is wrong in the case of + # Kubernetes because it uses the internal pod IP addresses. + apiGateways: [] + # - s3.example.com + # List of Versity Admin endpoints used by the Versity Web UI + # The list that is auto-generated by Versity GW is wrong in the case of + # Kubernetes because it uses the internal pod IP addresses. + adminGateways: [] + # - s3-admin.example.com + +# --- IAM (Identity and Access Management) --- +iam: + enabled: false + # TODO: implement other IAM backend + # Internal flat-file IAM is the default. For production, consider LDAP or Vault. + type: internal + # Disable IAM result caching. + cacheDisable: false + # IAM cache entry TTL in seconds. + cacheTtl: 120 + # IAM cache cleanup interval in seconds. + cachePrune: 3600 + # Enable debug output for IAM operations. + debug: false + +# Extra environment variables to pass to the container. +# Use this to configure advanced options not covered above (e.g. event notifications, +# LDAP IAM, S3 proxy backend credentials, StatsD metrics, etc.). +# Refer to https://github.com/versity/versitygw#configuration for the full list. +# Example: +# extraEnv: +# - name: VGW_EVENT_KAFKA_URL +# value: "kafka:9092" +# - name: VGW_IAM_LDAP_URL +# value: "ldap://ldap.example.com" +extraEnv: [] + +# --- TLS --- +# Enable HTTPS for the S3 API (and admin/webui if not separately configured). +tls: + # Set to true to enable TLS. Requires certificate.secretName or certificate.create. + enabled: false + +# --- cert-manager Certificate --- +certificate: + # Set to the name of an existing TLS Secret to use for HTTPS. + # If empty and certificate.create is false, defaults to -cert. + secretName: "" + # Create a cert-manager Certificate resource to automatically provision TLS. + # Requires cert-manager to be installed in the cluster. + create: false + # DNS names to include in the certificate. Required when certificate.create is true. + dnsNames: [] + # - versitygw.example.com + # cert-manager issuer reference. Required when certificate.create is true. + # issuerRef: + # group: cert-manager.io + # kind: ClusterIssuer + # name: "letsencrypt-production" + +# --- Persistence --- +# Storage for the S3 gateway backend data (required for posix/scoutfs backends). +# By default, an emptyDir (ephemeral) volume is used. +persistence: + # If disabled, an emptyDir (ephemeral!) will be used instead of a PVC. + # NOTE: Data will be lost on pod restart if persistence is disabled. + enabled: false + # Use an existing PVC instead of creating a new one. + claimName: "" + size: 10Gi + storageClassName: "" + # Access mode for the PVC. Use ReadWriteMany for multi-replica deployments. + accessMode: ReadWriteOnce + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 500m + # memory: 512Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +networkPolicy: + enabled: false + # allowIngressFromNamespaces: + # matchLabels: + # kubernetes.io/metadata.name: kube-system + # allowIngressFromPods: + # matchLabels: + # svccontroller.k3s.cattle.io/svcname: versitygw