Browse Source

helm: enhance all-in-one deployment configuration (#7639)

* helm: enhance all-in-one deployment configuration

Fixes #7110

This PR addresses multiple issues with the all-in-one Helm chart configuration:

## New Features

### Configurable Replicas
- Added `allInOne.replicas` (was hardcoded to 1)

### S3 Gateway Configuration
- Added full S3 config under `allInOne.s3`:
  - port, httpsPort, domainName, allowEmptyFolder
  - enableAuth, existingConfigSecret, auditLogConfig
  - createBuckets for declarative bucket creation

### SFTP Server Configuration
- Added full SFTP config under `allInOne.sftp`:
  - port, sshPrivateKey, hostKeysFolder, authMethods
  - maxAuthTries, bannerMessage, loginGraceTime
  - clientAliveInterval, clientAliveCountMax, enableAuth

### Command Line Arguments
- Added `allInOne.extraArgs` for custom CLI arguments

### Update Strategy
- Added `allInOne.updateStrategy.type` (Recreate/RollingUpdate)

### Secret Environment Variables
- Added `allInOne.secretExtraEnvironmentVars` for injecting secrets

### Ingress Support
- Added `allInOne.ingress` with S3, filer, and master sub-configs

### Storage Options
- Enhanced `allInOne.data` with existingClaim support
- Added PVC template for persistentVolumeClaim type

## CI Enhancements
- Added comprehensive tests for all-in-one configurations
- Tests cover replicas, S3, SFTP, extraArgs, strategies, PVC, ingress

* helm: add real cluster deployment tests to CI

- Deploy all-in-one cluster with S3 enabled on kind cluster
- Test Master API (/cluster/status endpoint)
- Test Filer API (file upload/download)
- Test S3 API (/status endpoint)
- Test S3 operations with AWS CLI:
  - Create/delete buckets
  - Upload/download/delete objects
  - Verify file content integrity

* helm: simplify CI and remove all-in-one ingress

Address review comments:
- Remove detailed all-in-one template rendering tests from CI
- Remove real cluster deployment tests from CI
- Remove all-in-one ingress template and values configuration

Keep the core improvements:
- allInOne.replicas configuration
- allInOne.s3.* full configuration
- allInOne.sftp.* full configuration
- allInOne.extraArgs support
- allInOne.updateStrategy configuration
- allInOne.secretExtraEnvironmentVars support

* helm: address review comments

- Fix post-install-bucket-hook.yaml: add filer.s3.enableAuth and
  filer.s3.existingConfigSecret to or statements for consistency
- Fix all-in-one-deployment.yaml: use default function for s3.domainName
- Fix all-in-one-deployment.yaml: use hasKey function for s3.allowEmptyFolder

* helm: clarify updateStrategy multi-replica behavior

Expand comment to warn users that RollingUpdate with multiple replicas
requires shared storage (ReadWriteMany) to avoid data loss.

* helm: address gemini-code-assist review comments

- Make PVC accessModes configurable to support ReadWriteMany for
  multi-replica deployments (defaults to ReadWriteOnce)
- Use configured readiness probe paths in post-install bucket hook
  instead of hardcoded paths, respecting custom configurations

* helm: simplify allowEmptyFolder logic using coalesce

Use coalesce function for cleaner template code as suggested in review.

* helm: fix extraArgs trailing backslash issue

Remove trailing backslash after the last extraArgs argument to avoid
shell syntax error. Use counter to only add backslash between arguments.

* helm: fix fallback logic for allInOne s3/sftp configuration

Changes:
- Set allInOne.s3.* and allInOne.sftp.* override parameters to null by default
  This allows proper inheritance from global s3.* and sftp.* settings
- Fix allowEmptyFolder logic to use explicit nil checking instead of coalesce
  The coalesce/default functions treat 'false' as empty, causing incorrect
  fallback behavior when users want to explicitly set false values

Addresses review feedback about default value conflicts with fallback logic.

* helm: fix exec in bucket creation loop causing premature termination

Remove 'exec' from the range loops that create and configure S3 buckets.
The exec command replaces the current shell process, causing the script
to terminate after the first bucket, preventing creation/configuration
of subsequent buckets.

* helm: quote extraArgs to handle arguments with spaces

Use the quote function to ensure each item in extraArgs is treated as
a single, complete argument even if it contains spaces.

* helm: make s3/filer ingress work for both normal and all-in-one modes

Modified s3-ingress.yaml and filer-ingress.yaml to dynamically select
the service name based on deployment mode:
- Normal mode: points to seaweedfs-s3 / seaweedfs-filer services
- All-in-one mode: points to seaweedfs-all-in-one service

This eliminates the need for separate all-in-one ingress templates.
Users can now use the standard s3.ingress and filer.ingress settings
for both deployment modes.

* helm: fix allInOne.data.size and storageClass to use null defaults

Change size and storageClass from empty strings to null so the template
defaults (10Gi for size, cluster default for storageClass) will apply
correctly. Empty strings prevent the Helm | default function from working.

* helm: fix S3 ingress to include standalone S3 gateway case

Add s3.enabled check to the $s3Enabled logic so the ingress works for:
1. Standalone S3 gateway (s3.enabled)
2. S3 on Filer (filer.s3.enabled) when not in all-in-one mode
3. S3 in all-in-one mode (allInOne.s3.enabled)
pull/7645/head
Chris Lu 3 weeks ago
committed by GitHub
parent
commit
62a83ed469
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 113
      k8s/charts/seaweedfs/templates/all-in-one/all-in-one-deployment.yaml
  2. 25
      k8s/charts/seaweedfs/templates/all-in-one/all-in-one-pvc.yaml
  3. 18
      k8s/charts/seaweedfs/templates/all-in-one/all-in-one-service.yml
  4. 13
      k8s/charts/seaweedfs/templates/filer/filer-ingress.yaml
  5. 16
      k8s/charts/seaweedfs/templates/s3/s3-ingress.yaml
  6. 71
      k8s/charts/seaweedfs/templates/shared/post-install-bucket-hook.yaml
  7. 93
      k8s/charts/seaweedfs/values.yaml

113
k8s/charts/seaweedfs/templates/all-in-one/all-in-one-deployment.yaml

@ -15,9 +15,9 @@ metadata:
{{- toYaml .Values.allInOne.annotations | nindent 4 }} {{- toYaml .Values.allInOne.annotations | nindent 4 }}
{{- end }} {{- end }}
spec: spec:
replicas: 1
replicas: {{ .Values.allInOne.replicas | default 1 }}
strategy: strategy:
type: Recreate
type: {{ .Values.allInOne.updateStrategy.type | default "Recreate" }}
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }} app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
@ -130,12 +130,23 @@ spec:
value: {{ include "seaweedfs.cluster.masterAddress" . | quote }} value: {{ include "seaweedfs.cluster.masterAddress" . | quote }}
- name: {{ $clusterFilerKey }} - name: {{ $clusterFilerKey }}
value: {{ include "seaweedfs.cluster.filerAddress" . | quote }} value: {{ include "seaweedfs.cluster.filerAddress" . | quote }}
{{- if .Values.allInOne.secretExtraEnvironmentVars }}
{{- range $key, $value := .Values.allInOne.secretExtraEnvironmentVars }}
- name: {{ $key }}
valueFrom:
{{ toYaml $value | nindent 16 }}
{{- end }}
{{- end }}
command: command:
- "/bin/sh" - "/bin/sh"
- "-ec" - "-ec"
- | - |
/usr/bin/weed \ /usr/bin/weed \
{{- if .Values.allInOne.loggingOverrideLevel }}
-v={{ .Values.allInOne.loggingOverrideLevel }} \
{{- else }}
-v={{ .Values.global.loggingLevel }} \ -v={{ .Values.global.loggingLevel }} \
{{- end }}
server \ server \
-dir=/data \ -dir=/data \
-master \ -master \
@ -191,6 +202,9 @@ spec:
{{- else if .Values.master.metricsPort }} {{- else if .Values.master.metricsPort }}
-metricsPort={{ .Values.master.metricsPort }} \ -metricsPort={{ .Values.master.metricsPort }} \
{{- end }} {{- end }}
{{- if .Values.allInOne.metricsIp }}
-metricsIp={{ .Values.allInOne.metricsIp }} \
{{- end }}
-filer \ -filer \
-filer.port={{ .Values.filer.port }} \ -filer.port={{ .Values.filer.port }} \
{{- if .Values.filer.disableDirListing }} {{- if .Values.filer.disableDirListing }}
@ -219,61 +233,80 @@ spec:
{{- end }} {{- end }}
{{- if .Values.allInOne.s3.enabled }} {{- if .Values.allInOne.s3.enabled }}
-s3 \ -s3 \
-s3.port={{ .Values.s3.port }} \
{{- if .Values.s3.domainName }}
-s3.domainName={{ .Values.s3.domainName }} \
-s3.port={{ .Values.allInOne.s3.port | default .Values.s3.port }} \
{{- $domainName := .Values.allInOne.s3.domainName | default .Values.s3.domainName }}
{{- if $domainName }}
-s3.domainName={{ $domainName }} \
{{- end }} {{- end }}
{{- if .Values.global.enableSecurity }} {{- if .Values.global.enableSecurity }}
{{- if .Values.s3.httpsPort }}
-s3.port.https={{ .Values.s3.httpsPort }} \
{{- $httpsPort := .Values.allInOne.s3.httpsPort | default .Values.s3.httpsPort }}
{{- if $httpsPort }}
-s3.port.https={{ $httpsPort }} \
{{- end }} {{- end }}
-s3.cert.file=/usr/local/share/ca-certificates/client/tls.crt \ -s3.cert.file=/usr/local/share/ca-certificates/client/tls.crt \
-s3.key.file=/usr/local/share/ca-certificates/client/tls.key \ -s3.key.file=/usr/local/share/ca-certificates/client/tls.key \
{{- end }} {{- end }}
{{- if eq (typeOf .Values.s3.allowEmptyFolder) "bool" }}
{{- if ne .Values.allInOne.s3.allowEmptyFolder nil }}
-s3.allowEmptyFolder={{ .Values.allInOne.s3.allowEmptyFolder }} \
{{- else if ne .Values.s3.allowEmptyFolder nil }}
-s3.allowEmptyFolder={{ .Values.s3.allowEmptyFolder }} \ -s3.allowEmptyFolder={{ .Values.s3.allowEmptyFolder }} \
{{- end }} {{- end }}
{{- if .Values.s3.enableAuth }}
{{- if or .Values.allInOne.s3.enableAuth .Values.s3.enableAuth .Values.filer.s3.enableAuth }}
-s3.config=/etc/sw/s3/seaweedfs_s3_config \ -s3.config=/etc/sw/s3/seaweedfs_s3_config \
{{- end }} {{- end }}
{{- if .Values.s3.auditLogConfig }}
{{- $auditLogConfig := .Values.allInOne.s3.auditLogConfig | default .Values.s3.auditLogConfig }}
{{- if $auditLogConfig }}
-s3.auditLogConfig=/etc/sw/s3/s3_auditLogConfig.json \ -s3.auditLogConfig=/etc/sw/s3/s3_auditLogConfig.json \
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- if .Values.allInOne.sftp.enabled }} {{- if .Values.allInOne.sftp.enabled }}
-sftp \ -sftp \
-sftp.port={{ .Values.sftp.port }} \
{{- if .Values.sftp.sshPrivateKey }}
-sftp.sshPrivateKey={{ .Values.sftp.sshPrivateKey }} \
-sftp.port={{ .Values.allInOne.sftp.port | default .Values.sftp.port }} \
{{- $sshPrivateKey := .Values.allInOne.sftp.sshPrivateKey | default .Values.sftp.sshPrivateKey }}
{{- if $sshPrivateKey }}
-sftp.sshPrivateKey={{ $sshPrivateKey }} \
{{- end }} {{- end }}
{{- if .Values.sftp.hostKeysFolder }}
-sftp.hostKeysFolder={{ .Values.sftp.hostKeysFolder }} \
{{- $hostKeysFolder := .Values.allInOne.sftp.hostKeysFolder | default .Values.sftp.hostKeysFolder }}
{{- if $hostKeysFolder }}
-sftp.hostKeysFolder={{ $hostKeysFolder }} \
{{- end }} {{- end }}
{{- if .Values.sftp.authMethods }}
-sftp.authMethods={{ .Values.sftp.authMethods }} \
{{- $authMethods := .Values.allInOne.sftp.authMethods | default .Values.sftp.authMethods }}
{{- if $authMethods }}
-sftp.authMethods={{ $authMethods }} \
{{- end }} {{- end }}
{{- if .Values.sftp.maxAuthTries }}
-sftp.maxAuthTries={{ .Values.sftp.maxAuthTries }} \
{{- $maxAuthTries := .Values.allInOne.sftp.maxAuthTries | default .Values.sftp.maxAuthTries }}
{{- if $maxAuthTries }}
-sftp.maxAuthTries={{ $maxAuthTries }} \
{{- end }} {{- end }}
{{- if .Values.sftp.bannerMessage }}
-sftp.bannerMessage="{{ .Values.sftp.bannerMessage }}" \
{{- $bannerMessage := .Values.allInOne.sftp.bannerMessage | default .Values.sftp.bannerMessage }}
{{- if $bannerMessage }}
-sftp.bannerMessage="{{ $bannerMessage }}" \
{{- end }} {{- end }}
{{- if .Values.sftp.loginGraceTime }}
-sftp.loginGraceTime={{ .Values.sftp.loginGraceTime }} \
{{- $loginGraceTime := .Values.allInOne.sftp.loginGraceTime | default .Values.sftp.loginGraceTime }}
{{- if $loginGraceTime }}
-sftp.loginGraceTime={{ $loginGraceTime }} \
{{- end }} {{- end }}
{{- if .Values.sftp.clientAliveInterval }}
-sftp.clientAliveInterval={{ .Values.sftp.clientAliveInterval }} \
{{- $clientAliveInterval := .Values.allInOne.sftp.clientAliveInterval | default .Values.sftp.clientAliveInterval }}
{{- if $clientAliveInterval }}
-sftp.clientAliveInterval={{ $clientAliveInterval }} \
{{- end }} {{- end }}
{{- if .Values.sftp.clientAliveCountMax }}
-sftp.clientAliveCountMax={{ .Values.sftp.clientAliveCountMax }} \
{{- $clientAliveCountMax := .Values.allInOne.sftp.clientAliveCountMax | default .Values.sftp.clientAliveCountMax }}
{{- if $clientAliveCountMax }}
-sftp.clientAliveCountMax={{ $clientAliveCountMax }} \
{{- end }} {{- end }}
{{- if or .Values.allInOne.sftp.enableAuth .Values.sftp.enableAuth }}
-sftp.userStoreFile=/etc/sw/sftp/seaweedfs_sftp_config \ -sftp.userStoreFile=/etc/sw/sftp/seaweedfs_sftp_config \
{{- end }} {{- end }}
{{- end }}
{{- $extraArgsCount := len .Values.allInOne.extraArgs }}
{{- range $i, $arg := .Values.allInOne.extraArgs }}
{{ $arg | quote }}{{ if ne (add1 $i) $extraArgsCount }} \{{ end }}
{{- end }}
volumeMounts: volumeMounts:
- name: data - name: data
mountPath: /data mountPath: /data
{{- if and .Values.allInOne.s3.enabled (or .Values.s3.enableAuth .Values.filer.s3.enableAuth) }}
{{- if and .Values.allInOne.s3.enabled (or .Values.allInOne.s3.enableAuth .Values.s3.enableAuth .Values.filer.s3.enableAuth) }}
- name: config-s3-users - name: config-s3-users
mountPath: /etc/sw/s3 mountPath: /etc/sw/s3
readOnly: true readOnly: true
@ -282,10 +315,12 @@ spec:
- name: config-ssh - name: config-ssh
mountPath: /etc/sw/ssh mountPath: /etc/sw/ssh
readOnly: true readOnly: true
{{- if or .Values.allInOne.sftp.enableAuth .Values.sftp.enableAuth }}
- mountPath: /etc/sw/sftp - mountPath: /etc/sw/sftp
name: config-users name: config-users
readOnly: true readOnly: true
{{- end }} {{- end }}
{{- end }}
{{- if .Values.filer.notificationConfig }} {{- if .Values.filer.notificationConfig }}
- name: notification-config - name: notification-config
mountPath: /etc/seaweedfs/notification.toml mountPath: /etc/seaweedfs/notification.toml
@ -332,15 +367,16 @@ spec:
- containerPort: {{ .Values.filer.grpcPort }} - containerPort: {{ .Values.filer.grpcPort }}
name: swfs-fil-grpc name: swfs-fil-grpc
{{- if .Values.allInOne.s3.enabled }} {{- if .Values.allInOne.s3.enabled }}
- containerPort: {{ .Values.s3.port }}
- containerPort: {{ .Values.allInOne.s3.port | default .Values.s3.port }}
name: swfs-s3 name: swfs-s3
{{- if .Values.s3.httpsPort }}
- containerPort: {{ .Values.s3.httpsPort }}
{{- $httpsPort := .Values.allInOne.s3.httpsPort | default .Values.s3.httpsPort }}
{{- if $httpsPort }}
- containerPort: {{ $httpsPort }}
name: swfs-s3-tls name: swfs-s3-tls
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- if .Values.allInOne.sftp.enabled }} {{- if .Values.allInOne.sftp.enabled }}
- containerPort: {{ .Values.sftp.port }}
- containerPort: {{ .Values.allInOne.sftp.port | default .Values.sftp.port }}
name: swfs-sftp name: swfs-sftp
{{- end }} {{- end }}
{{- if .Values.allInOne.metricsPort }} {{- if .Values.allInOne.metricsPort }}
@ -389,26 +425,31 @@ spec:
path: {{ .Values.allInOne.data.hostPathPrefix }}/seaweedfs-all-in-one-data/ path: {{ .Values.allInOne.data.hostPathPrefix }}/seaweedfs-all-in-one-data/
type: DirectoryOrCreate type: DirectoryOrCreate
{{- else if eq .Values.allInOne.data.type "persistentVolumeClaim" }} {{- else if eq .Values.allInOne.data.type "persistentVolumeClaim" }}
persistentVolumeClaim:
claimName: {{ template "seaweedfs.name" . }}-all-in-one-data
{{- else if eq .Values.allInOne.data.type "existingClaim" }}
persistentVolumeClaim: persistentVolumeClaim:
claimName: {{ .Values.allInOne.data.claimName }} claimName: {{ .Values.allInOne.data.claimName }}
{{- else if eq .Values.allInOne.data.type "emptyDir" }} {{- else if eq .Values.allInOne.data.type "emptyDir" }}
emptyDir: {} emptyDir: {}
{{- end }} {{- end }}
{{- if and .Values.allInOne.s3.enabled (or .Values.s3.enableAuth .Values.filer.s3.enableAuth) }}
{{- if and .Values.allInOne.s3.enabled (or .Values.allInOne.s3.enableAuth .Values.s3.enableAuth .Values.filer.s3.enableAuth) }}
- name: config-s3-users - name: config-s3-users
secret: secret:
defaultMode: 420 defaultMode: 420
secretName: {{ default (printf "%s-s3-secret" (include "seaweedfs.name" .)) (or .Values.s3.existingConfigSecret .Values.filer.s3.existingConfigSecret) }}
secretName: {{ default (printf "%s-s3-secret" (include "seaweedfs.name" .)) (or .Values.allInOne.s3.existingConfigSecret .Values.s3.existingConfigSecret .Values.filer.s3.existingConfigSecret) }}
{{- end }} {{- end }}
{{- if .Values.allInOne.sftp.enabled }} {{- if .Values.allInOne.sftp.enabled }}
- name: config-ssh - name: config-ssh
secret: secret:
defaultMode: 420 defaultMode: 420
secretName: {{ default (printf "%s-sftp-ssh-secret" (include "seaweedfs.name" .)) .Values.sftp.existingSshConfigSecret }}
secretName: {{ default (printf "%s-sftp-ssh-secret" (include "seaweedfs.name" .)) (or .Values.allInOne.sftp.existingSshConfigSecret .Values.sftp.existingSshConfigSecret) }}
{{- if or .Values.allInOne.sftp.enableAuth .Values.sftp.enableAuth }}
- name: config-users - name: config-users
secret: secret:
defaultMode: 420 defaultMode: 420
secretName: {{ default (printf "%s-sftp-secret" (include "seaweedfs.name" .)) .Values.sftp.existingConfigSecret }}
secretName: {{ default (printf "%s-sftp-secret" (include "seaweedfs.name" .)) (or .Values.allInOne.sftp.existingConfigSecret .Values.sftp.existingConfigSecret) }}
{{- end }}
{{- end }} {{- end }}
{{- if .Values.filer.notificationConfig }} {{- if .Values.filer.notificationConfig }}
- name: notification-config - name: notification-config

