diff --git a/packages/apps/bucket/Chart.yaml b/packages/apps/bucket/Chart.yaml
new file mode 100644
index 00000000..94b33a62
--- /dev/null
+++ b/packages/apps/bucket/Chart.yaml
@@ -0,0 +1,25 @@
+apiVersion: v2
+name: bucket
+description: S3 compatible storage
+icon: /logos/bucket.svg
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "0.1.0"
diff --git a/packages/apps/bucket/Makefile b/packages/apps/bucket/Makefile
new file mode 100644
index 00000000..207e2133
--- /dev/null
+++ b/packages/apps/bucket/Makefile
@@ -0,0 +1,2 @@
+generate:
+ readme-generator -v values.yaml -s values.schema.json -r README.md
diff --git a/packages/apps/bucket/logos/bucket.svg b/packages/apps/bucket/logos/bucket.svg
new file mode 100644
index 00000000..9f44da57
--- /dev/null
+++ b/packages/apps/bucket/logos/bucket.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/apps/bucket/templates/bucketclaim.yaml b/packages/apps/bucket/templates/bucketclaim.yaml
new file mode 100644
index 00000000..cebf95b4
--- /dev/null
+++ b/packages/apps/bucket/templates/bucketclaim.yaml
@@ -0,0 +1,20 @@
+{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }}
+{{- $seaweedfs := index $myNS.metadata.annotations "namespace.cozystack.io/seaweedfs" }}
+apiVersion: objectstorage.k8s.io/v1alpha1
+kind: BucketClaim
+metadata:
+ name: {{ .Release.Name }}
+spec:
+ bucketClassName: {{ $seaweedfs }}
+ protocols:
+ - s3
+---
+apiVersion: objectstorage.k8s.io/v1alpha1
+kind: BucketAccess
+metadata:
+ name: {{ .Release.Name }}
+spec:
+ bucketAccessClassName: {{ $seaweedfs }}
+ bucketClaimName: {{ .Release.Name }}
+ credentialsSecretName: {{ .Release.Name }}
+ protocol: s3
diff --git a/packages/apps/bucket/templates/dashboard-resourcemap.yaml b/packages/apps/bucket/templates/dashboard-resourcemap.yaml
new file mode 100644
index 00000000..560d0d29
--- /dev/null
+++ b/packages/apps/bucket/templates/dashboard-resourcemap.yaml
@@ -0,0 +1,12 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ .Release.Name }}-dashboard-resources
+rules:
+- apiGroups:
+ - ""
+ resources:
+ - secrets
+ resourceNames:
+ - {{ .Release.Name }}
+ verbs: ["get", "list", "watch"]
diff --git a/packages/apps/tenant/Chart.yaml b/packages/apps/tenant/Chart.yaml
index f40c3a6e..baefc0e2 100644
--- a/packages/apps/tenant/Chart.yaml
+++ b/packages/apps/tenant/Chart.yaml
@@ -4,4 +4,4 @@ description: Separated tenant namespace
icon: /logos/tenant.svg
type: application
-version: 1.3.1
+version: 1.4.0
diff --git a/packages/apps/tenant/README.md b/packages/apps/tenant/README.md
index 6d0373e2..6e270636 100644
--- a/packages/apps/tenant/README.md
+++ b/packages/apps/tenant/README.md
@@ -56,4 +56,5 @@ tenant-u1
| `etcd` | Deploy own Etcd cluster | `false` |
| `monitoring` | Deploy own Monitoring Stack | `false` |
| `ingress` | Deploy own Ingress Controller | `false` |
+| `seaweedfs` | Deploy own SeaweedFS | `false` |
| `isolated` | Enforce tenant namespace with network policies | `false` |
diff --git a/packages/apps/tenant/templates/monitoring.yaml b/packages/apps/tenant/templates/monitoring.yaml
index 93772546..f0fef4a2 100644
--- a/packages/apps/tenant/templates/monitoring.yaml
+++ b/packages/apps/tenant/templates/monitoring.yaml
@@ -23,9 +23,6 @@ spec:
interval: 1m0s
timeout: 5m0s
values:
- {{- with .Values.host }}
- host: grafana.{{ . }}
- {{- end }}
metricsStorages:
- name: shortterm
retentionPeriod: "3d"
diff --git a/packages/apps/tenant/templates/namespace.yaml b/packages/apps/tenant/templates/namespace.yaml
index 9b20d514..3d2ec3b1 100644
--- a/packages/apps/tenant/templates/namespace.yaml
+++ b/packages/apps/tenant/templates/namespace.yaml
@@ -1,7 +1,7 @@
{{- define "cozystack.namespace-anotations" }}
{{- $context := index . 0 }}
{{- $existingNS := index . 1 }}
-{{- range $x := list "etcd" "monitoring" "ingress" }}
+{{- range $x := list "etcd" "monitoring" "ingress" "seaweedfs" }}
{{- if (index $context.Values $x) }}
namespace.cozystack.io/{{ $x }}: "{{ include "tenant.name" $context }}"
{{- else }}
diff --git a/packages/apps/tenant/templates/seaweedfs.yaml b/packages/apps/tenant/templates/seaweedfs.yaml
new file mode 100644
index 00000000..5741d930
--- /dev/null
+++ b/packages/apps/tenant/templates/seaweedfs.yaml
@@ -0,0 +1,25 @@
+{{- if .Values.seaweedfs }}
+apiVersion: helm.toolkit.fluxcd.io/v2
+kind: HelmRelease
+metadata:
+ name: seaweedfs
+ namespace: {{ include "tenant.name" . }}
+ annotations:
+ helm.sh/resource-policy: keep
+ labels:
+ cozystack.io/ui: "true"
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/managed-by: {{ .Release.Service }}
+spec:
+ chart:
+ spec:
+ chart: seaweedfs
+ reconcileStrategy: Revision
+ sourceRef:
+ kind: HelmRepository
+ name: cozystack-extra
+ namespace: cozy-public
+ version: "*"
+ interval: 1m0s
+ timeout: 5m0s
+{{- end }}
diff --git a/packages/apps/tenant/values.schema.json b/packages/apps/tenant/values.schema.json
index 7f87cda1..4d270ecd 100644
--- a/packages/apps/tenant/values.schema.json
+++ b/packages/apps/tenant/values.schema.json
@@ -22,6 +22,11 @@
"description": "Deploy own Ingress Controller",
"default": false
},
+ "seaweedfs": {
+ "type": "boolean",
+ "description": "Deploy own SeaweedFS",
+ "default": false
+ },
"isolated": {
"type": "boolean",
"description": "Enforce tenant namespace with network policies",
diff --git a/packages/apps/tenant/values.yaml b/packages/apps/tenant/values.yaml
index d52e99ca..ec4dcb18 100644
--- a/packages/apps/tenant/values.yaml
+++ b/packages/apps/tenant/values.yaml
@@ -4,9 +4,11 @@
## @param etcd Deploy own Etcd cluster
## @param monitoring Deploy own Monitoring Stack
## @param ingress Deploy own Ingress Controller
+## @param seaweedfs Deploy own SeaweedFS
## @param isolated Enforce tenant namespace with network policies
host: ""
etcd: false
monitoring: false
ingress: false
+seaweedfs: false
isolated: false
diff --git a/packages/apps/versions_map b/packages/apps/versions_map
index d763f504..2742f60f 100644
--- a/packages/apps/versions_map
+++ b/packages/apps/versions_map
@@ -1,3 +1,4 @@
+bucket 0.1.0 HEAD
clickhouse 0.1.0 ca79f72
clickhouse 0.2.0 7cd7de73
clickhouse 0.2.1 HEAD
@@ -40,7 +41,8 @@ tenant 1.0.0 7cd7de7
tenant 1.1.0 4da8ac3b
tenant 1.2.0 15478a88
tenant 1.3.0 ceefae03
-tenant 1.3.1 HEAD
+tenant 1.3.1 c56e5769
+tenant 1.4.0 HEAD
virtual-machine 0.1.4 f2015d6
virtual-machine 0.1.5 7cd7de7
virtual-machine 0.2.0 HEAD
diff --git a/packages/core/platform/templates/apps.yaml b/packages/core/platform/templates/apps.yaml
index 073edbdb..859302db 100644
--- a/packages/core/platform/templates/apps.yaml
+++ b/packages/core/platform/templates/apps.yaml
@@ -19,6 +19,7 @@ metadata:
namespace.cozystack.io/etcd: tenant-root
namespace.cozystack.io/monitoring: tenant-root
namespace.cozystack.io/ingress: tenant-root
+ namespace.cozystack.io/seaweedfs: tenant-root
namespace.cozystack.io/host: "{{ $host }}"
name: tenant-root
---
diff --git a/packages/extra/seaweedfs/.helmignore b/packages/extra/seaweedfs/.helmignore
new file mode 100644
index 00000000..1ea0ae84
--- /dev/null
+++ b/packages/extra/seaweedfs/.helmignore
@@ -0,0 +1,3 @@
+.helmignore
+/logos
+/Makefile
diff --git a/packages/extra/seaweedfs/Chart.yaml b/packages/extra/seaweedfs/Chart.yaml
new file mode 100644
index 00000000..741983e1
--- /dev/null
+++ b/packages/extra/seaweedfs/Chart.yaml
@@ -0,0 +1,25 @@
+apiVersion: v2
+name: seaweedfs
+description: Seaweedfs
+icon: /logos/seaweedfs.svg
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "3.71"
diff --git a/packages/extra/seaweedfs/Makefile b/packages/extra/seaweedfs/Makefile
new file mode 100644
index 00000000..207e2133
--- /dev/null
+++ b/packages/extra/seaweedfs/Makefile
@@ -0,0 +1,2 @@
+generate:
+ readme-generator -v values.yaml -s values.schema.json -r README.md
diff --git a/packages/extra/seaweedfs/README.md b/packages/extra/seaweedfs/README.md
new file mode 100644
index 00000000..7b65ce17
--- /dev/null
+++ b/packages/extra/seaweedfs/README.md
@@ -0,0 +1,12 @@
+# Managed NATS Service
+
+## Parameters
+
+### Common parameters
+
+| Name | Description | Value |
+| ---------- | --------------------------------------------------------------------------------------------------------- | ----- |
+| `host` | The hostname used to access the grafana externally (defaults to 'grafana' subdomain for the tenant host). | `""` |
+| `replicas` | Persistent Volume size for NATS | `2` |
+| `size` | Persistent Volume size | `4Gi` |
+
diff --git a/packages/extra/seaweedfs/logos/seaweedfs.svg b/packages/extra/seaweedfs/logos/seaweedfs.svg
new file mode 100644
index 00000000..61fce568
--- /dev/null
+++ b/packages/extra/seaweedfs/logos/seaweedfs.svg
@@ -0,0 +1,317 @@
+
+
+
+
diff --git a/packages/extra/seaweedfs/templates/seaweedfs.yaml b/packages/extra/seaweedfs/templates/seaweedfs.yaml
new file mode 100644
index 00000000..739b1fa9
--- /dev/null
+++ b/packages/extra/seaweedfs/templates/seaweedfs.yaml
@@ -0,0 +1,55 @@
+{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }}
+{{- $ingress := index $myNS.metadata.annotations "namespace.cozystack.io/ingress" }}
+{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }}
+apiVersion: helm.toolkit.fluxcd.io/v2
+kind: HelmRelease
+metadata:
+ name: {{ .Release.Name }}-system
+spec:
+ chart:
+ spec:
+ chart: cozy-seaweedfs
+ reconcileStrategy: Revision
+ sourceRef:
+ kind: HelmRepository
+ name: cozystack-system
+ namespace: cozy-system
+ version: '*'
+ interval: 1m0s
+ timeout: 5m0s
+ values:
+ global:
+ serviceAccountName: "{{ .Release.Namespace }}-seaweedfs"
+
+ seaweedfs:
+
+ volume:
+ replicas: {{ .Values.replicas }}
+
+ # TODO: workaround for non-working online resize
+ podAnnotations:
+ volume-size: "{{ .Values.size }}"
+
+ dataDirs:
+ - name: data1
+ type: "persistentVolumeClaim"
+ size: "{{ .Values.size }}"
+ maxVolumes: 0
+
+ s3:
+ ingress:
+ className: {{ $ingress }}
+ host: {{ .Values.host | default (printf "s3.%s" $host) }}
+ annotations:
+ nginx.ingress.kubernetes.io/proxy-body-size: "0"
+ nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
+ acme.cert-manager.io/http01-ingress-class: {{ $ingress }}
+ cert-manager.io/cluster-issuer: letsencrypt-prod
+ tls:
+ - hosts:
+ - {{ .Values.host | default (printf "seaweedfs.%s" $host) }}
+ secretName: {{ .Release.Name }}-s3-ingress-tls
+
+ cosi:
+ driverName: "{{ .Release.Namespace }}.seaweedfs.objectstorage.k8s.io"
+ bucketClassName: "{{ .Release.Namespace }}"
diff --git a/packages/extra/seaweedfs/values.schema.json b/packages/extra/seaweedfs/values.schema.json
new file mode 100644
index 00000000..545b840b
--- /dev/null
+++ b/packages/extra/seaweedfs/values.schema.json
@@ -0,0 +1,21 @@
+{
+ "title": "Chart Values",
+ "type": "object",
+ "properties": {
+ "host": {
+ "type": "string",
+ "description": "The hostname used to access the grafana externally (defaults to 'grafana' subdomain for the tenant host).",
+ "default": ""
+ },
+ "replicas": {
+ "type": "number",
+ "description": "Persistent Volume size for NATS",
+ "default": 2
+ },
+ "size": {
+ "type": "string",
+ "description": "Persistent Volume size",
+ "default": "4Gi"
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/extra/seaweedfs/values.yaml b/packages/extra/seaweedfs/values.yaml
new file mode 100644
index 00000000..a74695af
--- /dev/null
+++ b/packages/extra/seaweedfs/values.yaml
@@ -0,0 +1,10 @@
+## @section Common parameters
+
+## @param host The hostname used to access the grafana externally (defaults to 'grafana' subdomain for the tenant host).
+host: ""
+
+## @param replicas Persistent Volume size for NATS
+## @param size Persistent Volume size
+##
+replicas: 2
+size: 10Gi
diff --git a/packages/extra/versions_map b/packages/extra/versions_map
index 8453643d..139b5c64 100644
--- a/packages/extra/versions_map
+++ b/packages/extra/versions_map
@@ -9,3 +9,4 @@ ingress 1.2.0 HEAD
monitoring 1.0.0 f642698
monitoring 1.1.0 15478a88
monitoring 1.2.0 HEAD
+seaweedfs 0.1.0 HEAD
diff --git a/packages/system/seaweedfs/Chart.yaml b/packages/system/seaweedfs/Chart.yaml
new file mode 100644
index 00000000..b6aee535
--- /dev/null
+++ b/packages/system/seaweedfs/Chart.yaml
@@ -0,0 +1,3 @@
+apiVersion: v2
+name: cozy-seaweedfs
+version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process
diff --git a/packages/system/seaweedfs/Makefile b/packages/system/seaweedfs/Makefile
new file mode 100644
index 00000000..e079734e
--- /dev/null
+++ b/packages/system/seaweedfs/Makefile
@@ -0,0 +1,7 @@
+update:
+ rm -rf charts
+ mkdir -p charts
+ curl -sSL https://github.com/seaweedfs/seaweedfs/archive/refs/heads/master.tar.gz | \
+ tar xzvf - --strip 3 -C charts seaweedfs-master/k8s/charts/seaweedfs
+ patch --no-backup-if-mismatch -p4 < patches/retention-policy-delete.yaml
+ patch --no-backup-if-mismatch -p4 < patches/resize-api-server-annotation.diff
diff --git a/packages/system/seaweedfs/charts/seaweedfs/.helmignore b/packages/system/seaweedfs/charts/seaweedfs/.helmignore
new file mode 100644
index 00000000..50af0317
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/.helmignore
@@ -0,0 +1,22 @@
+# 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
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/packages/system/seaweedfs/charts/seaweedfs/Chart.yaml b/packages/system/seaweedfs/charts/seaweedfs/Chart.yaml
new file mode 100644
index 00000000..073679af
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v1
+description: SeaweedFS
+name: seaweedfs
+appVersion: "3.71"
+# Dev note: Trigger a helm chart release by `git tag -a helm-`
+version: 4.0.0
diff --git a/packages/system/seaweedfs/charts/seaweedfs/README.md b/packages/system/seaweedfs/charts/seaweedfs/README.md
new file mode 100644
index 00000000..41707ba8
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/README.md
@@ -0,0 +1,146 @@
+# SEAWEEDFS - helm chart (2.x+)
+
+## Getting Started
+
+### Add the helm repo
+
+```bash
+helm repo add seaweedfs https://seaweedfs.github.io/seaweedfs/helm
+```
+
+### Install the helm chart
+
+```bash
+helm install seaweedfs seaweedfs/seaweedfs
+```
+
+### (Recommended) Provide `values.yaml`
+
+```bash
+helm install --values=values.yaml seaweedfs seaweedfs/seaweedfs
+```
+
+## Info:
+* master/filer/volume are stateful sets with anti-affinity on the hostname,
+so your deployment will be spread/HA.
+* chart is using memsql(mysql) as the filer backend to enable HA (multiple filer instances) and backup/HA memsql can provide.
+* mysql user/password are created in a k8s secret (secret-seaweedfs-db.yaml) and injected to the filer with ENV.
+* cert config exists and can be enabled, but not been tested, requires cert-manager to be installed.
+
+## Prerequisites
+### Database
+
+leveldb is the default database, this supports multiple filer replicas that will [sync automatically](https://github.com/seaweedfs/seaweedfs/wiki/Filer-Store-Replication), with some [limitations](https://github.com/seaweedfs/seaweedfs/wiki/Filer-Store-Replication#limitation).
+
+When the [limitations](https://github.com/seaweedfs/seaweedfs/wiki/Filer-Store-Replication#limitation) apply, or for a large number of filer replicas, an external datastore is recommended.
+
+Such as MySQL-compatible database, as specified in the `values.yaml` at `filer.extraEnvironmentVars`.
+This database should be pre-configured and initialized by running:
+```sql
+CREATE TABLE IF NOT EXISTS `filemeta` (
+ `dirhash` BIGINT NOT NULL COMMENT 'first 64 bits of MD5 hash value of directory field',
+ `name` VARCHAR(766) NOT NULL COMMENT 'directory or file name',
+ `directory` TEXT NOT NULL COMMENT 'full path to parent directory',
+ `meta` LONGBLOB,
+ PRIMARY KEY (`dirhash`, `name`)
+) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
+```
+
+Alternative database can also be configured (e.g. leveldb, postgres) following the instructions at `filer.extraEnvironmentVars`.
+
+### Node Labels
+Kubernetes nodes can have labels which help to define which node(Host) will run which pod:
+
+Here is an example:
+* s3/filer/master needs the label **sw-backend=true**
+* volume need the label **sw-volume=true**
+
+to label a node to be able to run all pod types in k8s:
+```
+kubectl label node YOUR_NODE_NAME sw-volume=true,sw-backend=true
+```
+
+on production k8s deployment you will want each pod to have a different host,
+especially the volume server and the masters, all pods (master/volume/filer)
+should have anti-affinity rules to disallow running multiple component pods on the same host.
+
+If you still want to run multiple pods of the same component (master/volume/filer) on the same host please set/update the corresponding affinity rule in values.yaml to an empty one:
+
+```affinity: ""```
+
+## PVC - storage class ###
+
+On the volume stateful set added support for k8s PVC, currently example
+with the simple local-path-provisioner from Rancher (comes included with k3d / k3s)
+https://github.com/rancher/local-path-provisioner
+
+you can use ANY storage class you like, just update the correct storage-class
+for your deployment.
+
+## current instances config (AIO):
+
+1 instance for each type (master/filer+s3/volume)
+
+You can update the replicas count for each node type in values.yaml,
+need to add more nodes with the corresponding labels if applicable.
+
+Most of the configuration are available through values.yaml any pull requests to expand functionality or usability are greatly appreciated. Any pull request must pass [chart-testing](https://github.com/helm/chart-testing).
+
+## S3 configuration
+
+To enable an s3 endpoint for your filer with a default install add the following to your values.yaml:
+
+```yaml
+filer:
+ s3:
+ enabled: true
+```
+
+### Enabling Authentication to S3
+
+To enable authentication for S3, you have two options:
+
+- let the helm chart create an admin user as well as a read only user
+- provide your own s3 config.json file via an existing Kubernetes Secret
+
+#### Use the default credentials for S3
+
+Example parameters for your values.yaml:
+
+```yaml
+filer:
+ s3:
+ enabled: true
+ enableAuth: true
+```
+
+#### Provide your own credentials for S3
+
+Example parameters for your values.yaml:
+
+```yaml
+filer:
+ s3:
+ enabled: true
+ enableAuth: true
+ existingConfigSecret: my-s3-secret
+```
+
+Example existing secret with your s3 config to create an admin user and readonly user, both with credentials:
+
+```yaml
+---
+# Source: seaweedfs/templates/seaweedfs-s3-secret.yaml
+apiVersion: v1
+kind: Secret
+type: Opaque
+metadata:
+ name: my-s3-secret
+ namespace: seaweedfs
+ labels:
+ app.kubernetes.io/name: seaweedfs
+ app.kubernetes.io/component: s3
+stringData:
+ # this key must be an inline json config file
+ seaweedfs_s3_config: '{"identities":[{"name":"anvAdmin","credentials":[{"accessKey":"snu8yoP6QAlY0ne4","secretKey":"PNzBcmeLNEdR0oviwm04NQAicOrDH1Km"}],"actions":["Admin","Read","Write"]},{"name":"anvReadOnly","credentials":[{"accessKey":"SCigFee6c5lbi04A","secretKey":"kgFhbT38R8WUYVtiFQ1OiSVOrYr3NKku"}],"actions":["Read"]}]}'
+```
diff --git a/packages/system/seaweedfs/charts/seaweedfs/dashboards/seaweedfs-grafana-dashboard.json b/packages/system/seaweedfs/charts/seaweedfs/dashboards/seaweedfs-grafana-dashboard.json
new file mode 100644
index 00000000..f4e3b020
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/dashboards/seaweedfs-grafana-dashboard.json
@@ -0,0 +1,3269 @@
+{
+ "annotations": {
+ "list": [
+ {
+ "builtIn": 1,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "enable": true,
+ "hide": true,
+ "iconColor": "rgba(0, 211, 255, 1)",
+ "limit": 100,
+ "name": "Annotations & Alerts",
+ "showIn": 0,
+ "type": "dashboard"
+ }
+ ]
+ },
+ "editable": true,
+ "fiscalYearStartMonth": 0,
+ "gnetId": 10423,
+ "graphTooltip": 0,
+ "id": 160,
+ "links": [],
+ "liveNow": false,
+ "panels": [
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
+ "id": 67,
+ "panels": [],
+ "title": "Master",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "description": "Whether master is leader or not",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
+ "unit": "bool_yes_no",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 0,
+ "y": 1
+ },
+ "id": 57,
+ "links": [],
+ "options": {
+ "colorMode": "value",
+ "graphMode": "area",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "reduceOptions": {
+ "calcs": [
+ "last"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "text": {},
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "exemplar": true,
+ "expr": "sum by (pod) (SeaweedFS_master_is_leader{job=\"seaweedfs-master\", namespace=\"$NAMESPACE\"})",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{pod}}",
+ "refId": "A",
+ "step": 60
+ }
+ ],
+ "title": "Raft leader",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "description": "Count times leader changed",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 4,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
+ "unit": "none",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 8,
+ "y": 1
+ },
+ "id": 68,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "8.1.2",
+ "targets": [
+ {
+ "exemplar": true,
+ "expr": "sum by (pod) (SeaweedFS_master_leader_changes{job=\"seaweedfs-master\", type=~\".+\", namespace=\"$NAMESPACE\"})",
+ "format": "time_series",
+ "hide": false,
+ "instant": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{pod}}",
+ "refId": "A",
+ "step": 60
+ }
+ ],
+ "title": "Master leader changes",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "description": "Heartbeats received from components",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 4,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
+ "unit": "none",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 16,
+ "y": 1
+ },
+ "id": 69,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "8.1.2",
+ "targets": [
+ {
+ "exemplar": true,
+ "expr": "sum by (type) (increase(SeaweedFS_master_received_heartbeats{job=\"seaweedfs-master\", namespace=\"$NAMESPACE\"}[$__rate_interval]))",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "A",
+ "step": 60
+ }
+ ],
+ "title": "Received heartbeats",
+ "type": "timeseries"
+ },
+ {
+ "alert": {
+ "alertRuleTags": {},
+ "conditions": [
+ {
+ "evaluator": {
+ "params": [
+ 0
+ ],
+ "type": "gt"
+ },
+ "operator": {
+ "type": "and"
+ },
+ "query": {
+ "params": [
+ "A",
+ "5m",
+ "now"
+ ]
+ },
+ "reducer": {
+ "params": [],
+ "type": "avg"
+ },
+ "type": "query"
+ }
+ ],
+ "executionErrorState": "alerting",
+ "for": "5m",
+ "frequency": "1m",
+ "handler": 1,
+ "message": "",
+ "name": "Replica Placement Mismatch alert",
+ "noDataState": "ok",
+ "notifications": []
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "description": "Count replica placement mismatch",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 4,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
+ "unit": "none",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 0,
+ "y": 7
+ },
+ "id": 70,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "8.1.2",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "editorMode": "code",
+ "exemplar": true,
+ "expr": "sum (SeaweedFS_master_replica_placement_mismatch{job=\"seaweedfs-master\", namespace=\"$NAMESPACE\"} > 0) by (pod)",
+ "format": "time_series",
+ "hide": false,
+ "instant": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{pod}}",
+ "refId": "A",
+ "step": 60
+ }
+ ],
+ "thresholds": [
+ {
+ "colorMode": "critical",
+ "op": "gt",
+ "value": 0,
+ "visible": true
+ }
+ ],
+ "title": "Replica Placement Mismatch",
+ "type": "timeseries"
+ },
+ {
+ "alert": {
+ "alertRuleTags": {},
+ "conditions": [
+ {
+ "evaluator": {
+ "params": [
+ 1,
+ 1
+ ],
+ "type": "outside_range"
+ },
+ "operator": {
+ "type": "and"
+ },
+ "query": {
+ "params": [
+ "A",
+ "5m",
+ "now"
+ ]
+ },
+ "reducer": {
+ "params": [],
+ "type": "avg"
+ },
+ "type": "query"
+ }
+ ],
+ "executionErrorState": "alerting",
+ "for": "5m",
+ "frequency": "1m",
+ "handler": 1,
+ "message": "Raft leader count of master-servers not equal to 1",
+ "name": "Raft leader alert",
+ "noDataState": "no_data",
+ "notifications": []
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "description": "Total count of raft leaders",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
+ "unit": "none",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 8,
+ "y": 7
+ },
+ "id": 71,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "8.1.2",
+ "targets": [
+ {
+ "exemplar": true,
+ "expr": "sum (SeaweedFS_master_is_leader{job=\"seaweedfs-master\", namespace=\"$NAMESPACE\"})",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "Leaders",
+ "refId": "A",
+ "step": 60
+ }
+ ],
+ "thresholds": [
+ {
+ "colorMode": "critical",
+ "op": "lt",
+ "value": 1,
+ "visible": true
+ },
+ {
+ "colorMode": "critical",
+ "op": "gt",
+ "value": 1,
+ "visible": true
+ }
+ ],
+ "title": "Raft leader count",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "description": "Whether cluster locked or not",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ }
+ ]
+ },
+ "unit": "bool_yes_no",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 6,
+ "w": 8,
+ "x": 16,
+ "y": 7
+ },
+ "id": 74,
+ "links": [],
+ "options": {
+ "colorMode": "value",
+ "graphMode": "area",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "reduceOptions": {
+ "calcs": [
+ "last"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "text": {},
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "editorMode": "code",
+ "exemplar": true,
+ "expr": "SeaweedFS_master_admin_lock{job=\"seaweedfs-master\", namespace=\"$NAMESPACE\"}",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "Client IP: {{client}}",
+ "range": true,
+ "refId": "A",
+ "step": 60
+ }
+ ],
+ "title": "Admin lock",
+ "type": "stat"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 13
+ },
+ "id": 60,
+ "panels": [],
+ "title": "Filer",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 0,
+ "y": 14
+ },
+ "id": 46,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "histogram_quantile(0.90, sum(rate(SeaweedFS_filer_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "average",
+ "refId": "A",
+ "step": 60
+ },
+ {
+ "expr": "histogram_quantile(0.90, sum(rate(SeaweedFS_filer_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le, type))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "B",
+ "step": 60
+ }
+ ],
+ "title": "Filer Request Duration 90th percentile",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 8,
+ "y": 14
+ },
+ "id": 49,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "histogram_quantile(0.95, sum(rate(SeaweedFS_filer_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "average",
+ "refId": "A",
+ "step": 60
+ },
+ {
+ "expr": "histogram_quantile(0.95, sum(rate(SeaweedFS_filer_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le, type))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "B",
+ "step": 60
+ },
+ {
+ "expr": "",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "refId": "C"
+ }
+ ],
+ "title": "Filer Request Duration 95th percentile",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 16,
+ "y": 14
+ },
+ "id": 45,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "histogram_quantile(0.99, sum(rate(SeaweedFS_filer_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "average",
+ "refId": "A",
+ "step": 60
+ },
+ {
+ "expr": "histogram_quantile(0.99, sum(rate(SeaweedFS_filer_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le, type))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "B",
+ "step": 60
+ },
+ {
+ "expr": "",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "refId": "C"
+ }
+ ],
+ "title": "Filer Request Duration 99th percentile",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short",
+ "unitScale": true
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "total"
+ },
+ "properties": [
+ {
+ "id": "custom.lineWidth",
+ "value": 0
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byValue",
+ "options": {
+ "op": "gte",
+ "reducer": "allIsZero",
+ "value": 0
+ }
+ },
+ "properties": [
+ {
+ "id": "custom.hideFrom",
+ "value": {
+ "legend": true,
+ "tooltip": true,
+ "viz": false
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byValue",
+ "options": {
+ "op": "gte",
+ "reducer": "allIsNull",
+ "value": 0
+ }
+ },
+ "properties": [
+ {
+ "id": "custom.hideFrom",
+ "value": {
+ "legend": true,
+ "tooltip": true,
+ "viz": false
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 21
+ },
+ "id": 2,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true,
+ "width": 250
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "desc"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "exemplar": true,
+ "expr": "sum by (type) (rate(SeaweedFS_filer_request_total{namespace=\"$NAMESPACE\"}[$__rate_interval]))",
+ "format": "time_series",
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "A",
+ "step": 30
+ }
+ ],
+ "title": "Filer QPS",
+ "type": "timeseries"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 28
+ },
+ "id": 61,
+ "panels": [],
+ "title": "S3 Gateway",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 0,
+ "y": 29
+ },
+ "id": 65,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "histogram_quantile(0.90, sum(rate(SeaweedFS_s3_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "average",
+ "refId": "A",
+ "step": 60
+ },
+ {
+ "expr": "histogram_quantile(0.90, sum(rate(SeaweedFS_s3_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le, type))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "B",
+ "step": 60
+ }
+ ],
+ "title": "S3 Request Duration 90th percentile",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 8,
+ "y": 29
+ },
+ "id": 56,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "histogram_quantile(0.95, sum(rate(SeaweedFS_s3_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "average",
+ "refId": "A",
+ "step": 60
+ },
+ {
+ "expr": "histogram_quantile(0.95, sum(rate(SeaweedFS_s3_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le, type))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "B",
+ "step": 60
+ }
+ ],
+ "title": "S3 Request Duration 95th percentile",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 16,
+ "y": 29
+ },
+ "id": 58,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "histogram_quantile(0.99, sum(rate(SeaweedFS_s3_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "average",
+ "refId": "A",
+ "step": 60
+ },
+ {
+ "exemplar": true,
+ "expr": "histogram_quantile(0.99, sum(rate(SeaweedFS_s3_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le, type))",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "B",
+ "step": 60
+ }
+ ],
+ "title": "S3 Request Duration 99th percentile",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 36
+ },
+ "id": 72,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "exemplar": true,
+ "expr": "histogram_quantile(0.99, sum(rate(SeaweedFS_s3_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le))",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "average",
+ "refId": "A",
+ "step": 60
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "exemplar": true,
+ "expr": "histogram_quantile(0.99, sum(rate(SeaweedFS_s3_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le, type, pod))",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}-{{pod}}",
+ "refId": "B",
+ "step": 60
+ }
+ ],
+ "title": "S3 Request. Duration 99th percentile per instance",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 43
+ },
+ "id": 73,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "exemplar": true,
+ "expr": "histogram_quantile(0.99, sum(rate(SeaweedFS_s3_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le, type, bucket))",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}-{{bucket}}",
+ "refId": "B",
+ "step": 60
+ }
+ ],
+ "title": "S3 Request Duration 99th percentile per bucket",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short",
+ "unitScale": true
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "total"
+ },
+ "properties": [
+ {
+ "id": "custom.lineWidth",
+ "value": 0
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byValue",
+ "options": {
+ "op": "gte",
+ "reducer": "allIsZero",
+ "value": 0
+ }
+ },
+ "properties": [
+ {
+ "id": "custom.hideFrom",
+ "value": {
+ "legend": true,
+ "tooltip": true,
+ "viz": false
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byValue",
+ "options": {
+ "op": "gte",
+ "reducer": "allIsNull",
+ "value": 0
+ }
+ },
+ "properties": [
+ {
+ "id": "custom.hideFrom",
+ "value": {
+ "legend": true,
+ "tooltip": true,
+ "viz": false
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 50
+ },
+ "id": 55,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true,
+ "width": 250
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "desc"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "expr": "sum (rate(SeaweedFS_s3_request_total{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (type)",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "A",
+ "step": 30
+ }
+ ],
+ "title": "S3 API QPS",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "Cost in US$",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "currencyUSD",
+ "unitScale": true
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "total"
+ },
+ "properties": [
+ {
+ "id": "custom.lineWidth",
+ "value": 0
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byValue",
+ "options": {
+ "op": "gte",
+ "reducer": "allIsZero",
+ "value": 0
+ }
+ },
+ "properties": [
+ {
+ "id": "custom.hideFrom",
+ "value": {
+ "legend": true,
+ "tooltip": true,
+ "viz": false
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byValue",
+ "options": {
+ "op": "gte",
+ "reducer": "allIsNull",
+ "value": 0
+ }
+ },
+ "properties": [
+ {
+ "id": "custom.hideFrom",
+ "value": {
+ "legend": true,
+ "tooltip": true,
+ "viz": false
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 57
+ },
+ "hideTimeOverride": false,
+ "id": 59,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true,
+ "width": 250
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "desc"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "sum by (type) (SeaweedFS_s3_request_total{type=~'PUT|COPY|POST|LIST', namespace=\"$NAMESPACE\"})*0.000005",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{type}} requests",
+ "refId": "A",
+ "step": 30
+ },
+ {
+ "expr": "sum (SeaweedFS_s3_request_total{type=~'PUT|COPY|POST|LIST', namespace=\"$NAMESPACE\"})*0.000005",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "All PUT, COPY, POST, LIST",
+ "refId": "C",
+ "step": 30
+ },
+ {
+ "expr": "sum (SeaweedFS_s3_request_total{type!~'PUT|COPY|POST|LIST', namespace=\"$NAMESPACE\"})*0.0000004",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "GET and all other",
+ "refId": "B"
+ },
+ {
+ "expr": "sum by (type) (SeaweedFS_s3_request_total{type!~'PUT|COPY|POST|LIST', namespace=\"$NAMESPACE\"})*0.0000004",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{type}} requests",
+ "refId": "D"
+ }
+ ],
+ "timeFrom": "1M",
+ "title": "S3 API Monthly Cost if on AWS",
+ "type": "timeseries"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 64
+ },
+ "id": 62,
+ "panels": [],
+ "title": "Volume Server",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 0,
+ "y": 65
+ },
+ "id": 47,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "histogram_quantile(0.99, sum(rate(SeaweedFS_volumeServer_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le, exported_instance))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{exported_instance}}",
+ "refId": "B"
+ },
+ {
+ "expr": "histogram_quantile(0.99, sum(rate(SeaweedFS_volumeServer_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le))",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "average",
+ "refId": "C"
+ }
+ ],
+ "title": "Volume Server Request Duration 99th percentile",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short",
+ "unitScale": true
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byValue",
+ "options": {
+ "op": "gte",
+ "reducer": "allIsZero",
+ "value": 0
+ }
+ },
+ "properties": [
+ {
+ "id": "custom.hideFrom",
+ "value": {
+ "legend": true,
+ "tooltip": true,
+ "viz": false
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byValue",
+ "options": {
+ "op": "gte",
+ "reducer": "allIsNull",
+ "value": 0
+ }
+ },
+ "properties": [
+ {
+ "id": "custom.hideFrom",
+ "value": {
+ "legend": true,
+ "tooltip": true,
+ "viz": false
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 12,
+ "y": 65
+ },
+ "id": 40,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "sum(rate(SeaweedFS_volumeServer_request_total{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (type)",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "A",
+ "step": 4
+ }
+ ],
+ "title": "Volume Server QPS",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 72
+ },
+ "id": 48,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "expr": "sum(SeaweedFS_volumeServer_volumes{namespace=\"$NAMESPACE\"}) by (collection, type)",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{collection}} {{type}}",
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "expr": "sum(SeaweedFS_volumeServer_volumes{namespace=\"$NAMESPACE\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "Total",
+ "refId": "B"
+ }
+ ],
+ "title": "Volume Count",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 79
+ },
+ "id": 50,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "sum(SeaweedFS_volumeServer_total_disk_size{namespace=\"$NAMESPACE\"}) by (collection, type)",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{collection}} {{type}}",
+ "refId": "A"
+ },
+ {
+ "expr": "sum(SeaweedFS_volumeServer_total_disk_size{namespace=\"$NAMESPACE\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "Total",
+ "refId": "B"
+ }
+ ],
+ "title": "Used Disk Space by Collection and Type",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 86
+ },
+ "id": 51,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "sum(SeaweedFS_volumeServer_total_disk_size{namespace=\"$NAMESPACE\"}) by (exported_instance)",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "{{exported_instance}}",
+ "refId": "A"
+ }
+ ],
+ "title": "Used Disk Space by Host",
+ "type": "timeseries"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 93
+ },
+ "id": 63,
+ "panels": [],
+ "title": "Filer Store",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 0,
+ "y": 94
+ },
+ "id": 12,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "histogram_quantile(0.99, sum(rate(SeaweedFS_filerStore_request_seconds_bucket{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (le, type))",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "B"
+ }
+ ],
+ "title": "Filer Store Request Duration 99th percentile",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 12,
+ "y": 94
+ },
+ "id": 14,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [
+ "mean",
+ "lastNotNull"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "expr": "sum(rate(SeaweedFS_filerStore_request_total{namespace=\"$NAMESPACE\"}[$__rate_interval])) by (type)",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{type}}",
+ "refId": "B"
+ }
+ ],
+ "title": "Filer Store QPS",
+ "type": "timeseries"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 101
+ },
+ "id": 64,
+ "panels": [],
+ "title": "Filer Instances",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 0,
+ "y": 102
+ },
+ "id": 52,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "exemplar": true,
+ "expr": "go_memstats_alloc_bytes{job=\"seaweedfs-filer\", namespace=\"$NAMESPACE\"}",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "bytes allocated",
+ "refId": "B"
+ },
+ {
+ "exemplar": true,
+ "expr": "rate(go_memstats_alloc_bytes_total{job=\"seaweedfs-filer\", namespace=\"$NAMESPACE\"}[$__rate_interval])",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "alloc rate",
+ "refId": "A"
+ },
+ {
+ "exemplar": true,
+ "expr": "go_memstats_stack_inuse_bytes{job=\"seaweedfs-filer\", namespace=\"$NAMESPACE\"}",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "stack inuse",
+ "refId": "C"
+ },
+ {
+ "exemplar": true,
+ "expr": "go_memstats_heap_inuse_bytes{job=\"seaweedfs-filer\", namespace=\"$NAMESPACE\"}",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "heap inuse",
+ "refId": "D"
+ }
+ ],
+ "title": "Filer Go Memory Stats",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 12,
+ "y": 102
+ },
+ "id": 54,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "exemplar": true,
+ "expr": "go_gc_duration_seconds{job=\"seaweedfs-filer\", namespace=\"$NAMESPACE\"}",
+ "format": "time_series",
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{quantile}}",
+ "refId": "B"
+ }
+ ],
+ "title": "Filer Go GC duration quantiles",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 2,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "none",
+ "unitScale": true
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 109
+ },
+ "id": 53,
+ "links": [],
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "10.3.1",
+ "targets": [
+ {
+ "exemplar": true,
+ "expr": "go_goroutines{job=\"seaweedfs-filer\", namespace=\"$NAMESPACE\"}",
+ "format": "time_series",
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{exported_instance}}",
+ "refId": "B"
+ }
+ ],
+ "title": "Filer Go Routines",
+ "type": "timeseries"
+ }
+ ],
+ "refresh": "",
+ "schemaVersion": 39,
+ "tags": [],
+ "templating": {
+ "list": [
+ {
+ "current": {
+ "selected": false,
+ "text": "Prometheus",
+ "value": "PBFA97CFB590B2093"
+ },
+ "hide": 0,
+ "includeAll": false,
+ "label": "Datasource",
+ "multi": false,
+ "name": "DS_PROMETHEUS",
+ "options": [],
+ "query": "prometheus",
+ "queryValue": "",
+ "refresh": 1,
+ "regex": "",
+ "skipUrlSync": false,
+ "type": "datasource"
+ },
+ {
+ "current": {
+ "selected": false,
+ "text": "mes",
+ "value": "mes"
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "${DS_PROMETHEUS}"
+ },
+ "definition": "label_values(SeaweedFS_master_is_leader,namespace)",
+ "hide": 0,
+ "includeAll": false,
+ "label": "Namespace",
+ "multi": false,
+ "name": "NAMESPACE",
+ "options": [],
+ "query": {
+ "qryType": 1,
+ "query": "label_values(SeaweedFS_master_is_leader,namespace)",
+ "refId": "PrometheusVariableQueryEditor-VariableQuery"
+ },
+ "refresh": 1,
+ "regex": "",
+ "skipUrlSync": false,
+ "sort": 2,
+ "type": "query"
+ }
+ ]
+ },
+ "time": {
+ "from": "now-1d",
+ "to": "now"
+ },
+ "timepicker": {
+ "refresh_intervals": [
+ "5s",
+ "10s",
+ "30s",
+ "1m",
+ "5m",
+ "15m",
+ "30m",
+ "1h",
+ "2h",
+ "1d"
+ ],
+ "time_options": [
+ "5m",
+ "15m",
+ "1h",
+ "6h",
+ "12h",
+ "24h",
+ "2d",
+ "7d",
+ "30d"
+ ]
+ },
+ "timezone": "browser",
+ "title": "SeaweedFS",
+ "uid": "a24009d7-cbda-4443-a132-1cc1c4677304",
+ "version": 1,
+ "weekStart": ""
+}
\ No newline at end of file
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/_helpers.tpl b/packages/system/seaweedfs/charts/seaweedfs/templates/_helpers.tpl
new file mode 100644
index 00000000..d8261eb3
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/_helpers.tpl
@@ -0,0 +1,167 @@
+{{/*
+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 "seaweedfs.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 "seaweedfs.chart" -}}
+{{- printf "%s-helm" .Chart.Name | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "seaweedfs.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Inject extra environment vars in the format key:value, if populated
+*/}}
+{{- define "seaweedfs.extraEnvironmentVars" -}}
+{{- if .extraEnvironmentVars -}}
+{{- range $key, $value := .extraEnvironmentVars }}
+- name: {{ $key }}
+ value: {{ $value | quote }}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+
+{{/* Return the proper filer image */}}
+{{- define "filer.image" -}}
+{{- if .Values.filer.imageOverride -}}
+{{- $imageOverride := .Values.filer.imageOverride -}}
+{{- printf "%s" $imageOverride -}}
+{{- else -}}
+{{- include "common.image" . }}
+{{- end -}}
+{{- end -}}
+
+{{/* Return the proper master image */}}
+{{- define "master.image" -}}
+{{- if .Values.master.imageOverride -}}
+{{- $imageOverride := .Values.master.imageOverride -}}
+{{- printf "%s" $imageOverride -}}
+{{- else -}}
+{{- include "common.image" . }}
+{{- end -}}
+{{- end -}}
+
+{{/* Return the proper s3 image */}}
+{{- define "s3.image" -}}
+{{- if .Values.s3.imageOverride -}}
+{{- $imageOverride := .Values.s3.imageOverride -}}
+{{- printf "%s" $imageOverride -}}
+{{- else -}}
+{{- include "common.image" . }}
+{{- end -}}
+{{- end -}}
+
+{{/* Return the proper volume image */}}
+{{- define "volume.image" -}}
+{{- if .Values.volume.imageOverride -}}
+{{- $imageOverride := .Values.volume.imageOverride -}}
+{{- printf "%s" $imageOverride -}}
+{{- else -}}
+{{- include "common.image" . }}
+{{- end -}}
+{{- end -}}
+
+{{/* Computes the container image name for all components (if they are not overridden) */}}
+{{- define "common.image" -}}
+{{- $registryName := default .Values.image.registry .Values.global.registry | toString -}}
+{{- $repositoryName := .Values.image.repository | toString -}}
+{{- $name := .Values.global.imageName | toString -}}
+{{- $tag := .Chart.AppVersion | toString -}}
+{{- if $registryName -}}
+{{- printf "%s/%s%s:%s" $registryName $repositoryName $name $tag -}}
+{{- else -}}
+{{- printf "%s%s:%s" $repositoryName $name $tag -}}
+{{- end -}}
+{{- end -}}
+
+{{/* check if any Volume PVC exists */}}
+{{- define "volume.pvc_exists" -}}
+{{- if or (or (eq .Values.volume.data.type "persistentVolumeClaim") (and (eq .Values.volume.idx.type "persistentVolumeClaim") .Values.volume.dir_idx )) (eq .Values.volume.logs.type "persistentVolumeClaim") -}}
+{{- printf "true" -}}
+{{- else -}}
+{{- printf "" -}}
+{{- end -}}
+{{- end -}}
+
+{{/* check if any Filer PVC exists */}}
+{{- define "filer.pvc_exists" -}}
+{{- if or (eq .Values.filer.data.type "persistentVolumeClaim") (eq .Values.filer.logs.type "persistentVolumeClaim") -}}
+{{- printf "true" -}}
+{{- else -}}
+{{- printf "" -}}
+{{- end -}}
+{{- end -}}
+
+{{/* check if any Master PVC exists */}}
+{{- define "master.pvc_exists" -}}
+{{- if or (eq .Values.master.data.type "persistentVolumeClaim") (eq .Values.master.logs.type "persistentVolumeClaim") -}}
+{{- printf "true" -}}
+{{- else -}}
+{{- printf "" -}}
+{{- end -}}
+{{- end -}}
+
+{{/* check if any InitContainers exist for Volumes */}}
+{{- define "volume.initContainers_exists" -}}
+{{- if or (not (empty .Values.volume.idx )) (not (empty .Values.volume.initContainers )) -}}
+{{- printf "true" -}}
+{{- else -}}
+{{- printf "" -}}
+{{- end -}}
+{{- end -}}
+
+{{/* Return the proper imagePullSecrets */}}
+{{- define "seaweedfs.imagePullSecrets" -}}
+{{- if .Values.global.imagePullSecrets }}
+{{- if kindIs "string" .Values.global.imagePullSecrets }}
+imagePullSecrets:
+ - name: {{ .Values.global.imagePullSecrets }}
+{{- else }}
+imagePullSecrets:
+{{- range .Values.global.imagePullSecrets }}
+ - name: {{ . }}
+{{- end }}
+{{- end }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Renders a value that contains template perhaps with scope if the scope is present.
+Usage:
+{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }}
+{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }}
+*/}}
+{{- define "common.tplvalues.render" -}}
+{{- $value := typeIs "string" .value | ternary .value (.value | toYaml) }}
+{{- if contains "{{" (toJson .value) }}
+ {{- if .scope }}
+ {{- tpl (cat "{{- with $.RelativeScope -}}" $value "{{- end }}") (merge (dict "RelativeScope" .scope) .context) }}
+ {{- else }}
+ {{- tpl $value .context }}
+ {{- end }}
+{{- else }}
+ {{- $value }}
+{{- end }}
+{{- end -}}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/ca-cert.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/ca-cert.yaml
new file mode 100644
index 00000000..0fd6615e
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/ca-cert.yaml
@@ -0,0 +1,19 @@
+{{- if and .Values.global.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
+apiVersion: cert-manager.io/v1{{ if .Values.global.certificates.alphacrds }}alpha1{{ end }}
+kind: Certificate
+metadata:
+ name: {{ template "seaweedfs.name" . }}-ca-cert
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+spec:
+ secretName: {{ template "seaweedfs.name" . }}-ca-cert
+ commonName: "{{ template "seaweedfs.name" . }}-root-ca"
+ isCA: true
+ issuerRef:
+ name: {{ template "seaweedfs.name" . }}-issuer
+ kind: Issuer
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/cert-caissuer.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/cert-caissuer.yaml
new file mode 100644
index 00000000..72de126e
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/cert-caissuer.yaml
@@ -0,0 +1,15 @@
+{{- if and .Values.global.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
+apiVersion: cert-manager.io/v1{{ if .Values.global.certificates.alphacrds }}alpha1{{ end }}
+kind: Issuer
+metadata:
+ name: {{ template "seaweedfs.name" . }}-ca-issuer
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+spec:
+ ca:
+ secretName: {{ template "seaweedfs.name" . }}-ca-cert
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/cert-issuer.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/cert-issuer.yaml
new file mode 100644
index 00000000..9f243d07
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/cert-issuer.yaml
@@ -0,0 +1,13 @@
+{{- if and .Values.global.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
+apiVersion: cert-manager.io/v1{{ if .Values.global.certificates.alphacrds }}alpha1{{ end }}
+kind: Issuer
+metadata:
+ name: {{ template "seaweedfs.name" . }}-issuer
+ 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 }}
+spec:
+ selfSigned: {}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/client-cert.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/client-cert.yaml
new file mode 100644
index 00000000..bda132a0
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/client-cert.yaml
@@ -0,0 +1,40 @@
+{{- if and .Values.global.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
+apiVersion: cert-manager.io/v1{{ if .Values.global.certificates.alphacrds }}alpha1{{ end }}
+kind: Certificate
+metadata:
+ name: {{ template "seaweedfs.name" . }}-client-cert
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+spec:
+ secretName: {{ template "seaweedfs.name" . }}-client-cert
+ issuerRef:
+ name: {{ template "seaweedfs.name" . }}-ca-issuer
+ kind: Issuer
+ commonName: {{ .Values.certificates.commonName }}
+ subject:
+ organizations:
+ - "SeaweedFS CA"
+ dnsNames:
+ - '*.{{ .Release.Namespace }}'
+ - '*.{{ .Release.Namespace }}.svc'
+ - '*.{{ .Release.Namespace }}.svc.cluster.local'
+ - '*.{{ template "seaweedfs.name" . }}-master'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}.svc'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}.svc.cluster.local'
+{{- if .Values.certificates.ipAddresses }}
+ ipAddresses:
+ {{- range .Values.certificates.ipAddresses }}
+ - {{ . }}
+ {{- end }}
+{{- end }}
+ privateKey:
+ algorithm: {{ .Values.certificates.keyAlgorithm }}
+ size: {{ .Values.certificates.keySize }}
+ duration: {{ .Values.certificates.duration }}
+ renewBefore: {{ .Values.certificates.renewBefore }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/cluster-role.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/cluster-role.yaml
new file mode 100644
index 00000000..154de067
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/cluster-role.yaml
@@ -0,0 +1,35 @@
+{{- if .Values.global.createClusterRole }}
+#hack for delete pod master after migration
+---
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: {{ .Values.global.serviceAccountName }}-rw-cr
+ 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 }}
+rules:
+ - apiGroups: [""]
+ resources: ["pods"]
+ verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: system:serviceaccount:{{ .Values.global.serviceAccountName }}:default
+ 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 }}
+subjects:
+ - kind: ServiceAccount
+ name: {{ .Values.global.serviceAccountName }}
+ namespace: {{ .Release.Namespace }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: {{ .Values.global.serviceAccountName }}-rw-cr
+{{- end }}
\ No newline at end of file
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-bucket-class.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-bucket-class.yaml
new file mode 100644
index 00000000..e5503abd
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-bucket-class.yaml
@@ -0,0 +1,16 @@
+{{- if and .Values.cosi.enabled .Values.cosi.bucketClassName }}
+---
+kind: BucketClass
+apiVersion: objectstorage.k8s.io/v1alpha1
+metadata:
+ name: {{ .Values.cosi.bucketClassName }}
+driverName: {{ .Values.cosi.driverName }}
+deletionPolicy: Delete
+---
+kind: BucketAccessClass
+apiVersion: objectstorage.k8s.io/v1alpha1
+metadata:
+ name: {{ .Values.cosi.bucketClassName }}
+driverName: {{ .Values.cosi.driverName }}
+authenticationType: KEY
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-cluster-role.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-cluster-role.yaml
new file mode 100644
index 00000000..75d3ec32
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-cluster-role.yaml
@@ -0,0 +1,69 @@
+{{- if .Values.cosi.enabled }}
+---
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: {{ .Values.global.serviceAccountName }}-objectstorage-provisioner
+ 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 }}
+rules:
+- apiGroups: ["objectstorage.k8s.io"]
+ resources:
+ - "buckets"
+ - "bucketaccesses"
+ - "bucketclaims"
+ - "bucketaccessclasses"
+ - "buckets/status"
+ - "bucketaccesses/status"
+ - "bucketclaims/status"
+ - "bucketaccessclasses/status"
+ verbs:
+ - "get"
+ - "list"
+ - "watch"
+ - "update"
+ - "create"
+ - "delete"
+- apiGroups: ["coordination.k8s.io"]
+ resources: ["leases"]
+ verbs:
+ - "get"
+ - "watch"
+ - "list"
+ - "delete"
+ - "update"
+ - "create"
+- apiGroups: [""]
+ resources:
+ - "secrets"
+ - "events"
+ verbs:
+ - "get"
+ - "list"
+ - "watch"
+ - "update"
+ - "create"
+ - "delete"
+ - "patch"
+---
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: {{ .Values.global.serviceAccountName }}-objectstorage-provisioner
+ 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 }}
+subjects:
+ - kind: ServiceAccount
+ name: {{ .Values.global.serviceAccountName }}-objectstorage-provisioner
+ namespace: {{ .Release.Namespace }}
+roleRef:
+ kind: ClusterRole
+ name: {{ .Values.global.serviceAccountName }}-objectstorage-provisioner
+ apiGroup: rbac.authorization.k8s.io
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-deployment.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-deployment.yaml
new file mode 100644
index 00000000..15e5fa6d
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-deployment.yaml
@@ -0,0 +1,204 @@
+{{- if .Values.cosi.enabled }}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ template "seaweedfs.name" . }}-objectstorage-provisioner
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+spec:
+ replicas: {{ .Values.cosi.replicas }}
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: objectstorage-provisioner
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: objectstorage-provisioner
+ {{ with .Values.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.cosi.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ annotations:
+ {{ with .Values.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.cosi.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ spec:
+ restartPolicy: {{ default .Values.global.restartPolicy .Values.cosi.restartPolicy }}
+ {{- if .Values.cosi.tolerations }}
+ tolerations:
+ {{ tpl .Values.cosi.tolerations . | nindent 8 | trim }}
+ {{- end }}
+ {{- include "seaweedfs.imagePullSecrets" . | nindent 6 }}
+ terminationGracePeriodSeconds: 10
+ {{- if .Values.cosi.priorityClassName }}
+ priorityClassName: {{ .Values.cosi.priorityClassName | quote }}
+ {{- end }}
+ enableServiceLinks: false
+ serviceAccountName: {{ .Values.global.serviceAccountName }}-objectstorage-provisioner
+ {{- if .Values.cosi.initContainers }}
+ initContainers:
+ {{ tpl .Values.cosi.initContainers . | nindent 8 | trim }}
+ {{- end }}
+ {{- if .Values.cosi.podSecurityContext.enabled }}
+ securityContext: {{- omit .Values.cosi.podSecurityContext "enabled" | toYaml | nindent 8 }}
+ {{- end }}
+ containers:
+ - name: seaweedfs-cosi-driver
+ image: "{{ .Values.cosi.image }}"
+ imagePullPolicy: {{ default "IfNotPresent" .Values.global.imagePullPolicy }}
+ env:
+ - name: DRIVERNAME
+ value: "{{ .Values.cosi.driverName }}"
+ - name: ENDPOINT
+ {{- if .Values.cosi.endpoint }}
+ value: "{{ .Values.cosi.endpoint }}"
+ {{- else if .Values.s3.ingress.enabled }}
+ value: "{{ printf "https://%s" .Values.s3.ingress.host }}"
+ {{- else if .Values.s3.enabled }}
+ value: "{{ printf "https://%s-s3.%s.svc" (include "seaweedfs.name" .) .Release.Namespace }}"
+ {{- else }}
+ value: "{{ printf "https://%s-filer.%s.svc" (include "seaweedfs.name" .) .Release.Namespace }}"
+ {{- end }}
+ {{- with .Values.cosi.region }}
+ - name: REGION
+ value: "{{ . }}"
+ {{- end }}
+ - name: SEAWEEDFS_FILER
+ value: "{{ template "seaweedfs.name" . }}-filer:{{ .Values.filer.grpcPort }}"
+ {{- if .Values.global.enableSecurity }}
+ - name: WEED_GRPC_CLIENT_KEY
+ value: /usr/local/share/ca-certificates/client/tls.key
+ - name: WEED_GRPC_CLIENT_CERT
+ value: /usr/local/share/ca-certificates/client/tls.crt
+ - name: WEED_GRPC_CA
+ value: /usr/local/share/ca-certificates/client/ca.crt
+ {{- end }}
+ {{- if .Values.cosi.extraEnvironmentVars }}
+ {{- range $key, $value := .Values.cosi.extraEnvironmentVars }}
+ - name: {{ $key }}
+ {{- if kindIs "string" $value }}
+ value: {{ $value | quote }}
+ {{- else }}
+ valueFrom:
+ {{ toYaml $value | nindent 16 | trim }}
+ {{- end -}}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.global.extraEnvironmentVars }}
+ {{- range $key, $value := .Values.global.extraEnvironmentVars }}
+ - name: {{ $key }}
+ {{- if kindIs "string" $value }}
+ value: {{ $value | quote }}
+ {{- else }}
+ valueFrom:
+ {{ toYaml $value | nindent 16 | trim }}
+ {{- end -}}
+ {{- end }}
+ {{- end }}
+ volumeMounts:
+ - mountPath: /var/lib/cosi
+ name: socket
+ {{- if .Values.cosi.enableAuth }}
+ - mountPath: /etc/sw
+ name: config-users
+ readOnly: true
+ {{- end }}
+ {{- if .Values.global.enableSecurity }}
+ - name: security-config
+ readOnly: true
+ mountPath: /etc/seaweedfs/security.toml
+ subPath: security.toml
+ - name: ca-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/ca/
+ - name: master-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/master/
+ - name: volume-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/volume/
+ - name: filer-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/filer/
+ - name: client-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/client/
+ {{- end }}
+ {{ tpl .Values.cosi.extraVolumeMounts . | nindent 12 | trim }}
+ - name: seaweedfs-cosi-sidecar
+ image: "{{ .Values.cosi.sidecar.image }}"
+ imagePullPolicy: {{ default "IfNotPresent" .Values.global.imagePullPolicy }}
+ args:
+ - {{ printf "--v=%s" (default "5" .Values.cosi.sidecar.logLevel) }}
+ env:
+ - name: POD_NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ volumeMounts:
+ - mountPath: /var/lib/cosi
+ name: socket
+ {{- with .Values.cosi.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- if .Values.cosi.containerSecurityContext.enabled }}
+ securityContext: {{- omit .Values.cosi.containerSecurityContext "enabled" | toYaml | nindent 12 }}
+ {{- end }}
+ {{- if .Values.cosi.sidecars }}
+ {{- include "common.tplvalues.render" (dict "value" .Values.cosi.sidecars "context" $) | nindent 8 }}
+ {{- end }}
+ volumes:
+ - name: socket
+ emptyDir: {}
+ {{- if .Values.cosi.enableAuth }}
+ - name: config-users
+ secret:
+ defaultMode: 420
+ {{- if .Values.cosi.existingConfigSecret }}
+ secretName: {{ .Values.cosi.existingConfigSecret }}
+ {{- else }}
+ secretName: seaweedfs-client-cert
+ {{- end }}
+ {{- end }}
+ {{- if .Values.global.enableSecurity }}
+ - name: security-config
+ configMap:
+ name: {{ template "seaweedfs.name" . }}-security-config
+ - name: ca-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-ca-cert
+ - name: master-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-master-cert
+ - name: volume-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-volume-cert
+ - name: filer-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-filer-cert
+ - name: client-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-client-cert
+ {{- end }}
+ {{ tpl .Values.cosi.extraVolumes . | indent 8 | trim }}
+ {{- if .Values.cosi.nodeSelector }}
+ nodeSelector:
+ {{ tpl .Values.cosi.nodeSelector . | indent 8 | trim }}
+ {{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-service-account.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-service-account.yaml
new file mode 100644
index 00000000..78227fde
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/cosi-service-account.yaml
@@ -0,0 +1,13 @@
+{{- if .Values.cosi.enabled }}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ .Values.global.serviceAccountName }}-objectstorage-provisioner
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+automountServiceAccountToken: {{ .Values.global.automountServiceAccountToken }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/filer-cert.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-cert.yaml
new file mode 100644
index 00000000..c17815af
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-cert.yaml
@@ -0,0 +1,41 @@
+{{- if and .Values.global.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
+apiVersion: cert-manager.io/v1{{ if .Values.global.certificates.alphacrds }}alpha1{{ end }}
+kind: Certificate
+metadata:
+ name: {{ template "seaweedfs.name" . }}-filer-cert
+ namespace: {{ .Release.Namespace }}
+ 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: filer
+spec:
+ secretName: {{ template "seaweedfs.name" . }}-filer-cert
+ issuerRef:
+ name: {{ template "seaweedfs.name" . }}-ca-issuer
+ kind: Issuer
+ commonName: {{ .Values.certificates.commonName }}
+ subject:
+ organizations:
+ - "SeaweedFS CA"
+ dnsNames:
+ - '*.{{ .Release.Namespace }}'
+ - '*.{{ .Release.Namespace }}.svc'
+ - '*.{{ .Release.Namespace }}.svc.cluster.local'
+ - '*.{{ template "seaweedfs.name" . }}-master'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}.svc'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}.svc.cluster.local'
+{{- if .Values.certificates.ipAddresses }}
+ ipAddresses:
+ {{- range .Values.certificates.ipAddresses }}
+ - {{ . }}
+ {{- end }}
+{{- end }}
+ privateKey:
+ algorithm: {{ .Values.certificates.keyAlgorithm }}
+ size: {{ .Values.certificates.keySize }}
+ duration: {{ .Values.certificates.duration }}
+ renewBefore: {{ .Values.certificates.renewBefore }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/filer-ingress.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-ingress.yaml
new file mode 100644
index 00000000..7a7c9886
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-ingress.yaml
@@ -0,0 +1,48 @@
+{{- if .Values.filer.enabled }}
+{{- if .Values.filer.ingress.enabled }}
+{{- 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: ingress-{{ template "seaweedfs.name" . }}-filer
+ namespace: {{ .Release.Namespace }}
+ {{- with .Values.filer.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ 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: filer
+spec:
+ ingressClassName: {{ .Values.filer.ingress.className | quote }}
+ tls:
+ {{ .Values.filer.ingress.tls | default list | toYaml | nindent 6}}
+ rules:
+ - http:
+ paths:
+ - path: /sw-filer/?(.*)
+ pathType: ImplementationSpecific
+ backend:
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
+ service:
+ name: {{ template "seaweedfs.name" . }}-filer
+ port:
+ number: {{ .Values.filer.port }}
+ #name:
+{{- else }}
+ serviceName: {{ template "seaweedfs.name" . }}-filer
+ servicePort: {{ .Values.filer.port }}
+{{- end }}
+{{- if .Values.filer.ingress.host }}
+ host: {{ .Values.filer.ingress.host }}
+{{- end }}
+{{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/filer-service-client.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-service-client.yaml
new file mode 100644
index 00000000..d7618c4c
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-service-client.yaml
@@ -0,0 +1,36 @@
+{{- if .Values.filer.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ template "seaweedfs.name" . }}-filer-client
+ namespace: {{ .Release.Namespace }}
+ 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: filer
+{{- if .Values.filer.metricsPort }}
+ monitoring: "true"
+{{- end }}
+spec:
+ clusterIP: None
+ ports:
+ - name: "swfs-filer"
+ port: {{ .Values.filer.port }}
+ targetPort: {{ .Values.filer.port }}
+ protocol: TCP
+ - name: "swfs-filer-grpc"
+ port: {{ .Values.filer.grpcPort }}
+ targetPort: {{ .Values.filer.grpcPort }}
+ protocol: TCP
+{{- if .Values.filer.metricsPort }}
+ - name: "metrics"
+ port: {{ .Values.filer.metricsPort }}
+ targetPort: {{ .Values.filer.metricsPort }}
+ protocol: TCP
+{{- end }}
+ selector:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: filer
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/filer-service.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-service.yaml
new file mode 100644
index 00000000..ab7e98df
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-service.yaml
@@ -0,0 +1,48 @@
+{{- if .Values.filer.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ annotations:
+ service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
+ name: {{ template "seaweedfs.name" . }}-filer
+ namespace: {{ .Release.Namespace }}
+ 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: filer
+spec:
+ clusterIP: None
+ publishNotReadyAddresses: true
+ ports:
+ - name: "swfs-filer"
+ port: {{ .Values.filer.port }}
+ targetPort: {{ .Values.filer.port }}
+ protocol: TCP
+ - name: "swfs-filer-grpc"
+ port: {{ .Values.filer.grpcPort }}
+ targetPort: {{ .Values.filer.grpcPort }}
+ protocol: TCP
+ {{- if .Values.filer.s3.enabled }}
+ - name: "swfs-s3"
+ port: {{ .Values.filer.s3.port }}
+ targetPort: {{ .Values.filer.s3.port }}
+ protocol: TCP
+ {{- if .Values.filer.s3.httpsPort }}
+ - name: "swfs-s3-tls"
+ port: {{ .Values.filer.s3.httpsPort }}
+ targetPort: {{ .Values.filer.s3.httpsPort }}
+ protocol: TCP
+ {{- end }}
+ {{- end }}
+ {{- if .Values.filer.metricsPort }}
+ - name: "metrics"
+ port: {{ .Values.filer.metricsPort }}
+ targetPort: {{ .Values.filer.metricsPort }}
+ protocol: TCP
+ {{- end }}
+ selector:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: filer
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/filer-servicemonitor.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-servicemonitor.yaml
new file mode 100644
index 00000000..76c981c1
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-servicemonitor.yaml
@@ -0,0 +1,29 @@
+{{- if .Values.filer.enabled }}
+{{- if .Values.filer.metricsPort }}
+{{- if .Values.global.monitoring.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ template "seaweedfs.name" . }}-filer
+ namespace: {{ .Release.Namespace }}
+ 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: filer
+ {{- with .Values.global.monitoring.additionalLabels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ endpoints:
+ - interval: 30s
+ port: metrics
+ scrapeTimeout: 5s
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: filer
+{{- end }}
+{{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/filer-statefulset.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-statefulset.yaml
new file mode 100644
index 00000000..49b62e86
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/filer-statefulset.yaml
@@ -0,0 +1,402 @@
+{{- if .Values.filer.enabled }}
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: {{ template "seaweedfs.name" . }}-filer
+ namespace: {{ .Release.Namespace }}
+ 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: filer
+spec:
+ serviceName: {{ template "seaweedfs.name" . }}-filer
+ podManagementPolicy: {{ .Values.filer.podManagementPolicy }}
+ replicas: {{ .Values.filer.replicas }}
+ {{- if (gt (int .Values.filer.updatePartition) 0) }}
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ partition: {{ .Values.filer.updatePartition }}
+ {{- end }}
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: filer
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: filer
+ {{- with .Values.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.filer.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ annotations:
+ {{- with .Values.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.filer.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- if .Values.filer.s3.existingConfigSecret }}
+ {{- $configSecret := (lookup "v1" "Secret" .Release.Namespace .Values.filer.s3.existingConfigSecret) | default dict }}
+ checksum/s3config: {{ $configSecret | toYaml | sha256sum }}
+ {{- else }}
+ checksum/s3config: {{ include (print .Template.BasePath "/s3-secret.yaml") . | sha256sum }}
+ {{- end }}
+ spec:
+ restartPolicy: {{ default .Values.global.restartPolicy .Values.filer.restartPolicy }}
+ {{- if .Values.filer.affinity }}
+ affinity:
+ {{ tpl .Values.filer.affinity . | nindent 8 | trim }}
+ {{- end }}
+ {{- if .Values.filer.tolerations }}
+ tolerations:
+ {{ tpl .Values.filer.tolerations . | nindent 8 | trim }}
+ {{- end }}
+ {{- include "seaweedfs.imagePullSecrets" . | nindent 6 }}
+ serviceAccountName: {{ .Values.filer.serviceAccountName | default .Values.global.serviceAccountName | quote }} # for deleting statefulset pods after migration
+ terminationGracePeriodSeconds: 60
+ {{- if .Values.filer.priorityClassName }}
+ priorityClassName: {{ .Values.filer.priorityClassName | quote }}
+ {{- end }}
+ enableServiceLinks: false
+ {{- if .Values.filer.initContainers }}
+ initContainers:
+ {{ tpl .Values.filer.initContainers . | nindent 8 | trim }}
+ {{- end }}
+ {{- if .Values.filer.podSecurityContext.enabled }}
+ securityContext: {{- omit .Values.filer.podSecurityContext "enabled" | toYaml | nindent 8 }}
+ {{- end }}
+ containers:
+ - name: seaweedfs
+ image: {{ template "filer.image" . }}
+ imagePullPolicy: {{ default "IfNotPresent" .Values.global.imagePullPolicy }}
+ env:
+ - name: POD_IP
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: WEED_MYSQL_USERNAME
+ valueFrom:
+ secretKeyRef:
+ name: secret-seaweedfs-db
+ key: user
+ optional: true
+ - name: WEED_MYSQL_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: secret-seaweedfs-db
+ key: password
+ optional: true
+ - name: SEAWEEDFS_FULLNAME
+ value: "{{ template "seaweedfs.name" . }}"
+ {{- if .Values.filer.extraEnvironmentVars }}
+ {{- range $key, $value := .Values.filer.extraEnvironmentVars }}
+ - name: {{ $key }}
+ {{- if kindIs "string" $value }}
+ value: {{ $value | quote }}
+ {{- else }}
+ valueFrom:
+ {{ toYaml $value | nindent 16 | trim }}
+ {{- end -}}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.global.extraEnvironmentVars }}
+ {{- range $key, $value := .Values.global.extraEnvironmentVars }}
+ - name: {{ $key }}
+ {{- if kindIs "string" $value }}
+ value: {{ $value | quote }}
+ {{- else }}
+ valueFrom:
+ {{ toYaml $value | nindent 16 | trim }}
+ {{- end -}}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.filer.secretExtraEnvironmentVars }}
+ {{- range $key, $value := .Values.filer.secretExtraEnvironmentVars }}
+ - name: {{ $key }}
+ valueFrom: {{ toYaml $value | nindent 16 }}
+ {{- end }}
+ {{- end }}
+ command:
+ - "/bin/sh"
+ - "-ec"
+ - |
+ exec /usr/bin/weed \
+ {{- if or (eq .Values.filer.logs.type "hostPath") (eq .Values.filer.logs.type "persistentVolumeClaim") (eq .Values.filer.logs.type "emptyDir") }}
+ -logdir=/logs \
+ {{- else }}
+ -logtostderr=true \
+ {{- end }}
+ {{- if .Values.filer.loggingOverrideLevel }}
+ -v={{ .Values.filer.loggingOverrideLevel }} \
+ {{- else }}
+ -v={{ .Values.global.loggingLevel }} \
+ {{- end }}
+ filer \
+ -port={{ .Values.filer.port }} \
+ {{- if .Values.filer.metricsPort }}
+ -metricsPort={{ .Values.filer.metricsPort }} \
+ {{- end }}
+ {{- if .Values.filer.redirectOnRead }}
+ -redirectOnRead \
+ {{- end }}
+ {{- if .Values.filer.disableHttp }}
+ -disableHttp \
+ {{- end }}
+ {{- if .Values.filer.disableDirListing }}
+ -disableDirListing \
+ {{- end }}
+ -dirListLimit={{ .Values.filer.dirListLimit }} \
+ {{- if .Values.global.enableReplication }}
+ -defaultReplicaPlacement={{ .Values.global.replicationPlacment }} \
+ {{- else }}
+ -defaultReplicaPlacement={{ .Values.filer.defaultReplicaPlacement }} \
+ {{- end }}
+ {{- if .Values.filer.disableDirListing }}
+ -disableDirListing \
+ {{- end }}
+ {{- if .Values.filer.maxMB }}
+ -maxMB={{ .Values.filer.maxMB }} \
+ {{- end }}
+ {{- if .Values.filer.encryptVolumeData }}
+ -encryptVolumeData \
+ {{- end }}
+ -ip=${POD_IP} \
+ {{- if .Values.filer.filerGroup}}
+ -filerGroup={{ .Values.filer.filerGroup}} \
+ {{- end }}
+ {{- if .Values.filer.s3.enabled }}
+ -s3 \
+ -s3.port={{ .Values.filer.s3.port }} \
+ {{- if .Values.filer.s3.domainName }}
+ -s3.domainName={{ .Values.filer.s3.domainName }} \
+ {{- end }}
+ {{- if .Values.global.enableSecurity }}
+ {{- if .Values.filer.s3.httpsPort }}
+ -s3.port.https={{ .Values.filer.s3.httpsPort }} \
+ {{- end }}
+ -s3.cert.file=/usr/local/share/ca-certificates/client/tls.crt \
+ -s3.key.file=/usr/local/share/ca-certificates/client/tls.key \
+ {{- end }}
+ {{- if .Values.filer.s3.allowEmptyFolder }}
+ -s3.allowEmptyFolder={{ .Values.filer.s3.allowEmptyFolder }} \
+ {{- end }}
+ {{- if .Values.filer.s3.enableAuth }}
+ -s3.config=/etc/sw/seaweedfs_s3_config \
+ {{- end }}
+ {{- if .Values.filer.s3.auditLogConfig }}
+ -s3.auditLogConfig=/etc/sw/filer_s3_auditLogConfig.json \
+ {{- end }}
+ {{- end }}
+ -master={{ if .Values.global.masterServer }}{{.Values.global.masterServer}}{{ else }}{{ range $index := until (.Values.master.replicas | int) }}${SEAWEEDFS_FULLNAME}-master-{{ $index }}.${SEAWEEDFS_FULLNAME}-master.{{ $.Release.Namespace }}:{{ $.Values.master.port }}{{ if lt $index (sub ($.Values.master.replicas | int) 1) }},{{ end }}{{ end }}{{ end }}
+ volumeMounts:
+ {{- if (or (eq .Values.filer.logs.type "hostPath") (eq .Values.filer.logs.type "persistentVolumeClaim") (eq .Values.filer.logs.type "emptyDir")) }}
+ - name: seaweedfs-filer-log-volume
+ mountPath: "/logs/"
+ {{- end }}
+ {{- if .Values.filer.s3.enableAuth }}
+ - name: config-users
+ mountPath: /etc/sw
+ readOnly: true
+ {{- end }}
+ {{- if (or .Values.filer.enablePVC (or (eq .Values.filer.data.type "hostPath") (eq .Values.filer.data.type "persistentVolumeClaim") (eq .Values.filer.data.type "emptyDir"))) }}
+ - name: data-filer
+ mountPath: /data
+ {{- end }}
+ {{- if .Values.global.enableSecurity }}
+ - name: security-config
+ readOnly: true
+ mountPath: /etc/seaweedfs/security.toml
+ subPath: security.toml
+ - name: ca-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/ca/
+ - name: master-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/master/
+ - name: volume-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/volume/
+ - name: filer-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/filer/
+ - name: client-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/client/
+ {{- end }}
+ {{ tpl .Values.filer.extraVolumeMounts . | nindent 12 | trim }}
+ ports:
+ - containerPort: {{ .Values.filer.port }}
+ name: swfs-filer
+ - containerPort: {{ .Values.filer.metricsPort }}
+ name: metrics
+ - containerPort: {{ .Values.filer.grpcPort }}
+ #name: swfs-filer-grpc
+ {{- if .Values.filer.readinessProbe.enabled }}
+ readinessProbe:
+ httpGet:
+ path: {{ .Values.filer.readinessProbe.httpGet.path }}
+ port: {{ .Values.filer.port }}
+ scheme: {{ .Values.filer.readinessProbe.scheme }}
+ initialDelaySeconds: {{ .Values.filer.readinessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.filer.readinessProbe.periodSeconds }}
+ successThreshold: {{ .Values.filer.readinessProbe.successThreshold }}
+ failureThreshold: {{ .Values.filer.readinessProbe.failureThreshold }}
+ timeoutSeconds: {{ .Values.filer.readinessProbe.timeoutSeconds }}
+ {{- end }}
+ {{- if .Values.filer.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ path: {{ .Values.filer.livenessProbe.httpGet.path }}
+ port: {{ .Values.filer.port }}
+ scheme: {{ .Values.filer.livenessProbe.scheme }}
+ initialDelaySeconds: {{ .Values.filer.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.filer.livenessProbe.periodSeconds }}
+ successThreshold: {{ .Values.filer.livenessProbe.successThreshold }}
+ failureThreshold: {{ .Values.filer.livenessProbe.failureThreshold }}
+ timeoutSeconds: {{ .Values.filer.livenessProbe.timeoutSeconds }}
+ {{- end }}
+ {{- with .Values.filer.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- if .Values.filer.containerSecurityContext.enabled }}
+ securityContext: {{- omit .Values.filer.containerSecurityContext "enabled" | toYaml | nindent 12 }}
+ {{- end }}
+ {{- if .Values.filer.sidecars }}
+ {{- include "common.tplvalues.render" (dict "value" .Values.filer.sidecars "context" $) | nindent 8 }}
+ {{- end }}
+ volumes:
+ {{- if eq .Values.filer.logs.type "hostPath" }}
+ - name: seaweedfs-filer-log-volume
+ hostPath:
+ path: {{ .Values.filer.logs.hostPathPrefix }}/logs/seaweedfs/filer
+ type: DirectoryOrCreate
+ {{- end }}
+ {{- if eq .Values.filer.logs.type "existingClaim" }}
+ - name: seaweedfs-filer-log-volume
+ persistentVolumeClaim:
+ claimName: {{ .Values.filer.logs.claimName }}
+ {{- end }}
+ {{- if eq .Values.filer.logs.type "emptyDir" }}
+ - name: seaweedfs-filer-log-volume
+ emptyDir: {}
+ {{- end }}
+ {{- if eq .Values.filer.data.type "hostPath" }}
+ - name: data-filer
+ hostPath:
+ path: {{ .Values.filer.data.hostPathPrefix }}/filer_store
+ type: DirectoryOrCreate
+ {{- end }}
+ {{- if eq .Values.filer.data.type "existingClaim" }}
+ - name: data-filer
+ persistentVolumeClaim:
+ claimName: {{ .Values.filer.data.claimName }}
+ {{- end }}
+ {{- if eq .Values.filer.data.type "emptyDir" }}
+ - name: data-filer
+ emptyDir: {}
+ {{- end }}
+ - name: db-schema-config-volume
+ configMap:
+ name: seaweedfs-db-init-config
+ {{- if and .Values.filer.s3.enabled .Values.filer.s3.enableAuth }}
+ - name: config-users
+ secret:
+ defaultMode: 420
+ {{- if .Values.filer.s3.existingConfigSecret }}
+ secretName: {{ .Values.filer.s3.existingConfigSecret }}
+ {{- else }}
+ secretName: seaweedfs-s3-secret
+ {{- end }}
+ {{- end }}
+ {{- if .Values.global.enableSecurity }}
+ - name: security-config
+ configMap:
+ name: {{ template "seaweedfs.name" . }}-security-config
+ - name: ca-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-ca-cert
+ - name: master-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-master-cert
+ - name: volume-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-volume-cert
+ - name: filer-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-filer-cert
+ - name: client-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-client-cert
+ {{- end }}
+ {{ tpl .Values.filer.extraVolumes . | indent 8 | trim }}
+ {{- if .Values.filer.nodeSelector }}
+ nodeSelector:
+ {{ tpl .Values.filer.nodeSelector . | indent 8 | trim }}
+ {{- end }}
+ {{- if and (.Values.filer.enablePVC) (eq .Values.filer.data.type "persistentVolumeClaim") }}
+ # DEPRECATION: Deprecate in favor of filer.data section below
+ volumeClaimTemplates:
+ - metadata:
+ name: data-filer
+ spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: {{ .Values.filer.storage }}
+ {{- if .Values.filer.storageClass }}
+ storageClassName: {{ .Values.filer.storageClass }}
+ {{- end }}
+ {{- end }}
+ {{- $pvc_exists := include "filer.pvc_exists" . -}}
+ {{- if $pvc_exists }}
+ volumeClaimTemplates:
+ {{- if eq .Values.filer.data.type "persistentVolumeClaim" }}
+ - metadata:
+ name: data-filer
+ {{- with .Values.filer.data.annotations }}
+ annotations:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ spec:
+ accessModes: [ "ReadWriteOnce" ]
+ storageClassName: {{ .Values.filer.data.storageClass }}
+ resources:
+ requests:
+ storage: {{ .Values.filer.data.size }}
+ {{- end }}
+ {{- if eq .Values.filer.logs.type "persistentVolumeClaim" }}
+ - metadata:
+ name: seaweedfs-filer-log-volume
+ {{- with .Values.filer.logs.annotations }}
+ annotations:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ spec:
+ accessModes: [ "ReadWriteOnce" ]
+ storageClassName: {{ .Values.filer.logs.storageClass }}
+ resources:
+ requests:
+ storage: {{ .Values.filer.logs.size }}
+ {{- end }}
+ {{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/master-cert.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/master-cert.yaml
new file mode 100644
index 00000000..47dcaacd
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/master-cert.yaml
@@ -0,0 +1,41 @@
+{{- if and .Values.global.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
+apiVersion: cert-manager.io/v1{{ if .Values.global.certificates.alphacrds }}alpha1{{ end }}
+kind: Certificate
+metadata:
+ name: {{ template "seaweedfs.name" . }}-master-cert
+ namespace: {{ .Release.Namespace }}
+ 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: master
+spec:
+ secretName: {{ template "seaweedfs.name" . }}-master-cert
+ issuerRef:
+ name: {{ template "seaweedfs.name" . }}-ca-issuer
+ kind: Issuer
+ commonName: {{ .Values.certificates.commonName }}
+ subject:
+ organizations:
+ - "SeaweedFS CA"
+ dnsNames:
+ - '*.{{ .Release.Namespace }}'
+ - '*.{{ .Release.Namespace }}.svc'
+ - '*.{{ .Release.Namespace }}.svc.cluster.local'
+ - '*.{{ template "seaweedfs.name" . }}-master'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}.svc'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}.svc.cluster.local'
+{{- if .Values.certificates.ipAddresses }}
+ ipAddresses:
+ {{- range .Values.certificates.ipAddresses }}
+ - {{ . }}
+ {{- end }}
+{{- end }}
+ privateKey:
+ algorithm: {{ .Values.certificates.keyAlgorithm }}
+ size: {{ .Values.certificates.keySize }}
+ duration: {{ .Values.certificates.duration }}
+ renewBefore: {{ .Values.certificates.renewBefore }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/master-configmap.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/master-configmap.yaml
new file mode 100644
index 00000000..73155e87
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/master-configmap.yaml
@@ -0,0 +1,15 @@
+{{- if .Values.master.enabled }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ template "seaweedfs.name" . }}-master-config
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+data:
+ master.toml: |-
+ {{ .Values.master.config | nindent 4 }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/master-ingress.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/master-ingress.yaml
new file mode 100644
index 00000000..62d7f7a5
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/master-ingress.yaml
@@ -0,0 +1,48 @@
+{{- if .Values.master.enabled }}
+{{- if .Values.master.ingress.enabled }}
+{{- 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: ingress-{{ template "seaweedfs.name" . }}-master
+ namespace: {{ .Release.Namespace }}
+ {{- with .Values.master.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ 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: master
+spec:
+ ingressClassName: {{ .Values.master.ingress.className | quote }}
+ tls:
+ {{ .Values.master.ingress.tls | default list | toYaml | nindent 6 }}
+ rules:
+ - http:
+ paths:
+ - path: /sw-master/?(.*)
+ pathType: ImplementationSpecific
+ backend:
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
+ service:
+ name: {{ template "seaweedfs.name" . }}-master
+ port:
+ number: {{ .Values.master.port }}
+ #name:
+{{- else }}
+ serviceName: {{ template "seaweedfs.name" . }}-master
+ servicePort: {{ .Values.master.port }}
+{{- end }}
+{{- if .Values.filer.ingress.host }}
+ host: {{ .Values.master.ingress.host }}
+{{- end }}
+{{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/master-service.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/master-service.yaml
new file mode 100644
index 00000000..9e69f94e
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/master-service.yaml
@@ -0,0 +1,35 @@
+{{- if .Values.master.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ template "seaweedfs.name" . }}-master
+ namespace: {{ .Release.Namespace }}
+ labels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: master
+ helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+ app.kubernetes.io/managed-by: {{ .Release.Service }}
+ annotations:
+ service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
+spec:
+ clusterIP: None
+ publishNotReadyAddresses: true
+ ports:
+ - name: "swfs-master"
+ port: {{ .Values.master.port }}
+ targetPort: {{ .Values.master.port }}
+ protocol: TCP
+ - name: "swfs-master-grpc"
+ port: {{ .Values.master.grpcPort }}
+ targetPort: {{ .Values.master.grpcPort }}
+ protocol: TCP
+ {{- if .Values.master.metricsPort }}
+ - name: "metrics"
+ port: {{ .Values.master.metricsPort }}
+ targetPort: {{ .Values.master.metricsPort }}
+ protocol: TCP
+ {{- end }}
+ selector:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: master
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/master-servicemonitor.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/master-servicemonitor.yaml
new file mode 100644
index 00000000..81cade2e
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/master-servicemonitor.yaml
@@ -0,0 +1,29 @@
+{{- if .Values.master.enabled }}
+{{- if .Values.master.metricsPort }}
+{{- if .Values.global.monitoring.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ template "seaweedfs.name" . }}-master
+ namespace: {{ .Release.Namespace }}
+ 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: master
+ {{- with .Values.global.monitoring.additionalLabels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ endpoints:
+ - interval: 30s
+ port: metrics
+ scrapeTimeout: 5s
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: master
+{{- end }}
+{{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/master-statefulset.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/master-statefulset.yaml
new file mode 100644
index 00000000..73d1f9fb
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/master-statefulset.yaml
@@ -0,0 +1,331 @@
+{{- if .Values.master.enabled }}
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: {{ template "seaweedfs.name" . }}-master
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+spec:
+ serviceName: {{ template "seaweedfs.name" . }}-master
+ podManagementPolicy: {{ .Values.master.podManagementPolicy }}
+ replicas: {{ .Values.master.replicas }}
+ {{- if (gt (int .Values.master.updatePartition) 0) }}
+ updateStrategy:
+ type: RollingUpdate
+ rollingUpdate:
+ partition: {{ .Values.master.updatePartition }}
+ {{- end }}
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: master
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: master
+ {{ with .Values.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.master.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ annotations:
+ {{ with .Values.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.master.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ spec:
+ restartPolicy: {{ default .Values.global.restartPolicy .Values.master.restartPolicy }}
+ {{- if .Values.master.affinity }}
+ affinity:
+ {{ tpl .Values.master.affinity . | nindent 8 | trim }}
+ {{- end }}
+ {{- if .Values.master.tolerations }}
+ tolerations:
+ {{ tpl .Values.master.tolerations . | nindent 8 | trim }}
+ {{- end }}
+ {{- include "seaweedfs.imagePullSecrets" . | nindent 6 }}
+ terminationGracePeriodSeconds: 60
+ {{- if .Values.master.priorityClassName }}
+ priorityClassName: {{ .Values.master.priorityClassName | quote }}
+ {{- end }}
+ enableServiceLinks: false
+ {{- if .Values.global.createClusterRole }}
+ serviceAccountName: {{ .Values.master.serviceAccountName | default .Values.global.serviceAccountName | quote }} # for deleting statefulset pods after migration
+ {{- end }}
+ {{- if .Values.master.initContainers }}
+ initContainers:
+ {{ tpl .Values.master.initContainers . | nindent 8 | trim }}
+ {{- end }}
+ {{- if .Values.master.podSecurityContext.enabled }}
+ securityContext: {{- omit .Values.master.podSecurityContext "enabled" | toYaml | nindent 8 }}
+ {{- end }}
+ containers:
+ - name: seaweedfs
+ image: {{ template "master.image" . }}
+ imagePullPolicy: {{ default "IfNotPresent" .Values.global.imagePullPolicy }}
+ env:
+ - name: POD_IP
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: SEAWEEDFS_FULLNAME
+ value: "{{ template "seaweedfs.name" . }}"
+ {{- if .Values.master.extraEnvironmentVars }}
+ {{- range $key, $value := .Values.master.extraEnvironmentVars }}
+ - name: {{ $key }}
+ {{- if kindIs "string" $value }}
+ value: {{ $value | quote }}
+ {{- else }}
+ valueFrom:
+ {{ toYaml $value | nindent 16 | trim }}
+ {{- end -}}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.global.extraEnvironmentVars }}
+ {{- range $key, $value := .Values.global.extraEnvironmentVars }}
+ - name: {{ $key }}
+ {{- if kindIs "string" $value }}
+ value: {{ $value | quote }}
+ {{- else }}
+ valueFrom:
+ {{ toYaml $value | nindent 16 | trim }}
+ {{- end -}}
+ {{- end }}
+ {{- end }}
+ command:
+ - "/bin/sh"
+ - "-ec"
+ - |
+ exec /usr/bin/weed \
+ {{- if or (eq .Values.master.logs.type "hostPath") (eq .Values.master.logs.type "persistentVolumeClaim") (eq .Values.master.logs.type "emptyDir") }}
+ -logdir=/logs \
+ {{- else }}
+ -logtostderr=true \
+ {{- end }}
+ {{- if .Values.master.loggingOverrideLevel }}
+ -v={{ .Values.master.loggingOverrideLevel }} \
+ {{- else }}
+ -v={{ .Values.global.loggingLevel }} \
+ {{- end }}
+ master \
+ -port={{ .Values.master.port }} \
+ -mdir=/data \
+ -ip.bind={{ .Values.master.ipBind }} \
+ {{- if .Values.global.enableReplication }}
+ -defaultReplication={{ .Values.global.replicationPlacment }} \
+ {{- else }}
+ -defaultReplication={{ .Values.master.defaultReplication }} \
+ {{- end }}
+ {{- if .Values.master.volumePreallocate }}
+ -volumePreallocate \
+ {{- end }}
+ {{- if .Values.global.monitoring.enabled }}
+ {{- if and .Values.global.monitoring.gatewayHost .Values.global.monitoring.gatewayPort }}
+ -metrics.address="{{ .Values.global.monitoring.gatewayHost }}:{{ .Values.global.monitoring.gatewayPort }}" \
+ {{- if .Values.master.metricsIntervalSec }}
+ -metrics.intervalSeconds={{ .Values.master.metricsIntervalSec }} \
+ {{- end }}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.master.metricsPort }}
+ -metricsPort={{ .Values.master.metricsPort }} \
+ {{- end }}
+ -volumeSizeLimitMB={{ .Values.master.volumeSizeLimitMB }} \
+ {{- if .Values.master.disableHttp }}
+ -disableHttp \
+ {{- end }}
+ {{- if .Values.master.pulseSeconds }}
+ -pulseSeconds={{ .Values.master.pulseSeconds }} \
+ {{- end }}
+ {{- if .Values.master.garbageThreshold }}
+ -garbageThreshold={{ .Values.master.garbageThreshold }} \
+ {{- end }}
+ -ip=${POD_NAME}.${SEAWEEDFS_FULLNAME}-master.{{ .Release.Namespace }} \
+ -peers={{ range $index := until (.Values.master.replicas | int) }}${SEAWEEDFS_FULLNAME}-master-{{ $index }}.${SEAWEEDFS_FULLNAME}-master.{{ $.Release.Namespace }}:{{ $.Values.master.port }}{{ if lt $index (sub ($.Values.master.replicas | int) 1) }},{{ end }}{{ end }}
+ volumeMounts:
+ - name : data-{{ .Release.Namespace }}
+ mountPath: /data
+ {{- if or (eq .Values.master.logs.type "hostPath") (eq .Values.master.logs.type "persistentVolumeClaim") (eq .Values.master.logs.type "emptyDir") }}
+ - name: seaweedfs-master-log-volume
+ mountPath: "/logs/"
+ {{- end }}
+ - name: master-config
+ readOnly: true
+ mountPath: /etc/seaweedfs/master.toml
+ subPath: master.toml
+ {{- if .Values.global.enableSecurity }}
+ - name: security-config
+ readOnly: true
+ mountPath: /etc/seaweedfs/security.toml
+ subPath: security.toml
+ - name: ca-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/ca/
+ - name: master-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/master/
+ - name: volume-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/volume/
+ - name: filer-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/filer/
+ - name: client-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/client/
+ {{- end }}
+ {{ tpl .Values.master.extraVolumeMounts . | nindent 12 | trim }}
+ ports:
+ - containerPort: {{ .Values.master.port }}
+ name: swfs-master
+ {{- if and .Values.global.monitoring.enabled .Values.master.metricsPort }}
+ - containerPort: {{ .Values.master.metricsPort }}
+ name: metrics
+ {{- end }}
+ - containerPort: {{ .Values.master.grpcPort }}
+ #name: swfs-master-grpc
+ {{- if .Values.master.readinessProbe.enabled }}
+ readinessProbe:
+ httpGet:
+ path: {{ .Values.master.readinessProbe.httpGet.path }}
+ port: {{ .Values.master.port }}
+ scheme: {{ .Values.master.readinessProbe.scheme }}
+ initialDelaySeconds: {{ .Values.master.readinessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.master.readinessProbe.periodSeconds }}
+ successThreshold: {{ .Values.master.readinessProbe.successThreshold }}
+ failureThreshold: {{ .Values.master.readinessProbe.failureThreshold }}
+ timeoutSeconds: {{ .Values.master.readinessProbe.timeoutSeconds }}
+ {{- end }}
+ {{- if .Values.master.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ path: {{ .Values.master.livenessProbe.httpGet.path }}
+ port: {{ .Values.master.port }}
+ scheme: {{ .Values.master.livenessProbe.scheme }}
+ initialDelaySeconds: {{ .Values.master.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.master.livenessProbe.periodSeconds }}
+ successThreshold: {{ .Values.master.livenessProbe.successThreshold }}
+ failureThreshold: {{ .Values.master.livenessProbe.failureThreshold }}
+ timeoutSeconds: {{ .Values.master.livenessProbe.timeoutSeconds }}
+ {{- end }}
+ {{- with .Values.master.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- if .Values.master.containerSecurityContext.enabled }}
+ securityContext: {{- omit .Values.master.containerSecurityContext "enabled" | toYaml | nindent 12 }}
+ {{- end }}
+ {{- if .Values.master.sidecars }}
+ {{- include "common.tplvalues.render" (dict "value" .Values.master.sidecars "context" $) | nindent 8 }}
+ {{- end }}
+ volumes:
+ {{- if eq .Values.master.logs.type "hostPath" }}
+ - name: seaweedfs-master-log-volume
+ hostPath:
+ path: {{ .Values.master.logs.hostPathPrefix }}/logs/seaweedfs/master
+ type: DirectoryOrCreate
+ {{- end }}
+ {{- if eq .Values.master.logs.type "existingClaim" }}
+ - name: seaweedfs-master-log-volume
+ persistentVolumeClaim:
+ claimName: {{ .Values.master.logs.claimName }}
+ {{- end }}
+ {{- if eq .Values.master.logs.type "emptyDir" }}
+ - name: seaweedfs-master-log-volume
+ emptyDir: {}
+ {{- end }}
+ {{- if eq .Values.master.data.type "hostPath" }}
+ - name: data-{{ .Release.Namespace }}
+ hostPath:
+ path: {{ .Values.master.data.hostPathPrefix }}/seaweed-master/
+ type: DirectoryOrCreate
+ {{- end }}
+ {{- if eq .Values.master.data.type "existingClaim" }}
+ - name: data-{{ .Release.Namespace }}
+ persistentVolumeClaim:
+ claimName: {{ .Values.master.data.claimName }}
+ {{- end }}
+ {{- if eq .Values.master.data.type "emptyDir" }}
+ - name: data-{{ .Release.Namespace }}
+ emptyDir: {}
+ {{- end }}
+ - name: master-config
+ configMap:
+ name: {{ template "seaweedfs.name" . }}-master-config
+ {{- if .Values.global.enableSecurity }}
+ - name: security-config
+ configMap:
+ name: {{ template "seaweedfs.name" . }}-security-config
+ - name: ca-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-ca-cert
+ - name: master-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-master-cert
+ - name: volume-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-volume-cert
+ - name: filer-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-filer-cert
+ - name: client-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-client-cert
+ {{- end }}
+ {{ tpl .Values.master.extraVolumes . | indent 8 | trim }}
+ {{- if .Values.master.nodeSelector }}
+ nodeSelector:
+ {{ tpl .Values.master.nodeSelector . | indent 8 | trim }}
+ {{- end }}
+ {{- $pvc_exists := include "master.pvc_exists" . -}}
+ {{- if $pvc_exists }}
+ volumeClaimTemplates:
+ {{- if eq .Values.master.data.type "persistentVolumeClaim"}}
+ - metadata:
+ name: data-{{ .Release.Namespace }}
+ {{- with .Values.master.data.annotations }}
+ annotations:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ spec:
+ accessModes: [ "ReadWriteOnce" ]
+ storageClassName: {{ .Values.master.data.storageClass }}
+ resources:
+ requests:
+ storage: {{ .Values.master.data.size }}
+ {{- end }}
+ {{- if eq .Values.master.logs.type "persistentVolumeClaim"}}
+ - metadata:
+ name: seaweedfs-master-log-volume
+ {{- with .Values.master.logs.annotations }}
+ annotations:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ spec:
+ accessModes: [ "ReadWriteOnce" ]
+ storageClassName: {{ .Values.master.logs.storageClass }}
+ resources:
+ requests:
+ storage: {{ .Values.master.logs.size }}
+ {{- end }}
+ {{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/post-install-bucket-hook.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/post-install-bucket-hook.yaml
new file mode 100644
index 00000000..2260bd84
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/post-install-bucket-hook.yaml
@@ -0,0 +1,102 @@
+{{- if .Values.master.enabled }}
+{{- if .Values.filer.s3.enabled }}
+{{- if .Values.filer.s3.createBuckets }}
+---
+apiVersion: batch/v1
+kind: Job
+metadata:
+ name: "{{ $.Release.Name }}-bucket-hook"
+ labels:
+ app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
+ app.kubernetes.io/instance: {{ .Release.Name | quote }}
+ annotations:
+ "helm.sh/hook": post-install
+ "helm.sh/hook-weight": "-5"
+ "helm.sh/hook-delete-policy": hook-succeeded
+spec:
+ template:
+ metadata:
+ name: "{{ .Release.Name }}"
+ labels:
+ app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
+ app.kubernetes.io/instance: {{ .Release.Name | quote }}
+ spec:
+ restartPolicy: Never
+ {{- if .Values.filer.podSecurityContext.enabled }}
+ securityContext: {{- omit .Values.filer.podSecurityContext "enabled" | toYaml | nindent 8 }}
+ {{- end }}
+ containers:
+ - name: post-install-job
+ image: {{ template "master.image" . }}
+ env:
+ - name: WEED_CLUSTER_DEFAULT
+ value: "sw"
+ - name: WEED_CLUSTER_SW_MASTER
+ value: "{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}:9333"
+ - name: WEED_CLUSTER_SW_FILER
+ value: "{{ template "seaweedfs.name" . }}-filer-client.{{ .Release.Namespace }}:8888"
+ - name: POD_IP
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: SEAWEEDFS_FULLNAME
+ value: "{{ template "seaweedfs.name" . }}"
+ command:
+ - "/bin/sh"
+ - "-ec"
+ - |
+ {{- range $reg, $props := $.Values.filer.s3.createBuckets }}
+ exec /bin/echo \
+ "s3.bucket.create --name {{ $props.name }}" |\
+ /usr/bin/weed shell
+ {{- end }}
+ {{- range $reg, $props := $.Values.filer.s3.createBuckets }}
+ {{- if $props.anonymousRead }}
+ exec /bin/echo \
+ "s3.configure --user anonymous \
+ --buckets {{ $props.name }} \
+ --actions Read \
+ --apply true" |\
+ /usr/bin/weed shell
+ {{- end }}
+ {{- end }}
+ {{- if .Values.filer.s3.enableAuth }}
+ volumeMounts:
+ - name: config-users
+ mountPath: /etc/sw
+ readOnly: true
+ {{- end }}
+ ports:
+ - containerPort: {{ .Values.master.port }}
+ name: swfs-master
+ {{- if and .Values.global.monitoring.enabled .Values.master.metricsPort }}
+ - containerPort: {{ .Values.master.metricsPort }}
+ name: metrics
+ {{- end }}
+ - containerPort: {{ .Values.master.grpcPort }}
+ #name: swfs-master-grpc
+ {{- if .Values.filer.containerSecurityContext.enabled }}
+ securityContext: {{- omit .Values.filer.containerSecurityContext "enabled" | toYaml | nindent 12 }}
+ {{- end }}
+ {{- if .Values.filer.s3.enableAuth }}
+ volumes:
+ - name: config-users
+ secret:
+ defaultMode: 420
+ {{- if not (empty .Values.filer.s3.existingConfigSecret) }}
+ secretName: {{ .Values.filer.s3.existingConfigSecret }}
+ {{- else }}
+ secretName: seaweedfs-s3-secret
+ {{- end }}
+ {{- end }}{{/** if .Values.filer.s3.enableAuth **/}}
+{{- end }}{{/** if .Values.master.enabled **/}}
+{{- end }}{{/** if .Values.filer.s3.enabled **/}}
+{{- end }}{{/** if .Values.filer.s3.createBuckets **/}}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/s3-deployment.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/s3-deployment.yaml
new file mode 100644
index 00000000..b678a0ef
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/s3-deployment.yaml
@@ -0,0 +1,263 @@
+{{- if .Values.s3.enabled }}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ template "seaweedfs.name" . }}-s3
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+spec:
+ replicas: {{ .Values.s3.replicas }}
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: s3
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: s3
+ {{ with .Values.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.s3.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ annotations:
+ {{ with .Values.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.s3.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ spec:
+ restartPolicy: {{ default .Values.global.restartPolicy .Values.s3.restartPolicy }}
+ {{- if .Values.s3.tolerations }}
+ tolerations:
+ {{ tpl .Values.s3.tolerations . | nindent 8 | trim }}
+ {{- end }}
+ {{- include "seaweedfs.imagePullSecrets" . | nindent 6 }}
+ terminationGracePeriodSeconds: 10
+ {{- if .Values.s3.priorityClassName }}
+ priorityClassName: {{ .Values.s3.priorityClassName | quote }}
+ {{- end }}
+ enableServiceLinks: false
+ {{- if .Values.s3.serviceAccountName }}
+ serviceAccountName: {{ .Values.s3.serviceAccountName | quote }}
+ {{- end }}
+ {{- if .Values.s3.initContainers }}
+ initContainers:
+ {{ tpl .Values.s3.initContainers . | nindent 8 | trim }}
+ {{- end }}
+ {{- if .Values.s3.podSecurityContext.enabled }}
+ securityContext: {{- omit .Values.s3.podSecurityContext "enabled" | toYaml | nindent 8 }}
+ {{- end }}
+ containers:
+ - name: seaweedfs
+ image: {{ template "s3.image" . }}
+ imagePullPolicy: {{ default "IfNotPresent" .Values.global.imagePullPolicy }}
+ env:
+ - name: POD_IP
+ valueFrom:
+ fieldRef:
+ fieldPath: status.podIP
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: SEAWEEDFS_FULLNAME
+ value: "{{ template "seaweedfs.name" . }}"
+ {{- if .Values.s3.extraEnvironmentVars }}
+ {{- range $key, $value := .Values.s3.extraEnvironmentVars }}
+ - name: {{ $key }}
+ {{- if kindIs "string" $value }}
+ value: {{ $value | quote }}
+ {{- else }}
+ valueFrom:
+ {{ toYaml $value | nindent 16 | trim }}
+ {{- end -}}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.global.extraEnvironmentVars }}
+ {{- range $key, $value := .Values.global.extraEnvironmentVars }}
+ - name: {{ $key }}
+ {{- if kindIs "string" $value }}
+ value: {{ $value | quote }}
+ {{- else }}
+ valueFrom:
+ {{ toYaml $value | nindent 16 | trim }}
+ {{- end -}}
+ {{- end }}
+ {{- end }}
+ command:
+ - "/bin/sh"
+ - "-ec"
+ - |
+ exec /usr/bin/weed \
+ {{- if or (eq .Values.s3.logs.type "hostPath") (eq .Values.s3.logs.type "emptyDir") }}
+ -logdir=/logs \
+ {{- else }}
+ -logtostderr=true \
+ {{- end }}
+ {{- if .Values.s3.loggingOverrideLevel }}
+ -v={{ .Values.s3.loggingOverrideLevel }} \
+ {{- else }}
+ -v={{ .Values.global.loggingLevel }} \
+ {{- end }}
+ s3 \
+ -ip.bind={{ .Values.s3.bindAddress }} \
+ -port={{ .Values.s3.port }} \
+ {{- if .Values.s3.metricsPort }}
+ -metricsPort {{ .Values.s3.metricsPort }} \
+ {{- end }}
+ {{- if .Values.global.enableSecurity }}
+ {{- if .Values.s3.httpsPort }}
+ -port.https={{ .Values.s3.httpsPort }} \
+ {{- end }}
+ -cert.file=/usr/local/share/ca-certificates/client/tls.crt \
+ -key.file=/usr/local/share/ca-certificates/client/tls.key \
+ {{- end }}
+ {{- if .Values.s3.domainName }}
+ -domainName={{ .Values.s3.domainName }} \
+ {{- end }}
+ {{- if .Values.s3.allowEmptyFolder }}
+ -allowEmptyFolder={{ .Values.s3.allowEmptyFolder }} \
+ {{- end }}
+ {{- if .Values.s3.enableAuth }}
+ -config=/etc/sw/seaweedfs_s3_config \
+ {{- end }}
+ {{- if .Values.s3.auditLogConfig }}
+ -auditLogConfig=/etc/sw/s3_auditLogConfig.json \
+ {{- end }}
+ -filer={{ template "seaweedfs.name" . }}-filer-client.{{ .Release.Namespace }}:{{ .Values.filer.port }}
+ volumeMounts:
+ {{- if or (eq .Values.s3.logs.type "hostPath") (eq .Values.s3.logs.type "emptyDir") }}
+ - name: logs
+ mountPath: "/logs/"
+ {{- end }}
+ {{- if .Values.s3.enableAuth }}
+ - mountPath: /etc/sw
+ name: config-users
+ readOnly: true
+ {{- end }}
+ {{- if .Values.global.enableSecurity }}
+ - name: security-config
+ readOnly: true
+ mountPath: /etc/seaweedfs/security.toml
+ subPath: security.toml
+ - name: ca-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/ca/
+ - name: master-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/master/
+ - name: volume-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/volume/
+ - name: filer-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/filer/
+ - name: client-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/client/
+ {{- end }}
+ {{ tpl .Values.s3.extraVolumeMounts . | nindent 12 | trim }}
+ ports:
+ - containerPort: {{ .Values.s3.port }}
+ name: swfs-s3
+ {{- if .Values.s3.metricsPort }}
+ - containerPort: {{ .Values.s3.metricsPort }}
+ name: "metrics"
+ {{- end }}
+ {{- if .Values.s3.readinessProbe.enabled }}
+ readinessProbe:
+ httpGet:
+ path: {{ .Values.s3.readinessProbe.httpGet.path }}
+ port: {{ .Values.s3.port }}
+ scheme: {{ .Values.s3.readinessProbe.scheme }}
+ initialDelaySeconds: {{ .Values.s3.readinessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.s3.readinessProbe.periodSeconds }}
+ successThreshold: {{ .Values.s3.readinessProbe.successThreshold }}
+ failureThreshold: {{ .Values.s3.readinessProbe.failureThreshold }}
+ timeoutSeconds: {{ .Values.s3.readinessProbe.timeoutSeconds }}
+ {{- end }}
+ {{- if .Values.s3.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ path: {{ .Values.s3.livenessProbe.httpGet.path }}
+ port: {{ .Values.s3.port }}
+ scheme: {{ .Values.s3.livenessProbe.scheme }}
+ initialDelaySeconds: {{ .Values.s3.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.s3.livenessProbe.periodSeconds }}
+ successThreshold: {{ .Values.s3.livenessProbe.successThreshold }}
+ failureThreshold: {{ .Values.s3.livenessProbe.failureThreshold }}
+ timeoutSeconds: {{ .Values.s3.livenessProbe.timeoutSeconds }}
+ {{- end }}
+ {{- with .Values.s3.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- if .Values.s3.containerSecurityContext.enabled }}
+ securityContext: {{- omit .Values.s3.containerSecurityContext "enabled" | toYaml | nindent 12 }}
+ {{- end }}
+ {{- if .Values.s3.sidecars }}
+ {{- include "common.tplvalues.render" (dict "value" .Values.s3.sidecars "context" $) | nindent 8 }}
+ {{- end }}
+ volumes:
+ {{- if .Values.s3.enableAuth }}
+ - name: config-users
+ secret:
+ defaultMode: 420
+ {{- if .Values.s3.existingConfigSecret }}
+ secretName: {{ .Values.s3.existingConfigSecret }}
+ {{- else }}
+ secretName: seaweedfs-s3-secret
+ {{- end }}
+ {{- end }}
+ {{- if eq .Values.s3.logs.type "hostPath" }}
+ - name: logs
+ hostPath:
+ path: {{ .Values.s3.logs.hostPathPrefix }}/logs/seaweedfs/s3
+ type: DirectoryOrCreate
+ {{- end }}
+ {{- if eq .Values.s3.logs.type "emptyDir" }}
+ - name: logs
+ emptyDir: {}
+ {{- end }}
+ {{- if .Values.global.enableSecurity }}
+ - name: security-config
+ configMap:
+ name: {{ template "seaweedfs.name" . }}-security-config
+ - name: ca-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-ca-cert
+ - name: master-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-master-cert
+ - name: volume-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-volume-cert
+ - name: filer-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-filer-cert
+ - name: client-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-client-cert
+ {{- end }}
+ {{ tpl .Values.s3.extraVolumes . | indent 8 | trim }}
+ {{- if .Values.s3.nodeSelector }}
+ nodeSelector:
+ {{ tpl .Values.s3.nodeSelector . | indent 8 | trim }}
+ {{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/s3-ingress.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/s3-ingress.yaml
new file mode 100644
index 00000000..7b279793
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/s3-ingress.yaml
@@ -0,0 +1,46 @@
+{{- if .Values.s3.ingress.enabled }}
+{{- 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: ingress-{{ template "seaweedfs.name" . }}-s3
+ namespace: {{ .Release.Namespace }}
+ {{- with .Values.s3.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+ 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: s3
+spec:
+ ingressClassName: {{ .Values.s3.ingress.className | quote }}
+ tls:
+ {{ .Values.s3.ingress.tls | default list | toYaml | nindent 6}}
+ rules:
+ - http:
+ paths:
+ - path: /
+ pathType: ImplementationSpecific
+ backend:
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
+ service:
+ name: {{ template "seaweedfs.name" . }}-s3
+ port:
+ number: {{ .Values.s3.port }}
+ #name:
+{{- else }}
+ serviceName: {{ template "seaweedfs.name" . }}-s3
+ servicePort: {{ .Values.s3.port }}
+{{- end }}
+{{- if .Values.s3.ingress.host }}
+ host: {{ .Values.s3.ingress.host }}
+{{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/s3-secret.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/s3-secret.yaml
new file mode 100644
index 00000000..969b31f5
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/s3-secret.yaml
@@ -0,0 +1,35 @@
+{{- if or (and .Values.filer.s3.enabled .Values.filer.s3.enableAuth (not .Values.filer.s3.existingConfigSecret)) (and .Values.s3.enabled .Values.s3.enableAuth (not .Values.s3.existingConfigSecret)) }}
+{{- $access_key_admin := randAlphaNum 16 -}}
+{{- $secret_key_admin := randAlphaNum 32 -}}
+{{- $access_key_read := randAlphaNum 16 -}}
+{{- $secret_key_read := randAlphaNum 32 -}}
+apiVersion: v1
+kind: Secret
+type: Opaque
+metadata:
+ name: seaweedfs-s3-secret
+ namespace: {{ .Release.Namespace }}
+ annotations:
+ "helm.sh/resource-policy": keep
+ "helm.sh/hook": "pre-install"
+ 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: s3
+stringData:
+ admin_access_key_id: {{ $access_key_admin }}
+ admin_secret_access_key: {{ $secret_key_admin }}
+ read_access_key_id: {{ $access_key_read }}
+ read_secret_access_key: {{ $secret_key_read }}
+ seaweedfs_s3_config: '{"identities":[{"name":"anvAdmin","credentials":[{"accessKey":"{{ $access_key_admin }}","secretKey":"{{ $secret_key_admin }}"}],"actions":["Admin","Read","Write"]},{"name":"anvReadOnly","credentials":[{"accessKey":"{{ $access_key_read }}","secretKey":"{{ $secret_key_read }}"}],"actions":["Read"]}]}'
+ {{- if .Values.filer.s3.auditLogConfig }}
+ filer_s3_auditLogConfig.json: |
+ {{ toJson .Values.filer.s3.auditLogConfig | nindent 4 }}
+ {{- end }}
+ {{- if .Values.s3.auditLogConfig }}
+ s3_auditLogConfig.json: |
+ {{ toJson .Values.s3.auditLogConfig | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/s3-service.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/s3-service.yaml
new file mode 100644
index 00000000..01d79ad7
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/s3-service.yaml
@@ -0,0 +1,34 @@
+{{- if or .Values.s3.enabled .Values.filer.s3.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ template "seaweedfs.name" . }}-s3
+ namespace: {{ .Release.Namespace }}
+ labels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: s3
+ helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+ app.kubernetes.io/managed-by: {{ .Release.Service }}
+spec:
+ internalTrafficPolicy: {{ .Values.s3.internalTrafficPolicy | default "Cluster" }}
+ ports:
+ - name: "swfs-s3"
+ port: {{ if .Values.s3.enabled }}{{ .Values.s3.port }}{{ else }}{{ .Values.filer.s3.port }}{{ end }}
+ targetPort: {{ if .Values.s3.enabled }}{{ .Values.s3.port }}{{ else }}{{ .Values.filer.s3.port }}{{ end }}
+ protocol: TCP
+{{- if and .Values.s3.enabled .Values.s3.httpsPort }}
+ - name: "swfs-s3-tls"
+ port: {{ .Values.s3.httpsPort }}
+ targetPort: {{ .Values.s3.httpsPort }}
+ protocol: TCP
+{{- end }}
+{{- if and .Values.s3.enabled .Values.s3.metricsPort }}
+ - name: "metrics"
+ port: {{ .Values.s3.metricsPort }}
+ targetPort: {{ .Values.s3.metricsPort }}
+ protocol: TCP
+{{- end }}
+ selector:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: {{ if .Values.s3.enabled }}s3{{ else }}filer{{ end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/s3-servicemonitor.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/s3-servicemonitor.yaml
new file mode 100644
index 00000000..b47ba8ee
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/s3-servicemonitor.yaml
@@ -0,0 +1,29 @@
+{{- if or .Values.s3.enabled .Values.filer.s3.enabled }}
+{{- if .Values.s3.metricsPort }}
+{{- if .Values.global.monitoring.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ template "seaweedfs.name" . }}-s3
+ namespace: {{ .Release.Namespace }}
+ 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: s3
+ {{- with .Values.global.monitoring.additionalLabels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ endpoints:
+ - interval: 30s
+ port: metrics
+ scrapeTimeout: 5s
+ selector:
+ matchLabels:
+ app: {{ template "seaweedfs.name" . }}
+ component: s3
+{{- end }}
+{{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/seaweedfs-grafana-dashboard.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/seaweedfs-grafana-dashboard.yaml
new file mode 100644
index 00000000..eb5a5eba
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/seaweedfs-grafana-dashboard.yaml
@@ -0,0 +1,20 @@
+{{- if .Values.global.monitoring.enabled }}
+{{- $files := .Files.Glob "dashboards/*.json" }}
+{{- if $files }}
+apiVersion: v1
+kind: ConfigMapList
+items:
+{{- range $path, $fileContents := $files }}
+{{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }}
+- apiVersion: v1
+ kind: ConfigMap
+ metadata:
+ name: {{ printf "%s" $dashboardName | lower | replace "_" "-" }}
+ namespace: {{ $.Release.Namespace }}
+ labels:
+ grafana_dashboard: "1"
+ data:
+ {{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }}
+{{- end }}
+{{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/secret-seaweedfs-db.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/secret-seaweedfs-db.yaml
new file mode 100644
index 00000000..5b7a8103
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/secret-seaweedfs-db.yaml
@@ -0,0 +1,21 @@
+{{- if .Values.filer.enabled }}
+apiVersion: v1
+kind: Secret
+type: Opaque
+metadata:
+ name: secret-seaweedfs-db
+ namespace: {{ .Release.Namespace }}
+ annotations:
+ "helm.sh/resource-policy": keep
+ "helm.sh/hook": "pre-install"
+ 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 }}
+stringData:
+ user: "YourSWUser"
+ password: "HardCodedPassword"
+ # better to random generate and create in DB
+ # password: {{ randAlphaNum 10 | sha256sum | b64enc | trunc 32 }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/security-configmap.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/security-configmap.yaml
new file mode 100644
index 00000000..884fe6bb
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/security-configmap.yaml
@@ -0,0 +1,80 @@
+{{- if .Values.global.enableSecurity }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ template "seaweedfs.name" . }}-security-config
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+data:
+ security.toml: |-
+ # this file is read by master, volume server, and filer
+
+ {{- if .Values.global.securityConfig.jwtSigning.volumeWrite }}
+ # the jwt signing key is read by master and volume server
+ # a jwt expires in 10 seconds
+ [jwt.signing]
+ key = "{{ randAlphaNum 10 | b64enc }}"
+ {{- end }}
+
+ {{- if .Values.global.securityConfig.jwtSigning.volumeRead }}
+ # this jwt signing key is read by master and volume server, and it is used for read operations:
+ # - the Master server generates the JWT, which can be used to read a certain file on a volume server
+ # - the Volume server validates the JWT on reading
+ [jwt.signing.read]
+ key = "{{ randAlphaNum 10 | b64enc }}"
+ {{- end }}
+
+ {{- if .Values.global.securityConfig.jwtSigning.filerWrite }}
+ # If this JWT key is configured, Filer only accepts writes over HTTP if they are signed with this JWT:
+ # - f.e. the S3 API Shim generates the JWT
+ # - the Filer server validates the JWT on writing
+ # the jwt defaults to expire after 10 seconds.
+ [jwt.filer_signing]
+ key = "{{ randAlphaNum 10 | b64enc }}"
+ {{- end }}
+
+ {{- if .Values.global.securityConfig.jwtSigning.filerRead }}
+ # If this JWT key is configured, Filer only accepts reads over HTTP if they are signed with this JWT:
+ # - f.e. the S3 API Shim generates the JWT
+ # - the Filer server validates the JWT on writing
+ # the jwt defaults to expire after 10 seconds.
+ [jwt.filer_signing.read]
+ key = "{{ randAlphaNum 10 | b64enc }}"
+ {{- end }}
+
+ # all grpc tls authentications are mutual
+ # the values for the following ca, cert, and key are paths to the PERM files.
+ [grpc]
+ ca = "/usr/local/share/ca-certificates/ca/tls.crt"
+
+ [grpc.volume]
+ cert = "/usr/local/share/ca-certificates/volume/tls.crt"
+ key = "/usr/local/share/ca-certificates/volume/tls.key"
+
+ [grpc.master]
+ cert = "/usr/local/share/ca-certificates/master/tls.crt"
+ key = "/usr/local/share/ca-certificates/master/tls.key"
+
+ [grpc.filer]
+ cert = "/usr/local/share/ca-certificates/filer/tls.crt"
+ key = "/usr/local/share/ca-certificates/filer/tls.key"
+
+ # use this for any place needs a grpc client
+ # i.e., "weed backup|benchmark|filer.copy|filer.replicate|mount|s3|upload"
+ [grpc.client]
+ cert = "/usr/local/share/ca-certificates/client/tls.crt"
+ key = "/usr/local/share/ca-certificates/client/tls.key"
+
+ # volume server https options
+ # Note: work in progress!
+ # this does not work with other clients, e.g., "weed filer|mount" etc, yet.
+ [https.client]
+ enabled = false
+ [https.volume]
+ cert = ""
+ key = ""
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/service-account.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/service-account.yaml
new file mode 100644
index 00000000..429158a2
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/service-account.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ .Values.global.serviceAccountName }}
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+automountServiceAccountToken: {{ .Values.global.automountServiceAccountToken }}
\ No newline at end of file
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/volume-cert.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-cert.yaml
new file mode 100644
index 00000000..4df63db2
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-cert.yaml
@@ -0,0 +1,41 @@
+{{- if and .Values.global.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
+apiVersion: cert-manager.io/v1{{ if .Values.global.certificates.alphacrds }}alpha1{{ end }}
+kind: Certificate
+metadata:
+ name: {{ template "seaweedfs.name" . }}-volume-cert
+ namespace: {{ .Release.Namespace }}
+ 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: volume
+spec:
+ secretName: {{ template "seaweedfs.name" . }}-volume-cert
+ issuerRef:
+ name: {{ template "seaweedfs.name" . }}-ca-issuer
+ kind: Issuer
+ commonName: {{ .Values.certificates.commonName }}
+ subject:
+ organizations:
+ - "SeaweedFS CA"
+ dnsNames:
+ - '*.{{ .Release.Namespace }}'
+ - '*.{{ .Release.Namespace }}.svc'
+ - '*.{{ .Release.Namespace }}.svc.cluster.local'
+ - '*.{{ template "seaweedfs.name" . }}-master'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}.svc'
+ - '*.{{ template "seaweedfs.name" . }}-master.{{ .Release.Namespace }}.svc.cluster.local'
+{{- if .Values.certificates.ipAddresses }}
+ ipAddresses:
+ {{- range .Values.certificates.ipAddresses }}
+ - {{ . }}
+ {{- end }}
+{{- end }}
+ privateKey:
+ algorithm: {{ .Values.certificates.keyAlgorithm }}
+ size: {{ .Values.certificates.keySize }}
+ duration: {{ .Values.certificates.duration }}
+ renewBefore: {{ .Values.certificates.renewBefore }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/volume-resize-hook.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-resize-hook.yaml
new file mode 100644
index 00000000..9f186eaa
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-resize-hook.yaml
@@ -0,0 +1,117 @@
+{{- if and .Values.volume.enabled .Values.volume.resizeHook.enabled }}
+{{- $seaweedfsName := include "seaweedfs.name" $ }}
+{{- $replicas := int .Values.volume.replicas -}}
+{{- $statefulsetName := printf "%s-volume" $seaweedfsName -}}
+{{- $statefulset := (lookup "apps/v1" "StatefulSet" .Release.Namespace $statefulsetName) -}}
+
+{{/* Check for changes in volumeClaimTemplates */}}
+{{- $templateChangesRequired := false -}}
+{{- if $statefulset -}}
+ {{- range $dir := .Values.volume.dataDirs -}}
+ {{- if eq .type "persistentVolumeClaim" -}}
+ {{- $desiredSize := .size -}}
+ {{- range $statefulset.spec.volumeClaimTemplates -}}
+ {{- if and (eq .metadata.name $dir.name) (ne .spec.resources.requests.storage $desiredSize) -}}
+ {{- $templateChangesRequired = true -}}
+ {{- end -}}
+ {{- end -}}
+ {{- end -}}
+ {{- end -}}
+{{- end -}}
+
+{{/* Check for the need for patching existing PVCs */}}
+{{- $pvcChangesRequired := false -}}
+{{- range $dir := .Values.volume.dataDirs -}}
+ {{- if eq .type "persistentVolumeClaim" -}}
+ {{- $desiredSize := .size -}}
+ {{- range $i, $e := until $replicas }}
+ {{- $pvcName := printf "%s-%s-volume-%d" $dir.name $seaweedfsName $e -}}
+ {{- $currentPVC := (lookup "v1" "PersistentVolumeClaim" $.Release.Namespace $pvcName) -}}
+ {{- if and $currentPVC (ne ($currentPVC.spec.resources.requests.storage | toString) $desiredSize) -}}
+ {{- $pvcChangesRequired = true -}}
+ {{- end -}}
+ {{- end -}}
+ {{- end -}}
+{{- end -}}
+
+{{- if or $templateChangesRequired $pvcChangesRequired }}
+apiVersion: batch/v1
+kind: Job
+metadata:
+ name: "{{ $seaweedfsName }}-volume-resize-hook"
+ annotations:
+ helm.sh/hook: pre-install,pre-upgrade
+ helm.sh/hook-weight: "0"
+ helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation
+spec:
+ template:
+ metadata:
+ labels:
+ policy.cozystack.io/allow-to-apiserver: "true"
+ spec:
+ serviceAccountName: {{ $seaweedfsName }}-volume-resize-hook
+ restartPolicy: Never
+ backoffLimit: 1
+ containers:
+ - name: resize
+ image: {{ .Values.volume.resizeHook.image }}
+ command: ["sh", "-xec"]
+ args:
+ - |
+ {{- if $pvcChangesRequired -}}
+ {{- range $dir := .Values.volume.dataDirs -}}
+ {{- if eq .type "persistentVolumeClaim" -}}
+ {{- $desiredSize := .size -}}
+ {{- range $i, $e := until $replicas }}
+ kubectl patch pvc {{ printf "%s-%s-volume-%d" $dir.name $seaweedfsName $e }} -p '{"spec":{"resources":{"requests":{"storage":"{{ $desiredSize }}"}}}}'
+ {{- end }}
+ {{- end }}
+ {{- end }}
+ {{- end -}}
+
+ {{- if $templateChangesRequired }}
+ kubectl delete statefulset {{ $statefulsetName }} --cascade=orphan
+ {{- end }}
+{{- end }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ $seaweedfsName }}-volume-resize-hook
+ annotations:
+ helm.sh/hook: pre-install,pre-upgrade
+ helm.sh/hook-weight: "-5"
+ helm.sh/hook-delete-policy: before-hook-creation
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ $seaweedfsName }}-volume-resize-hook
+ annotations:
+ helm.sh/hook: pre-install,pre-upgrade
+ helm.sh/hook-weight: "-5"
+ helm.sh/hook-delete-policy: before-hook-creation
+rules:
+ - apiGroups: ["apps"]
+ resources: ["statefulsets"]
+ verbs: ["delete", "get", "list", "watch"]
+ - apiGroups: [""]
+ resources: ["persistentvolumeclaims"]
+ verbs: ["patch", "get", "list", "watch"]
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ $seaweedfsName }}-volume-resize-hook
+ annotations:
+ helm.sh/hook: pre-install,pre-upgrade
+ helm.sh/hook-weight: "-5"
+ helm.sh/hook-delete-policy: before-hook-creation
+subjects:
+ - kind: ServiceAccount
+ name: {{ $seaweedfsName }}-volume-resize-hook
+roleRef:
+ kind: Role
+ name: {{ $seaweedfsName }}-volume-resize-hook
+ apiGroup: rbac.authorization.k8s.io
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/volume-service.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-service.yaml
new file mode 100644
index 00000000..1205f4fa
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-service.yaml
@@ -0,0 +1,33 @@
+{{- if .Values.volume.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ template "seaweedfs.name" . }}-volume
+ namespace: {{ .Release.Namespace }}
+ labels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: volume
+ helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+ app.kubernetes.io/managed-by: {{ .Release.Service }}
+spec:
+ clusterIP: None
+ internalTrafficPolicy: {{ .Values.volume.internalTrafficPolicy | default "Cluster" }}
+ ports:
+ - name: "swfs-volume"
+ port: {{ .Values.volume.port }}
+ targetPort: {{ .Values.volume.port }}
+ protocol: TCP
+ - name: "swfs-volume-18080"
+ port: {{ .Values.volume.grpcPort }}
+ targetPort: {{ .Values.volume.grpcPort }}
+ protocol: TCP
+{{- if .Values.volume.metricsPort }}
+ - name: "metrics"
+ port: {{ .Values.volume.metricsPort }}
+ targetPort: {{ .Values.volume.metricsPort }}
+ protocol: TCP
+{{- end }}
+ selector:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: volume
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/volume-servicemonitor.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-servicemonitor.yaml
new file mode 100644
index 00000000..4aeacc41
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-servicemonitor.yaml
@@ -0,0 +1,29 @@
+{{- if .Values.volume.enabled }}
+{{- if .Values.volume.metricsPort }}
+{{- if .Values.global.monitoring.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+ name: {{ template "seaweedfs.name" . }}-volume
+ namespace: {{ .Release.Namespace }}
+ 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: volume
+ {{- with .Values.global.monitoring.additionalLabels }}
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ endpoints:
+ - interval: 30s
+ port: metrics
+ scrapeTimeout: 5s
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/component: volume
+{{- end }}
+{{- end }}
+{{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/volume-statefulset.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-statefulset.yaml
new file mode 100644
index 00000000..eb3bb913
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-statefulset.yaml
@@ -0,0 +1,388 @@
+{{- if .Values.volume.enabled }}
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: {{ template "seaweedfs.name" . }}-volume
+ namespace: {{ .Release.Namespace }}
+ 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 }}
+spec:
+ persistentVolumeClaimRetentionPolicy:
+ whenDeleted: Delete
+ whenScaled: Delete
+ serviceName: {{ template "seaweedfs.name" . }}-volume
+ replicas: {{ .Values.volume.replicas }}
+ podManagementPolicy: {{ .Values.volume.podManagementPolicy }}
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: volume
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: volume
+ {{ with .Values.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.volume.podLabels }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ annotations:
+ {{ with .Values.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.volume.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ spec:
+ {{- if .Values.volume.affinity }}
+ affinity:
+ {{ tpl .Values.volume.affinity . | nindent 8 | trim }}
+ {{- end }}
+ restartPolicy: {{ default .Values.global.restartPolicy .Values.volume.restartPolicy }}
+ {{- if .Values.volume.tolerations }}
+ tolerations:
+ {{ tpl .Values.volume.tolerations . | nindent 8 | trim }}
+ {{- end }}
+ {{- include "seaweedfs.imagePullSecrets" . | nindent 6 }}
+ terminationGracePeriodSeconds: 150
+ {{- if .Values.volume.priorityClassName }}
+ priorityClassName: {{ .Values.volume.priorityClassName | quote }}
+ {{- end }}
+ enableServiceLinks: false
+ {{- if .Values.global.createClusterRole }}
+ serviceAccountName: {{ .Values.volume.serviceAccountName | default .Values.global.serviceAccountName | quote }} # for deleting statefulset pods after migration
+ {{- end }}
+ {{- $initContainers_exists := include "volume.initContainers_exists" . -}}
+ {{- if $initContainers_exists }}
+ initContainers:
+ {{- if .Values.volume.idx }}
+ - name: seaweedfs-vol-move-idx
+ image: {{ template "volume.image" . }}
+ imagePullPolicy: {{ .Values.global.imagePullPolicy | default "IfNotPresent" }}
+ command: [ '/bin/sh', '-c' ]
+ args: [ '{{range $dir := .Values.volume.dataDirs }}if ls /{{$dir.name}}/*.idx >/dev/null 2>&1; then mv /{{$dir.name}}/*.idx /idx/ ; fi; {{end}}' ]
+ volumeMounts:
+ - name: idx
+ mountPath: /idx
+ {{- range $dir := .Values.volume.dataDirs }}
+ - name: {{ $dir.name }}
+ mountPath: /{{ $dir.name }}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.volume.initContainers }}
+ {{ tpl .Values.volume.initContainers . | nindent 8 | trim }}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.volume.podSecurityContext.enabled }}
+ securityContext: {{- omit .Values.volume.podSecurityContext "enabled" | toYaml | nindent 8 }}
+ {{- end }}
+ containers:
+ - name: seaweedfs
+ image: {{ template "volume.image" . }}
+ imagePullPolicy: {{ default "IfNotPresent" .Values.global.imagePullPolicy }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: NAMESPACE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.namespace
+ - name: HOST_IP
+ valueFrom:
+ fieldRef:
+ fieldPath: status.hostIP
+ - name: SEAWEEDFS_FULLNAME
+ value: "{{ template "seaweedfs.name" . }}"
+ {{- if .Values.volume.extraEnvironmentVars }}
+ {{- range $key, $value := .Values.volume.extraEnvironmentVars }}
+ - name: {{ $key }}
+ {{- if kindIs "string" $value }}
+ value: {{ $value | quote }}
+ {{- else }}
+ valueFrom:
+ {{ toYaml $value | nindent 16 | trim }}
+ {{- end -}}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.global.extraEnvironmentVars }}
+ {{- range $key, $value := .Values.global.extraEnvironmentVars }}
+ - name: {{ $key }}
+ {{- if kindIs "string" $value }}
+ value: {{ $value | quote }}
+ {{- else }}
+ valueFrom:
+ {{ toYaml $value | nindent 16 | trim }}
+ {{- end -}}
+ {{- end }}
+ {{- end }}
+ command:
+ - "/bin/sh"
+ - "-ec"
+ - |
+ exec /usr/bin/weed \
+ {{- if .Values.volume.logs }}
+ -logdir=/logs \
+ {{- else }}
+ -logtostderr=true \
+ {{- end }}
+ {{- if .Values.volume.loggingOverrideLevel }}
+ -v={{ .Values.volume.loggingOverrideLevel }} \
+ {{- else }}
+ -v={{ .Values.global.loggingLevel }} \
+ {{- end }}
+ volume \
+ -port={{ .Values.volume.port }} \
+ {{- if .Values.volume.metricsPort }}
+ -metricsPort={{ .Values.volume.metricsPort }} \
+ {{- end }}
+ -dir {{range $index, $dir := .Values.volume.dataDirs }}{{if ne $index 0}},{{end}}/{{$dir.name}}{{end}} \
+ {{- if .Values.volume.idx }}
+ -dir.idx=/idx \
+ {{- end }}
+ -max {{range $index, $dir := .Values.volume.dataDirs }}{{if ne $index 0}},{{end}}{{$dir.maxVolumes}}{{end}} \
+ {{- if .Values.volume.rack }}
+ -rack={{ .Values.volume.rack }} \
+ {{- end }}
+ {{- if .Values.volume.dataCenter }}
+ -dataCenter={{ .Values.volume.dataCenter }} \
+ {{- end }}
+ -ip.bind={{ .Values.volume.ipBind }} \
+ -readMode={{ .Values.volume.readMode }} \
+ {{- if .Values.volume.whiteList }}
+ -whiteList={{ .Values.volume.whiteList }} \
+ {{- end }}
+ {{- if .Values.volume.imagesFixOrientation }}
+ -images.fix.orientation \
+ {{- end }}
+ {{- if .Values.volume.pulseSeconds }}
+ -pulseSeconds={{ .Values.volume.pulseSeconds }} \
+ {{- end }}
+ {{- if .Values.volume.index }}
+ -index={{ .Values.volume.index }} \
+ {{- end }}
+ {{- if .Values.volume.fileSizeLimitMB }}
+ -fileSizeLimitMB={{ .Values.volume.fileSizeLimitMB }} \
+ {{- end }}
+ -minFreeSpacePercent={{ .Values.volume.minFreeSpacePercent }} \
+ -ip=${POD_NAME}.${SEAWEEDFS_FULLNAME}-volume.{{ .Release.Namespace }} \
+ -compactionMBps={{ .Values.volume.compactionMBps }} \
+ -mserver={{ if .Values.global.masterServer }}{{.Values.global.masterServer}}{{ else }}{{ range $index := until (.Values.master.replicas | int) }}${SEAWEEDFS_FULLNAME}-master-{{ $index }}.${SEAWEEDFS_FULLNAME}-master.{{ $.Release.Namespace }}:{{ $.Values.master.port }}{{ if lt $index (sub ($.Values.master.replicas | int) 1) }},{{ end }}{{ end }}{{ end }}
+ volumeMounts:
+ {{- range $dir := .Values.volume.dataDirs }}
+ - name: {{ $dir.name }}
+ mountPath: "/{{ $dir.name }}/"
+ {{- end }}
+ {{- if .Values.volume.logs }}
+ - name: logs
+ mountPath: "/logs/"
+ {{- end }}
+ {{- if .Values.volume.idx }}
+ - name: idx
+ mountPath: "/idx/"
+ {{- end }}
+ {{- if .Values.global.enableSecurity }}
+ - name: security-config
+ readOnly: true
+ mountPath: /etc/seaweedfs/security.toml
+ subPath: security.toml
+ - name: ca-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/ca/
+ - name: master-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/master/
+ - name: volume-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/volume/
+ - name: filer-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/filer/
+ - name: client-cert
+ readOnly: true
+ mountPath: /usr/local/share/ca-certificates/client/
+ {{- end }}
+ {{ tpl .Values.volume.extraVolumeMounts . | nindent 12 | trim }}
+ ports:
+ - containerPort: {{ .Values.volume.port }}
+ name: swfs-vol
+ {{- if .Values.volume.metricsPort }}
+ - containerPort: {{ .Values.volume.metricsPort }}
+ name: metrics
+ {{- end }}
+ - containerPort: {{ .Values.volume.grpcPort }}
+ name: swfs-vol-grpc
+ {{- if .Values.volume.readinessProbe.enabled }}
+ readinessProbe:
+ httpGet:
+ path: {{ .Values.volume.readinessProbe.httpGet.path }}
+ port: {{ .Values.volume.port }}
+ scheme: {{ .Values.volume.readinessProbe.scheme }}
+ initialDelaySeconds: {{ .Values.volume.readinessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.volume.readinessProbe.periodSeconds }}
+ successThreshold: {{ .Values.volume.readinessProbe.successThreshold }}
+ failureThreshold: {{ .Values.volume.readinessProbe.failureThreshold }}
+ timeoutSeconds: {{ .Values.volume.readinessProbe.timeoutSeconds }}
+ {{- end }}
+ {{- if .Values.volume.livenessProbe.enabled }}
+ livenessProbe:
+ httpGet:
+ path: {{ .Values.volume.livenessProbe.httpGet.path }}
+ port: {{ .Values.volume.port }}
+ scheme: {{ .Values.volume.livenessProbe.scheme }}
+ initialDelaySeconds: {{ .Values.volume.livenessProbe.initialDelaySeconds }}
+ periodSeconds: {{ .Values.volume.livenessProbe.periodSeconds }}
+ successThreshold: {{ .Values.volume.livenessProbe.successThreshold }}
+ failureThreshold: {{ .Values.volume.livenessProbe.failureThreshold }}
+ timeoutSeconds: {{ .Values.volume.livenessProbe.timeoutSeconds }}
+ {{- end }}
+ {{- with .Values.volume.resources }}
+ resources:
+ {{- toYaml . | nindent 12 }}
+ {{- end }}
+ {{- if .Values.volume.containerSecurityContext.enabled }}
+ securityContext: {{- omit .Values.volume.containerSecurityContext "enabled" | toYaml | nindent 12 }}
+ {{- end }}
+ {{- if .Values.volume.sidecars }}
+ {{- include "common.tplvalues.render" (dict "value" .Values.volume.sidecars "context" $) | nindent 8 }}
+ {{- end }}
+ volumes:
+
+ {{- range $dir := .Values.volume.dataDirs }}
+
+ {{- if eq $dir.type "hostPath" }}
+ - name: {{ $dir.name }}
+ hostPath:
+ path: {{ $dir.hostPathPrefix }}/object_store/
+ type: DirectoryOrCreate
+ {{- end }}
+ {{- if eq $dir.type "existingClaim" }}
+ - name: {{ $dir.name }}
+ persistentVolumeClaim:
+ claimName: {{ $dir.claimName }}
+ {{- end }}
+ {{- if eq $dir.type "emptyDir" }}
+ - name: {{ $dir.name }}
+ emptyDir: {}
+ {{- end }}
+
+ {{- end }}
+
+ {{- if .Values.volume.idx }}
+ {{- if eq .Values.volume.idx.type "hostPath" }}
+ - name: idx
+ hostPath:
+ path: {{ .Values.volume.idx.hostPathPrefix }}/seaweedfs-volume-idx/
+ type: DirectoryOrCreate
+ {{- end }}
+ {{- if eq .Values.volume.idx.type "existingClaim" }}
+ - name: idx
+ persistentVolumeClaim:
+ claimName: {{ .Values.volume.idx.claimName }}
+ {{- end }}
+ {{- if eq .Values.volume.idx.type "emptyDir" }}
+ - name: idx
+ emptyDir: {}
+ {{- end }}
+ {{- end }}
+
+ {{- if .Values.volume.logs }}
+ {{- if eq .Values.volume.logs.type "hostPath" }}
+ - name: logs
+ hostPath:
+ path: {{ .Values.volume.logs.hostPathPrefix }}/logs/seaweedfs/volume
+ type: DirectoryOrCreate
+ {{- end }}
+ {{- if eq .Values.volume.logs.type "existingClaim" }}
+ - name: logs
+ persistentVolumeClaim:
+ claimName: {{ .Values.volume.logs.claimName }}
+ {{- end }}
+ {{- if eq .Values.volume.logs.type "emptyDir" }}
+ - name: logs
+ emptyDir: {}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.global.enableSecurity }}
+ - name: security-config
+ configMap:
+ name: {{ template "seaweedfs.name" . }}-security-config
+ - name: ca-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-ca-cert
+ - name: master-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-master-cert
+ - name: volume-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-volume-cert
+ - name: filer-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-filer-cert
+ - name: client-cert
+ secret:
+ secretName: {{ template "seaweedfs.name" . }}-client-cert
+ {{- end }}
+ {{- if .Values.volume.extraVolumes }}
+ {{ tpl .Values.volume.extraVolumes . | indent 8 | trim }}
+ {{- end }}
+ {{- if .Values.volume.nodeSelector }}
+ nodeSelector:
+ {{ tpl .Values.volume.nodeSelector . | indent 8 | trim }}
+ {{- end }}
+ volumeClaimTemplates:
+ {{- range $dir := .Values.volume.dataDirs }}
+ {{- if eq $dir.type "persistentVolumeClaim" }}
+ - metadata:
+ name: {{ $dir.name }}
+ {{- with $dir.annotations }}
+ annotations:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ spec:
+ accessModes: [ "ReadWriteOnce" ]
+ storageClassName: {{ $dir.storageClass }}
+ resources:
+ requests:
+ storage: {{ $dir.size }}
+ {{- end }}
+ {{- end }}
+
+ {{- if and .Values.volume.idx (eq .Values.volume.idx.type "persistentVolumeClaim") }}
+ - metadata:
+ name: idx
+ {{- with .Values.volume.idx.annotations }}
+ annotations:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ spec:
+ accessModes: [ "ReadWriteOnce" ]
+ storageClassName: {{ .Values.volume.idx.storageClass }}
+ resources:
+ requests:
+ storage: {{ .Values.volume.idx.size }}
+ {{- end }}
+ {{- if and .Values.volume.logs (eq .Values.volume.logs.type "persistentVolumeClaim") }}
+ - metadata:
+ name: logs
+ {{- with .Values.volume.logs.annotations }}
+ annotations:
+ {{- toYaml . | nindent 10 }}
+ {{- end }}
+ spec:
+ accessModes: [ "ReadWriteOnce" ]
+ storageClassName: {{ .Values.volume.logs.storageClass }}
+ resources:
+ requests:
+ storage: {{ .Values.volume.logs.size }}
+ {{- end }}
+ {{- end }}
diff --git a/packages/system/seaweedfs/charts/seaweedfs/values.yaml b/packages/system/seaweedfs/charts/seaweedfs/values.yaml
new file mode 100644
index 00000000..e53fa596
--- /dev/null
+++ b/packages/system/seaweedfs/charts/seaweedfs/values.yaml
@@ -0,0 +1,917 @@
+# Available parameters and their default values for the SeaweedFS chart.
+
+global:
+ createClusterRole: true
+ registry: ""
+ repository: ""
+ imageName: chrislusf/seaweedfs
+ imagePullPolicy: IfNotPresent
+ imagePullSecrets: ""
+ restartPolicy: Always
+ loggingLevel: 1
+ enableSecurity: false
+ masterServer: null
+ securityConfig:
+ jwtSigning:
+ volumeWrite: true
+ volumeRead: false
+ filerWrite: false
+ filerRead: false
+ # we will use this serviceAccountName for all ClusterRoles/ClusterRoleBindings
+ serviceAccountName: "seaweedfs"
+ automountServiceAccountToken: true
+ certificates:
+ alphacrds: false
+ monitoring:
+ enabled: false
+ gatewayHost: null
+ gatewayPort: null
+ additionalLabels: {}
+ # if enabled will use global.replicationPlacment and override master & filer defaultReplicaPlacement config
+ enableReplication: false
+ # replication type is XYZ:
+ # X number of replica in other data centers
+ # Y number of replica in other racks in the same data center
+ # Z number of replica in other servers in the same rack
+ replicationPlacment: "001"
+ extraEnvironmentVars:
+ WEED_CLUSTER_DEFAULT: "sw"
+ WEED_CLUSTER_SW_MASTER: "seaweedfs-master.seaweedfs:9333"
+ WEED_CLUSTER_SW_FILER: "seaweedfs-filer-client.seaweedfs:8888"
+ # WEED_JWT_SIGNING_KEY:
+ # secretKeyRef:
+ # name: seaweedfs-signing-key
+ # key: signingKey
+
+image:
+ registry: ""
+ repository: ""
+
+master:
+ enabled: true
+ imageOverride: null
+ restartPolicy: null
+ replicas: 1
+ port: 9333
+ grpcPort: 19333
+ metricsPort: 9327
+ ipBind: "0.0.0.0"
+ volumePreallocate: false
+ volumeSizeLimitMB: 1000
+ loggingOverrideLevel: null
+ # number of seconds between heartbeats, default 5
+ pulseSeconds: null
+ # threshold to vacuum and reclaim spaces, default 0.3 (30%)
+ garbageThreshold: null
+ # Prometheus push interval in seconds, default 15
+ metricsIntervalSec: 15
+ # replication type is XYZ:
+ # X number of replica in other data centers
+ # Y number of replica in other racks in the same data center
+ # Z number of replica in other servers in the same rack
+ defaultReplication: "000"
+
+ # Disable http request, only gRpc operations are allowed
+ disableHttp: false
+
+ config: |-
+ # Enter any extra configuration for master.toml here.
+ # It may be a multi-line string.
+
+ # You may use ANY storage-class, example with local-path-provisioner
+ # Annotations are optional.
+ # data:
+ # type: "persistentVolumeClaim"
+ # size: "24Ti"
+ # storageClass: "local-path-provisioner"
+ # annotations:
+ # "key": "value"
+ #
+ # You may also spacify an existing claim:
+ # data:
+ # type: "existingClaim"
+ # claimName: "my-pvc"
+ #
+ # You can also use emptyDir storage:
+ # data:
+ # type: "emptyDir"
+ data:
+ type: "hostPath"
+ storageClass: ""
+ hostPathPrefix: /ssd
+
+ # You can also use emptyDir storage:
+ # logs:
+ # type: "emptyDir"
+ logs:
+ type: "hostPath"
+ size: ""
+ storageClass: ""
+ hostPathPrefix: /storage
+
+ ## @param master.sidecars Add additional sidecar containers to the master pod(s)
+ ## e.g:
+ ## sidecars:
+ ## - name: your-image-name
+ ## image: your-image
+ ## imagePullPolicy: Always
+ ## ports:
+ ## - name: portname
+ ## containerPort: 1234
+ ##
+ sidecars: []
+ initContainers: ""
+
+ extraVolumes: ""
+ extraVolumeMounts: ""
+
+ # Labels to be added to the master pods
+ podLabels: {}
+
+ # Annotations to be added to the master pods
+ podAnnotations: {}
+
+ ## Set podManagementPolicy
+ podManagementPolicy: Parallel
+
+ # Resource requests, limits, etc. for the master cluster placement. This
+ # should map directly to the value of the resources field for a PodSpec,
+ # formatted as a multi-line string. By default no direct resource request
+ # is made.
+ resources: {}
+
+ # updatePartition is used to control a careful rolling update of SeaweedFS
+ # masters.
+ updatePartition: 0
+
+ # Affinity Settings
+ # Commenting out or setting as empty the affinity variable, will allow
+ # deployment to single node services such as Minikube
+ affinity: |
+ podAntiAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ - labelSelector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: master
+ topologyKey: kubernetes.io/hostname
+
+ # Toleration Settings for master pods
+ # This should be a multi-line string matching the Toleration array
+ # in a PodSpec.
+ tolerations: ""
+
+ # nodeSelector labels for master pod assignment, formatted as a muli-line string.
+ # ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
+ # Example:
+ nodeSelector: |
+ kubernetes.io/arch: amd64
+ # nodeSelector: |
+ # sw-backend: "true"
+
+ # used to assign priority to master pods
+ # ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
+ priorityClassName: ""
+
+ # used to assign a service account.
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
+ serviceAccountName: ""
+
+ # Configure security context for Pod
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+ # Example:
+ # podSecurityContext:
+ # enabled: true
+ # runAsUser: 1000
+ # runAsGroup: 3000
+ # fsGroup: 2000
+ podSecurityContext: {}
+
+ # Configure security context for Container
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+ # Example:
+ # containerSecurityContext:
+ # enabled: true
+ # runAsUser: 2000
+ # allowPrivilegeEscalation: false
+ containerSecurityContext: {}
+
+ ingress:
+ enabled: false
+ className: "nginx"
+ # host: false for "*" hostname
+ host: "master.seaweedfs.local"
+ annotations:
+ nginx.ingress.kubernetes.io/auth-type: "basic"
+ nginx.ingress.kubernetes.io/auth-secret: "default/ingress-basic-auth-secret"
+ nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - SW-Master'
+ nginx.ingress.kubernetes.io/service-upstream: "true"
+ nginx.ingress.kubernetes.io/rewrite-target: /$1
+ nginx.ingress.kubernetes.io/use-regex: "true"
+ nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
+ nginx.ingress.kubernetes.io/ssl-redirect: "false"
+ nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
+ nginx.ingress.kubernetes.io/configuration-snippet: |
+ sub_filter '' ' '; #add base url
+ sub_filter '="/' '="./'; #make absolute paths to relative
+ sub_filter '=/' '=./';
+ sub_filter '/seaweedfsstatic' './seaweedfsstatic';
+ sub_filter_once off;
+ tls: []
+
+ extraEnvironmentVars:
+ WEED_MASTER_VOLUME_GROWTH_COPY_1: '7'
+ WEED_MASTER_VOLUME_GROWTH_COPY_2: '6'
+ WEED_MASTER_VOLUME_GROWTH_COPY_3: '3'
+ WEED_MASTER_VOLUME_GROWTH_COPY_OTHER: '1'
+
+ # used to configure livenessProbe on master-server containers
+ #
+ livenessProbe:
+ enabled: true
+ httpGet:
+ path: /cluster/status
+ scheme: HTTP
+ initialDelaySeconds: 20
+ periodSeconds: 30
+ successThreshold: 1
+ failureThreshold: 4
+ timeoutSeconds: 10
+
+ # used to configure readinessProbe on master-server containers
+ #
+ readinessProbe:
+ enabled: true
+ httpGet:
+ path: /cluster/status
+ scheme: HTTP
+ initialDelaySeconds: 10
+ periodSeconds: 45
+ successThreshold: 2
+ failureThreshold: 100
+ timeoutSeconds: 10
+
+volume:
+ enabled: true
+ imageOverride: null
+ restartPolicy: null
+ port: 8080
+ grpcPort: 18080
+ metricsPort: 9327
+ ipBind: "0.0.0.0"
+ replicas: 1
+ loggingOverrideLevel: null
+ # number of seconds between heartbeats, must be smaller than or equal to the master's setting
+ pulseSeconds: null
+ # Choose [memory|leveldb|leveldbMedium|leveldbLarge] mode for memory~performance balance., default memory
+ index: null
+ # limit file size to avoid out of memory, default 256mb
+ fileSizeLimitMB: null
+ # minimum free disk space(in percents). If free disk space lower this value - all volumes marks as ReadOnly
+ minFreeSpacePercent: 7
+
+ # For each data disk you may use ANY storage-class, example with local-path-provisioner
+ # Annotations are optional.
+ # dataDirs:
+ # - name: data:
+ # type: "persistentVolumeClaim"
+ # size: "24Ti"
+ # storageClass: "local-path-provisioner"
+ # annotations:
+ # "key": "value"
+ # maxVolumes: 0 # If set to zero on non-windows OS, the limit will be auto configured. (default "7")
+ #
+ # You may also spacify an existing claim:
+ # - name: data
+ # type: "existingClaim"
+ # claimName: "my-pvc"
+ # maxVolumes: 0 # If set to zero on non-windows OS, the limit will be auto configured. (default "7")
+ #
+ # You can also use emptyDir storage:
+ # - name: data
+ # type: "emptyDir"
+ # maxVolumes: 0 # If set to zero on non-windows OS, the limit will be auto configured. (default "7")
+
+ dataDirs:
+ - name: data1
+ type: "hostPath"
+ hostPathPrefix: /ssd
+ maxVolumes: 0
+
+ # - name: data2
+ # type: "persistentVolumeClaim"
+ # storageClass: "yourClassNameOfChoice"
+ # size: "800Gi"
+ # maxVolumes: 0
+
+ # This will automatically create a job for patching Kubernetes resources if the dataDirs type is 'persistentVolumeClaim' and the size has changed.
+ resizeHook:
+ enabled: true
+ image: bitnami/kubectl
+
+ # idx can be defined by:
+ #
+ # idx:
+ # type: "hostPath"
+ # hostPathPrefix: /ssd
+ #
+ # or
+ #
+ # idx:
+ # type: "persistentVolumeClaim"
+ # size: "20Gi"
+ # storageClass: "local-path-provisioner"
+ #
+ # or
+ #
+ # idx:
+ # type: "existingClaim"
+ # claimName: "myClaim"
+ #
+ # or
+ #
+ # idx:
+ # type: "emptyDir"
+
+ # same applies to "logs"
+
+ idx: {}
+
+ logs: {}
+
+ # limit background compaction or copying speed in mega bytes per second
+ compactionMBps: "50"
+
+
+ # Volume server's rack name
+ rack: null
+
+ # Volume server's data center name
+ dataCenter: null
+
+ # Redirect moved or non-local volumes. (default proxy)
+ readMode: proxy
+
+ # Comma separated Ip addresses having write permission. No limit if empty.
+ whiteList: null
+
+ # Adjust jpg orientation when uploading.
+ imagesFixOrientation: false
+
+ ## @param volume.sidecars Add additional sidecar containers to the volume pod(s)
+ ## e.g:
+ ## sidecars:
+ ## - name: your-image-name
+ ## image: your-image
+ ## imagePullPolicy: Always
+ ## ports:
+ ## - name: portname
+ ## containerPort: 1234
+ ##
+ sidecars: []
+ initContainers: ""
+
+ extraVolumes: ""
+ extraVolumeMounts: ""
+
+ # Labels to be added to the volume pods
+ podLabels: {}
+
+ # Annotations to be added to the volume pods
+ podAnnotations: {}
+
+ ## Set podManagementPolicy
+ podManagementPolicy: Parallel
+
+ # Affinity Settings
+ # Commenting out or setting as empty the affinity variable, will allow
+ # deployment to single node services such as Minikube
+ affinity: |
+ podAntiAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ - labelSelector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: volume
+ topologyKey: kubernetes.io/hostname
+
+ # Resource requests, limits, etc. for the server cluster placement. This
+ # should map directly to the value of the resources field for a PodSpec,
+ # formatted as a multi-line string. By default no direct resource request
+ # is made.
+ resources: {}
+
+ # Toleration Settings for server pods
+ # This should be a multi-line string matching the Toleration array
+ # in a PodSpec.
+ tolerations: ""
+
+ # nodeSelector labels for server pod assignment, formatted as a muli-line string.
+ # ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
+ # Example:
+ nodeSelector: |
+ kubernetes.io/arch: amd64
+ # nodeSelector: |
+ # sw-volume: "true"
+
+ # used to assign priority to server pods
+ # ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
+ priorityClassName: ""
+
+ # used to assign a service account.
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
+ serviceAccountName: ""
+
+ extraEnvironmentVars:
+
+ # Configure security context for Pod
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+ # Example:
+ # podSecurityContext:
+ # enabled: true
+ # runAsUser: 1000
+ # runAsGroup: 3000
+ # fsGroup: 2000
+ podSecurityContext: {}
+
+ # Configure security context for Container
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+ # Example:
+ # containerSecurityContext:
+ # enabled: true
+ # runAsUser: 2000
+ # allowPrivilegeEscalation: false
+ containerSecurityContext: {}
+
+ # used to configure livenessProbe on volume-server containers
+ #
+ livenessProbe:
+ enabled: true
+ httpGet:
+ path: /status
+ scheme: HTTP
+ initialDelaySeconds: 20
+ periodSeconds: 90
+ successThreshold: 1
+ failureThreshold: 4
+ timeoutSeconds: 30
+
+ # used to configure readinessProbe on volume-server containers
+ #
+ readinessProbe:
+ enabled: true
+ httpGet:
+ path: /status
+ scheme: HTTP
+ initialDelaySeconds: 15
+ periodSeconds: 15
+ successThreshold: 1
+ failureThreshold: 100
+ timeoutSeconds: 30
+
+filer:
+ enabled: true
+ imageOverride: null
+ restartPolicy: null
+ replicas: 1
+ port: 8888
+ grpcPort: 18888
+ metricsPort: 9327
+ loggingOverrideLevel: null
+ filerGroup: ""
+ # replication type is XYZ:
+ # X number of replica in other data centers
+ # Y number of replica in other racks in the same data center
+ # Z number of replica in other servers in the same rack
+ defaultReplicaPlacement: "000"
+ # turn off directory listing
+ disableDirListing: false
+ # split files larger than the limit, default 32
+ maxMB: null
+ # encrypt data on volume servers
+ encryptVolumeData: false
+
+ # Whether proxy or redirect to volume server during file GET request
+ redirectOnRead: false
+
+ # Limit sub dir listing size (default 100000)
+ dirListLimit: 100000
+
+ # Disable http request, only gRpc operations are allowed
+ disableHttp: false
+
+ # DEPRECATE: enablePVC, storage, storageClass
+ # Consider replacing with filer.data section below instead.
+
+ # Settings for configuring stateful storage of filer pods.
+ # enablePVC will create a pvc for filer for data persistence.
+ enablePVC: false
+ # storage should be set to the disk size of the attached volume.
+ storage: 25Gi
+ # storageClass is the class of storage which defaults to null (the Kube cluster will pick the default).
+ storageClass: null
+ # You may use ANY storage-class, example with local-path-provisioner
+ # Annotations are optional.
+ # data:
+ # type: "persistentVolumeClaim"
+ # size: "24Ti"
+ # storageClass: "local-path-provisioner"
+ # annotations:
+ # "key": "value"
+ #
+ # You may also specify an existing claim:
+ # data:
+ # type: "existingClaim"
+ # claimName: "my-pvc"
+ #
+ # You can also use emptyDir storage:
+ # data:
+ # type: "emptyDir"
+ data:
+ type: "hostPath"
+ size: ""
+ storageClass: ""
+ hostPathPrefix: /storage
+
+ # You can also use emptyDir storage:
+ # logs:
+ # type: "emptyDir"
+ logs:
+ type: "hostPath"
+ size: ""
+ storageClass: ""
+ hostPathPrefix: /storage
+
+ ## @param filer.sidecars Add additional sidecar containers to the filer pod(s)
+ ## e.g:
+ ## sidecars:
+ ## - name: your-image-name
+ ## image: your-image
+ ## imagePullPolicy: Always
+ ## ports:
+ ## - name: portname
+ ## containerPort: 1234
+ ##
+ sidecars: []
+ initContainers: ""
+
+ extraVolumes: ""
+ extraVolumeMounts: ""
+
+ # Labels to be added to the filer pods
+ podLabels: {}
+
+ # Annotations to be added to the filer pods
+ podAnnotations: {}
+
+ ## Set podManagementPolicy
+ podManagementPolicy: Parallel
+
+ # Affinity Settings
+ # Commenting out or setting as empty the affinity variable, will allow
+ # deployment to single node services such as Minikube
+ affinity: |
+ podAntiAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ - labelSelector:
+ matchLabels:
+ app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ app.kubernetes.io/component: filer
+ topologyKey: kubernetes.io/hostname
+
+ # updatePartition is used to control a careful rolling update of SeaweedFS
+ # masters.
+ updatePartition: 0
+
+ # Resource requests, limits, etc. for the server cluster placement. This
+ # should map directly to the value of the resources field for a PodSpec,
+ # formatted as a multi-line string. By default no direct resource request
+ # is made.
+ resources: {}
+
+ # Toleration Settings for server pods
+ # This should be a multi-line string matching the Toleration array
+ # in a PodSpec.
+ tolerations: ""
+
+ # nodeSelector labels for server pod assignment, formatted as a muli-line string.
+ # ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
+ # Example:
+ nodeSelector: |
+ kubernetes.io/arch: amd64
+ # nodeSelector: |
+ # sw-backend: "true"
+
+ # used to assign priority to server pods
+ # ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
+ priorityClassName: ""
+
+ # used to assign a service account.
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
+ serviceAccountName: ""
+
+ # Configure security context for Pod
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+ # Example:
+ # podSecurityContext:
+ # enabled: true
+ # runAsUser: 1000
+ # runAsGroup: 3000
+ # fsGroup: 2000
+ podSecurityContext: {}
+
+ # Configure security context for Container
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+ # Example:
+ # containerSecurityContext:
+ # enabled: true
+ # runAsUser: 2000
+ # allowPrivilegeEscalation: false
+ containerSecurityContext: {}
+
+ ingress:
+ enabled: false
+ className: "nginx"
+ # host: false for "*" hostname
+ host: "seaweedfs.cluster.local"
+ annotations:
+ nginx.ingress.kubernetes.io/backend-protocol: GRPC
+ nginx.ingress.kubernetes.io/auth-type: "basic"
+ nginx.ingress.kubernetes.io/auth-secret: "default/ingress-basic-auth-secret"
+ nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - SW-Filer'
+ nginx.ingress.kubernetes.io/service-upstream: "true"
+ nginx.ingress.kubernetes.io/rewrite-target: /$1
+ nginx.ingress.kubernetes.io/use-regex: "true"
+ nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
+ nginx.ingress.kubernetes.io/ssl-redirect: "false"
+ nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
+ nginx.ingress.kubernetes.io/configuration-snippet: |
+ sub_filter '' ' '; #add base url
+ sub_filter '="/' '="./'; #make absolute paths to relative
+ sub_filter '=/' '=./';
+ sub_filter '/seaweedfsstatic' './seaweedfsstatic';
+ sub_filter_once off;
+
+ # extraEnvVars is a list of extra enviroment variables to set with the stateful set.
+ extraEnvironmentVars:
+ WEED_MYSQL_ENABLED: "false"
+ WEED_MYSQL_HOSTNAME: "mysql-db-host"
+ WEED_MYSQL_PORT: "3306"
+ WEED_MYSQL_DATABASE: "sw_database"
+ WEED_MYSQL_CONNECTION_MAX_IDLE: "5"
+ WEED_MYSQL_CONNECTION_MAX_OPEN: "75"
+ # "refresh" connection every 10 minutes, eliminating mysql closing "old" connections
+ WEED_MYSQL_CONNECTION_MAX_LIFETIME_SECONDS: "600"
+ # enable usage of memsql as filer backend
+ WEED_MYSQL_INTERPOLATEPARAMS: "true"
+ # if you want to use leveldb2, then should enable "enablePVC". or you may lose your data.
+ WEED_LEVELDB2_ENABLED: "true"
+ # with http DELETE, by default the filer would check whether a folder is empty.
+ # recursive_delete will delete all sub folders and files, similar to "rm -Rf"
+ WEED_FILER_OPTIONS_RECURSIVE_DELETE: "false"
+ # directories under this folder will be automatically creating a separate bucket
+ WEED_FILER_BUCKETS_FOLDER: "/buckets"
+
+ # used to configure livenessProbe on filer containers
+ #
+ livenessProbe:
+ enabled: true
+ httpGet:
+ path: /
+ scheme: HTTP
+ initialDelaySeconds: 20
+ periodSeconds: 30
+ successThreshold: 1
+ failureThreshold: 5
+ timeoutSeconds: 10
+
+ # used to configure readinessProbe on filer containers
+ #
+ readinessProbe:
+ enabled: true
+ httpGet:
+ path: /
+ scheme: HTTP
+ initialDelaySeconds: 10
+ periodSeconds: 15
+ successThreshold: 1
+ failureThreshold: 100
+ timeoutSeconds: 10
+
+ # secret env variables
+ secretExtraEnvironmentVars: {}
+ # WEED_POSTGRES_USERNAME:
+ # secretKeyRef:
+ # name: postgres-credentials
+ # key: username
+ # WEED_POSTGRES_PASSWORD:
+ # secretKeyRef:
+ # name: postgres-credentials
+ # key: password
+
+ s3:
+ enabled: false
+ port: 8333
+ # add additional https port
+ httpsPort: 0
+ # allow empty folders
+ allowEmptyFolder: false
+ # Suffix of the host name, {bucket}.{domainName}
+ domainName: ""
+ # enable user & permission to s3 (need to inject to all services)
+ enableAuth: false
+ # 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 configure
+ existingConfigSecret: null
+ 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
+
+s3:
+ enabled: false
+ imageOverride: null
+ restartPolicy: null
+ replicas: 1
+ bindAddress: 0.0.0.0
+ port: 8333
+ # add additional https port
+ httpsPort: 0
+ metricsPort: 9327
+ loggingOverrideLevel: null
+ # allow empty folders
+ allowEmptyFolder: true
+ # enable user & permission to s3 (need to inject to all services)
+ enableAuth: false
+ # 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: {}
+
+ # Suffix of the host name, {bucket}.{domainName}
+ domainName: ""
+
+ ## @param s3.sidecars Add additional sidecar containers to the s3 pod(s)
+ ## e.g:
+ ## sidecars:
+ ## - name: your-image-name
+ ## image: your-image
+ ## imagePullPolicy: Always
+ ## ports:
+ ## - name: portname
+ ## containerPort: 1234
+ ##
+ sidecars: []
+ initContainers: ""
+
+ extraVolumes: ""
+ extraVolumeMounts: ""
+
+ # Labels to be added to the s3 pods
+ podLabels: {}
+
+ # Annotations to be added to the s3 pods
+ podAnnotations: {}
+
+ # Resource requests, limits, etc. for the server cluster placement. This
+ # should map directly to the value of the resources field for a PodSpec,
+ # formatted as a multi-line string. By default no direct resource request
+ # is made.
+ resources: {}
+
+ # Toleration Settings for server pods
+ # This should be a multi-line string matching the Toleration array
+ # in a PodSpec.
+ tolerations: ""
+
+ # nodeSelector labels for server pod assignment, formatted as a muli-line string.
+ # ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
+ # Example:
+ nodeSelector: |
+ kubernetes.io/arch: amd64
+ # nodeSelector: |
+ # sw-backend: "true"
+
+ # used to assign priority to server pods
+ # ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
+ priorityClassName: ""
+
+ # used to assign a service account.
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
+ serviceAccountName: ""
+
+ # Configure security context for Pod
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+ # Example:
+ # podSecurityContext:
+ # enabled: true
+ # runAsUser: 1000
+ # runAsGroup: 3000
+ # fsGroup: 2000
+ podSecurityContext: {}
+
+ # Configure security context for Container
+ # ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
+ # Example:
+ # containerSecurityContext:
+ # enabled: true
+ # runAsUser: 2000
+ # allowPrivilegeEscalation: false
+ containerSecurityContext: {}
+
+ # You can also use emptyDir storage:
+ # logs:
+ # type: "emptyDir"
+ logs:
+ type: "hostPath"
+ size: ""
+ storageClass: ""
+ hostPathPrefix: /storage
+
+ extraEnvironmentVars:
+
+ # used to configure livenessProbe on s3 containers
+ #
+ livenessProbe:
+ enabled: true
+ httpGet:
+ path: /status
+ scheme: HTTP
+ initialDelaySeconds: 20
+ periodSeconds: 60
+ successThreshold: 1
+ failureThreshold: 20
+ timeoutSeconds: 10
+
+ # used to configure readinessProbe on s3 containers
+ #
+ readinessProbe:
+ enabled: true
+ httpGet:
+ path: /status
+ scheme: HTTP
+ initialDelaySeconds: 15
+ periodSeconds: 15
+ successThreshold: 1
+ failureThreshold: 100
+ timeoutSeconds: 10
+
+ ingress:
+ enabled: false
+ className: "nginx"
+ # host: false for "*" hostname
+ host: "seaweedfs.cluster.local"
+ # additional ingress annotations for the s3 endpoint
+ annotations: {}
+ tls: []
+
+# Deploy Kubernetes COSI Driver for SeaweedFS
+# Requires COSI CRDs and controller to be installed in the cluster
+# For more information, visit: https://container-object-storage-interface.github.io/docs/deployment-guide
+cosi:
+ enabled: false
+ image: "ghcr.io/seaweedfs/seaweedfs-cosi-driver:v0.1.1"
+ driverName: "seaweedfs.objectstorage.k8s.io"
+ bucketClassName: "seaweedfs"
+ endpoint: ""
+ region: ""
+
+ sidecar:
+ image: gcr.io/k8s-staging-sig-storage/objectstorage-sidecar/objectstorage-sidecar:v20230130-v0.1.0-24-gc0cf995
+
+ # enable user & permission to s3 (need to inject to all services)
+ enableAuth: false
+ # 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 configure
+ existingConfigSecret: null
+
+ podSecurityContext: {}
+ containerSecurityContext: {}
+
+ extraVolumes: ""
+ extraVolumeMounts: ""
+
+certificates:
+ commonName: "SeaweedFS CA"
+ ipAddresses: []
+ keyAlgorithm: RSA
+ keySize: 2048
+ duration: 2160h # 90d
+ renewBefore: 360h # 15d
+ externalCertificates:
+ # This will avoid the need to use cert-manager and will rely on providing your own external certificates and CA
+ # you will need to store your provided certificates in the secret read by the different services:
+ # seaweedfs-master-cert, seaweedfs-filer-cert, etc. Can see any statefulset definition to see secret names
+ enabled: false
+
+# Labels to be added to all the created pods
+podLabels: {}
+# Annotations to be added to all the created pods
+podAnnotations: {}
diff --git a/packages/system/seaweedfs/patches/resize-api-server-annotation.diff b/packages/system/seaweedfs/patches/resize-api-server-annotation.diff
new file mode 100644
index 00000000..2b41f297
--- /dev/null
+++ b/packages/system/seaweedfs/patches/resize-api-server-annotation.diff
@@ -0,0 +1,14 @@
+diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/volume-resize-hook.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-resize-hook.yaml
+index 436a785..9f186ea 100644
+--- a/packages/system/seaweedfs/charts/seaweedfs/templates/volume-resize-hook.yaml
++++ b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-resize-hook.yaml
+@@ -45,6 +45,9 @@ metadata:
+ helm.sh/hook-delete-policy: hook-succeeded,before-hook-creation
+ spec:
+ template:
++ metadata:
++ labels:
++ policy.cozystack.io/allow-to-apiserver: "true"
+ spec:
+ serviceAccountName: {{ $seaweedfsName }}-volume-resize-hook
+ restartPolicy: Never
diff --git a/packages/system/seaweedfs/patches/retention-policy-delete.yaml b/packages/system/seaweedfs/patches/retention-policy-delete.yaml
new file mode 100644
index 00000000..d57d1ea4
--- /dev/null
+++ b/packages/system/seaweedfs/patches/retention-policy-delete.yaml
@@ -0,0 +1,14 @@
+diff --git a/packages/system/seaweedfs/charts/seaweedfs/templates/volume-statefulset.yaml b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-statefulset.yaml
+index 0a70d8c..eb3bb91 100644
+--- a/packages/system/seaweedfs/charts/seaweedfs/templates/volume-statefulset.yaml
++++ b/packages/system/seaweedfs/charts/seaweedfs/templates/volume-statefulset.yaml
+@@ -10,6 +10,9 @@ metadata:
+ app.kubernetes.io/managed-by: {{ .Release.Service }}
+ app.kubernetes.io/instance: {{ .Release.Name }}
+ spec:
++ persistentVolumeClaimRetentionPolicy:
++ whenDeleted: Delete
++ whenScaled: Delete
+ serviceName: {{ template "seaweedfs.name" . }}-volume
+ replicas: {{ .Values.volume.replicas }}
+ podManagementPolicy: {{ .Values.volume.podManagementPolicy }}
diff --git a/packages/system/seaweedfs/templates/database.yaml b/packages/system/seaweedfs/templates/database.yaml
new file mode 100644
index 00000000..1b0bbf22
--- /dev/null
+++ b/packages/system/seaweedfs/templates/database.yaml
@@ -0,0 +1,13 @@
+---
+apiVersion: postgresql.cnpg.io/v1
+kind: Cluster
+metadata:
+ name: seaweedfs-db
+spec:
+ instances: 2
+ storage:
+ size: 10Gi
+
+ inheritedMetadata:
+ labels:
+ policy.cozystack.io/allow-to-apiserver: "true"
diff --git a/packages/system/seaweedfs/values.yaml b/packages/system/seaweedfs/values.yaml
new file mode 100644
index 00000000..9fb8f886
--- /dev/null
+++ b/packages/system/seaweedfs/values.yaml
@@ -0,0 +1,129 @@
+global:
+ enableSecurity: true
+ serviceAccountName: "tenant-foo-seaweedfs"
+ extraEnvironmentVars:
+ WEED_CLUSTER_SW_MASTER: "seaweedfs-master:9333"
+ WEED_CLUSTER_SW_FILER: "seaweedfs-filer-client:8888"
+
+seaweedfs:
+
+ master:
+ replicas: 3
+ volumeSizeLimitMB: 100
+ # replication type is XYZ:
+ # X number of replica in other data centers
+ # Y number of replica in other racks in the same data center
+ # Z number of replica in other servers in the same rack
+ defaultReplication: "001"
+
+ data:
+ type: "emptyDir"
+
+ logs:
+ type: ""
+
+ volume:
+ replicas: 2
+ # minimum free disk space(in percents). If free disk space lower this value - all volumes marks as ReadOnly
+ minFreeSpacePercent: 5
+
+ dataDirs:
+ - name: data1
+ type: "persistentVolumeClaim"
+ size: "10Gi"
+ maxVolumes: 0
+
+ filer:
+ replicas: 2
+ # replication type is XYZ:
+ # X number of replica in other data centers
+ # Y number of replica in other racks in the same data center
+ # Z number of replica in other servers in the same rack
+ defaultReplicaPlacement: "001"
+ data:
+ type: "emptyDir"
+
+ logs:
+ type: ""
+
+ extraEnvironmentVars:
+ WEED_LEVELDB2_ENABLED: "false"
+ WEED_POSTGRES2_ENABLED: "true"
+ WEED_POSTGRES2_CREATETABLE: |
+ CREATE TABLE IF NOT EXISTS "%s" (
+ dirhash BIGINT,
+ name VARCHAR(65535),
+ directory VARCHAR(65535),
+ meta bytea,
+ PRIMARY KEY (dirhash, name)
+ );
+ secretExtraEnvironmentVars:
+ WEED_POSTGRES2_HOSTNAME:
+ secretKeyRef:
+ key: host
+ name: seaweedfs-db-app
+ WEED_POSTGRES2_DATABASE:
+ secretKeyRef:
+ key: dbname
+ name: seaweedfs-db-app
+ WEED_POSTGRES2_USERNAME:
+ secretKeyRef:
+ key: username
+ name: seaweedfs-db-app
+ WEED_POSTGRES2_PASSWORD:
+ secretKeyRef:
+ key: password
+ name: seaweedfs-db-app
+
+ s3:
+ enabled: true
+ port: 8333
+ httpsPort: 0
+ # Suffix of the host name, {bucket}.{domainName}
+ domainName: ""
+ # enable user & permission to s3 (need to inject to all services)
+ enableAuth: false
+ # 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 configure
+ existingConfigSecret: null
+ auditLogConfig: {}
+
+ s3:
+ enableAuth: true
+
+ logs:
+ type: ""
+
+ ingress:
+ enabled: true
+ className: "tenant-root"
+ host: "seaweedfs2.demo.cozystack.io"
+ annotations:
+ nginx.ingress.kubernetes.io/proxy-body-size: "0"
+ nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
+ acme.cert-manager.io/http01-ingress-class: tenant-root
+ cert-manager.io/cluster-issuer: letsencrypt-prod
+ tls:
+ - hosts:
+ - seaweedfs.demo.cozystack.io
+ secretName: seaweedfs-s3-ingress-tls
+
+ cosi:
+ enabled: true
+ podLabels:
+ policy.cozystack.io/allow-to-apiserver: "true"
+ driverName: "seaweedfs.objectstorage.k8s.io"
+ bucketClassName: "seaweedfs"
+ image: "ghcr.io/seaweedfs/seaweedfs-cosi-driver:v0.1.1"
+ region: ""
+
+ sidecar:
+ image: "ghcr.io/kvaps/test:cosi-provisioner-sidecar-25"
+
+ certificates:
+ commonName: "SeaweedFS CA"
+ ipAddresses: []
+ keyAlgorithm: RSA
+ keySize: 2048
+ duration: 2160h # 90d
+ renewBefore: 360h # 15d