25
k8s/charts/seaweedfs/templates/all-in-one/all-in-one-pvc.yaml

@ -1,21 +1,28 @@
{{- if and .Values.allInOne.enabled (eq .Values.allInOne.data.type "persistentVolumeClaim") }}
{{- if .Values.allInOne.enabled }}
{{- if eq .Values.allInOne.data.type "persistentVolumeClaim" }}
apiVersion: v1 apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: {{ .Values.allInOne.data.claimName }}
name: {{ template "seaweedfs.name" . }}-all-in-one-data
namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: seaweedfs-all-in-one app.kubernetes.io/component: seaweedfs-all-in-one
{{- if .Values.allInOne.annotations }}
{{- with .Values.allInOne.data.annotations }}
annotations: annotations:
{{- toYaml .Values.allInOne.annotations | nindent 4 }}
{{- toYaml . | nindent 4 }}
{{- end }} {{- end }}
spec: spec:
accessModes: accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.allInOne.data.size }}
{{- toYaml (.Values.allInOne.data.accessModes | default (list "ReadWriteOnce")) | nindent 4 }}
{{- if .Values.allInOne.data.storageClass }} {{- if .Values.allInOne.data.storageClass }}
storageClassName: {{ .Values.allInOne.data.storageClass }} storageClassName: {{ .Values.allInOne.data.storageClass }}
{{- end }} {{- end }}
{{- end }}
resources:
requests:
storage: {{ .Values.allInOne.data.size | default "10Gi" }}
{{- end }}
{{- end }}

18
k8s/charts/seaweedfs/templates/all-in-one/all-in-one-service.yml

@ -15,6 +15,7 @@ metadata:
{{- toYaml .Values.allInOne.service.annotations | nindent 4 }} {{- toYaml .Values.allInOne.service.annotations | nindent 4 }}
{{- end }} {{- end }}
spec: spec:
type: {{ .Values.allInOne.service.type | default "ClusterIP" }}
internalTrafficPolicy: {{ .Values.allInOne.service.internalTrafficPolicy | default "Cluster" }} internalTrafficPolicy: {{ .Values.allInOne.service.internalTrafficPolicy | default "Cluster" }}
ports: ports:
# Master ports # Master ports
@ -50,13 +51,14 @@ spec:
# S3 ports (if enabled) # S3 ports (if enabled)
{{- if .Values.allInOne.s3.enabled }} {{- if .Values.allInOne.s3.enabled }}
- name: "swfs-s3" - name: "swfs-s3"
port: {{ if .Values.allInOne.s3.enabled }}{{ .Values.s3.port }}{{ else }}{{ .Values.filer.s3.port }}{{ end }}
targetPort: {{ if .Values.allInOne.s3.enabled }}{{ .Values.s3.port }}{{ else }}{{ .Values.filer.s3.port }}{{ end }}
port: {{ .Values.allInOne.s3.port | default .Values.s3.port }}
targetPort: {{ .Values.allInOne.s3.port | default .Values.s3.port }}
protocol: TCP protocol: TCP
{{- if and .Values.allInOne.s3.enabled .Values.s3.httpsPort }}
{{- $httpsPort := .Values.allInOne.s3.httpsPort | default .Values.s3.httpsPort }}
{{- if $httpsPort }}
- name: "swfs-s3-tls" - name: "swfs-s3-tls"
port: {{ .Values.s3.httpsPort }}
targetPort: {{ .Values.s3.httpsPort }}
port: {{ $httpsPort }}
targetPort: {{ $httpsPort }}
protocol: TCP protocol: TCP
{{- end }} {{- end }}
{{- end }} {{- end }}
@ -64,8 +66,8 @@ spec:
# SFTP ports (if enabled) # SFTP ports (if enabled)
{{- if .Values.allInOne.sftp.enabled }} {{- if .Values.allInOne.sftp.enabled }}
- name: "swfs-sftp" - name: "swfs-sftp"
port: {{ .Values.sftp.port }}
targetPort: {{ .Values.sftp.port }}
port: {{ .Values.allInOne.sftp.port | default .Values.sftp.port }}
targetPort: {{ .Values.allInOne.sftp.port | default .Values.sftp.port }}
protocol: TCP protocol: TCP
{{- end }} {{- end }}
@ -80,4 +82,4 @@ spec:
selector: selector:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }} app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/component: seaweedfs-all-in-one app.kubernetes.io/component: seaweedfs-all-in-one
{{- end }}
{{- end }}

13
k8s/charts/seaweedfs/templates/filer/filer-ingress.yaml

@ -1,5 +1,8 @@
{{- if .Values.filer.enabled }}
{{- if .Values.filer.ingress.enabled }}
{{- /* Filer ingress works for both normal mode (filer.enabled) and all-in-one mode (allInOne.enabled) */}}
{{- $filerEnabled := or .Values.filer.enabled .Values.allInOne.enabled }}
{{- if and $filerEnabled .Values.filer.ingress.enabled }}
{{- /* Determine service name based on deployment mode */}}
{{- $serviceName := ternary (printf "%s-all-in-one" (include "seaweedfs.name" .)) (printf "%s-filer" (include "seaweedfs.name" .)) .Values.allInOne.enabled }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }} {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1 apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }} {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }}
@ -33,16 +36,14 @@ spec:
backend: backend:
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }} {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
service: service:
name: {{ template "seaweedfs.name" . }}-filer
name: {{ $serviceName }}
port: port:
number: {{ .Values.filer.port }} number: {{ .Values.filer.port }}
#name:
{{- else }} {{- else }}
serviceName: {{ template "seaweedfs.name" . }}-filer
serviceName: {{ $serviceName }}
servicePort: {{ .Values.filer.port }} servicePort: {{ .Values.filer.port }}
{{- end }} {{- end }}
{{- if .Values.filer.ingress.host }} {{- if .Values.filer.ingress.host }}
host: {{ .Values.filer.ingress.host }} host: {{ .Values.filer.ingress.host }}
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- end }}

16
k8s/charts/seaweedfs/templates/s3/s3-ingress.yaml

@ -1,4 +1,9 @@
{{- if .Values.s3.ingress.enabled }}
{{- /* S3 ingress works for standalone S3 gateway (s3.enabled), S3 on Filer (filer.s3.enabled), and all-in-one mode (allInOne.s3.enabled) */}}
{{- $s3Enabled := or .Values.s3.enabled (and .Values.filer.s3.enabled (not .Values.allInOne.enabled)) (and .Values.allInOne.enabled .Values.allInOne.s3.enabled) }}
{{- if and $s3Enabled .Values.s3.ingress.enabled }}
{{- /* Determine service name based on deployment mode */}}
{{- $serviceName := ternary (printf "%s-all-in-one" (include "seaweedfs.name" .)) (printf "%s-s3" (include "seaweedfs.name" .)) .Values.allInOne.enabled }}
{{- $s3Port := .Values.allInOne.s3.port | default .Values.s3.port }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }} {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1 apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }} {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }}
@ -32,13 +37,12 @@ spec:
backend: backend:
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }} {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
service: service:
name: {{ template "seaweedfs.name" . }}-s3
name: {{ $serviceName }}
port: port:
number: {{ .Values.s3.port }}
#name:
number: {{ $s3Port }}
{{- else }} {{- else }}
serviceName: {{ template "seaweedfs.name" . }}-s3
servicePort: {{ .Values.s3.port }}
serviceName: {{ $serviceName }}
servicePort: {{ $s3Port }}
{{- end }} {{- end }}
{{- if .Values.s3.ingress.host }} {{- if .Values.s3.ingress.host }}
host: {{ .Values.s3.ingress.host | quote }} host: {{ .Values.s3.ingress.host | quote }}

71
k8s/charts/seaweedfs/templates/shared/post-install-bucket-hook.yaml

@ -1,6 +1,32 @@
{{- if .Values.master.enabled }}
{{- if .Values.filer.s3.enabled }}
{{- if .Values.filer.s3.createBuckets }}
{{- /* Support bucket creation for both standalone filer.s3 and allInOne modes */}}
{{- $createBuckets := list }}
{{- $s3Enabled := false }}
{{- $enableAuth := false }}
{{- $existingConfigSecret := "" }}
{{- /* Check allInOne mode first */}}
{{- if .Values.allInOne.enabled }}
{{- if .Values.allInOne.s3.enabled }}
{{- $s3Enabled = true }}
{{- if .Values.allInOne.s3.createBuckets }}
{{- $createBuckets = .Values.allInOne.s3.createBuckets }}
{{- end }}
{{- $enableAuth = or .Values.allInOne.s3.enableAuth .Values.s3.enableAuth .Values.filer.s3.enableAuth }}
{{- $existingConfigSecret = or .Values.allInOne.s3.existingConfigSecret .Values.s3.existingConfigSecret .Values.filer.s3.existingConfigSecret }}
{{- end }}
{{- else if .Values.master.enabled }}
{{- /* Check standalone filer.s3 mode */}}
{{- if .Values.filer.s3.enabled }}
{{- $s3Enabled = true }}
{{- if .Values.filer.s3.createBuckets }}
{{- $createBuckets = .Values.filer.s3.createBuckets }}
{{- end }}
{{- $enableAuth = .Values.filer.s3.enableAuth }}
{{- $existingConfigSecret = .Values.filer.s3.existingConfigSecret }}
{{- end }}
{{- end }}
{{- if and $s3Enabled $createBuckets }}
--- ---
apiVersion: batch/v1 apiVersion: batch/v1
kind: Job kind: Job
@ -32,9 +58,9 @@ spec:
- name: WEED_CLUSTER_DEFAULT - name: WEED_CLUSTER_DEFAULT
value: "sw" value: "sw"
- name: WEED_CLUSTER_SW_MASTER - name: WEED_CLUSTER_SW_MASTER
value: "{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}:{{ .Values.master.port }}"
value: {{ include "seaweedfs.cluster.masterAddress" . | quote }}
- name: WEED_CLUSTER_SW_FILER - name: WEED_CLUSTER_SW_FILER
value: "{{ template "seaweedfs.name" . }}-filer-client.{{ .Release.Namespace }}:{{ .Values.filer.port }}"
value: {{ include "seaweedfs.cluster.filerAddress" . | quote }}
- name: POD_IP - name: POD_IP
valueFrom: valueFrom:
fieldRef: fieldRef:
@ -71,24 +97,29 @@ spec:
echo "Service at $url failed to become ready within 5 minutes" echo "Service at $url failed to become ready within 5 minutes"
exit 1 exit 1
} }
{{- if .Values.allInOne.enabled }}
wait_for_service "http://$WEED_CLUSTER_SW_MASTER{{ .Values.allInOne.readinessProbe.httpGet.path }}"
wait_for_service "http://$WEED_CLUSTER_SW_FILER{{ .Values.filer.readinessProbe.httpGet.path }}"
{{- else }}
wait_for_service "http://$WEED_CLUSTER_SW_MASTER{{ .Values.master.readinessProbe.httpGet.path }}" wait_for_service "http://$WEED_CLUSTER_SW_MASTER{{ .Values.master.readinessProbe.httpGet.path }}"
wait_for_service "http://$WEED_CLUSTER_SW_FILER{{ .Values.filer.readinessProbe.httpGet.path }}" wait_for_service "http://$WEED_CLUSTER_SW_FILER{{ .Values.filer.readinessProbe.httpGet.path }}"
{{- range $reg, $props := $.Values.filer.s3.createBuckets }}
exec /bin/echo \
"s3.bucket.create --name {{ $props.name }}" |\
{{- end }}
{{- range $createBuckets }}
/bin/echo \
"s3.bucket.create --name {{ .name }}" |\
/usr/bin/weed shell /usr/bin/weed shell
{{- end }} {{- end }}
{{- range $reg, $props := $.Values.filer.s3.createBuckets }}
{{- if $props.anonymousRead }}
exec /bin/echo \
{{- range $createBuckets }}
{{- if .anonymousRead }}
/bin/echo \
"s3.configure --user anonymous \ "s3.configure --user anonymous \
--buckets {{ $props.name }} \
--buckets {{ .name }} \
--actions Read \ --actions Read \
--apply true" |\ --apply true" |\
/usr/bin/weed shell /usr/bin/weed shell
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- if .Values.filer.s3.enableAuth }}
{{- if $enableAuth }}
volumeMounts: volumeMounts:
- name: config-users - name: config-users
mountPath: /etc/sw mountPath: /etc/sw
@ -106,17 +137,15 @@ spec:
{{- if .Values.filer.containerSecurityContext.enabled }} {{- if .Values.filer.containerSecurityContext.enabled }}
securityContext: {{- omit .Values.filer.containerSecurityContext "enabled" | toYaml | nindent 12 }} securityContext: {{- omit .Values.filer.containerSecurityContext "enabled" | toYaml | nindent 12 }}
{{- end }} {{- end }}
{{- if .Values.filer.s3.enableAuth }}
{{- if $enableAuth }}
volumes: volumes:
- name: config-users - name: config-users
secret: secret:
defaultMode: 420 defaultMode: 420
{{- if not (empty .Values.filer.s3.existingConfigSecret) }}
secretName: {{ .Values.filer.s3.existingConfigSecret }}
{{- if $existingConfigSecret }}
secretName: {{ $existingConfigSecret }}
{{- else }} {{- else }}
secretName: seaweedfs-s3-secret
secretName: {{ template "seaweedfs.name" . }}-s3-secret
{{- end }} {{- end }}
{{- end }}{{/** if .Values.filer.s3.enableAuth **/}}
{{- end }}{{/** if .Values.master.enabled **/}}
{{- end }}{{/** if .Values.filer.s3.enabled **/}}
{{- end }}{{/** if .Values.filer.s3.createBuckets **/}}
{{- end }}
{{- end }}

93
k8s/charts/seaweedfs/values.yaml

@ -1097,6 +1097,7 @@ allInOne:
enabled: false enabled: false
imageOverride: null imageOverride: null
restartPolicy: Always restartPolicy: Always
replicas: 1 # Number of replicas (note: multiple replicas may require shared storage)
# Core configuration # Core configuration
idleTimeout: 30 # Connection idle seconds idleTimeout: 30 # Connection idle seconds
@ -1108,24 +1109,86 @@ allInOne:
metricsIp: "" # Metrics listen IP. If empty, defaults to bindAddress metricsIp: "" # Metrics listen IP. If empty, defaults to bindAddress
loggingOverrideLevel: null # Override logging level loggingOverrideLevel: null # Override logging level
# Service configuration
# Custom command line arguments to add to the server command
# Example to fix IPv6 metrics connectivity issues:
# extraArgs: ["-metricsIp", "0.0.0.0"]
# Example with multiple args:
# extraArgs: ["-customFlag", "value", "-anotherFlag"]
extraArgs: []
# Update strategy configuration
# type: Recreate or RollingUpdate
# For single replica, Recreate is recommended to avoid data conflicts.
# For multiple replicas with RollingUpdate, you MUST use shared storage
# (e.g., data.type: persistentVolumeClaim with ReadWriteMany access mode)
# to avoid data loss or inconsistency between pods.
updateStrategy:
type: Recreate
# S3 gateway configuration
# Note: Most parameters below default to null, which means they inherit from
# the global s3.* settings. Set explicit values here to override for allInOne only.
s3: s3:
enabled: false # Whether to enable S3 gateway enabled: false # Whether to enable S3 gateway
port: null # S3 gateway port (null inherits from s3.port)
httpsPort: null # S3 gateway HTTPS port (null inherits from s3.httpsPort)
domainName: null # Suffix of the host name (null inherits from s3.domainName)
allowEmptyFolder: null # Allow empty folders in S3 (null inherits from s3.allowEmptyFolder)
enableAuth: false # Enable user & permission to S3
# Set to the name of an existing kubernetes Secret with the s3 json config file
# should have a secret key called seaweedfs_s3_config with an inline json config
existingConfigSecret: null
auditLogConfig: null # S3 audit log configuration (null inherits from s3.auditLogConfig)
# You may specify buckets to be created during the install process.
# Buckets may be exposed publicly by setting `anonymousRead` to `true`
# createBuckets:
# - name: bucket-a
# anonymousRead: true
# - name: bucket-b
# anonymousRead: false
# SFTP server configuration
# Note: Most parameters below default to null, which means they inherit from
# the global sftp.* settings. Set explicit values here to override for allInOne only.
sftp: sftp:
enabled: false # Whether to enable SFTP server enabled: false # Whether to enable SFTP server
port: null # SFTP port (null inherits from sftp.port)
sshPrivateKey: null # Path to SSH private key (null inherits from sftp.sshPrivateKey)
hostKeysFolder: null # Path to SSH host keys folder (null inherits from sftp.hostKeysFolder)
authMethods: null # Comma-separated auth methods (null inherits from sftp.authMethods)
maxAuthTries: null # Maximum authentication attempts (null inherits from sftp.maxAuthTries)
bannerMessage: null # Banner message (null inherits from sftp.bannerMessage)
loginGraceTime: null # Login grace time (null inherits from sftp.loginGraceTime)
clientAliveInterval: null # Client keep-alive interval (null inherits from sftp.clientAliveInterval)
clientAliveCountMax: null # Maximum missed keep-alive messages (null inherits from sftp.clientAliveCountMax)
enableAuth: false # Enable SFTP authentication
# Set to the name of an existing kubernetes Secret with the sftp json config file
existingConfigSecret: null
# Set to the name of an existing kubernetes Secret with the SSH keys
existingSshConfigSecret: null
# Service settings # Service settings
service: service:
annotations: {} # Annotations for the service annotations: {} # Annotations for the service
type: ClusterIP # Service type (ClusterIP, NodePort, LoadBalancer) type: ClusterIP # Service type (ClusterIP, NodePort, LoadBalancer)
internalTrafficPolicy: Cluster # Internal traffic policy
# Note: For ingress in all-in-one mode, use the standard s3.ingress and
# filer.ingress settings. The templates automatically detect all-in-one mode
# and point to the correct service (seaweedfs-all-in-one instead of
# seaweedfs-s3 or seaweedfs-filer).
# Storage configuration # Storage configuration
data: data:
type: "emptyDir" # Options: "hostPath", "persistentVolumeClaim", "emptyDir"
type: "emptyDir" # Options: "hostPath", "persistentVolumeClaim", "emptyDir", "existingClaim"
hostPathPrefix: /mnt/data # Path prefix for hostPath volumes hostPathPrefix: /mnt/data # Path prefix for hostPath volumes
claimName: seaweedfs-data-pvc # Name of the PVC to use
size: "" # Size of the PVC
storageClass: "" # Storage class for the PVC
claimName: seaweedfs-data-pvc # Name of the PVC to use (for existingClaim type)
size: null # Size of the PVC (null defaults to 10Gi for persistentVolumeClaim type)
storageClass: null # Storage class for the PVC (null uses cluster default)
# accessModes for the PVC. Default is ["ReadWriteOnce"].
# For multi-replica deployments, use ["ReadWriteMany"] with a compatible storage class.
accessModes: []
annotations: {} # Annotations for the PVC
# Health checks # Health checks
readinessProbe: readinessProbe:
@ -1154,6 +1217,18 @@ allInOne:
# Additional resources # Additional resources
extraEnvironmentVars: {} # Additional environment variables extraEnvironmentVars: {} # Additional environment variables
# Secret environment variables (for database credentials, etc.)
# Example:
# secretExtraEnvironmentVars:
# WEED_POSTGRES_USERNAME:
# secretKeyRef:
# name: postgres-credentials
# key: username
# WEED_POSTGRES_PASSWORD:
# secretKeyRef:
# name: postgres-credentials
# key: password
secretExtraEnvironmentVars: {}
extraVolumeMounts: "" # Additional volume mounts extraVolumeMounts: "" # Additional volume mounts
extraVolumes: "" # Additional volumes extraVolumes: "" # Additional volumes
initContainers: "" # Init containers initContainers: "" # Init containers
@ -1173,7 +1248,7 @@ allInOne:
matchLabels: matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }} app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: master
app.kubernetes.io/component: seaweedfs-all-in-one
topologyKey: kubernetes.io/hostname topologyKey: kubernetes.io/hostname
# Topology Spread Constraints Settings # Topology Spread Constraints Settings
@ -1181,16 +1256,16 @@ allInOne:
# for a PodSpec. By Default no constraints are set. # for a PodSpec. By Default no constraints are set.
topologySpreadConstraints: "" topologySpreadConstraints: ""
# Toleration Settings for master pods
# Toleration Settings for pods
# This should be a multi-line string matching the Toleration array # This should be a multi-line string matching the Toleration array
# in a PodSpec. # in a PodSpec.
tolerations: "" tolerations: ""
# nodeSelector labels for master pod assignment, formatted as a muli-line string.
# nodeSelector labels for pod assignment, formatted as a muli-line string.
# ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector # ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
nodeSelector: "" nodeSelector: ""
# Used to assign priority to master pods
# Used to assign priority to pods
# ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ # ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
priorityClassName: "" priorityClassName: ""

Loading…
Cancel
Save