snapshot of https://github.com/seaweedfs/seaweedfs.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-16 03:23:42 +05:00
commit 89f5be005d
3997 changed files with 961970 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
# Artifact Hub repository metadata file
#
# Some settings like the verified publisher flag or the ignored packages won't
# be applied until the next time the repository is processed. Please keep in
# mind that the repository won't be processed if it has not changed since the
# last time it was processed. Depending on the repository kind, this is checked
# in a different way. For Helm http based repositories, we consider it has
# changed if the `index.yaml` file changes. For git based repositories, it does
# when the hash of the last commit in the branch you set up changes. This does
# NOT apply to ownership claim operations, which are processed immediately.
#
repositoryID: 5b2f1fe2-20e5-486e-9746-183484642aa2
# owners: # (optional, used to claim repository ownership)
# - name: username
# email: email

View File

@@ -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/

View File

@@ -0,0 +1,6 @@
apiVersion: v1
description: SeaweedFS
name: seaweedfs
appVersion: "4.47"
# Dev note: Trigger a helm chart release by `git tag -a helm-<version>`
version: 4.47.1

View File

@@ -0,0 +1,624 @@
# SEAWEEDFS - helm chart (2.x+)
### 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.
* leveldb2 is the default filer backend; a mysql-compatible database (memsql, ...) enables HA (multiple filer instances) and the backup/HA it can provide.
* with `filer.extraEnvironmentVars.WEED_MYSQL_ENABLED` set to `"true"`, mysql user/password are created in a k8s secret (default: `<release>-seaweedfs-db-secret`) and injected to the filer with ENV. On any other store neither the secret nor the `WEED_MYSQL_*` env, plain or secret-backed, is rendered.
* 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. If using the default `db-init-config`, the configmap name is now dynamic (e.g., `<release>-seaweedfs-db-init-config`). You can override this name via `filer.dbInitConfigName`.
To initialize manually:
```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`.
#### RocksDB variant
The `_large_disk_rocksdb` image tag ships with RocksDB pre-configured as the filer backend.
To use this image with the Helm chart, override the image on all three components and disable
the chart's default `WEED_LEVELDB2_ENABLED`, which would otherwise re-enable LevelDB2 and
override the image's built-in RocksDB configuration:
```yaml
# Replace <VERSION> with the desired seaweedfs version, e.g. 3.80_large_disk_rocksdb.
master:
imageOverride: chrislusf/seaweedfs:<VERSION>_large_disk_rocksdb
volume:
imageOverride: chrislusf/seaweedfs:<VERSION>_large_disk_rocksdb
filer:
enablePVC: true
imageOverride: chrislusf/seaweedfs:<VERSION>_large_disk_rocksdb
extraEnvironmentVars:
WEED_LEVELDB2_ENABLED: "false"
```
Notes:
* `master` and `volume` use the same image tag so that all components share a consistent
SeaweedFS build; RocksDB itself is only used by the filer.
* `filer.enablePVC: true` (or another form of persistent storage for the filer) is required
so that the RocksDB metadata store survives pod restarts — otherwise metadata will be lost.
### 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.
### Master data: hostPath vs a claim
The master's `-mdir` holds its Raft log and snapshots, and with them the
cluster's identity (its topology UUID). `master.data.type` defaults to
`hostPath`, which does not follow a pod to another node: a master that is
rescheduled comes back with an empty data directory and a brand new cluster
UUID. With the chart's default of a single master replica there is no peer to
recover the identity from either.
Putting the master's data on a claim avoids that:
```yaml
master:
data:
type: "persistentVolumeClaim"
size: "1Gi"
storageClass: "" # empty uses the cluster's default StorageClass
```
Raft state is small, so a modest claim is enough — sizing matters far more for
volume and filer.
The default is left at `hostPath` for backward compatibility:
`volumeClaimTemplates` is immutable on a StatefulSet, so flipping the type on a
release that already exists fails, whether the chart changes the default or you
change it yourself:
```text
StatefulSet.apps "<release>-seaweedfs-master" is invalid: spec: Forbidden:
updates to statefulset spec for fields other than 'replicas', ... are forbidden
```
New installs can set the claim from the start. To move an **existing** release
onto a claim without losing the cluster UUID, use the migration below. The
claim has to be seeded while the master is stopped: a running master rewrites
its Raft state, so copying into a live pod is silently undone by the next
restart.
The steps below are for the chart's default of a single master
(`master.replicas: 1`). With several master replicas, repeat steps 1, 3 and 4
for every ordinal, or migrate one at a time and let the remaining quorum
re-replicate.
Take the names from the cluster rather than assembling them — the release
name, `nameOverride` and `fullnameOverride` all feed the chart's fullname
helper, so `<release>-seaweedfs` is not always right:
```bash
NS=<namespace>; REL=<release>
# scope by instance as well as component: several releases can share a namespace
STS=$(kubectl -n $NS get sts \
-l app.kubernetes.io/instance=$REL,app.kubernetes.io/component=master \
-o jsonpath='{.items[0].metadata.name}')
POD=$STS-0
# a StatefulSet names its claims <template>-<statefulset>-<ordinal>, and this
# chart's template is data-<namespace>
PVC=data-$NS-$STS-0
# 1. back up the master data directory
kubectl -n $NS cp $POD:/data ./master-backup
# 2. stop the master, leaving the rest of the release running
kubectl -n $NS delete sts $STS --cascade=orphan
kubectl -n $NS delete pod $POD
# 3. create the claim the new StatefulSet will adopt, and seed it through a
# pod that actually mounts it
kubectl -n $NS apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: $PVC
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
name: seed
spec:
containers:
- name: seed
image: alpine:3.20
command: ["sleep", "600"]
volumeMounts:
- name: d
mountPath: /data
volumes:
- name: d
persistentVolumeClaim:
claimName: $PVC
EOF
kubectl -n $NS wait --for=condition=Ready pod/seed --timeout=120s
kubectl -n $NS cp ./master-backup/m9333 seed:/data/
kubectl -n $NS exec seed -- ls /data/m9333 # conf, log, snapshot, state
kubectl -n $NS delete pod seed
# 4. upgrade; the StatefulSet adopts the claim you created
helm upgrade $REL seaweedfs/seaweedfs -n $NS -f values.yaml
```
Confirm the UUID survived — it must match what the cluster reported before the
migration:
```bash
kubectl -n $NS exec $POD -- curl -s localhost:9333/license/status
```
**Or accept a new cluster UUID** and, if you run the enterprise edition, have
the license re-issued against it.
## 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","List"]}]}'
```
#### Source S3 credentials from an existing Secret
To keep the keys out of `values.yaml` while still letting the chart generate the
identities file, point an identity at an existing Secret:
```yaml
s3:
enabled: true
enableAuth: true
credentials:
admin:
existingSecret: minio-root
accessKeyKey: root-user
secretKeyKey: root-password
```
`accessKeyKey` and `secretKeyKey` default to the chart's own key names
(`admin_access_key_id`, `admin_secret_access_key`, and the `read_` pair). The
generated `seaweedfs_s3_config` references the keys as `${SEAWEEDFS_S3_ADMIN_ACCESS_KEY_ID}`
and the gateway resolves them from the environment, which the chart wires up
from the Secret. Nothing is read from the cluster at render time, so
`helm template`, `--dry-run` and an Argo CD diff all render what an install
applies. Rotating a key in the Secret takes effect on the next pod restart, as
with any other environment variable. The COSI driver parses the config itself
and does not resolve these references.
## Admin Component
The admin component provides a modern web-based administration interface for managing SeaweedFS clusters. It includes:
- **Dashboard**: Real-time cluster status and metrics
- **Volume Management**: Monitor volume servers, capacity, and health
- **File Browser**: Browse and manage files in the filer
- **Maintenance Operations**: Trigger maintenance tasks via workers
- **Object Store Management**: Create and manage buckets with web interface
### Enabling Admin
To enable the admin interface, add the following to your values.yaml:
```yaml
admin:
enabled: true
port: 23646
grpcPort: 33646 # For worker connections
secret:
adminUser: "admin"
adminPassword: "your-secure-password" # Leave empty to disable auth
# Optional: persist admin data
data:
type: "persistentVolumeClaim"
size: "10Gi"
storageClass: "your-storage-class"
# Optional: enable ingress
ingress:
enabled: true
host: "admin.seaweedfs.local"
className: "nginx"
```
The admin interface will be available at `http://<admin-service>:23646` (or via ingress). Workers connect to the admin server via gRPC on port `33646`.
### Admin Authentication
If `adminPassword` is set, the admin interface requires authentication:
- Username: Value of `adminUser` (default: `admin`)
- Password: Value of `adminPassword`
If `adminPassword` is empty or not set, the admin interface runs without authentication (not recommended for production).
As an alternative, a kubernetes Secret can be used (`admin.secret.existingSecret`).
### Admin listen address
Since SeaweedFS 4.46, `weed admin` defaults to listening on loopback (`127.0.0.1`).
The chart's httpGet readiness/liveness probes dial the pod IP, so the admin
server must bind a non-loopback address for the probes to succeed. The chart
therefore passes `-ip={{ .Values.admin.ip }}`, defaulting `admin.ip` to `0.0.0.0`
(the pre-4.46 behaviour of listening on all interfaces).
Binding a non-loopback address requires authentication: `weed admin` refuses to
start on a non-loopback address without `-adminPassword`, so the chart fails at
render time if `admin.ip` is non-loopback and authentication is not configured via
`admin.secret.adminPassword`, `admin.secret.existingSecret`, or
`WEED_ADMIN_PASSWORD` supplied through `admin.extraEnvironmentVars` /
`admin.secretExtraEnvironmentVars`. The whole `127.0.0.0/8` range and `::1` are
treated as loopback (matching `weed admin`); `localhost` is treated as
non-loopback. Set `admin.ip` to a loopback address only if you also replace the
httpGet probes (e.g. with an `exec` probe that checks `127.0.0.1`).
The `-ip` flag requires SeaweedFS 4.46 or newer; pinning `admin.imageOverride`
to an older image is not supported with this chart version.
### Admin Data Persistence
The admin component can store configuration and maintenance data. You can configure storage in several ways:
- **emptyDir** (default): Data is lost when pod restarts
- **persistentVolumeClaim**: Data persists across pod restarts
- **hostPath**: Data stored on the host filesystem
- **existingClaim**: Use an existing PVC
## Worker Component
Workers are maintenance agents that execute cluster maintenance tasks such as vacuum, volume balancing, and erasure coding. Workers connect to the admin server via gRPC and receive task assignments.
### Enabling Workers
To enable workers, add the following to your values.yaml:
```yaml
worker:
enabled: true
replicas: 2 # Scale based on workload
jobType: "vacuum,volume_balance,erasure_coding" # Job types this worker can handle
maxDetect: 1 # Maximum concurrent detection requests
maxExecute: 4 # Maximum concurrent execution jobs per worker
# Working directory for task execution
# Default: "/tmp/seaweedfs-worker"
# Note: /tmp is ephemeral - use persistent storage (hostPath/existingClaim) for long-running tasks
workingDir: "/tmp/seaweedfs-worker"
# Optional: configure admin server address
# If not specified, auto-discovers from admin service in the same namespace by looking for
# a service named "<release-name>-admin" (e.g., "seaweedfs-admin").
# Auto-discovery only works if the admin is in the same namespace and same Helm release.
# For cross-namespace or separate release scenarios, explicitly set this value.
# Example: If main SeaweedFS is deployed in "production" namespace:
# adminServer: "seaweedfs-admin.production.svc:33646"
adminServer: ""
# Workers need storage for task execution
# Note: Workers use a Deployment, which does not support `volumeClaimTemplates`
# for dynamic PVC creation per pod. To use persistent storage, you must
# pre-provision a PersistentVolumeClaim and use `type: "existingClaim"`.
data:
type: "emptyDir" # Options: "emptyDir", "hostPath", or "existingClaim"
hostPathPrefix: /storage # For hostPath
# claimName: "worker-pvc" # For existingClaim with pre-provisioned PVC
# Resource limits for worker pods
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2"
memory: "2Gi"
```
### Worker Job Types
Workers can be configured with different job types:
- **vacuum**: Reclaim deleted file space
- **volume_balance**: Balance volumes across volume servers
- **erasure_coding**: Handle erasure coding operations
You can configure workers with all job types or create specialized worker pools with specific job types.
### Worker Deployment Strategy
For production deployments, consider:
1. **Multiple Workers**: Deploy 2+ worker replicas for high availability
2. **Resource Allocation**: Workers need sufficient CPU/memory for maintenance tasks
3. **Storage**: Workers need temporary storage for vacuum and balance operations (size depends on volume size)
4. **Specialized Workers**: Create separate worker deployments for different job types if needed
Example specialized worker configuration:
For specialized worker pools, deploy separate Helm releases with different job types:
**values-worker-vacuum.yaml** (for vacuum operations):
```yaml
# Disable all other components, enable only workers
master:
enabled: false
volume:
enabled: false
filer:
enabled: false
s3:
enabled: false
admin:
enabled: false
worker:
enabled: true
replicas: 2
jobType: "vacuum"
maxExecute: 2
# REQUIRED: Point to the admin service of your main SeaweedFS release
# Replace <namespace> with the namespace where your main seaweedfs is deployed
# Example: If deploying in namespace "production":
# adminServer: "seaweedfs-admin.production.svc:33646"
adminServer: "seaweedfs-admin.<namespace>.svc:33646"
```
**values-worker-balance.yaml** (for balance operations):
```yaml
# Disable all other components, enable only workers
master:
enabled: false
volume:
enabled: false
filer:
enabled: false
s3:
enabled: false
admin:
enabled: false
worker:
enabled: true
replicas: 1
jobType: "volume_balance"
maxExecute: 1
# REQUIRED: Point to the admin service of your main SeaweedFS release
# Replace <namespace> with the namespace where your main seaweedfs is deployed
# Example: If deploying in namespace "production":
# adminServer: "seaweedfs-admin.production.svc:33646"
adminServer: "seaweedfs-admin.<namespace>.svc:33646"
```
Deploy the specialized workers as separate releases:
### Specialized Worker Deployment
```bash
# Deploy vacuum workers
helm install seaweedfs-worker-vacuum seaweedfs/seaweedfs -f values-worker-vacuum.yaml
# Deploy balance workers
helm install seaweedfs-worker-balance seaweedfs/seaweedfs -f values-worker-balance.yaml
```
## Network Policies
In a namespace with a default-deny policy the install hangs: the components cannot resolve each other, and the post-install bucket hook waits on the master and filer until it gives up. `networkPolicy.enabled` renders one `NetworkPolicy` per component, selecting its pods by the standard `app.kubernetes.io/{name,instance,component}` labels and admitting traffic from the other pods of the release on the ports that component listens on.
```bash
helm install seaweedfs seaweedfs/seaweedfs --set networkPolicy.enabled=true
```
That alone leaves outbound traffic untouched, which is enough when the namespace's default-deny only restricts ingress. If it lists `Egress` in its `policyTypes` too - the usual baseline - the components still cannot resolve DNS, and you need the second opt-in below as well.
Egress is separate because the chart knows where its own components live but not where your filer store, notification sink or remote tier does, and because in a namespace with no default-deny at all, adding egress rules would narrow the components from "may reach anything" to "may reach these peers":
```yaml
networkPolicy:
enabled: true
egress:
enabled: true
kubeApiServer:
# the endpoint behind the kubernetes service, not its ClusterIP
cidrs: ["172.18.0.2/32"]
extraEgress:
- to:
- podSelector:
matchLabels:
app.kubernetes.io/name: postgresql
ports:
- protocol: TCP
port: 5432
```
`kubeApiServer.cidrs` is only demanded when something in the release actually needs the API server, which is the COSI sidecar and, on an upgrade that grows a volume PVC, the resize hook. No seaweedfs component itself speaks to it.
Anything reaching the release from outside - an ingress controller, a Prometheus in another namespace - goes into `networkPolicy.extraIngress`, or into `networkPolicy.components.<component>.extraIngress` for a single component. See the `networkPolicy` block in `values.yaml` for the full set.
Two things worth knowing before you turn this on:
- **Monitoring stops.** The metrics ports are admitted from release pods like every other port, so with `global.seaweedfs.monitoring.enabled` the ServiceMonitors keep scraping targets a Prometheus in another namespace can no longer reach. Nothing reports it; add the scraper's namespace to `extraIngress`.
- **The resize hook's policy is a Helm hook.** Its Job runs before the release manifest is applied, so the policy has to be a `pre-install` hook too. Helm does not garbage-collect hook resources, so on an upgrade that grows a volume PVC the policy is created and then left behind on uninstall - delete `<release>-seaweedfs-volume-resize-hook` by hand if it bothers you.
The DNS selectors default to CoreDNS as kubeadm, kind and the managed offerings from AWS, Google and Azure install it. On OpenShift, override `egress.dnsNamespaceSelector` and `egress.dnsPodSelector` to match `openshift-dns`; see the comment in `values.yaml`.
## OpenShift Support
SeaweedFS can be deployed on OpenShift or any cluster enforcing the Kubernetes "restricted" Pod Security Standard. By default, OpenShift blocks containers that run as root or use `hostPath` volumes.
To deploy on OpenShift, use the provided `openshift-values.yaml` which overrides the default configuration to:
1. Use `PersistentVolumeClaims` instead of `hostPath`.
2. Enable `runAsNonRoot` and omit hardcoded UIDs to allow OpenShift to assign valid UIDs automatically.
3. Apply appropriate `seccompProfile` and drop capabilities.
Usage:
```bash
helm install seaweedfs seaweedfs/seaweedfs \
-n seaweedfs --create-namespace \
-f openshift-values.yaml
```
## Enterprise
For enterprise users, please visit [seaweedfs.com](https://seaweedfs.com) for the SeaweedFS Enterprise Edition,
which has advanced features, including data recovery, self-healing storage, customizable erasure coding, EC vacuum and repair, etc.
To run it, set the image and point the chart at a Secret holding the license
file:
```bash
kubectl create secret generic seaweedfs-license -n <namespace> \
--from-file=seaweed-license.json=/path/to/seaweed-license.json
```
```yaml
global:
seaweedfs:
image:
name: chrislusf/seaweedfs-enterprise
license:
existingSecret: seaweedfs-license
# secretKey: seaweed-license.json # key within the Secret
# mountPath: /etc/seaweedfs/license # directory it is mounted at
```
Set the image globally rather than per component: a per-component
`imageOverride` wins, and a cluster that mixes editions comes up looking
healthy with enterprise features quietly off.
Only the master reads the license, so the Secret is mounted read-only there
and on all-in-one (which runs `weed server -master`). It is mounted as a
directory, not a `subPath`, so a renewed Secret reaches the running master —
which re-reads the file periodically — without a restart.
The license is tied to the cluster UUID kept in the master's Raft state, so put
`master.data` on a claim — a master that restarts onto an empty data directory
generates a new UUID and the license stops matching. See
[Master data](#master-data-hostpath-vs-a-claim). Check the binding with
`kubectl exec <master-pod> -- curl -s localhost:9333/license/status`
(`cluster_uuid` must equal `license_uuid`).

View File

@@ -0,0 +1,7 @@
# Admin install: exercises the admin StatefulSet, which passes -ip (default
# 0.0.0.0) and therefore requires authentication to bind a non-loopback address.
admin:
enabled: true
secret:
adminUser: "admin"
adminPassword: "ci-admin-password"

View File

@@ -0,0 +1 @@
# Default configuration, kept so chart-testing still installs the chart as-is.

View File

@@ -0,0 +1,5 @@
# SFTP install: the pod only becomes ready if the server loads a host key
# from the generated sftp-ssh-secret, so this exercises the whole path.
sftp:
enabled: true
enableAuth: true

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
# openshift-values.yaml
#
# Example overrides for deploying SeaweedFS on OpenShift (or any cluster
# enforcing the Kubernetes "restricted" Pod Security Standard).
#
# OpenShift's default "restricted" SCC blocks containers that:
# - Run as UID 0 (root)
# - Request privilege escalation
# - Use hostPath volumes
# - Omit a seccompProfile
#
# These overrides satisfy all four requirements by:
# 1. Replacing hostPath volumes with PersistentVolumeClaims (or emptyDir for logs)
# 2. Enabling runAsNonRoot: true. By omitting runAsUser, OpenShift will
# automatically assign a valid UID from the namespace's allocated range.
# 3. Dropping all Linux capabilities and setting allowPrivilegeEscalation: false
# 4. Enabling RuntimeDefault seccompProfile
#
# Usage:
# helm install seaweedfs seaweedfs/seaweedfs \
# -n seaweedfs --create-namespace \
# -f openshift-values.yaml
#
# Adjust storageClass and sizes to match your cluster's available StorageClasses.
# On OpenShift you can discover them with: oc get storageclass
global:
enableReplication: true
# 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
replicationPlacement: "000" # no data replica
master:
replicas: 1
data:
type: "persistentVolumeClaim"
size: "10Gi"
storageClass: "" # leave empty to use the cluster default StorageClass
logs:
type: "emptyDir" # avoids hostPath; use persistentVolumeClaim if you need log persistence
podSecurityContext:
enabled: true
# On OpenShift, we omit runAsUser/runAsGroup/fsGroup to let the admission
# controller assign them automatically based on the namespace's SCC.
runAsNonRoot: true
containerSecurityContext:
enabled: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
volume:
replicas: 1
dataDirs:
- name: data1
type: "persistentVolumeClaim"
size: "100Gi"
storageClass: "" # leave empty to use the cluster default StorageClass
maxVolumes: 0
logs:
type: "emptyDir"
podSecurityContext:
enabled: true
# On OpenShift, we omit runAsUser/runAsGroup/fsGroup to let the admission
# controller assign them automatically based on the namespace's SCC.
runAsNonRoot: true
containerSecurityContext:
enabled: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
filer:
replicas: 1
data:
type: "persistentVolumeClaim"
size: "25Gi"
storageClass: "" # leave empty to use the cluster default StorageClass
logs:
type: "emptyDir"
podSecurityContext:
enabled: true
# On OpenShift, we omit runAsUser/runAsGroup/fsGroup to let the admission
# controller assign them automatically based on the namespace's SCC.
runAsNonRoot: true
containerSecurityContext:
enabled: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
# S3 gateway (if enabled)
s3:
enabled: true
replicas: 1
port: 8333
enableAuth: true
podSecurityContext:
enabled: true
# On OpenShift, we omit runAsUser/runAsGroup/fsGroup to let the admission
# controller assign them automatically based on the namespace's SCC.
runAsNonRoot: true
logs:
type: "emptyDir"
containerSecurityContext:
enabled: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault

View File

@@ -0,0 +1,55 @@
{{- if and .Values.admin.enabled .Values.admin.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-{{ include "seaweedfs.fullname" . }}-admin
namespace: {{ .Release.Namespace }}
annotations:
{{- if and (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) .Values.admin.ingress.className }}
kubernetes.io/ingress.class: {{ .Values.admin.ingress.className }}
{{- end }}
{{- with .Values.admin.ingress.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: admin
{{- with .Values.admin.ingress.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) .Values.admin.ingress.className }}
ingressClassName: {{ .Values.admin.ingress.className | quote }}
{{- end }}
tls:
{{ .Values.admin.ingress.tls | default list | toYaml | nindent 6}}
rules:
- {{- if .Values.admin.ingress.host }}
host: {{ .Values.admin.ingress.host | quote }}
{{- end }}
http:
paths:
- path: {{ .Values.admin.ingress.path | quote }}
{{- if semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion }}
pathType: {{ .Values.admin.ingress.pathType | quote }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
service:
name: {{ include "seaweedfs.componentName" (list . "admin") }}
port:
number: {{ .Values.admin.port }}
{{- else }}
serviceName: {{ include "seaweedfs.componentName" (list . "admin") }}
servicePort: {{ .Values.admin.port }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,20 @@
{{- if and .Values.admin.enabled .Values.admin.secret.adminPassword (not .Values.admin.secret.existingSecret) }}
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ include "seaweedfs.fullname" . }}-admin-secret
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/resource-policy": keep
"helm.sh/hook": "pre-install,pre-upgrade"
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: admin
data:
adminUser: {{ .Values.admin.secret.adminUser | b64enc }}
adminPassword: {{ .Values.admin.secret.adminPassword | b64enc }}
{{- end}}

View File

@@ -0,0 +1,45 @@
{{- if .Values.admin.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "seaweedfs.componentName" (list . "admin") }}
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: admin
{{- if .Values.admin.service.annotations }}
annotations:
{{- toYaml .Values.admin.service.annotations | nindent 4 }}
{{- end }}
spec:
{{- $serviceType := .Values.admin.service.type }}
{{- $nodePorts := dict }}
{{- if or (eq $serviceType "NodePort") (eq $serviceType "LoadBalancer") }}
{{- $nodePorts = .Values.admin.service.nodePorts | default dict }}
{{- end }}
type: {{ $serviceType }}
{{- include "seaweedfs.service.loadBalancerFields" .Values.admin.service }}
ports:
- name: "http"
port: {{ .Values.admin.port }}
targetPort: {{ .Values.admin.port }}
{{- if $nodePorts.http }}
nodePort: {{ $nodePorts.http }}
{{- end }}
protocol: TCP
- name: "grpc"
port: {{ .Values.admin.grpcPort }}
targetPort: {{ .Values.admin.grpcPort }}
{{- if $nodePorts.grpc }}
nodePort: {{ $nodePorts.grpc }}
{{- end }}
protocol: TCP
selector:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: admin
{{- end }}

View File

@@ -0,0 +1,33 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.admin.enabled }}
{{- if .Values.global.seaweedfs.monitoring.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "seaweedfs.fullname" . }}-admin
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: admin
{{- with .Values.global.seaweedfs.monitoring.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.admin.serviceMonitor.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
endpoints:
- interval: 30s
port: http
scrapeTimeout: 5s
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: admin
{{- end }}
{{- end }}

View File

@@ -0,0 +1,359 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.admin.enabled }}
{{- if gt (.Values.admin.replicas | int) 1 }}
{{- fail "admin.replicas must be 0 or 1" -}}
{{- end }}
{{- if and (not .Values.admin.masters) (not .Values.global.seaweedfs.masterServer) (not .Values.master.enabled) }}
{{- fail "admin.masters or global.seaweedfs.masterServer must be set if master.enabled is false" -}}
{{- end }}
{{- $adminAuthEnabled := include "seaweedfs.admin.authEnabled" . }}
{{- $adminIp := .Values.admin.ip | default "0.0.0.0" }}
{{- if and (not (include "seaweedfs.admin.isLoopbackIp" $adminIp)) (ne $adminAuthEnabled "true") }}
{{- fail (printf "admin.ip is set to %q (non-loopback) but admin authentication is not configured. Since `weed admin` 4.46 refuses to bind a non-loopback address without authentication, the admin container would exit on startup. Set admin.secret.adminPassword or admin.secret.existingSecret, or supply WEED_ADMIN_PASSWORD via admin.extraEnvironmentVars / admin.secretExtraEnvironmentVars, or set admin.ip to a loopback address such as 127.0.0.1 (note: a loopback bind makes the chart's httpGet readiness/liveness probes fail)." $adminIp) -}}
{{- end }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "seaweedfs.componentName" (list . "admin") }}
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: admin
{{- if .Values.admin.annotations }}
annotations:
{{- toYaml .Values.admin.annotations | nindent 4 }}
{{- end }}
spec:
serviceName: {{ include "seaweedfs.componentName" (list . "admin") }}
podManagementPolicy: {{ .Values.admin.podManagementPolicy }}
replicas: {{ .Values.admin.replicas }}
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: admin
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: admin
{{ with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.admin.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
annotations:
{{ with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.admin.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
restartPolicy: {{ default .Values.global.seaweedfs.restartPolicy .Values.admin.restartPolicy }}
{{- if .Values.admin.affinity }}
affinity:
{{ tpl .Values.admin.affinity . | nindent 8 | trim }}
{{- end }}
{{- if .Values.admin.topologySpreadConstraints }}
topologySpreadConstraints:
{{ tpl .Values.admin.topologySpreadConstraints . | nindent 8 | trim }}
{{- end }}
{{- if .Values.admin.tolerations }}
tolerations:
{{ tpl .Values.admin.tolerations . | nindent 8 | trim }}
{{- end }}
{{- include "seaweedfs.imagePullSecrets" . | nindent 6 }}
terminationGracePeriodSeconds: 30
{{- if .Values.admin.priorityClassName }}
priorityClassName: {{ .Values.admin.priorityClassName | quote }}
{{- end }}
{{- if .Values.admin.schedulerName }}
schedulerName: {{ .Values.admin.schedulerName | quote }}
{{- end }}
enableServiceLinks: false
{{- if .Values.admin.serviceAccountName }}
serviceAccountName: {{ .Values.admin.serviceAccountName | quote }}
{{- end }}
{{- if .Values.admin.initContainers }}
initContainers:
{{ tpl .Values.admin.initContainers . | nindent 8 | trim }}
{{- end }}
{{- if .Values.admin.podSecurityContext.enabled }}
securityContext: {{- omit .Values.admin.podSecurityContext "enabled" | toYaml | nindent 8 }}
{{- end }}
containers:
- name: seaweedfs
image: {{ template "seaweedfs.admin.image" . }}
imagePullPolicy: {{ default "IfNotPresent" .Values.global.seaweedfs.imagePullPolicy }}
{{- $adminAuthEnabled := or .Values.admin.secret.existingSecret .Values.admin.secret.adminPassword }}
{{- $urlPrefix := .Values.admin.urlPrefix }}
{{- if and (not $urlPrefix) .Values.admin.ingress.enabled (ne .Values.admin.ingress.path "/") }}
{{- $urlPrefix = trimSuffix "/" .Values.admin.ingress.path }}
{{- end }}
{{- if and .Values.admin.secret.existingSecret (not .Values.admin.secret.userKey) -}}
{{- fail "admin.secret.userKey must be set when admin.secret.existingSecret is provided" -}}
{{- end -}}
{{- if and .Values.admin.secret.existingSecret (not .Values.admin.secret.pwKey) -}}
{{- fail "admin.secret.pwKey must be set when admin.secret.existingSecret is provided" -}}
{{- end -}}
{{- $adminSecretName := .Values.admin.secret.existingSecret | default (printf "%s-admin-secret" (include "seaweedfs.fullname" .)) }}
env:
{{- if $adminAuthEnabled }}
- name: WEED_ADMIN_USER
valueFrom:
secretKeyRef:
name: {{ $adminSecretName }}
key: {{ if .Values.admin.secret.existingSecret }}{{ .Values.admin.secret.userKey }}{{ else }}adminUser{{ end }}
- name: WEED_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: {{ $adminSecretName }}
key: {{ if .Values.admin.secret.existingSecret }}{{ .Values.admin.secret.pwKey }}{{ else }}adminPassword{{ end }}
{{- end }}
- 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: "{{ include "seaweedfs.fullname" . }}"
{{- $mergedExtraEnvironmentVars := dict }}
{{- include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" .Values.global.seaweedfs "component" .Values.admin "target" $mergedExtraEnvironmentVars) }}
{{- range $key := keys $mergedExtraEnvironmentVars | sortAlpha }}
{{- $value := index $mergedExtraEnvironmentVars $key }}
- name: {{ $key }}
{{- if kindIs "string" $value }}
value: {{ tpl $value $ | quote }}
{{- else }}
valueFrom:
{{ toYaml $value | nindent 16 | trim }}
{{- end -}}
{{- end }}
{{- $secretExtraEnvironmentVars := .Values.admin.secretExtraEnvironmentVars }}
{{- if $secretExtraEnvironmentVars }}
{{- range $key := keys $secretExtraEnvironmentVars | sortAlpha }}
{{- $value := index $secretExtraEnvironmentVars $key }}
- name: {{ $key }}
valueFrom: {{ toYaml $value | nindent 16 }}
{{- end }}
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
exec /usr/bin/weed \
{{- if or (eq .Values.admin.logs.type "hostPath") (eq .Values.admin.logs.type "persistentVolumeClaim") (eq .Values.admin.logs.type "emptyDir") (eq .Values.admin.logs.type "existingClaim") }}
-logdir=/logs \
{{- else }}
-logtostderr=true \
{{- end }}
{{- if .Values.admin.loggingOverrideLevel }}
-v={{ .Values.admin.loggingOverrideLevel }} \
{{- else }}
-v={{ .Values.global.seaweedfs.loggingLevel }} \
{{- end }}
admin \
-ip={{ .Values.admin.ip | default "0.0.0.0" }} \
-port={{ .Values.admin.port }} \
-port.grpc={{ .Values.admin.grpcPort }} \
{{- if or (eq .Values.admin.data.type "hostPath") (eq .Values.admin.data.type "persistentVolumeClaim") (eq .Values.admin.data.type "emptyDir") (eq .Values.admin.data.type "existingClaim") }}
-dataDir=/data \
{{- else if .Values.admin.dataDir }}
-dataDir={{ .Values.admin.dataDir }} \
{{- end }}
{{- if .Values.admin.masters }}
-masters={{ .Values.admin.masters }}{{- if or $urlPrefix .Values.admin.extraArgs }} \{{ end }}
{{- else if .Values.global.seaweedfs.masterServer }}
-masters={{ .Values.global.seaweedfs.masterServer }}{{- if or $urlPrefix .Values.admin.extraArgs }} \{{ end }}
{{- else }}
-masters={{ 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 }}{{- if or $urlPrefix .Values.admin.extraArgs }} \{{ end }}
{{- end }}
{{- if $urlPrefix }}
-urlPrefix={{ $urlPrefix }}{{- if .Values.admin.extraArgs }} \{{ end }}
{{- end }}
{{- range $index, $arg := .Values.admin.extraArgs }}
{{ $arg }}{{- if lt $index (sub (len $.Values.admin.extraArgs) 1) }} \{{ end }}
{{- end }}
volumeMounts:
{{- if or (eq .Values.admin.data.type "hostPath") (eq .Values.admin.data.type "persistentVolumeClaim") (eq .Values.admin.data.type "emptyDir") (eq .Values.admin.data.type "existingClaim") }}
- name: admin-data
mountPath: /data
{{- end }}
{{- if or (eq .Values.admin.logs.type "hostPath") (eq .Values.admin.logs.type "persistentVolumeClaim") (eq .Values.admin.logs.type "emptyDir") (eq .Values.admin.logs.type "existingClaim") }}
- name: admin-logs
mountPath: /logs
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
readOnly: true
mountPath: /etc/seaweedfs/security.toml
subPath: security.toml
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- 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/
- name: admin-cert
readOnly: true
mountPath: /usr/local/share/ca-certificates/admin/
{{- end }}
{{ tpl .Values.admin.extraVolumeMounts . | nindent 12 | trim }}
ports:
- containerPort: {{ .Values.admin.port }}
name: http
- containerPort: {{ .Values.admin.grpcPort }}
name: grpc
{{- if .Values.admin.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: {{ if $urlPrefix }}{{ $urlPrefix }}{{ end }}{{ .Values.admin.readinessProbe.httpGet.path }}
port: http
scheme: {{ .Values.admin.readinessProbe.httpGet.scheme }}
initialDelaySeconds: {{ .Values.admin.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.admin.readinessProbe.periodSeconds }}
successThreshold: {{ .Values.admin.readinessProbe.successThreshold }}
failureThreshold: {{ .Values.admin.readinessProbe.failureThreshold }}
timeoutSeconds: {{ .Values.admin.readinessProbe.timeoutSeconds }}
{{- end }}
{{- if .Values.admin.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: {{ if $urlPrefix }}{{ $urlPrefix }}{{ end }}{{ .Values.admin.livenessProbe.httpGet.path }}
port: http
scheme: {{ .Values.admin.livenessProbe.httpGet.scheme }}
initialDelaySeconds: {{ .Values.admin.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.admin.livenessProbe.periodSeconds }}
successThreshold: {{ .Values.admin.livenessProbe.successThreshold }}
failureThreshold: {{ .Values.admin.livenessProbe.failureThreshold }}
timeoutSeconds: {{ .Values.admin.livenessProbe.timeoutSeconds }}
{{- end }}
{{- with .Values.admin.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.admin.containerSecurityContext.enabled }}
securityContext: {{- omit .Values.admin.containerSecurityContext "enabled" | toYaml | nindent 12 }}
{{- end }}
{{- if .Values.admin.sidecars }}
{{- include "seaweedfs.tplvalues.render" (dict "value" .Values.admin.sidecars "context" $) | nindent 8 }}
{{- end }}
volumes:
{{- if eq .Values.admin.data.type "hostPath" }}
- name: admin-data
hostPath:
path: {{ .Values.admin.data.hostPathPrefix }}/seaweedfs-admin-data
type: DirectoryOrCreate
{{- end }}
{{- if eq .Values.admin.data.type "emptyDir" }}
- name: admin-data
emptyDir: {}
{{- end }}
{{- if eq .Values.admin.data.type "existingClaim" }}
- name: admin-data
persistentVolumeClaim:
claimName: {{ .Values.admin.data.claimName }}
{{- end }}
{{- if eq .Values.admin.logs.type "hostPath" }}
- name: admin-logs
hostPath:
path: {{ .Values.admin.logs.hostPathPrefix }}/logs/seaweedfs/admin
type: DirectoryOrCreate
{{- end }}
{{- if eq .Values.admin.logs.type "emptyDir" }}
- name: admin-logs
emptyDir: {}
{{- end }}
{{- if eq .Values.admin.logs.type "existingClaim" }}
- name: admin-logs
persistentVolumeClaim:
claimName: {{ .Values.admin.logs.claimName }}
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-security-config
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- name: ca-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-ca-cert
- name: master-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-master-cert
- name: volume-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-volume-cert
- name: filer-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-filer-cert
- name: client-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-client-cert
- name: admin-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-admin-cert
{{- end }}
{{ tpl .Values.admin.extraVolumes . | indent 8 | trim }}
{{- if .Values.admin.nodeSelector }}
nodeSelector:
{{ tpl .Values.admin.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- $pvc_exists := include "seaweedfs.admin.pvc_exists" . -}}
{{- if $pvc_exists }}
volumeClaimTemplates:
{{- if eq .Values.admin.data.type "persistentVolumeClaim" }}
- metadata:
name: admin-data
{{- with .Values.admin.data.annotations }}
annotations:
{{- toYaml . | nindent 10 }}
{{- end }}
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: {{ .Values.admin.data.storageClass }}
resources:
requests:
storage: {{ .Values.admin.data.size }}
{{- end }}
{{- if eq .Values.admin.logs.type "persistentVolumeClaim" }}
- metadata:
name: admin-logs
{{- with .Values.admin.logs.annotations }}
annotations:
{{- toYaml . | nindent 10 }}
{{- end }}
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: {{ .Values.admin.logs.storageClass }}
resources:
requests:
storage: {{ .Values.admin.logs.size }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,519 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.allInOne.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "seaweedfs.fullname" . }}-all-in-one
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: seaweedfs-all-in-one
{{- if .Values.allInOne.annotations }}
annotations:
{{- toYaml .Values.allInOne.annotations | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.allInOne.replicas | default 1 }}
strategy:
type: {{ .Values.allInOne.updateStrategy.type | default "Recreate" }}
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: seaweedfs-all-in-one
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: seaweedfs-all-in-one
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.allInOne.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- $podAnnotations := mergeOverwrite (deepCopy (.Values.podAnnotations | default dict)) (.Values.allInOne.podAnnotations | default dict) }}
{{- $existingS3ConfigSecret := or .Values.allInOne.s3.existingConfigSecret .Values.s3.existingConfigSecret .Values.filer.s3.existingConfigSecret }}
{{- if $existingS3ConfigSecret }}
{{- $configSecret := (lookup "v1" "Secret" .Release.Namespace $existingS3ConfigSecret) | default dict }}
{{- $_ := set $podAnnotations "checksum/s3config" ($configSecret | toYaml | sha256sum) }}
{{- else }}
{{- $_ := set $podAnnotations "checksum/s3config" (include (print .Template.BasePath "/s3/s3-secret.yaml") . | sha256sum) }}
{{- end }}
{{- $_ := set $podAnnotations "checksum/master-config" (include (print .Template.BasePath "/master/master-configmap.yaml") . | sha256sum) }}
annotations:
{{- toYaml $podAnnotations | nindent 8 }}
spec:
restartPolicy: {{ default .Values.global.seaweedfs.restartPolicy .Values.allInOne.restartPolicy }}
{{- if .Values.allInOne.affinity }}
affinity:
{{ tpl .Values.allInOne.affinity . | nindent 8 | trim }}
{{- end }}
{{- if .Values.allInOne.topologySpreadConstraints }}
topologySpreadConstraints:
{{ tpl .Values.allInOne.topologySpreadConstraints . | nindent 8 | trim }}
{{- end }}
{{- if .Values.allInOne.tolerations }}
tolerations:
{{- tpl .Values.allInOne.tolerations . | nindent 8 }}
{{- end }}
{{- include "seaweedfs.imagePullSecrets" . | nindent 6 }}
terminationGracePeriodSeconds: 60
enableServiceLinks: false
{{- if .Values.allInOne.priorityClassName }}
priorityClassName: {{ .Values.allInOne.priorityClassName | quote }}
{{- end }}
{{- if .Values.allInOne.schedulerName }}
schedulerName: {{ .Values.allInOne.schedulerName | quote }}
{{- end }}
{{- if .Values.allInOne.serviceAccountName }}
serviceAccountName: {{ .Values.allInOne.serviceAccountName | quote }}
{{- end }}
{{- if .Values.allInOne.initContainers }}
initContainers:
{{- tpl .Values.allInOne.initContainers . | nindent 8 }}
{{- end }}
{{- if .Values.allInOne.podSecurityContext.enabled }}
securityContext:
{{- omit .Values.allInOne.podSecurityContext "enabled" | toYaml | nindent 8 }}
{{- end }}
containers:
- name: seaweedfs
image: {{ template "seaweedfs.master.image" . }}
imagePullPolicy: {{ default "IfNotPresent" .Values.global.seaweedfs.imagePullPolicy }}
env:
{{- include "seaweedfs.licenseEnv" . | nindent 12 }}
{{- if and .Values.allInOne.s3.enabled (or .Values.allInOne.s3.enableAuth .Values.s3.enableAuth .Values.filer.s3.enableAuth) }}
{{- include "seaweedfs.s3.credentialEnv" . | nindent 12 }}
{{- end }}
{{- /* Determine default cluster alias and the corresponding env var keys to avoid conflicts */}}
{{- $mergedExtraEnvironmentVars := dict }}
{{- include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" .Values.global.seaweedfs "component" .Values.allInOne "target" $mergedExtraEnvironmentVars) }}
{{- $clusterDefault := default "sw" (index $mergedExtraEnvironmentVars "WEED_CLUSTER_DEFAULT") }}
{{- $clusterUpper := upper $clusterDefault }}
{{- $clusterMasterKey := printf "WEED_CLUSTER_%s_MASTER" $clusterUpper }}
{{- $clusterFilerKey := printf "WEED_CLUSTER_%s_FILER" $clusterUpper }}
- 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: "{{ include "seaweedfs.fullname" . }}"
{{- range $key := keys $mergedExtraEnvironmentVars | sortAlpha }}
{{- $value := index $mergedExtraEnvironmentVars $key }}
{{- if and (ne $key $clusterMasterKey) (ne $key $clusterFilerKey) }}
- name: {{ $key }}
{{- if kindIs "string" $value }}
value: {{ tpl $value $ | quote }}
{{- else }}
valueFrom:
{{ toYaml $value | nindent 16 }}
{{- end }}
{{- end }}
{{- end }}
# Inject computed cluster endpoints for the default cluster
- name: {{ $clusterMasterKey }}
value: {{ include "seaweedfs.cluster.masterAddress" . | quote }}
- name: {{ $clusterFilerKey }}
value: {{ include "seaweedfs.cluster.filerAddress" . | quote }}
{{- if .Values.allInOne.secretExtraEnvironmentVars }}
{{- range $key, $value := .Values.allInOne.secretExtraEnvironmentVars }}
{{- if not (and $key (eq $key "SEAWEED_LICENSE") (include "seaweedfs.licenseEnabled" $)) }}
- name: {{ $key }}
valueFrom:
{{ toYaml $value | nindent 16 }}
{{- end }}
{{- end }}
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
/usr/bin/weed \
{{- if .Values.allInOne.loggingOverrideLevel }}
-v={{ .Values.allInOne.loggingOverrideLevel }} \
{{- else }}
-v={{ .Values.global.seaweedfs.loggingLevel }} \
{{- end }}
server \
-dir=/data \
-master \
-volume \
-ip=${POD_IP} \
-ip.bind=0.0.0.0 \
{{- if .Values.allInOne.idleTimeout }}
-idleTimeout={{ .Values.allInOne.idleTimeout }} \
{{- end }}
{{- if .Values.allInOne.dataCenter }}
-dataCenter={{ .Values.allInOne.dataCenter }} \
{{- end }}
{{- if .Values.allInOne.rack }}
-rack={{ .Values.allInOne.rack }} \
{{- end }}
{{- if .Values.allInOne.whiteList }}
-whiteList={{ .Values.allInOne.whiteList }} \
{{- end }}
{{- if .Values.allInOne.disableHttp }}
-disableHttp={{ .Values.allInOne.disableHttp }} \
{{- end }}
{{- if .Values.volume.dataDirs }}
{{- with (first .Values.volume.dataDirs) }}
{{- if and (hasKey . "maxVolumes") (ne .maxVolumes nil) }}
-volume.max={{ .maxVolumes }} \
{{- end }}
{{- end }}
{{- end }}
-master.port={{ .Values.master.port }} \
{{- if .Values.global.seaweedfs.enableReplication }}
-master.defaultReplication={{ .Values.global.seaweedfs.replicationPlacement }} \
{{- else }}
-master.defaultReplication={{ .Values.master.defaultReplication }} \
{{- end }}
{{- if .Values.master.volumePreallocate }}
-master.volumePreallocate \
{{- end }}
-master.volumeSizeLimitMB={{ .Values.master.volumeSizeLimitMB }} \
{{- if .Values.master.garbageThreshold }}
-master.garbageThreshold={{ .Values.master.garbageThreshold }} \
{{- end }}
-volume.port={{ .Values.volume.port }} \
-volume.readMode={{ .Values.volume.readMode }} \
{{- if .Values.volume.imagesFixOrientation }}
-volume.images.fix.orientation \
{{- end }}
{{- if .Values.volume.index }}
-volume.index={{ .Values.volume.index }} \
{{- end }}
{{- if .Values.volume.fileSizeLimitMB }}
-volume.fileSizeLimitMB={{ .Values.volume.fileSizeLimitMB }} \
{{- end }}
-volume.minFreeSpacePercent={{ .Values.volume.minFreeSpacePercent }} \
-volume.compactionMBps={{ .Values.volume.compactionMBps }} \
{{- if .Values.allInOne.metricsPort }}
-metricsPort={{ .Values.allInOne.metricsPort }} \
{{- else if .Values.master.metricsPort }}
-metricsPort={{ .Values.master.metricsPort }} \
{{- end }}
{{- if .Values.allInOne.metricsIp }}
-metricsIp={{ .Values.allInOne.metricsIp }} \
{{- end }}
-filer \
-filer.port={{ .Values.filer.port }} \
{{- if .Values.filer.disableDirListing }}
-filer.disableDirListing \
{{- end }}
-filer.dirListLimit={{ .Values.filer.dirListLimit }} \
{{- if .Values.global.seaweedfs.enableReplication }}
-filer.defaultReplicaPlacement={{ .Values.global.seaweedfs.replicationPlacement }} \
{{- else }}
-filer.defaultReplicaPlacement={{ .Values.filer.defaultReplicaPlacement }} \
{{- end }}
{{- if .Values.filer.maxMB }}
-filer.maxMB={{ .Values.filer.maxMB }} \
{{- end }}
{{- if .Values.filer.encryptVolumeData }}
-filer.encryptVolumeData \
{{- end }}
{{- if .Values.filer.filerGroup}}
-filer.filerGroup={{ .Values.filer.filerGroup}} \
{{- end }}
{{- if .Values.filer.rack }}
-filer.rack={{ .Values.filer.rack }} \
{{- end }}
{{- if .Values.filer.dataCenter }}
-filer.dataCenter={{ .Values.filer.dataCenter }} \
{{- end }}
{{- if .Values.allInOne.s3.enabled }}
-s3 \
-s3.port={{ .Values.allInOne.s3.port | default .Values.s3.port }} \
{{- $domainName := .Values.allInOne.s3.domainName | default .Values.s3.domainName }}
{{- if $domainName }}
-s3.domainName={{ $domainName }} \
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
{{- $httpsPort := .Values.allInOne.s3.httpsPort | default .Values.s3.httpsPort }}
{{- if $httpsPort }}
-s3.port.https={{ $httpsPort }} \
{{- include "seaweedfs.s3.tlsArgs" (dict "root" . "prefix" "s3.") | nindent 14 }}
{{- end }}
{{- end }}
{{- if or .Values.allInOne.s3.enableAuth .Values.s3.enableAuth .Values.filer.s3.enableAuth }}
-s3.config=/etc/sw/s3/seaweedfs_s3_config \
{{- end }}
{{- $auditLogConfig := .Values.allInOne.s3.auditLogConfig | default .Values.s3.auditLogConfig }}
{{- if $auditLogConfig }}
-s3.auditLogConfig=/etc/sw/s3/s3_auditLogConfig.json \
{{- end }}
{{- end }}
{{- if .Values.allInOne.sftp.enabled }}
-sftp \
-sftp.port={{ .Values.allInOne.sftp.port | default .Values.sftp.port }} \
{{- $sshPrivateKey := .Values.allInOne.sftp.sshPrivateKey | default .Values.sftp.sshPrivateKey }}
{{- if $sshPrivateKey }}
-sftp.sshPrivateKey={{ $sshPrivateKey }} \
{{- end }}
{{- $hostKeysFolder := .Values.allInOne.sftp.hostKeysFolder | default .Values.sftp.hostKeysFolder }}
{{- if $hostKeysFolder }}
-sftp.hostKeysFolder={{ $hostKeysFolder }} \
{{- end }}
{{- $authMethods := .Values.allInOne.sftp.authMethods | default .Values.sftp.authMethods }}
{{- if $authMethods }}
-sftp.authMethods={{ $authMethods }} \
{{- if contains "certificate" $authMethods }}
-sftp.trustedUserCAKeysFile=/etc/sw/sftp_ca/ca_user.pub \
{{- end }}
{{- end }}
{{- $maxAuthTries := .Values.allInOne.sftp.maxAuthTries | default .Values.sftp.maxAuthTries }}
{{- if $maxAuthTries }}
-sftp.maxAuthTries={{ $maxAuthTries }} \
{{- end }}
{{- $bannerMessage := .Values.allInOne.sftp.bannerMessage | default .Values.sftp.bannerMessage }}
{{- if $bannerMessage }}
-sftp.bannerMessage="{{ $bannerMessage }}" \
{{- end }}
{{- $loginGraceTime := .Values.allInOne.sftp.loginGraceTime | default .Values.sftp.loginGraceTime }}
{{- if $loginGraceTime }}
-sftp.loginGraceTime={{ $loginGraceTime }} \
{{- end }}
{{- $clientAliveInterval := .Values.allInOne.sftp.clientAliveInterval | default .Values.sftp.clientAliveInterval }}
{{- if $clientAliveInterval }}
-sftp.clientAliveInterval={{ $clientAliveInterval }} \
{{- end }}
{{- $clientAliveCountMax := .Values.allInOne.sftp.clientAliveCountMax | default .Values.sftp.clientAliveCountMax }}
{{- if $clientAliveCountMax }}
-sftp.clientAliveCountMax={{ $clientAliveCountMax }} \
{{- end }}
{{- if or .Values.allInOne.sftp.enableAuth .Values.sftp.enableAuth }}
-sftp.userStoreFile=/etc/sw/sftp/seaweedfs_sftp_config \
{{- end }}
{{- end }}
{{- $extraArgsCount := len .Values.allInOne.extraArgs }}
{{- range $i, $arg := .Values.allInOne.extraArgs }}
{{ $arg | quote }}{{ if ne (add1 $i) $extraArgsCount }} \{{ end }}
{{- end }}
volumeMounts:
- name: data
mountPath: /data
{{- if and .Values.allInOne.s3.enabled (or .Values.allInOne.s3.enableAuth .Values.s3.enableAuth .Values.filer.s3.enableAuth) }}
- name: config-s3-users
mountPath: /etc/sw/s3
readOnly: true
{{- end }}
{{- if .Values.allInOne.sftp.enabled }}
- name: config-ssh
mountPath: {{ .Values.allInOne.sftp.hostKeysFolder | default .Values.sftp.hostKeysFolder | default "/etc/sw/ssh" }}
readOnly: true
{{- if or .Values.allInOne.sftp.enableAuth .Values.sftp.enableAuth }}
- mountPath: /etc/sw/sftp
name: config-users
readOnly: true
{{- end }}
{{- $aioAuthMethods := .Values.allInOne.sftp.authMethods | default .Values.sftp.authMethods }}
{{- if and $aioAuthMethods (contains "certificate" $aioAuthMethods) }}
- mountPath: /etc/sw/sftp_ca
name: config-sftp-ca
readOnly: true
{{- end }}
{{- end }}
{{- if .Values.filer.notificationConfig }}
- name: notification-config
mountPath: /etc/seaweedfs/notification.toml
subPath: notification.toml
readOnly: true
{{- end }}
- name: master-config
mountPath: /etc/seaweedfs/master.toml
subPath: master.toml
readOnly: true
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
mountPath: /etc/seaweedfs/security.toml
subPath: security.toml
readOnly: true
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- name: ca-cert
mountPath: /usr/local/share/ca-certificates/ca/
readOnly: true
- name: master-cert
mountPath: /usr/local/share/ca-certificates/master/
readOnly: true
- name: volume-cert
mountPath: /usr/local/share/ca-certificates/volume/
readOnly: true
- name: filer-cert
mountPath: /usr/local/share/ca-certificates/filer/
readOnly: true
- name: client-cert
mountPath: /usr/local/share/ca-certificates/client/
readOnly: true
{{- if .Values.allInOne.s3.enabled }}
{{- include "seaweedfs.s3.tlsVolumeMount" . | nindent 12 }}
{{- end }}
{{- end }}
{{- include "seaweedfs.licenseVolumeMount" . | nindent 12 }}
{{ tpl .Values.allInOne.extraVolumeMounts . | nindent 12 }}
ports:
- containerPort: {{ .Values.master.port }}
name: swfs-mas
- containerPort: {{ .Values.master.grpcPort }}
name: swfs-mas-grpc
- containerPort: {{ .Values.volume.port }}
name: swfs-vol
- containerPort: {{ .Values.volume.grpcPort }}
name: swfs-vol-grpc
- containerPort: {{ .Values.filer.port }}
name: swfs-fil
- containerPort: {{ .Values.filer.grpcPort }}
name: swfs-fil-grpc
{{- if .Values.allInOne.s3.enabled }}
- containerPort: {{ .Values.allInOne.s3.port | default .Values.s3.port }}
name: swfs-s3
{{- $httpsPort := .Values.allInOne.s3.httpsPort | default .Values.s3.httpsPort }}
{{- if $httpsPort }}
- containerPort: {{ $httpsPort }}
name: swfs-s3-tls
{{- end }}
{{- end }}
{{- if .Values.allInOne.sftp.enabled }}
- containerPort: {{ .Values.allInOne.sftp.port | default .Values.sftp.port }}
name: swfs-sftp
{{- end }}
{{- if .Values.allInOne.metricsPort }}
- containerPort: {{ .Values.allInOne.metricsPort }}
name: server-metrics
{{- end }}
{{- if .Values.allInOne.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: {{ .Values.allInOne.readinessProbe.httpGet.path }}
port: {{ .Values.master.port }}
scheme: {{ .Values.allInOne.readinessProbe.httpGet.scheme }}
initialDelaySeconds: {{ .Values.allInOne.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.allInOne.readinessProbe.periodSeconds }}
successThreshold: {{ .Values.allInOne.readinessProbe.successThreshold }}
failureThreshold: {{ .Values.allInOne.readinessProbe.failureThreshold }}
timeoutSeconds: {{ .Values.allInOne.readinessProbe.timeoutSeconds }}
{{- end }}
{{- if .Values.allInOne.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: {{ .Values.allInOne.livenessProbe.httpGet.path }}
port: {{ .Values.master.port }}
scheme: {{ .Values.allInOne.livenessProbe.httpGet.scheme }}
initialDelaySeconds: {{ .Values.allInOne.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.allInOne.livenessProbe.periodSeconds }}
successThreshold: {{ .Values.allInOne.livenessProbe.successThreshold }}
failureThreshold: {{ .Values.allInOne.livenessProbe.failureThreshold }}
timeoutSeconds: {{ .Values.allInOne.livenessProbe.timeoutSeconds }}
{{- end }}
{{- with .Values.allInOne.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.allInOne.containerSecurityContext.enabled }}
securityContext:
{{- omit .Values.allInOne.containerSecurityContext "enabled" | toYaml | nindent 12 }}
{{- end }}
{{- if .Values.allInOne.sidecars }}
{{- include "seaweedfs.tplvalues.render" (dict "value" .Values.allInOne.sidecars "context" $) | nindent 8 }}
{{- end }}
volumes:
{{- include "seaweedfs.licenseVolume" . | nindent 8 }}
- name: data
{{- if eq .Values.allInOne.data.type "hostPath" }}
hostPath:
path: {{ .Values.allInOne.data.hostPathPrefix }}/seaweedfs-all-in-one-data/
type: DirectoryOrCreate
{{- else if eq .Values.allInOne.data.type "persistentVolumeClaim" }}
persistentVolumeClaim:
claimName: {{ include "seaweedfs.fullname" . }}-all-in-one-data
{{- else if eq .Values.allInOne.data.type "existingClaim" }}
persistentVolumeClaim:
claimName: {{ .Values.allInOne.data.claimName }}
{{- else if eq .Values.allInOne.data.type "emptyDir" }}
emptyDir: {}
{{- end }}
{{- if and .Values.allInOne.s3.enabled (or .Values.allInOne.s3.enableAuth .Values.s3.enableAuth .Values.filer.s3.enableAuth) }}
- name: config-s3-users
secret:
defaultMode: 420
secretName: {{ default (printf "%s-s3-secret" (include "seaweedfs.fullname" .)) (or .Values.allInOne.s3.existingConfigSecret .Values.s3.existingConfigSecret .Values.filer.s3.existingConfigSecret) }}
{{- end }}
{{- if .Values.allInOne.sftp.enabled }}
- name: config-ssh
secret:
defaultMode: 420
secretName: {{ default (printf "%s-sftp-ssh-secret" (include "seaweedfs.fullname" .)) (or .Values.allInOne.sftp.existingSshConfigSecret .Values.sftp.existingSshConfigSecret) }}
{{- if or .Values.allInOne.sftp.enableAuth .Values.sftp.enableAuth }}
- name: config-users
secret:
defaultMode: 420
secretName: {{ default (printf "%s-sftp-secret" (include "seaweedfs.fullname" .)) (or .Values.allInOne.sftp.existingConfigSecret .Values.sftp.existingConfigSecret) }}
{{- end }}
{{- $aioAuthMethodsVol := .Values.allInOne.sftp.authMethods | default .Values.sftp.authMethods }}
{{- if and $aioAuthMethodsVol (contains "certificate" $aioAuthMethodsVol) }}
{{- $aioCASecret := or .Values.allInOne.sftp.existingCAKeysSecret .Values.sftp.existingCAKeysSecret }}
{{- $aioCAKeys := or .Values.allInOne.sftp.trustedUserCAKeys .Values.sftp.trustedUserCAKeys }}
{{- if and (not $aioCASecret) (not $aioCAKeys) }}
{{- fail "allInOne.sftp.authMethods includes \"certificate\" but neither trustedUserCAKeys nor existingCAKeysSecret is set" }}
{{- end }}
- name: config-sftp-ca
secret:
defaultMode: 420
secretName: {{ default (printf "%s-sftp-ca-secret" (include "seaweedfs.fullname" .)) $aioCASecret }}
{{- end }}
{{- end }}
{{- if .Values.filer.notificationConfig }}
- name: notification-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-notification-config
{{- end }}
- name: master-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-master-config
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-security-config
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- name: ca-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-ca-cert
- name: master-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-master-cert
- name: volume-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-volume-cert
- name: filer-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-filer-cert
- name: client-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-client-cert
{{- if .Values.allInOne.s3.enabled }}
{{- include "seaweedfs.s3.tlsVolume" . | nindent 8 }}
{{- end }}
{{- end }}
{{ tpl .Values.allInOne.extraVolumes . | nindent 8 }}
{{- if .Values.allInOne.nodeSelector }}
nodeSelector:
{{ tpl .Values.allInOne.nodeSelector . | nindent 8 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,28 @@
{{- if .Values.allInOne.enabled }}
{{- if eq .Values.allInOne.data.type "persistentVolumeClaim" }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "seaweedfs.fullname" . }}-all-in-one-data
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: seaweedfs-all-in-one
{{- with .Values.allInOne.data.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
accessModes:
{{- toYaml (.Values.allInOne.data.accessModes | default (list "ReadWriteOnce")) | nindent 4 }}
{{- if .Values.allInOne.data.storageClass }}
storageClassName: {{ .Values.allInOne.data.storageClass }}
{{- end }}
resources:
requests:
storage: {{ .Values.allInOne.data.size | default "10Gi" }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,125 @@
{{- if .Values.allInOne.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "seaweedfs.componentName" (list . "all-in-one") }}
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: seaweedfs-all-in-one
{{- if .Values.allInOne.service.annotations }}
annotations:
{{- toYaml .Values.allInOne.service.annotations | nindent 4 }}
{{- end }}
spec:
{{- $serviceType := .Values.allInOne.service.type | default "ClusterIP" }}
{{- $nodePorts := dict }}
{{- if or (eq $serviceType "NodePort") (eq $serviceType "LoadBalancer") }}
{{- $nodePorts = .Values.allInOne.service.nodePorts | default dict }}
{{- end }}
type: {{ $serviceType }}
{{- include "seaweedfs.service.loadBalancerFields" .Values.allInOne.service }}
internalTrafficPolicy: {{ .Values.allInOne.service.internalTrafficPolicy | default "Cluster" }}
{{- if and (semverCompare ">=1.31-0" .Capabilities.KubeVersion.GitVersion) .Values.allInOne.s3.trafficDistribution }}
trafficDistribution: {{ include "seaweedfs.trafficDistribution" (dict "value" .Values.allInOne.s3.trafficDistribution "Capabilities" .Capabilities) }}
{{- end }}
ports:
# Master ports
- name: "swfs-master"
port: {{ .Values.master.port }}
targetPort: {{ .Values.master.port }}
{{- if $nodePorts.master }}
nodePort: {{ $nodePorts.master }}
{{- end }}
protocol: TCP
- name: "swfs-master-grpc"
port: {{ .Values.master.grpcPort }}
targetPort: {{ .Values.master.grpcPort }}
{{- if $nodePorts.masterGrpc }}
nodePort: {{ $nodePorts.masterGrpc }}
{{- end }}
protocol: TCP
# Volume ports
- name: "swfs-volume"
port: {{ .Values.volume.port }}
targetPort: {{ .Values.volume.port }}
{{- if $nodePorts.volume }}
nodePort: {{ $nodePorts.volume }}
{{- end }}
protocol: TCP
- name: "swfs-volume-grpc"
port: {{ .Values.volume.grpcPort }}
targetPort: {{ .Values.volume.grpcPort }}
{{- if $nodePorts.volumeGrpc }}
nodePort: {{ $nodePorts.volumeGrpc }}
{{- end }}
protocol: TCP
# Filer ports
- name: "swfs-filer"
port: {{ .Values.filer.port }}
targetPort: {{ .Values.filer.port }}
{{- if $nodePorts.filer }}
nodePort: {{ $nodePorts.filer }}
{{- end }}
protocol: TCP
- name: "swfs-filer-grpc"
port: {{ .Values.filer.grpcPort }}
targetPort: {{ .Values.filer.grpcPort }}
{{- if $nodePorts.filerGrpc }}
nodePort: {{ $nodePorts.filerGrpc }}
{{- end }}
protocol: TCP
# S3 ports (if enabled)
{{- if .Values.allInOne.s3.enabled }}
- name: "swfs-s3"
port: {{ .Values.allInOne.s3.port | default .Values.s3.port }}
targetPort: {{ .Values.allInOne.s3.port | default .Values.s3.port }}
{{- if $nodePorts.s3 }}
nodePort: {{ $nodePorts.s3 }}
{{- end }}
protocol: TCP
{{- $httpsPort := .Values.allInOne.s3.httpsPort | default .Values.s3.httpsPort }}
{{- if $httpsPort }}
- name: "swfs-s3-tls"
port: {{ $httpsPort }}
targetPort: {{ $httpsPort }}
{{- if $nodePorts.s3Https }}
nodePort: {{ $nodePorts.s3Https }}
{{- end }}
protocol: TCP
{{- end }}
{{- end }}
# SFTP ports (if enabled)
{{- if .Values.allInOne.sftp.enabled }}
- name: "swfs-sftp"
port: {{ .Values.allInOne.sftp.port | default .Values.sftp.port }}
targetPort: {{ .Values.allInOne.sftp.port | default .Values.sftp.port }}
{{- if $nodePorts.sftp }}
nodePort: {{ $nodePorts.sftp }}
{{- end }}
protocol: TCP
{{- end }}
# Server metrics port (single metrics endpoint for all services)
{{- if .Values.allInOne.metricsPort }}
- name: "server-metrics"
port: {{ .Values.allInOne.metricsPort }}
targetPort: {{ .Values.allInOne.metricsPort }}
{{- if $nodePorts.metrics }}
nodePort: {{ $nodePorts.metrics }}
{{- end }}
protocol: TCP
{{- end }}
selector:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: seaweedfs-all-in-one
{{- end }}

View File

@@ -0,0 +1,31 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.allInOne.enabled }}
{{- if .Values.global.seaweedfs.monitoring.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "seaweedfs.fullname" . }}-all-in-one
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: all-in-one
{{- with .Values.global.seaweedfs.monitoring.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
endpoints:
{{- if .Values.allInOne.metricsPort }}
- interval: 30s
port: server-metrics
scrapeTimeout: 5s
{{- end }}
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: seaweedfs-all-in-one
{{- end }}
{{- end }}

View File

@@ -0,0 +1,49 @@
{{- include "seaweedfs.compat" . -}}
{{- if and .Values.global.seaweedfs.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
apiVersion: cert-manager.io/v1{{ if .Values.global.seaweedfs.certificates.alphacrds }}alpha1{{ end }}
kind: Certificate
metadata:
name: {{ include "seaweedfs.fullname" . }}-admin-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: admin
{{- if .Values.admin.annotations }}
annotations:
{{- toYaml .Values.admin.annotations | nindent 4 }}
{{- end }}
spec:
secretName: {{ include "seaweedfs.fullname" . }}-admin-cert
issuerRef:
name: {{ include "seaweedfs.fullname" . }}-ca-issuer
kind: Issuer
commonName: {{ .Values.certificates.commonName }}
subject:
organizations:
- "SeaweedFS CA"
dnsNames:
- '*.{{ include "seaweedfs.fullname" . }}-admin'
- '*.{{ include "seaweedfs.fullname" . }}-admin.{{ .Release.Namespace }}'
- '*.{{ include "seaweedfs.fullname" . }}-admin.{{ .Release.Namespace }}.svc'
- '*.{{ include "seaweedfs.fullname" . }}-admin.{{ .Release.Namespace }}.svc.cluster.local'
{{- if .Values.certificates.dnsNames }}
{{- range .Values.certificates.dnsNames }}
- {{ . | quote }}
{{- end }}
{{- end }}
{{- 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 }}

View File

@@ -0,0 +1,26 @@
{{- include "seaweedfs.compat" . -}}
{{- if and .Values.global.seaweedfs.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
apiVersion: cert-manager.io/v1{{ if .Values.global.seaweedfs.certificates.alphacrds }}alpha1{{ end }}
kind: Certificate
metadata:
name: {{ include "seaweedfs.fullname" . }}-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: {{ include "seaweedfs.fullname" . }}-ca-cert
commonName: "{{ include "seaweedfs.fullname" . }}-root-ca"
isCA: true
{{- if .Values.certificates.ca.duration }}
duration: {{ .Values.certificates.ca.duration }}
{{- end }}
{{- if .Values.certificates.ca.renewBefore }}
renewBefore: {{ .Values.certificates.ca.renewBefore }}
{{- end }}
issuerRef:
name: {{ include "seaweedfs.fullname" . }}-issuer
kind: Issuer
{{- end }}

View File

@@ -0,0 +1,16 @@
{{- include "seaweedfs.compat" . -}}
{{- if and .Values.global.seaweedfs.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
apiVersion: cert-manager.io/v1{{ if .Values.global.seaweedfs.certificates.alphacrds }}alpha1{{ end }}
kind: Issuer
metadata:
name: {{ include "seaweedfs.fullname" . }}-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: {{ include "seaweedfs.fullname" . }}-ca-cert
{{- end }}

View File

@@ -0,0 +1,14 @@
{{- include "seaweedfs.compat" . -}}
{{- if and .Values.global.seaweedfs.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
apiVersion: cert-manager.io/v1{{ if .Values.global.seaweedfs.certificates.alphacrds }}alpha1{{ end }}
kind: Issuer
metadata:
name: {{ include "seaweedfs.fullname" . }}-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 }}

View File

@@ -0,0 +1,46 @@
{{- include "seaweedfs.compat" . -}}
{{- if and .Values.global.seaweedfs.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
apiVersion: cert-manager.io/v1{{ if .Values.global.seaweedfs.certificates.alphacrds }}alpha1{{ end }}
kind: Certificate
metadata:
name: {{ include "seaweedfs.fullname" . }}-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: {{ include "seaweedfs.fullname" . }}-client-cert
issuerRef:
name: {{ include "seaweedfs.fullname" . }}-ca-issuer
kind: Issuer
commonName: {{ .Values.certificates.commonName }}
subject:
organizations:
- "SeaweedFS CA"
dnsNames:
- '*.{{ .Release.Namespace }}'
- '*.{{ .Release.Namespace }}.svc'
- '*.{{ .Release.Namespace }}.svc.cluster.local'
{{- if .Values.certificates.dnsNames }}
{{- range .Values.certificates.dnsNames }}
- {{ . | quote }}
{{- end }}
{{- end }}
- '*.{{ include "seaweedfs.fullname" . }}-master'
- '*.{{ include "seaweedfs.fullname" . }}-master.{{ .Release.Namespace }}'
- '*.{{ include "seaweedfs.fullname" . }}-master.{{ .Release.Namespace }}.svc'
- '*.{{ include "seaweedfs.fullname" . }}-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 }}

View File

@@ -0,0 +1,51 @@
{{- include "seaweedfs.compat" . -}}
{{- if and .Values.global.seaweedfs.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
apiVersion: cert-manager.io/v1{{ if .Values.global.seaweedfs.certificates.alphacrds }}alpha1{{ end }}
kind: Certificate
metadata:
name: {{ include "seaweedfs.fullname" . }}-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
{{- if .Values.filer.annotations }}
annotations:
{{- toYaml .Values.filer.annotations | nindent 4 }}
{{- end }}
spec:
secretName: {{ include "seaweedfs.fullname" . }}-filer-cert
issuerRef:
name: {{ include "seaweedfs.fullname" . }}-ca-issuer
kind: Issuer
commonName: {{ .Values.certificates.commonName }}
subject:
organizations:
- "SeaweedFS CA"
dnsNames:
- '*.{{ .Release.Namespace }}'
- '*.{{ .Release.Namespace }}.svc'
- '*.{{ .Release.Namespace }}.svc.cluster.local'
{{- if .Values.certificates.dnsNames }}
{{- range .Values.certificates.dnsNames }}
- {{ . | quote }}
{{- end }}
{{- end }}
- '*.{{ include "seaweedfs.fullname" . }}-master'
- '*.{{ include "seaweedfs.fullname" . }}-master.{{ .Release.Namespace }}'
- '*.{{ include "seaweedfs.fullname" . }}-master.{{ .Release.Namespace }}.svc'
- '*.{{ include "seaweedfs.fullname" . }}-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 }}

View File

@@ -0,0 +1,51 @@
{{- include "seaweedfs.compat" . -}}
{{- if and .Values.global.seaweedfs.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
apiVersion: cert-manager.io/v1{{ if .Values.global.seaweedfs.certificates.alphacrds }}alpha1{{ end }}
kind: Certificate
metadata:
name: {{ include "seaweedfs.fullname" . }}-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
{{- if .Values.master.annotations }}
annotations:
{{- toYaml .Values.master.annotations | nindent 4 }}
{{- end }}
spec:
secretName: {{ include "seaweedfs.fullname" . }}-master-cert
issuerRef:
name: {{ include "seaweedfs.fullname" . }}-ca-issuer
kind: Issuer
commonName: {{ .Values.certificates.commonName }}
subject:
organizations:
- "SeaweedFS CA"
dnsNames:
- '*.{{ .Release.Namespace }}'
- '*.{{ .Release.Namespace }}.svc'
- '*.{{ .Release.Namespace }}.svc.cluster.local'
{{- if .Values.certificates.dnsNames }}
{{- range .Values.certificates.dnsNames }}
- {{ . | quote }}
{{- end }}
{{- end }}
- '*.{{ include "seaweedfs.fullname" . }}-master'
- '*.{{ include "seaweedfs.fullname" . }}-master.{{ .Release.Namespace }}'
- '*.{{ include "seaweedfs.fullname" . }}-master.{{ .Release.Namespace }}.svc'
- '*.{{ include "seaweedfs.fullname" . }}-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 }}

View File

@@ -0,0 +1,51 @@
{{- include "seaweedfs.compat" . -}}
{{- if and .Values.global.seaweedfs.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
apiVersion: cert-manager.io/v1{{ if .Values.global.seaweedfs.certificates.alphacrds }}alpha1{{ end }}
kind: Certificate
metadata:
name: {{ include "seaweedfs.fullname" . }}-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
{{- if .Values.volume.annotations }}
annotations:
{{- toYaml .Values.volume.annotations | nindent 4 }}
{{- end }}
spec:
secretName: {{ include "seaweedfs.fullname" . }}-volume-cert
issuerRef:
name: {{ include "seaweedfs.fullname" . }}-ca-issuer
kind: Issuer
commonName: {{ .Values.certificates.commonName }}
subject:
organizations:
- "SeaweedFS CA"
dnsNames:
- '*.{{ .Release.Namespace }}'
- '*.{{ .Release.Namespace }}.svc'
- '*.{{ .Release.Namespace }}.svc.cluster.local'
{{- if .Values.certificates.dnsNames }}
{{- range .Values.certificates.dnsNames }}
- {{ . | quote }}
{{- end }}
{{- end }}
- '*.{{ include "seaweedfs.fullname" . }}-master'
- '*.{{ include "seaweedfs.fullname" . }}-master.{{ .Release.Namespace }}'
- '*.{{ include "seaweedfs.fullname" . }}-master.{{ .Release.Namespace }}.svc'
- '*.{{ include "seaweedfs.fullname" . }}-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 }}

View File

@@ -0,0 +1,49 @@
{{- include "seaweedfs.compat" . -}}
{{- if and .Values.global.seaweedfs.enableSecurity (not .Values.certificates.externalCertificates.enabled)}}
apiVersion: cert-manager.io/v1{{ if .Values.global.seaweedfs.certificates.alphacrds }}alpha1{{ end }}
kind: Certificate
metadata:
name: {{ include "seaweedfs.fullname" . }}-worker-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: worker
{{- if .Values.worker.annotations }}
annotations:
{{- toYaml .Values.worker.annotations | nindent 4 }}
{{- end }}
spec:
secretName: {{ include "seaweedfs.fullname" . }}-worker-cert
issuerRef:
name: {{ include "seaweedfs.fullname" . }}-ca-issuer
kind: Issuer
commonName: {{ .Values.certificates.commonName }}
subject:
organizations:
- "SeaweedFS CA"
dnsNames:
- '*.{{ include "seaweedfs.fullname" . }}-worker'
- '*.{{ include "seaweedfs.fullname" . }}-worker.{{ .Release.Namespace }}'
- '*.{{ include "seaweedfs.fullname" . }}-worker.{{ .Release.Namespace }}.svc'
- '*.{{ include "seaweedfs.fullname" . }}-worker.{{ .Release.Namespace }}.svc.cluster.local'
{{- if .Values.certificates.dnsNames }}
{{- range .Values.certificates.dnsNames }}
- {{ . | quote }}
{{- end }}
{{- end }}
{{- 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 }}

View File

@@ -0,0 +1,20 @@
{{- 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
{{- with .Values.cosi.bucketClassParameters }}
parameters:
{{- toYaml . | nindent 2 }}
{{- end }}
---
kind: BucketAccessClass
apiVersion: objectstorage.k8s.io/v1alpha1
metadata:
name: {{ .Values.cosi.bucketClassName }}
driverName: {{ .Values.cosi.driverName }}
authenticationType: KEY
{{- end }}

View File

@@ -0,0 +1,70 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.cosi.enabled }}
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "seaweedfs.fullname" . }}-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: {{ include "seaweedfs.fullname" . }}-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.seaweedfs.serviceAccountName }}-objectstorage-provisioner
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: {{ include "seaweedfs.fullname" . }}-objectstorage-provisioner
apiGroup: rbac.authorization.k8s.io
{{- end }}

View File

@@ -0,0 +1,214 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.cosi.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "seaweedfs.fullname" . }}-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 }}
app.kubernetes.io/component: objectstorage-provisioner
spec:
replicas: {{ .Values.cosi.replicas }}
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
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.seaweedfs.restartPolicy .Values.cosi.restartPolicy }}
{{- if .Values.cosi.affinity }}
affinity:
{{ tpl .Values.cosi.affinity . | nindent 8 | trim }}
{{- end }}
{{- if .Values.cosi.topologySpreadConstraints }}
topologySpreadConstraints:
{{ tpl .Values.cosi.topologySpreadConstraint . | nindent 8 | trim }}
{{- end }}
{{- 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 }}
{{- if .Values.cosi.schedulerName }}
schedulerName: {{ .Values.cosi.schedulerName | quote }}
{{- end }}
enableServiceLinks: false
serviceAccountName: {{ include "seaweedfs.componentName" (list . "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.seaweedfs.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.%s.svc" (include "seaweedfs.componentName" (list . "s3")) .Release.Namespace }}"
{{- else }}
value: "{{ printf "https://%s.%s.svc" (include "seaweedfs.componentName" (list . "filer")) .Release.Namespace }}"
{{- end }}
{{- with .Values.cosi.region }}
- name: REGION
value: "{{ . }}"
{{- end }}
- name: SEAWEEDFS_FILER
value: "{{ include "seaweedfs.componentName" (list . "filer") }}:{{ .Values.filer.grpcPort }}"
{{- if .Values.global.seaweedfs.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 }}
{{- $mergedExtraEnvironmentVars := dict }}
{{- include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" .Values.global.seaweedfs "component" .Values.cosi "target" $mergedExtraEnvironmentVars) }}
{{- range $key := keys $mergedExtraEnvironmentVars | sortAlpha }}
{{- $value := index $mergedExtraEnvironmentVars $key }}
- name: {{ $key }}
{{- if kindIs "string" $value }}
value: {{ tpl $value $ | quote }}
{{- else }}
valueFrom:
{{ toYaml $value | nindent 16 | trim }}
{{- end -}}
{{- end }}
volumeMounts:
- mountPath: /var/lib/cosi
name: socket
{{- if .Values.cosi.enableAuth }}
- mountPath: /etc/sw
name: config-users
readOnly: true
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
readOnly: true
mountPath: /etc/seaweedfs/security.toml
subPath: security.toml
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- 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 }}
{{- with .Values.cosi.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
- name: seaweedfs-cosi-sidecar
image: "{{ .Values.cosi.sidecar.image }}"
imagePullPolicy: {{ default "IfNotPresent" .Values.global.seaweedfs.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.sidecar.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 "seaweedfs.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: {{ include "seaweedfs.fullname" . }}-s3-secret
{{- end }}
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-security-config
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- name: ca-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-ca-cert
- name: master-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-master-cert
- name: volume-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-volume-cert
- name: filer-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-filer-cert
- name: client-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-client-cert
{{- end }}
{{ tpl .Values.cosi.extraVolumes . | indent 8 | trim }}
{{- if .Values.cosi.nodeSelector }}
nodeSelector:
{{ tpl .Values.cosi.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,14 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.cosi.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.global.seaweedfs.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.seaweedfs.automountServiceAccountToken }}
{{- end }}

View File

@@ -0,0 +1,50 @@
{{- /* Traefik IngressRouteTCP for the filer gRPC port. Rendered instead of the
standard Ingress when the gRPC ingress className starts with "traefik",
since a Kubernetes Ingress can't do raw TCP/gRPC passthrough.
global.seaweedfs.enableSecurity controls the mode:
false: plain TCP, Traefik forwards h2c to the pod. A non-TLS TCP
router can only match HostSNI(`*`) (SNI needs TLS).
true: TLS passthrough, matched by SNI so it can route on the host. */}}
{{- $filerEnabled := or .Values.filer.enabled .Values.allInOne.enabled }}
{{- $isTraefik := hasPrefix "traefik" (default "" .Values.filer.ingresses.grpc.className) }}
{{- $securityEnabled := .Values.global.seaweedfs.enableSecurity }}
{{- if and $filerEnabled .Values.filer.ingresses.grpc.enabled $isTraefik }}
{{- $serviceName := ternary (include "seaweedfs.componentName" (list . "all-in-one")) (include "seaweedfs.componentName" (list . "filer")) .Values.allInOne.enabled }}
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: {{ include "seaweedfs.fullname" . }}-filer-grpc
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.filer.ingresses.grpc.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if $securityEnabled }}
tls:
passthrough: true
{{- end }}
entryPoints:
{{- with .Values.filer.ingresses.grpc.entryPoint }}
- {{ . | quote }}
{{- else }}
- filer-grpc
{{- end }}
routes:
{{- if $securityEnabled }}
- match: HostSNI(`{{ .Values.filer.ingresses.grpc.host }}`)
{{- else }}
- match: HostSNI(`*`)
{{- end }}
services:
- name: {{ $serviceName }}
port: {{ .Values.filer.grpcPort }}
{{- end }}

View File

@@ -0,0 +1,122 @@
{{- /* Filer ingresses work for both normal mode (filer.enabled) and all-in-one mode (allInOne.enabled) */}}
{{- $filerEnabled := or .Values.filer.enabled .Values.allInOne.enabled }}
{{- /* HTTP Ingress */}}
{{- if and $filerEnabled .Values.filer.ingresses.http.enabled }}
{{- /* Determine service name based on deployment mode */}}
{{- $serviceName := ternary (include "seaweedfs.componentName" (list . "all-in-one")) (include "seaweedfs.componentName" (list . "filer")) .Values.allInOne.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-{{ include "seaweedfs.fullname" . }}-filer-http
namespace: {{ .Release.Namespace }}
annotations:
{{- if and (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) .Values.filer.ingresses.http.className }}
kubernetes.io/ingress.class: {{ .Values.filer.ingresses.http.className }}
{{- end }}
{{- with .Values.filer.ingresses.http.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
{{- with .Values.filer.ingresses.http.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) .Values.filer.ingresses.http.className }}
ingressClassName: {{ .Values.filer.ingresses.http.className | quote }}
{{- end }}
tls:
{{ .Values.filer.ingresses.http.tls | default list | toYaml | nindent 6}}
rules:
- {{- if .Values.filer.ingresses.http.host }}
host: {{ .Values.filer.ingresses.http.host | quote }}
{{- end }}
http:
paths:
- path: {{ .Values.filer.ingresses.http.path | quote }}
{{- if semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion }}
pathType: {{ .Values.filer.ingresses.http.pathType | quote }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $serviceName }}
port:
number: {{ .Values.filer.port }}
{{- else }}
serviceName: {{ $serviceName }}
servicePort: {{ .Values.filer.port }}
{{- end }}
{{- end }}
---
{{- /* gRPC Ingress (standard Kubernetes Ingress, NOT for Traefik) */}}
{{- if and $filerEnabled .Values.filer.ingresses.grpc.enabled (not (hasPrefix "traefik" (default "" .Values.filer.ingresses.grpc.className))) }}
{{- /* Determine service name based on deployment mode */}}
{{- $serviceName := ternary (include "seaweedfs.componentName" (list . "all-in-one")) (include "seaweedfs.componentName" (list . "filer")) .Values.allInOne.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-{{ include "seaweedfs.fullname" . }}-filer-grpc
namespace: {{ .Release.Namespace }}
annotations:
{{- if and (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) .Values.filer.ingresses.grpc.className }}
kubernetes.io/ingress.class: {{ .Values.filer.ingresses.grpc.className }}
{{- end }}
{{- with .Values.filer.ingresses.grpc.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
{{- with .Values.filer.ingresses.grpc.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) .Values.filer.ingresses.grpc.className }}
ingressClassName: {{ .Values.filer.ingresses.grpc.className | quote }}
{{- end }}
tls:
{{ .Values.filer.ingresses.grpc.tls | default list | toYaml | nindent 6}}
rules:
- {{- if .Values.filer.ingresses.grpc.host }}
host: {{ .Values.filer.ingresses.grpc.host | quote }}
{{- end }}
http:
paths:
- path: {{ .Values.filer.ingresses.grpc.path | quote }}
{{- if semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion }}
pathType: {{ .Values.filer.ingresses.grpc.pathType | quote }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $serviceName }}
port:
number: {{ .Values.filer.grpcPort }}
{{- else }}
serviceName: {{ $serviceName }}
servicePort: {{ .Values.filer.grpcPort }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,38 @@
{{- if .Values.filer.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "seaweedfs.componentName" (list . "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.annotations }}
annotations:
{{- toYaml .Values.filer.annotations | nindent 4 }}
{{- 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/instance: {{ .Release.Name }}
app.kubernetes.io/component: filer
{{- end }}

View File

@@ -0,0 +1,55 @@
{{- if .Values.filer.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "seaweedfs.componentName" (list . "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
{{- if .Values.filer.metricsPort }}
monitoring: "true"
{{- end }}
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
{{- if .Values.filer.annotations }}
{{- toYaml .Values.filer.annotations | nindent 4 }}
{{- end }}
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/instance: {{ .Release.Name }}
app.kubernetes.io/component: filer
{{- end }}

View File

@@ -0,0 +1,36 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.filer.enabled }}
{{- if .Values.filer.metricsPort }}
{{- if .Values.global.seaweedfs.monitoring.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "seaweedfs.fullname" . }}-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.seaweedfs.monitoring.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if .Values.filer.annotations }}
annotations:
{{- toYaml .Values.filer.annotations | nindent 4 }}
{{- end }}
spec:
endpoints:
- interval: 30s
port: metrics
scrapeTimeout: 5s
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: filer
monitoring: "true"
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,472 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.filer.enabled }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "seaweedfs.componentName" (list . "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
{{- if .Values.filer.annotations }}
annotations:
{{- toYaml .Values.filer.annotations | nindent 4 }}
{{- end }}
spec:
serviceName: {{ include "seaweedfs.componentName" (list . "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 }}
{{- $podAnnotations := mergeOverwrite (deepCopy (.Values.podAnnotations | default dict)) (.Values.filer.podAnnotations | default dict) }}
{{- if .Values.filer.s3.existingConfigSecret }}
{{- $configSecret := (lookup "v1" "Secret" .Release.Namespace .Values.filer.s3.existingConfigSecret) | default dict }}
{{- $_ := set $podAnnotations "checksum/s3config" ($configSecret | toYaml | sha256sum) }}
{{- else }}
{{- $_ := set $podAnnotations "checksum/s3config" (include (print .Template.BasePath "/s3/s3-secret.yaml") . | sha256sum) }}
{{- end }}
annotations:
{{- toYaml $podAnnotations | nindent 8 }}
spec:
restartPolicy: {{ default .Values.global.seaweedfs.restartPolicy .Values.filer.restartPolicy }}
{{- if .Values.filer.affinity }}
affinity:
{{ tpl .Values.filer.affinity . | nindent 8 | trim }}
{{- end }}
{{- if .Values.filer.topologySpreadConstraints }}
topologySpreadConstraints:
{{ tpl .Values.filer.topologySpreadConstraints . | 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 (include "seaweedfs.serviceAccountName" .) | quote }} # for deleting statefulset pods after migration
terminationGracePeriodSeconds: 60
{{- if .Values.filer.priorityClassName }}
priorityClassName: {{ .Values.filer.priorityClassName | quote }}
{{- end }}
{{- if .Values.filer.schedulerName }}
schedulerName: {{ .Values.filer.schedulerName | 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 "seaweedfs.filer.image" . }}
imagePullPolicy: {{ default "IfNotPresent" .Values.global.seaweedfs.imagePullPolicy }}
env:
{{- $mysqlEnabled := include "seaweedfs.filer.mysqlEnabled" . }}
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
{{- if $mysqlEnabled }}
- name: WEED_MYSQL_USERNAME
valueFrom:
secretKeyRef:
name: {{ include "seaweedfs.fullname" . }}-db-secret
key: user
optional: true
- name: WEED_MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "seaweedfs.fullname" . }}-db-secret
key: password
optional: true
{{- end }}
- name: SEAWEEDFS_FULLNAME
value: "{{ include "seaweedfs.fullname" . }}"
{{- if and .Values.filer.s3.enabled .Values.filer.s3.enableAuth }}
{{- include "seaweedfs.s3.credentialEnv" . | nindent 12 }}
{{- end }}
{{- $mergedExtraEnvironmentVars := dict }}
{{- include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" .Values.global.seaweedfs "component" .Values.filer "target" $mergedExtraEnvironmentVars) }}
{{- if not $mysqlEnabled }}
{{- range $key := keys $mergedExtraEnvironmentVars }}
{{- if hasPrefix "WEED_MYSQL_" $key }}
{{- $_ := unset $mergedExtraEnvironmentVars $key }}
{{- end }}
{{- end }}
{{- end }}
{{- range $key := keys $mergedExtraEnvironmentVars | sortAlpha }}
{{- $value := index $mergedExtraEnvironmentVars $key }}
- name: {{ $key }}
{{- if kindIs "string" $value }}
value: {{ tpl $value $ | quote }}
{{- else }}
valueFrom:
{{ toYaml $value | nindent 16 | trim }}
{{- end -}}
{{- end }}
{{- if .Values.filer.secretExtraEnvironmentVars }}
{{- range $key, $value := .Values.filer.secretExtraEnvironmentVars }}
{{- if or $mysqlEnabled (not (hasPrefix "WEED_MYSQL_" $key)) }}
- name: {{ $key }}
valueFrom: {{ toYaml $value | nindent 16 }}
{{- end }}
{{- 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.seaweedfs.loggingLevel }} \
{{- end }}
filer \
-port={{ .Values.filer.port }} \
{{- if .Values.filer.metricsPort }}
-metricsPort={{ .Values.filer.metricsPort }} \
{{- end }}
{{- if .Values.filer.metricsIp }}
-metricsIp={{ .Values.filer.metricsIp }} \
{{- 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.seaweedfs.enableReplication }}
-defaultReplicaPlacement={{ .Values.global.seaweedfs.replicationPlacement }} \
{{- 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} \
-ip.bind={{ .Values.filer.ipBind }} \
{{- if .Values.filer.filerGroup}}
-filerGroup={{ .Values.filer.filerGroup}} \
{{- end }}
{{- if .Values.filer.rack }}
-rack={{ .Values.filer.rack }} \
{{- end }}
{{- if .Values.filer.dataCenter }}
-dataCenter={{ .Values.filer.dataCenter }} \
{{- 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.seaweedfs.enableSecurity }}
{{- if .Values.filer.s3.httpsPort }}
-s3.port.https={{ .Values.filer.s3.httpsPort }} \
{{- include "seaweedfs.s3.tlsArgs" (dict "root" . "prefix" "s3.") | nindent 14 }}
{{- end }}
{{- 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={{ include "seaweedfs.masterServerArg" . }} \
{{- range .Values.filer.extraArgs }}
{{ . }} \
{{- 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 and .Values.filer.s3.enabled .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.filer.notificationConfig }}
- name: notification-config
readOnly: true
mountPath: /etc/seaweedfs/notification.toml
subPath: notification.toml
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
readOnly: true
mountPath: /etc/seaweedfs/security.toml
subPath: security.toml
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- 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
{{- if .Values.filer.s3.enabled }}
{{- include "seaweedfs.s3.tlsVolumeMount" . | nindent 12 }}
{{- end }}
{{- 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.s3.enabled }}
- containerPort: {{ .Values.filer.s3.port }}
name: swfs-s3
{{- if .Values.filer.s3.httpsPort }}
- containerPort: {{ .Values.filer.s3.httpsPort }}
name: swfs-s3-tls
{{- end }}
{{- end }}
{{- $jwt := (.Values.global.seaweedfs.securityConfig).jwtSigning | default dict }}
{{- $isJwtEnabled := or $jwt.filerWrite $jwt.filerRead }}
{{- if .Values.filer.readinessProbe.enabled }}
readinessProbe:
{{- if or $isJwtEnabled .Values.filer.readinessProbe.tcpSocket }}
tcpSocket:
port: {{ if $isJwtEnabled }}{{ .Values.filer.port }}{{ else }}{{ .Values.filer.readinessProbe.tcpSocket.port }}{{ end }}
{{- else }}
httpGet:
path: {{ .Values.filer.readinessProbe.httpGet.path }}
port: {{ .Values.filer.port }}
scheme: {{ .Values.filer.readinessProbe.httpGet.scheme }}
{{- end }}
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:
{{- if or $isJwtEnabled .Values.filer.livenessProbe.tcpSocket }}
tcpSocket:
port: {{ if $isJwtEnabled }}{{ .Values.filer.port }}{{ else }}{{ .Values.filer.livenessProbe.tcpSocket.port }}{{ end }}
{{- else }}
httpGet:
path: {{ .Values.filer.livenessProbe.httpGet.path }}
port: {{ .Values.filer.port }}
scheme: {{ .Values.filer.livenessProbe.httpGet.scheme }}
{{- end }}
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 "seaweedfs.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: {{ default (printf "%s-db-init-config" (include "seaweedfs.fullname" .)) .Values.filer.dbInitConfigName }}
optional: true
{{- 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: {{ include "seaweedfs.fullname" . }}-s3-secret
{{- end }}
{{- end }}
{{- if .Values.filer.notificationConfig }}
- name: notification-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-notification-config
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-security-config
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- name: ca-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-ca-cert
- name: master-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-master-cert
- name: volume-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-volume-cert
- name: filer-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-filer-cert
- name: client-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-client-cert
{{- if .Values.filer.s3.enabled }}
{{- include "seaweedfs.s3.tlsVolume" . | nindent 8 }}
{{- end }}
{{- 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) (not .Values.filer.data) }}
# DEPRECATION: Deprecate in favor of filer.data section below
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
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 "seaweedfs.filer.pvc_exists" . -}}
{{- if $pvc_exists }}
volumeClaimTemplates:
{{- if eq .Values.filer.data.type "persistentVolumeClaim" }}
- apiVersion: v1
kind: 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" }}
- apiVersion: v1
kind: 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 }}

View File

@@ -0,0 +1,19 @@
{{- if or .Values.master.enabled .Values.allInOne.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "seaweedfs.fullname" . }}-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 }}
{{- if .Values.master.annotations }}
annotations:
{{- toYaml .Values.master.annotations | nindent 4 }}
{{- end }}
data:
master.toml: |-
{{ .Values.master.config | nindent 4 }}
{{- end }}

View File

@@ -0,0 +1,51 @@
{{- 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-{{ include "seaweedfs.fullname" . }}-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
{{- with .Values.master.ingress.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.master.ingress.className | quote }}
tls:
{{ .Values.master.ingress.tls | default list | toYaml | nindent 6 }}
rules:
- http:
paths:
- path: {{ .Values.master.ingress.path | quote }}
pathType: {{ .Values.master.ingress.pathType | quote }}
backend:
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
service:
name: {{ include "seaweedfs.componentName" (list . "master") }}
port:
number: {{ .Values.master.port }}
#name:
{{- else }}
serviceName: {{ include "seaweedfs.componentName" (list . "master") }}
servicePort: {{ .Values.master.port }}
{{- end }}
{{- if .Values.master.ingress.host }}
host: {{ .Values.master.ingress.host }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,40 @@
{{- if .Values.master.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "seaweedfs.componentName" (list . "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 }}
app.kubernetes.io/instance: {{ .Release.Name }}
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
{{- if .Values.master.annotations }}
{{- toYaml .Values.master.annotations | nindent 4 }}
{{- end }}
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/instance: {{ .Release.Name }}
app.kubernetes.io/component: master
{{- end }}

View File

@@ -0,0 +1,35 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.master.enabled }}
{{- if .Values.master.metricsPort }}
{{- if .Values.global.seaweedfs.monitoring.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "seaweedfs.fullname" . }}-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.seaweedfs.monitoring.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if .Values.master.annotations }}
annotations:
{{- toYaml .Values.master.annotations | nindent 4 }}
{{- end }}
spec:
endpoints:
- interval: 30s
port: metrics
scrapeTimeout: 5s
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: master
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,358 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.master.enabled }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "seaweedfs.componentName" (list . "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
{{- if .Values.master.annotations }}
annotations:
{{- toYaml .Values.master.annotations | nindent 4 }}
{{- end }}
spec:
serviceName: {{ include "seaweedfs.componentName" (list . "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 }}
{{- $podAnnotations := mergeOverwrite (deepCopy (.Values.podAnnotations | default dict)) (.Values.master.podAnnotations | default dict) }}
{{- $_ := set $podAnnotations "checksum/master-config" (include (print .Template.BasePath "/master/master-configmap.yaml") . | sha256sum) }}
annotations:
{{- toYaml $podAnnotations | nindent 8 }}
spec:
restartPolicy: {{ default .Values.global.seaweedfs.restartPolicy .Values.master.restartPolicy }}
{{- if .Values.master.affinity }}
affinity:
{{ tpl .Values.master.affinity . | nindent 8 | trim }}
{{- end }}
{{- if .Values.master.topologySpreadConstraints }}
topologySpreadConstraints:
{{ tpl .Values.master.topologySpreadConstraints . | 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 }}
{{- if .Values.master.schedulerName }}
schedulerName: {{ .Values.master.schedulerName | quote }}
{{- end }}
enableServiceLinks: false
serviceAccountName: {{ .Values.master.serviceAccountName | default (include "seaweedfs.serviceAccountName" .) | quote }} # for deleting statefulset pods after migration
{{- 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 "seaweedfs.master.image" . }}
imagePullPolicy: {{ default "IfNotPresent" .Values.global.seaweedfs.imagePullPolicy }}
env:
{{- include "seaweedfs.licenseEnv" . | nindent 12 }}
- 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: "{{ include "seaweedfs.fullname" . }}"
{{- $mergedExtraEnvironmentVars := dict }}
{{- include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" .Values.global.seaweedfs "component" .Values.master "target" $mergedExtraEnvironmentVars) }}
{{- range $key := keys $mergedExtraEnvironmentVars | sortAlpha }}
{{- $value := index $mergedExtraEnvironmentVars $key }}
- name: {{ $key }}
{{- if kindIs "string" $value }}
value: {{ tpl $value $ | quote }}
{{- else }}
valueFrom:
{{ toYaml $value | nindent 16 | trim }}
{{- 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.seaweedfs.loggingLevel }} \
{{- end }}
master \
-port={{ .Values.master.port }} \
-mdir=/data \
-ip.bind={{ .Values.master.ipBind }} \
{{- if .Values.global.seaweedfs.enableReplication }}
-defaultReplication={{ .Values.global.seaweedfs.replicationPlacement }} \
{{- else }}
-defaultReplication={{ .Values.master.defaultReplication }} \
{{- end }}
{{- if .Values.master.volumePreallocate }}
-volumePreallocate \
{{- end }}
{{- if .Values.global.seaweedfs.monitoring.enabled }}
{{- if and .Values.global.seaweedfs.monitoring.gatewayHost .Values.global.seaweedfs.monitoring.gatewayPort }}
-metrics.address="{{ .Values.global.seaweedfs.monitoring.gatewayHost }}:{{ .Values.global.seaweedfs.monitoring.gatewayPort }}" \
{{- if .Values.master.metricsIntervalSec }}
-metrics.intervalSeconds={{ .Values.master.metricsIntervalSec }} \
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.master.metricsPort }}
-metricsPort={{ .Values.master.metricsPort }} \
{{- end }}
{{- if .Values.master.metricsIp }}
-metricsIp={{ .Values.master.metricsIp }} \
{{- end }}
-volumeSizeLimitMB={{ .Values.master.volumeSizeLimitMB }} \
{{- if .Values.master.disableHttp }}
-disableHttp \
{{- end }}
{{- if .Values.master.resumeState }}
-resumeState \
{{- end }}
{{- if .Values.master.raftHashicorp }}
-raftHashicorp \
{{- end }}
{{- if .Values.master.raftBootstrap }}
-raftBootstrap \
{{- end }}
{{- if .Values.master.electionTimeout }}
-electionTimeout={{ .Values.master.electionTimeout }} \
{{- end }}
{{- if .Values.master.heartbeatInterval }}
-heartbeatInterval={{ .Values.master.heartbeatInterval }} \
{{- end }}
{{- if .Values.master.garbageThreshold }}
-garbageThreshold={{ .Values.master.garbageThreshold }} \
{{- end }}
-ip=${POD_NAME}.{{ include "seaweedfs.componentName" (list . "master") }}.{{ .Release.Namespace }} \
-peers={{ include "seaweedfs.masterServers" . }} \
{{- range .Values.master.extraArgs }}
{{ . }} \
{{- 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 include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
readOnly: true
mountPath: /etc/seaweedfs/security.toml
subPath: security.toml
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- 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 }}
{{- include "seaweedfs.licenseVolumeMount" . | nindent 12 }}
{{ tpl .Values.master.extraVolumeMounts . | nindent 12 | trim }}
ports:
- containerPort: {{ .Values.master.port }}
name: swfs-master
{{- if and .Values.global.seaweedfs.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.httpGet.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.httpGet.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 "seaweedfs.tplvalues.render" (dict "value" .Values.master.sidecars "context" $) | nindent 8 }}
{{- end }}
volumes:
{{- include "seaweedfs.licenseVolume" . | nindent 8 }}
{{- 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: {{ include "seaweedfs.fullname" . }}-master-config
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-security-config
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- name: ca-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-ca-cert
- name: master-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-master-cert
- name: volume-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-volume-cert
- name: filer-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-filer-cert
- name: client-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-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 "seaweedfs.master.pvc_exists" . -}}
{{- if $pvc_exists }}
volumeClaimTemplates:
{{- if eq .Values.master.data.type "persistentVolumeClaim"}}
- apiVersion: v1
kind: 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"}}
- apiVersion: v1
kind: 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 }}

View File

@@ -0,0 +1,296 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.s3.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "seaweedfs.fullname" . }}-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
{{- if .Values.s3.annotations }}
annotations:
{{- toYaml .Values.s3.annotations | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.s3.replicas }}
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
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 }}
{{- $podAnnotations := mergeOverwrite (deepCopy (.Values.podAnnotations | default dict)) (.Values.s3.podAnnotations | default dict) }}
{{- if .Values.s3.existingConfigSecret }}
{{- $configSecret := (lookup "v1" "Secret" .Release.Namespace .Values.s3.existingConfigSecret) | default dict }}
{{- $_ := set $podAnnotations "checksum/s3config" ($configSecret | toYaml | sha256sum) }}
{{- else }}
{{- $_ := set $podAnnotations "checksum/s3config" (include (print .Template.BasePath "/s3/s3-secret.yaml") . | sha256sum) }}
{{- end }}
annotations:
{{- toYaml $podAnnotations | nindent 8 }}
spec:
restartPolicy: {{ default .Values.global.seaweedfs.restartPolicy .Values.s3.restartPolicy }}
{{- if .Values.s3.affinity }}
affinity:
{{ tpl .Values.s3.affinity . | nindent 8 | trim }}
{{- end }}
{{- if .Values.s3.topologySpreadConstraints }}
topologySpreadConstraints:
{{ tpl .Values.s3.topologySpreadConstraints . | nindent 8 | trim }}
{{- end }}
{{- 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 }}
{{- if .Values.s3.schedulerName }}
schedulerName: {{ .Values.s3.schedulerName | 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 "seaweedfs.s3.image" . }}
imagePullPolicy: {{ default "IfNotPresent" .Values.global.seaweedfs.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: "{{ include "seaweedfs.fullname" . }}"
{{- if .Values.s3.enableAuth }}
{{- include "seaweedfs.s3.credentialEnv" . | nindent 12 }}
{{- end }}
{{- $mergedExtraEnvironmentVars := dict }}
{{- include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" .Values.global.seaweedfs "component" .Values.s3 "target" $mergedExtraEnvironmentVars) }}
{{- range $key := keys $mergedExtraEnvironmentVars | sortAlpha }}
{{- $value := index $mergedExtraEnvironmentVars $key }}
- name: {{ $key }}
{{- if kindIs "string" $value }}
value: {{ tpl $value $ | quote }}
{{- else }}
valueFrom:
{{ toYaml $value | nindent 16 | trim }}
{{- 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.seaweedfs.loggingLevel }} \
{{- end }}
s3 \
-ip.bind={{ .Values.s3.bindAddress }} \
-port={{ .Values.s3.port }} \
{{- if .Values.s3.metricsPort }}
-metricsPort {{ .Values.s3.metricsPort }} \
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
{{- if .Values.s3.httpsPort }}
-port.https={{ .Values.s3.httpsPort }} \
{{- include "seaweedfs.s3.tlsArgs" (dict "root" . "prefix" "") | nindent 14 }}
{{- end }}
{{- end }}
{{- if .Values.s3.domainName }}
-domainName={{ .Values.s3.domainName }} \
{{- end }}
{{- if .Values.s3.enableAuth }}
-config=/etc/sw/seaweedfs_s3_config \
{{- end }}
{{- if .Values.s3.auditLogConfig }}
-auditLogConfig=/etc/sw/s3_auditLogConfig.json \
{{- end }}
-filer={{ include "seaweedfs.componentName" (list . "filer-client") }}.{{ .Release.Namespace }}:{{ .Values.filer.port }} \
{{- if .Values.s3.icebergPort }}
-port.iceberg={{ .Values.s3.icebergPort }} \
{{- end }}
{{- /* rendered even when 0: an if would drop the flag and weed would serve its default */}}
-port.lance={{ .Values.s3.lancePort | default 0 }} \
{{- range .Values.s3.extraArgs }}
{{ . }} \
{{- end }}
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 include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
readOnly: true
mountPath: /etc/seaweedfs/security.toml
subPath: security.toml
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- 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/
{{- include "seaweedfs.s3.tlsVolumeMount" . | nindent 12 }}
{{- end }}
{{ tpl .Values.s3.extraVolumeMounts . | nindent 12 | trim }}
ports:
- containerPort: {{ .Values.s3.port }}
name: swfs-s3
{{- if .Values.s3.httpsPort }}
- containerPort: {{ .Values.s3.httpsPort }}
name: swfs-s3-tls
{{- end }}
{{- if .Values.s3.icebergPort }}
- containerPort: {{ .Values.s3.icebergPort }}
name: swfs-iceberg
{{- end }}
{{- if .Values.s3.lancePort }}
- containerPort: {{ .Values.s3.lancePort }}
name: swfs-lance
{{- end }}
{{- 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.httpGet.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.httpGet.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 "seaweedfs.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: {{ include "seaweedfs.fullname" . }}-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 include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-security-config
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- name: ca-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-ca-cert
- name: master-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-master-cert
- name: volume-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-volume-cert
- name: filer-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-filer-cert
- name: client-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-client-cert
{{- include "seaweedfs.s3.tlsVolume" . | nindent 8 }}
{{- end }}
{{ tpl .Values.s3.extraVolumes . | indent 8 | trim }}
{{- if .Values.s3.nodeSelector }}
nodeSelector:
{{ tpl .Values.s3.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,64 @@
{{- define "seaweedfs.s3.iceberg.ingress.paths" -}}
paths:
- path: {{ .Values.s3.icebergIngress.path | quote }}
pathType: {{ .Values.s3.icebergIngress.pathType | quote }}
backend:
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
service:
name: {{ include "seaweedfs.componentName" (list . "s3") }}
port:
number: {{ .Values.s3.icebergPort }}
{{- else }}
serviceName: {{ include "seaweedfs.componentName" (list . "s3") }}
servicePort: {{ .Values.s3.icebergPort }}
{{- end }}
{{- end -}}
{{- if and .Values.s3.enabled .Values.s3.icebergPort .Values.s3.icebergIngress.enabled }}
{{- $hosts := list }}
{{- if kindIs "slice" .Values.s3.icebergIngress.host }}
{{- $hosts = .Values.s3.icebergIngress.host }}
{{- else if .Values.s3.icebergIngress.host }}
{{- $hosts = list .Values.s3.icebergIngress.host }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1beta1
{{- else }}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: ingress-{{ include "seaweedfs.fullname" . }}-s3-iceberg
namespace: {{ .Release.Namespace }}
{{- with .Values.s3.icebergIngress.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-iceberg
{{- with .Values.s3.icebergIngress.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.s3.icebergIngress.className }}
ingressClassName: {{ .Values.s3.icebergIngress.className | quote }}
{{- end }}
tls:
{{ .Values.s3.icebergIngress.tls | default list | toYaml | nindent 6}}
rules:
{{- if $hosts }}
{{- range $host := $hosts }}
- host: {{ $host | quote }}
http:
{{- include "seaweedfs.s3.iceberg.ingress.paths" $ | nindent 6 }}
{{- end }}
{{- else }}
- http:
{{- include "seaweedfs.s3.iceberg.ingress.paths" . | nindent 4 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,77 @@
{{- /* S3 ingress works for standalone S3 gateway (s3.enabled), S3 on Filer (filer.s3.enabled), and all-in-one mode (allInOne.s3.enabled) */}}
{{- $s3Enabled := or .Values.s3.enabled (and .Values.filer.s3.enabled (not .Values.allInOne.enabled)) (and .Values.allInOne.enabled .Values.allInOne.s3.enabled) }}
{{- if and $s3Enabled .Values.s3.ingress.enabled }}
{{- /* Determine service name based on deployment mode */}}
{{- $serviceName := ternary (include "seaweedfs.componentName" (list . "all-in-one")) (include "seaweedfs.componentName" (list . "s3")) .Values.allInOne.enabled }}
{{- $s3Port := .Values.allInOne.s3.port | default .Values.s3.port }}
{{- /* Build hosts list - support both legacy .host (string) and new .hosts (array) for backwards compatibility */}}
{{- $hosts := list }}
{{- if kindIs "slice" .Values.s3.ingress.host }}
{{- $hosts = .Values.s3.ingress.host }}
{{- else if .Values.s3.ingress.host }}
{{- $hosts = list .Values.s3.ingress.host }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1beta1
{{- else }}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: ingress-{{ include "seaweedfs.fullname" . }}-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
{{- with .Values.s3.ingress.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.s3.ingress.className | quote }}
tls:
{{ .Values.s3.ingress.tls | default list | toYaml | nindent 6}}
rules:
{{- if $hosts }}
{{- range $hosts }}
- host: {{ . | quote }}
http:
paths:
- path: {{ $.Values.s3.ingress.path | quote }}
pathType: {{ $.Values.s3.ingress.pathType | quote }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $serviceName }}
port:
number: {{ $s3Port }}
{{- else }}
serviceName: {{ $serviceName }}
servicePort: {{ $s3Port }}
{{- end }}
{{- end }}
{{- else }}
- http:
paths:
- path: {{ .Values.s3.ingress.path | quote }}
pathType: {{ .Values.s3.ingress.pathType | quote }}
backend:
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $serviceName }}
port:
number: {{ $s3Port }}
{{- else }}
serviceName: {{ $serviceName }}
servicePort: {{ $s3Port }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,64 @@
{{- define "seaweedfs.s3.lance.ingress.paths" -}}
paths:
- path: {{ .Values.s3.lanceIngress.path | quote }}
pathType: {{ .Values.s3.lanceIngress.pathType | quote }}
backend:
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
service:
name: {{ include "seaweedfs.componentName" (list . "s3") }}
port:
number: {{ .Values.s3.lancePort }}
{{- else }}
serviceName: {{ include "seaweedfs.componentName" (list . "s3") }}
servicePort: {{ .Values.s3.lancePort }}
{{- end }}
{{- end -}}
{{- if and .Values.s3.enabled .Values.s3.lancePort .Values.s3.lanceIngress.enabled }}
{{- $hosts := list }}
{{- if kindIs "slice" .Values.s3.lanceIngress.host }}
{{- $hosts = .Values.s3.lanceIngress.host }}
{{- else if .Values.s3.lanceIngress.host }}
{{- $hosts = list .Values.s3.lanceIngress.host }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion }}
apiVersion: networking.k8s.io/v1beta1
{{- else }}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: ingress-{{ include "seaweedfs.fullname" . }}-s3-lance
namespace: {{ .Release.Namespace }}
{{- with .Values.s3.lanceIngress.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-lance
{{- with .Values.s3.lanceIngress.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.s3.lanceIngress.className }}
ingressClassName: {{ .Values.s3.lanceIngress.className | quote }}
{{- end }}
tls:
{{ .Values.s3.lanceIngress.tls | default list | toYaml | nindent 6}}
rules:
{{- if $hosts }}
{{- range $host := $hosts }}
- host: {{ $host | quote }}
http:
{{- include "seaweedfs.s3.lance.ingress.paths" $ | nindent 6 }}
{{- end }}
{{- else }}
- http:
{{- include "seaweedfs.s3.lance.ingress.paths" . | nindent 4 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,72 @@
{{- /* Mirrors the condition the all-in-one deployment mounts this secret under,
so the flags that make it mount are exactly the flags that create it. */}}
{{- $allInOneAuth := and .Values.allInOne.enabled .Values.allInOne.s3.enabled (or .Values.allInOne.s3.enableAuth .Values.s3.enableAuth .Values.filer.s3.enableAuth) (not (or .Values.allInOne.s3.existingConfigSecret .Values.s3.existingConfigSecret .Values.filer.s3.existingConfigSecret)) }}
{{- if or (and (or .Values.s3.enabled .Values.allInOne.enabled) .Values.s3.enableAuth (not .Values.s3.existingConfigSecret)) (and .Values.filer.s3.enabled .Values.filer.s3.enableAuth (not .Values.filer.s3.existingConfigSecret)) $allInOneAuth }}
{{- $secretName := printf "%s-s3-secret" (include "seaweedfs.fullname" .) }}
{{- $legacySecretName := "seaweedfs-s3-secret" }}
{{- $lookupName := $secretName }}
{{- if .Values.s3.reuseLegacySecret }}
{{- $lookupName = default $legacySecretName .Values.s3.legacySecretName }}
{{- end }}
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace $lookupName }}
{{- $reuse := false }}
{{- if and .Values.s3.reuseLegacySecret $existingSecret }}
{{- $reuse = true }}
{{- end }}
{{- $creds := .Values.s3.credentials | default dict -}}
{{- $adminCreds := $creds.admin | default dict -}}
{{- $access_key_admin := $adminCreds.accessKey -}}
{{- $secret_key_admin := $adminCreds.secretKey -}}
{{- if $adminCreds.existingSecret -}}
{{- $access_key_admin = printf "${%s}" (include "seaweedfs.s3.credentialEnvName" (list "admin" "accessKey")) -}}
{{- $secret_key_admin = printf "${%s}" (include "seaweedfs.s3.credentialEnvName" (list "admin" "secretKey")) -}}
{{- else if not (and $access_key_admin $secret_key_admin) -}}
{{- $access_key_admin = include "seaweedfs.getOrGeneratePassword" (dict "namespace" .Release.Namespace "secretName" $secretName "key" "admin_access_key_id" "length" 20 "existingSecret" (ternary $existingSecret nil $reuse)) -}}
{{- $secret_key_admin = include "seaweedfs.getOrGeneratePassword" (dict "namespace" .Release.Namespace "secretName" $secretName "key" "admin_secret_access_key" "length" 40 "existingSecret" (ternary $existingSecret nil $reuse)) -}}
{{- end -}}
{{- $readCreds := $creds.read | default dict -}}
{{- $access_key_read := $readCreds.accessKey -}}
{{- $secret_key_read := $readCreds.secretKey -}}
{{- if $readCreds.existingSecret -}}
{{- $access_key_read = printf "${%s}" (include "seaweedfs.s3.credentialEnvName" (list "read" "accessKey")) -}}
{{- $secret_key_read = printf "${%s}" (include "seaweedfs.s3.credentialEnvName" (list "read" "secretKey")) -}}
{{- else if not (and $access_key_read $secret_key_read) -}}
{{- $access_key_read = include "seaweedfs.getOrGeneratePassword" (dict "namespace" .Release.Namespace "secretName" $secretName "key" "read_access_key_id" "length" 20 "existingSecret" (ternary $existingSecret nil $reuse)) -}}
{{- $secret_key_read = include "seaweedfs.getOrGeneratePassword" (dict "namespace" .Release.Namespace "secretName" $secretName "key" "read_secret_access_key" "length" 40 "existingSecret" (ternary $existingSecret nil $reuse)) -}}
{{- end -}}
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ $secretName }}
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/resource-policy": keep
"helm.sh/hook": "pre-install,pre-upgrade"
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:
{{- /* An identity read from an existing Secret keeps its keys there; the
config below names the environment variables carrying them. */}}
{{- if not $adminCreds.existingSecret }}
admin_access_key_id: {{ $access_key_admin }}
admin_secret_access_key: {{ $secret_key_admin }}
{{- end }}
{{- if not $readCreds.existingSecret }}
read_access_key_id: {{ $access_key_read }}
read_secret_access_key: {{ $secret_key_read }}
{{- end }}
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","List"]}]}'
{{- 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 }}

View File

@@ -0,0 +1,78 @@
{{- if or .Values.s3.enabled .Values.filer.s3.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "seaweedfs.componentName" (list . "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 }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- if .Values.s3.annotations }}
annotations:
{{- toYaml .Values.s3.annotations | nindent 4 }}
{{- end }}
spec:
{{- $serviceType := .Values.s3.service.type }}
{{- $nodePorts := dict }}
{{- if or (eq $serviceType "NodePort") (eq $serviceType "LoadBalancer") }}
{{- $nodePorts = .Values.s3.service.nodePorts | default dict }}
{{- end }}
type: {{ $serviceType }}
{{- include "seaweedfs.service.loadBalancerFields" .Values.s3.service }}
internalTrafficPolicy: {{ .Values.s3.internalTrafficPolicy | default "Cluster" }}
{{- $td := .Values.s3.trafficDistribution | default .Values.filer.s3.trafficDistribution }}
{{- if and (semverCompare ">=1.31-0" .Capabilities.KubeVersion.GitVersion) $td }}
trafficDistribution: {{ include "seaweedfs.trafficDistribution" (dict "value" $td "Capabilities" .Capabilities) }}
{{- end }}
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 }}
{{- if $nodePorts.http }}
nodePort: {{ $nodePorts.http }}
{{- end }}
protocol: TCP
{{- if and .Values.s3.enabled .Values.s3.icebergPort }}
- name: "swfs-iceberg"
port: {{ .Values.s3.icebergPort }}
targetPort: {{ .Values.s3.icebergPort }}
{{- if $nodePorts.iceberg }}
nodePort: {{ $nodePorts.iceberg }}
{{- end }}
protocol: TCP
{{- end }}
{{- if and .Values.s3.enabled .Values.s3.lancePort }}
- name: "swfs-lance"
port: {{ .Values.s3.lancePort }}
targetPort: {{ .Values.s3.lancePort }}
{{- if $nodePorts.lance }}
nodePort: {{ $nodePorts.lance }}
{{- end }}
protocol: TCP
{{- end }}
{{- if and .Values.s3.enabled .Values.s3.httpsPort }}
- name: "swfs-s3-tls"
port: {{ .Values.s3.httpsPort }}
targetPort: {{ .Values.s3.httpsPort }}
{{- if $nodePorts.https }}
nodePort: {{ $nodePorts.https }}
{{- end }}
protocol: TCP
{{- end }}
{{- if and .Values.s3.enabled .Values.s3.metricsPort }}
- name: "metrics"
port: {{ .Values.s3.metricsPort }}
targetPort: {{ .Values.s3.metricsPort }}
{{- if $nodePorts.metrics }}
nodePort: {{ $nodePorts.metrics }}
{{- end }}
protocol: TCP
{{- end }}
selector:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: {{ if .Values.s3.enabled }}s3{{ else }}filer{{ end }}
{{- end }}

View File

@@ -0,0 +1,36 @@
{{- include "seaweedfs.compat" . -}}
{{- /*
The seaweedfs-s3 Service only gains a "metrics" port when the standalone S3
gateway is enabled. With only the embedded filer S3 gateway, metrics live on
the filer process and are already scraped by the filer ServiceMonitor.
*/ -}}
{{- if and .Values.s3.enabled .Values.s3.metricsPort .Values.global.seaweedfs.monitoring.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "seaweedfs.fullname" . }}-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.seaweedfs.monitoring.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if .Values.s3.annotations }}
annotations:
{{- toYaml .Values.s3.annotations | nindent 4 }}
{{- end }}
spec:
endpoints:
- interval: 30s
port: metrics
scrapeTimeout: 5s
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: s3
{{- end }}

View File

@@ -0,0 +1,40 @@
{{- include "seaweedfs.compat" . -}}
{{- /*
Render a chart-managed Secret carrying the SSH user CA public key(s) for
certificate-based SFTP authentication, but only when:
- SFTP (standalone or all-in-one) is enabled,
- "certificate" is in the relevant authMethods list,
- the user provided inline CA keys via sftp.trustedUserCAKeys, and
- no existingCAKeysSecret is set (which would supersede this Secret).
*/}}
{{- $sftpEnabled := or .Values.sftp.enabled (and .Values.allInOne.enabled .Values.allInOne.sftp.enabled) -}}
{{- $authMethods := .Values.sftp.authMethods -}}
{{- if and .Values.allInOne.enabled .Values.allInOne.sftp.authMethods -}}
{{- $authMethods = .Values.allInOne.sftp.authMethods -}}
{{- end -}}
{{- $certInMethods := and $authMethods (contains "certificate" $authMethods) -}}
{{- $inlineCAKeys := .Values.sftp.trustedUserCAKeys -}}
{{- if and .Values.allInOne.enabled .Values.allInOne.sftp.trustedUserCAKeys -}}
{{- $inlineCAKeys = .Values.allInOne.sftp.trustedUserCAKeys -}}
{{- end -}}
{{- $existingSecret := .Values.sftp.existingCAKeysSecret -}}
{{- if and .Values.allInOne.enabled .Values.allInOne.sftp.existingCAKeysSecret -}}
{{- $existingSecret = .Values.allInOne.sftp.existingCAKeysSecret -}}
{{- end -}}
{{- if and $sftpEnabled $certInMethods $inlineCAKeys (not $existingSecret) }}
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ include "seaweedfs.fullname" . }}-sftp-ca-secret
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: sftp
stringData:
ca_user.pub: |
{{ $inlineCAKeys | indent 4 }}
{{- end }}

View File

@@ -0,0 +1,320 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.sftp.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "seaweedfs.fullname" . }}-sftp
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: sftp
{{- if .Values.sftp.annotations }}
annotations:
{{- toYaml .Values.sftp.annotations | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.sftp.replicas }}
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: sftp
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: sftp
{{ with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.sftp.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
annotations:
{{ with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.sftp.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
restartPolicy: {{ default .Values.global.seaweedfs.restartPolicy .Values.sftp.restartPolicy }}
{{- if .Values.sftp.affinity }}
affinity:
{{ tpl .Values.sftp.affinity . | nindent 8 | trim }}
{{- end }}
{{- if .Values.sftp.topologySpreadConstraints }}
topologySpreadConstraints:
{{ tpl .Values.sftp.topologySpreadConstraints . | nindent 8 | trim }}
{{- end }}
{{- if .Values.sftp.tolerations }}
tolerations:
{{ tpl .Values.sftp.tolerations . | nindent 8 | trim }}
{{- end }}
{{- include "seaweedfs.imagePullSecrets" . | nindent 6 }}
terminationGracePeriodSeconds: 10
{{- if .Values.sftp.priorityClassName }}
priorityClassName: {{ .Values.sftp.priorityClassName | quote }}
{{- end }}
{{- if .Values.sftp.schedulerName }}
schedulerName: {{ .Values.sftp.schedulerName | quote }}
{{- end }}
enableServiceLinks: false
{{- if .Values.sftp.serviceAccountName }}
serviceAccountName: {{ .Values.sftp.serviceAccountName | quote }}
{{- end }}
{{- if .Values.sftp.initContainers }}
initContainers:
{{ tpl .Values.sftp.initContainers . | nindent 8 | trim }}
{{- end }}
{{- if .Values.sftp.podSecurityContext.enabled }}
securityContext: {{- omit .Values.sftp.podSecurityContext "enabled" | toYaml | nindent 8 }}
{{- end }}
containers:
- name: seaweedfs
image: {{ template "seaweedfs.sftp.image" . }}
imagePullPolicy: {{ default "IfNotPresent" .Values.global.seaweedfs.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: "{{ include "seaweedfs.fullname" . }}"
{{- $mergedExtraEnvironmentVars := dict }}
{{- include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" .Values.global.seaweedfs "component" .Values.sftp "target" $mergedExtraEnvironmentVars) }}
{{- range $key := keys $mergedExtraEnvironmentVars | sortAlpha }}
{{- $value := index $mergedExtraEnvironmentVars $key }}
- name: {{ $key }}
{{- if kindIs "string" $value }}
value: {{ tpl $value $ | quote }}
{{- else }}
valueFrom:
{{ toYaml $value | nindent 16 | trim }}
{{- end -}}
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
exec /usr/bin/weed \
{{- if or (eq .Values.sftp.logs.type "hostPath") (eq .Values.sftp.logs.type "emptyDir") }}
-logdir=/logs \
{{- else }}
-logtostderr=true \
{{- end }}
{{- if .Values.sftp.loggingOverrideLevel }}
-v={{ .Values.sftp.loggingOverrideLevel }} \
{{- else }}
-v={{ .Values.global.seaweedfs.loggingLevel }} \
{{- end }}
sftp \
-ip.bind={{ .Values.sftp.bindAddress }} \
-port={{ .Values.sftp.port }} \
{{- if .Values.sftp.metricsPort }}
-metricsPort={{ .Values.sftp.metricsPort }} \
{{- end }}
{{- if .Values.sftp.metricsIp }}
-metricsIp={{ .Values.sftp.metricsIp }} \
{{- end }}
{{- if .Values.sftp.sshPrivateKey }}
-sshPrivateKey={{ .Values.sftp.sshPrivateKey }} \
{{- end }}
{{- if .Values.sftp.hostKeysFolder }}
-hostKeysFolder={{ .Values.sftp.hostKeysFolder }} \
{{- end }}
{{- if .Values.sftp.authMethods }}
-authMethods={{ .Values.sftp.authMethods }} \
{{- if contains "certificate" .Values.sftp.authMethods }}
-trustedUserCAKeysFile=/etc/sw/sftp_ca/ca_user.pub \
{{- end }}
{{- end }}
{{- if .Values.sftp.maxAuthTries }}
-maxAuthTries={{ .Values.sftp.maxAuthTries }} \
{{- end }}
{{- if .Values.sftp.bannerMessage }}
-bannerMessage="{{ .Values.sftp.bannerMessage }}" \
{{- end }}
{{- if .Values.sftp.loginGraceTime }}
-loginGraceTime={{ .Values.sftp.loginGraceTime }} \
{{- end }}
{{- if .Values.sftp.clientAliveInterval }}
-clientAliveInterval={{ .Values.sftp.clientAliveInterval }} \
{{- end }}
{{- if .Values.sftp.clientAliveCountMax }}
-clientAliveCountMax={{ .Values.sftp.clientAliveCountMax }} \
{{- end }}
{{- if .Values.sftp.dataCenter }}
-dataCenter={{ .Values.sftp.dataCenter }} \
{{- end }}
{{- if .Values.sftp.localSocket }}
-localSocket={{ .Values.sftp.localSocket }} \
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
-cert.file=/usr/local/share/ca-certificates/client/tls.crt \
-key.file=/usr/local/share/ca-certificates/client/tls.key \
{{- end }}
-userStoreFile=/etc/sw/seaweedfs_sftp_config \
-filer={{ include "seaweedfs.componentName" (list . "filer-client") }}.{{ .Release.Namespace }}:{{ .Values.filer.port }}
volumeMounts:
{{- if or (eq .Values.sftp.logs.type "hostPath") (eq .Values.sftp.logs.type "emptyDir") }}
- name: logs
mountPath: "/logs/"
{{- end }}
{{- if .Values.sftp.enableAuth }}
- mountPath: /etc/sw
name: config-users
readOnly: true
{{- end }}
- mountPath: {{ .Values.sftp.hostKeysFolder | default "/etc/sw/ssh" }}
name: config-ssh
readOnly: true
{{- if and .Values.sftp.authMethods (contains "certificate" .Values.sftp.authMethods) }}
- mountPath: /etc/sw/sftp_ca
name: config-sftp-ca
readOnly: true
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
readOnly: true
mountPath: /etc/seaweedfs/security.toml
subPath: security.toml
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- 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.sftp.extraVolumeMounts . | nindent 12 | trim }}
ports:
- containerPort: {{ .Values.sftp.port }}
name: swfs-sftp
{{- if .Values.sftp.metricsPort }}
- containerPort: {{ .Values.sftp.metricsPort }}
name: metrics
{{- end }}
{{- if .Values.sftp.readinessProbe.enabled }}
readinessProbe:
tcpSocket:
port: {{ .Values.sftp.port }}
initialDelaySeconds: {{ .Values.sftp.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.sftp.readinessProbe.periodSeconds }}
successThreshold: {{ .Values.sftp.readinessProbe.successThreshold }}
failureThreshold: {{ .Values.sftp.readinessProbe.failureThreshold }}
timeoutSeconds: {{ .Values.sftp.readinessProbe.timeoutSeconds }}
{{- end }}
{{- if .Values.sftp.livenessProbe.enabled }}
livenessProbe:
tcpSocket:
port: {{ .Values.sftp.port }}
initialDelaySeconds: {{ .Values.sftp.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.sftp.livenessProbe.periodSeconds }}
successThreshold: {{ .Values.sftp.livenessProbe.successThreshold }}
failureThreshold: {{ .Values.sftp.livenessProbe.failureThreshold }}
timeoutSeconds: {{ .Values.sftp.livenessProbe.timeoutSeconds }}
{{- end }}
{{- with .Values.sftp.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.sftp.containerSecurityContext.enabled }}
securityContext: {{- omit .Values.sftp.containerSecurityContext "enabled" | toYaml | nindent 12 }}
{{- end }}
{{- if .Values.sftp.sidecars }}
{{- include "seaweedfs.tplvalues.render" (dict "value" .Values.sftp.sidecars "context" $) | nindent 8 }}
{{- end }}
volumes:
{{- if .Values.sftp.enableAuth }}
- name: config-users
secret:
defaultMode: 420
{{- if .Values.sftp.existingConfigSecret }}
secretName: {{ .Values.sftp.existingConfigSecret }}
{{- else }}
secretName: {{ include "seaweedfs.fullname" . }}-sftp-secret
{{- end }}
{{- end }}
- name: config-ssh
secret:
defaultMode: 420
{{- if .Values.sftp.existingSshConfigSecret }}
secretName: {{ .Values.sftp.existingSshConfigSecret }}
{{- else }}
secretName: {{ include "seaweedfs.fullname" . }}-sftp-ssh-secret
{{- end }}
{{- if and .Values.sftp.authMethods (contains "certificate" .Values.sftp.authMethods) }}
{{- if and (not .Values.sftp.existingCAKeysSecret) (not .Values.sftp.trustedUserCAKeys) }}
{{- fail "sftp.authMethods includes \"certificate\" but neither sftp.trustedUserCAKeys nor sftp.existingCAKeysSecret is set" }}
{{- end }}
- name: config-sftp-ca
secret:
defaultMode: 420
{{- if .Values.sftp.existingCAKeysSecret }}
secretName: {{ .Values.sftp.existingCAKeysSecret }}
{{- else }}
secretName: {{ include "seaweedfs.fullname" . }}-sftp-ca-secret
{{- end }}
{{- end }}
{{- if eq .Values.sftp.logs.type "hostPath" }}
- name: logs
hostPath:
path: {{ .Values.sftp.logs.hostPathPrefix }}/logs/seaweedfs/sftp
type: DirectoryOrCreate
{{- end }}
{{- if eq .Values.sftp.logs.type "emptyDir" }}
- name: logs
emptyDir: {}
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-security-config
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- name: ca-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-ca-cert
- name: master-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-master-cert
- name: volume-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-volume-cert
- name: filer-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-filer-cert
- name: client-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-client-cert
{{- end }}
{{ tpl .Values.sftp.extraVolumes . | indent 8 | trim }}
{{- if .Values.sftp.nodeSelector }}
nodeSelector:
{{ tpl .Values.sftp.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,37 @@
{{- if or .Values.sftp.enabled .Values.allInOne.enabled }}
{{- $secretName := printf "%s-sftp-secret" (include "seaweedfs.fullname" .) }}
{{- $admin_pwd := include "seaweedfs.getOrGeneratePassword" (dict "namespace" .Release.Namespace "secretName" $secretName "key" "admin_password" "length" 20) -}}
{{- $read_user_pwd := include "seaweedfs.getOrGeneratePassword" (dict "namespace" .Release.Namespace "secretName" $secretName "key" "readonly_password" "length" 20) -}}
{{- $public_user_pwd := include "seaweedfs.getOrGeneratePassword" (dict "namespace" .Release.Namespace "secretName" $secretName "key" "public_user_password" "length" 20) -}}
{{- $ssh_private_key := "" -}}
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace $secretName -}}
{{- if and $existingSecret (index $existingSecret.data "seaweedfs_sftp_ssh_private_key") -}}
{{- $ssh_private_key = index $existingSecret.data "seaweedfs_sftp_ssh_private_key" | b64dec | trim -}}
{{- end -}}
{{/* generate a fresh host key; also replace the key earlier chart versions bundled */}}
{{- if or (not $ssh_private_key) (contains "H4McwcDphteXVullu6q7ephEN1N60z" $ssh_private_key) -}}
{{- $ssh_private_key = genPrivateKey "ed25519" -}}
{{- end -}}
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ $secretName }}
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/resource-policy": keep
"helm.sh/hook": "pre-install,pre-upgrade"
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: sftp
stringData:
admin_password: {{ $admin_pwd }}
readonly_password: {{ $read_user_pwd }}
public_user_password: {{ $public_user_pwd }}
seaweedfs_sftp_config: '[{"Username":"admin","Password":"{{ $admin_pwd }}","PublicKeys":[],"HomeDir":"/","Permissions":{"/":["read","write","list"]},"Uid":0,"Gid":0},{"Username":"readonly_user","Password":"{{ $read_user_pwd }}","PublicKeys":[],"HomeDir":"/","Permissions":{"/":["read","list"]},"Uid":1112,"Gid":1112},{"Username":"public_user","Password":"{{ $public_user_pwd }}","PublicKeys":[],"HomeDir":"/public","Permissions":{"/public":["write","read","list"]},"Uid":1113,"Gid":1113}]'
seaweedfs_sftp_ssh_private_key: |
{{ $ssh_private_key | trim | indent 4 }}
{{- end }}

View File

@@ -0,0 +1,47 @@
{{- if .Values.sftp.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "seaweedfs.componentName" (list . "sftp") }}
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: sftp
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- if .Values.sftp.annotations }}
annotations:
{{- toYaml .Values.sftp.annotations | nindent 4 }}
{{- end }}
spec:
{{- $serviceType := .Values.sftp.service.type }}
{{- $nodePorts := dict }}
{{- if or (eq $serviceType "NodePort") (eq $serviceType "LoadBalancer") }}
{{- $nodePorts = .Values.sftp.service.nodePorts | default dict }}
{{- end }}
type: {{ $serviceType }}
{{- include "seaweedfs.service.loadBalancerFields" .Values.sftp.service }}
internalTrafficPolicy: {{ .Values.sftp.internalTrafficPolicy | default "Cluster" }}
ports:
- name: "swfs-sftp"
port: {{ .Values.sftp.port }}
targetPort: {{ .Values.sftp.port }}
{{- if $nodePorts.sftp }}
nodePort: {{ $nodePorts.sftp }}
{{- end }}
protocol: TCP
{{- if .Values.sftp.metricsPort }}
- name: "metrics"
port: {{ .Values.sftp.metricsPort }}
targetPort: {{ .Values.sftp.metricsPort }}
{{- if $nodePorts.metrics }}
nodePort: {{ $nodePorts.metrics }}
{{- end }}
protocol: TCP
{{- end }}
selector:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: sftp
{{- end }}

View File

@@ -0,0 +1,35 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.sftp.enabled }}
{{- if .Values.sftp.metricsPort }}
{{- if .Values.global.seaweedfs.monitoring.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "seaweedfs.fullname" . }}-sftp
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: sftp
{{- with .Values.global.seaweedfs.monitoring.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if .Values.sftp.annotations }}
annotations:
{{- toYaml .Values.sftp.annotations | nindent 4 }}
{{- end }}
spec:
endpoints:
- interval: 30s
port: metrics
scrapeTimeout: 5s
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: sftp
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,35 @@
{{- if or (and .Values.sftp.enabled (not .Values.sftp.existingSshConfigSecret)) (and .Values.allInOne.enabled .Values.allInOne.sftp.enabled (not (or .Values.allInOne.sftp.existingSshConfigSecret .Values.sftp.existingSshConfigSecret))) }}
{{/* Host keys mounted at sftp.hostKeysFolder; existing keys are kept across upgrades, except the key earlier chart versions bundled. */}}
{{- $secretName := printf "%s-sftp-ssh-secret" (include "seaweedfs.fullname" .) }}
{{- $hostKeys := dict }}
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace $secretName }}
{{- if $existingSecret }}
{{- range $name, $value := $existingSecret.data }}
{{- if not (contains "H4McwcDphteXVullu6q7ephEN1N60z" (b64dec $value)) }}
{{- $_ := set $hostKeys $name $value }}
{{- end }}
{{- end }}
{{- end }}
{{- if eq (len $hostKeys) 0 }}
{{- $_ := set $hostKeys "ssh_host_ed25519_key" (genPrivateKey "ed25519" | b64enc) }}
{{- end }}
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ $secretName }}
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/resource-policy": keep
"helm.sh/hook": "pre-install,pre-upgrade"
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: sftp
data:
{{- range $name, $value := $hostKeys }}
{{ $name }}: {{ $value }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,59 @@
{{/*
Backward-compatibility shim for the global.* → global.seaweedfs.* migration.
When the chart is used as a subchart, .Values.global is shared with sibling
charts. To avoid namespace pollution, app-specific values were moved under
global.seaweedfs.* (and global.registry was renamed to global.imageRegistry).
If a user still passes the OLD key paths (e.g. --set global.enableSecurity=true),
those keys will no longer have defaults in values.yaml, so their mere presence in
.Values.global means the user explicitly provided them. This helper merges them
into global.seaweedfs.* so the rest of the templates see a single, canonical
location.
The helper mutates .Values.global.seaweedfs in-place via `set` and produces no
output. It is idempotent (safe to call more than once in the same render).
Usage: {{- include "seaweedfs.compat" . -}}
*/}}
{{- define "seaweedfs.compat" -}}
{{- $g := .Values.global -}}
{{- $sw := $g.seaweedfs | default dict -}}
{{/* --- image-related renames --- */}}
{{- if hasKey $g "registry" -}}
{{- $_ := set $g "imageRegistry" (default $g.imageRegistry $g.registry) -}}
{{- end -}}
{{- if hasKey $g "repository" -}}
{{- $img := $sw.image | default dict -}}
{{- $_ := set $img "repository" (default $img.repository $g.repository) -}}
{{- $_ := set $sw "image" $img -}}
{{- end -}}
{{- if hasKey $g "imageName" -}}
{{- $img := $sw.image | default dict -}}
{{- $_ := set $img "name" (default $img.name $g.imageName) -}}
{{- $_ := set $sw "image" $img -}}
{{- end -}}
{{/* --- scalar keys that moved 1:1 under global.seaweedfs --- */}}
{{- range $key := list "createClusterRole" "imagePullPolicy" "restartPolicy" "loggingLevel" "enableSecurity" "masterServer" "serviceAccountName" "automountServiceAccountToken" "enableReplication" "replicationPlacement" -}}
{{- if hasKey $g $key -}}
{{- $_ := set $sw $key (index $g $key) -}}
{{- end -}}
{{- end -}}
{{/* --- nested dict keys: deep-merge so partial overrides work --- */}}
{{- range $key := list "securityConfig" "certificates" "monitoring" "serviceAccountAnnotations" "extraEnvironmentVars" -}}
{{- if hasKey $g $key -}}
{{- $old := index $g $key | default dict -}}
{{- $new := index $sw $key | default dict -}}
{{- if and (kindIs "map" $old) (kindIs "map" $new) -}}
{{- $_ := set $sw $key (merge $old $new) -}}
{{- else -}}
{{- $_ := set $sw $key $old -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- $_ := set $g "seaweedfs" $sw -}}
{{- end -}}

View File

@@ -0,0 +1,616 @@
{{/*
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 a truncated component name.
Usage: {{ include "seaweedfs.componentName" (list . "component-suffix") }}
*/}}
{{- define "seaweedfs.componentName" -}}
{{- $context := index . 0 -}}
{{- $suffix := index . 1 -}}
{{- if gt (len $suffix) 61 -}}
{{- fail (printf "Suffix '%s' is too long for componentName helper. Max length is 61." $suffix) -}}
{{- end -}}
{{- $fullname := include "seaweedfs.fullname" $context -}}
{{- $maxLen := sub 62 (len $suffix) | int -}}
{{- $truncatedFullname := trunc $maxLen $fullname | trimSuffix "-" -}}
{{- printf "%s-%s" $truncatedFullname $suffix -}}
{{- 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 -}}
{{- define "seaweedfs.mergeExtraEnvironmentVars" -}}
{{- $global := ((.global | default dict).extraEnvironmentVars | default dict) -}}
{{- $component := ((.component | default dict).extraEnvironmentVars | default dict) -}}
{{- $target := .target -}}
{{- range $key, $value := $global }}
{{- $_ := set $target $key $value }}
{{- end }}
{{- range $key, $value := $component }}
{{- $_ := set $target $key $value }}
{{- end }}
{{/* the license block owns SEAWEED_LICENSE; letting one through here too would
render the key twice in one container */}}
{{- if ((.global | default dict).license | default dict).existingSecret }}
{{- $_ := unset $target "SEAWEED_LICENSE" }}
{{- end }}
{{- end -}}
{{/* Whether the mysql filer store is selected; a flag the chart cannot read counts as selected. */}}
{{- define "seaweedfs.filer.mysqlEnabled" -}}
{{- $merged := dict -}}
{{- $_ := include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" .Values.global.seaweedfs "component" .Values.filer "target" $merged) -}}
{{- $enabled := index $merged "WEED_MYSQL_ENABLED" -}}
{{- if or (kindIs "map" $enabled) (hasKey (.Values.filer.secretExtraEnvironmentVars | default dict) "WEED_MYSQL_ENABLED") -}}
true
{{- else if and $enabled (eq (lower (toString $enabled)) "true") -}}
true
{{- end -}}
{{- end -}}
{{/* Classify an admin bind address as loopback, mirroring weed admin's
isLoopbackIp (net.ParseIP + IsLoopback). Helm templates cannot call
net.ParseIP, so we approximate: valid IPv4 addresses in 127.0.0.0/8
(validated via regex to reject malformed values like "127.not-an-ip")
and the IPv6 loopback "::1" / its expanded form "0:0:0:0:0:0:0:1" are
loopback. Hostnames (e.g. "localhost") and wildcard addresses
("0.0.0.0", "::") are non-loopback, matching the binary, which
treats unparseable hostnames as non-loopback to be safe. Other IPv6
loopback representations are not matched; the binary's own runtime
validation is the authoritative guard. */}}
{{- define "seaweedfs.admin.isLoopbackIp" -}}
{{- $ip := toString . -}}
{{- if or (regexMatch "^127\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$" $ip) (eq $ip "::1") (eq $ip "0:0:0:0:0:0:0:1") -}}
true
{{- end -}}
{{- end -}}
{{/* Whether admin authentication is enabled from any supported source:
admin.secret (adminPassword or existingSecret), or WEED_ADMIN_PASSWORD
supplied via extraEnvironmentVars / secretExtraEnvironmentVars (which
weed admin picks up through viper's AutomaticEnv). A secret-backed
entry counts as enabled even though the chart cannot read its value. */}}
{{- define "seaweedfs.admin.authEnabled" -}}
{{- if or .Values.admin.secret.existingSecret .Values.admin.secret.adminPassword -}}
true
{{- else -}}
{{- $merged := dict -}}
{{- $_ := include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" .Values.global.seaweedfs "component" .Values.admin "target" $merged) -}}
{{- $envPassword := index $merged "WEED_ADMIN_PASSWORD" -}}
{{- if or (kindIs "map" $envPassword) (hasKey (.Values.admin.secretExtraEnvironmentVars | default dict) "WEED_ADMIN_PASSWORD") -}}
true
{{- else if and $envPassword (ne (toString $envPassword) "") -}}
true
{{- end -}}
{{- end -}}
{{- end -}}
{{/* Return the proper filer image */}}
{{- define "seaweedfs.filer.image" -}}
{{- if .Values.filer.imageOverride -}}
{{- $imageOverride := .Values.filer.imageOverride -}}
{{- printf "%s" $imageOverride -}}
{{- else -}}
{{- include "seaweedfs.image" . }}
{{- end -}}
{{- end -}}
{{/* Return the proper master image */}}
{{- define "seaweedfs.master.image" -}}
{{- if .Values.master.imageOverride -}}
{{- $imageOverride := .Values.master.imageOverride -}}
{{- printf "%s" $imageOverride -}}
{{- else -}}
{{- include "seaweedfs.image" . }}
{{- end -}}
{{- end -}}
{{/* Return the proper s3 image */}}
{{- define "seaweedfs.s3.image" -}}
{{- if .Values.s3.imageOverride -}}
{{- $imageOverride := .Values.s3.imageOverride -}}
{{- printf "%s" $imageOverride -}}
{{- else -}}
{{- include "seaweedfs.image" . }}
{{- end -}}
{{- end -}}
{{/* Return the proper sftp image */}}
{{- define "seaweedfs.sftp.image" -}}
{{- if .Values.sftp.imageOverride -}}
{{- $imageOverride := .Values.sftp.imageOverride -}}
{{- printf "%s" $imageOverride -}}
{{- else -}}
{{- include "seaweedfs.image" . }}
{{- end -}}
{{- end -}}
{{/* Return the proper admin image */}}
{{- define "seaweedfs.admin.image" -}}
{{- if .Values.admin.imageOverride -}}
{{- $imageOverride := .Values.admin.imageOverride -}}
{{- printf "%s" $imageOverride -}}
{{- else -}}
{{- include "seaweedfs.image" . }}
{{- end -}}
{{- end -}}
{{/* Return the proper worker image */}}
{{- define "seaweedfs.worker.image" -}}
{{- if .Values.worker.imageOverride -}}
{{- $imageOverride := .Values.worker.imageOverride -}}
{{- printf "%s" $imageOverride -}}
{{- else -}}
{{- include "seaweedfs.image" . }}
{{- end -}}
{{- end -}}
{{/* Lance namespace URL the worker's Lance container maintains; empty when unreachable */}}
{{- define "seaweedfs.worker.lanceNamespaceUrl" -}}
{{- if .Values.worker.namespaceUrl -}}
{{- .Values.worker.namespaceUrl -}}
{{- else if and .Values.s3.enabled .Values.s3.lancePort -}}
{{- printf "http://%s.%s:%d" (include "seaweedfs.componentName" (list . "s3")) .Release.Namespace (int .Values.s3.lancePort) -}}
{{- end -}}
{{- end -}}
{{/* Return the proper volume image */}}
{{- define "seaweedfs.volume.image" -}}
{{- if .Values.volume.imageOverride -}}
{{- $imageOverride := .Values.volume.imageOverride -}}
{{- printf "%s" $imageOverride -}}
{{- else -}}
{{- include "seaweedfs.image" . }}
{{- end -}}
{{- end -}}
{{/* Computes the container image name for all components (if they are not overridden) */}}
{{- define "seaweedfs.image" -}}
{{- $registryName := default .Values.image.registry .Values.global.imageRegistry | toString -}}
{{- $repositoryName := default .Values.image.repository .Values.global.seaweedfs.image.repository | toString -}}
{{- $name := .Values.global.seaweedfs.image.name | toString -}}
{{- $tag := default .Chart.AppVersion .Values.image.tag | toString -}}
{{- if .Values.image.repository -}}
{{- $name = $repositoryName -}}
{{- else if $repositoryName -}}
{{- $name = printf "%s/%s" (trimSuffix "/" $repositoryName) (base $name) -}}
{{- end -}}
{{- if $registryName -}}
{{- printf "%s/%s:%s" $registryName $name $tag -}}
{{- else -}}
{{- printf "%s:%s" $name $tag -}}
{{- end -}}
{{- end -}}
{{/* check if any Volume PVC exists */}}
{{- define "seaweedfs.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 "seaweedfs.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 "seaweedfs.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 Admin PVC exists */}}
{{- define "seaweedfs.admin.pvc_exists" -}}
{{- if or (eq .Values.admin.data.type "persistentVolumeClaim") (eq .Values.admin.logs.type "persistentVolumeClaim") -}}
{{- printf "true" -}}
{{- else -}}
{{- printf "" -}}
{{- end -}}
{{- end -}}
{{/* check if any InitContainers exist for Volumes */}}
{{- define "seaweedfs.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" -}}
{{- with .Values.global.imagePullSecrets }}
imagePullSecrets:
{{- if kindIs "string" . }}
- name: {{ . }}
{{- else }}
{{- range . }}
{{- if kindIs "string" . }}
- name: {{ . }}
{{- else }}
- {{ toYaml . }}
{{- end}}
{{- end }}
{{- end }}
{{- end }}
{{- end -}}
{{/*
Renders a value that contains template perhaps with scope if the scope is present.
Usage:
{{ include "seaweedfs.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ ) }}
{{ include "seaweedfs.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $ "scope" $app ) }}
*/}}
{{- define "seaweedfs.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 -}}
{{/*
Converts a Kubernetes quantity like "256Mi" or "2G" to a float64 in base units,
handling both binary (Ki, Mi, Gi) and decimal (m, k, M) suffixes; numeric inputs
Usage:
{{ include "seaweedfs.resource-quantity" "10Gi" }}
*/}}
{{- define "seaweedfs.resource-quantity" -}}
{{- $value := . -}}
{{- $unit := 1.0 -}}
{{- if typeIs "string" . -}}
{{- $base2 := dict "Ki" 0x1p10 "Mi" 0x1p20 "Gi" 0x1p30 "Ti" 0x1p40 "Pi" 0x1p50 "Ei" 0x1p60 -}}
{{- $base10 := dict "m" 1e-3 "k" 1e3 "M" 1e6 "G" 1e9 "T" 1e12 "P" 1e15 "E" 1e18 -}}
{{- range $k, $v := merge $base2 $base10 -}}
{{- if hasSuffix $k $ -}}
{{- $value = trimSuffix $k $ -}}
{{- $unit = $v -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- mulf (float64 $value) $unit -}}
{{- end -}}
{{/*
getOrGeneratePassword will check if a password exists in a secret and return it,
or generate a new random password if it doesn't exist.
*/}}
{{- define "seaweedfs.getOrGeneratePassword" -}}
{{- $params := . -}}
{{- $namespace := $params.namespace -}}
{{- $secretName := $params.secretName -}}
{{- $key := $params.key -}}
{{- $length := default 16 $params.length -}}
{{- $existingSecret := default (lookup "v1" "Secret" $namespace $secretName) $params.existingSecret -}}
{{- if and $existingSecret (index $existingSecret.data $key) -}}
{{- index $existingSecret.data $key | b64dec -}}
{{- else -}}
{{- randAlphaNum $length -}}
{{- end -}}
{{- end -}}
{{/*
Compute the master service address to be used in cluster env vars.
If allInOne is enabled, point to the all-in-one service; otherwise, point to the master service.
*/}}
{{- define "seaweedfs.cluster.masterAddress" -}}
{{- $component := ternary "all-in-one" "master" .Values.allInOne.enabled -}}
{{- printf "%s.%s:%d" (include "seaweedfs.componentName" (list . $component)) .Release.Namespace (int .Values.master.port) -}}
{{- end -}}
{{/*
Compute the filer service address to be used in cluster env vars.
If allInOne is enabled, point to the all-in-one service; otherwise, point to the filer-client service.
*/}}
{{- define "seaweedfs.cluster.filerAddress" -}}
{{- $component := ternary "all-in-one" "filer-client" .Values.allInOne.enabled -}}
{{- printf "%s.%s:%d" (include "seaweedfs.componentName" (list . $component)) .Release.Namespace (int .Values.filer.port) -}}
{{- end -}}
{{/*
Generate comma-separated list of master server addresses.
Usage: {{ include "seaweedfs.masterServers" . }}
Output example: my-release-master-0.my-release-master.namespace:9333,my-release-master-1...
*/}}
{{- define "seaweedfs.masterServers" -}}
{{- $masterName := include "seaweedfs.componentName" (list . "master") -}}
{{- range $index := until (.Values.master.replicas | int) -}}
{{- if $index }},{{ end -}}
{{ $masterName }}-{{ $index }}.{{ $masterName }}.{{ $.Release.Namespace }}:{{ $.Values.master.port }}
{{- end -}}
{{- end -}}
{{/*
Generate master server argument value, using global.masterServer if set, otherwise the generated list.
Usage: {{ include "seaweedfs.masterServerArg" . }}
*/}}
{{- define "seaweedfs.masterServerArg" -}}
{{- if .Values.global.seaweedfs.masterServer -}}
{{- .Values.global.seaweedfs.masterServer -}}
{{- else -}}
{{- include "seaweedfs.masterServers" . -}}
{{- end -}}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "seaweedfs.serviceAccountName" -}}
{{- .Values.global.seaweedfs.serviceAccountName | default "seaweedfs" -}}
{{- end -}}
{{/* True when security.toml should be rendered and mounted. volumeWrite is
excluded unless its non-default expiration is configured. */}}
{{- define "seaweedfs.securityConfigEnabled" -}}
{{- $sec := (.Values.global.seaweedfs).securityConfig | default dict -}}
{{- $jwt := $sec.jwtSigning | default dict -}}
{{- $expiresAfterSeconds := $jwt.expiresAfterSeconds | default dict -}}
{{- $volumeWriteExpirationConfigured := and $jwt.volumeWrite (gt (int $expiresAfterSeconds.volumeWrite) 0) -}}
{{- if or .Values.global.seaweedfs.enableSecurity $volumeWriteExpirationConfigured $jwt.volumeRead $jwt.filerWrite $jwt.filerRead -}}
true
{{- end -}}
{{- end -}}
{{/* True when the post-install bucket hook Job renders: an S3 endpoint, plus
buckets to create on it. Read by the Job itself and by its NetworkPolicy,
which has to appear exactly when the Job does - a Job without its policy
hangs in a default-deny namespace. */}}
{{- define "seaweedfs.bucketHookEnabled" -}}
{{- if .Values.allInOne.enabled -}}
{{- if and .Values.allInOne.s3.enabled .Values.allInOne.s3.createBuckets -}}
true
{{- end -}}
{{- else if .Values.master.enabled -}}
{{- if and (or .Values.filer.s3.enabled .Values.s3.enabled) (or .Values.s3.createBuckets .Values.filer.s3.createBuckets) -}}
true
{{- end -}}
{{- end -}}
{{- end -}}
{{/* The kubectl commands the volume resize hook has to run, one per line: a
cascade-orphan delete for every StatefulSet whose volumeClaimTemplates no
longer match the values, and a patch for every PVC the values grew.
Empty when there is nothing to resize, which is what gates the Job. Read by
its NetworkPolicy too, which has to appear exactly when the Job does - a Job
without its policy hangs in a default-deny namespace, and a policy without
its Job is an orphaned hook resource on every install.
Built on lookup, so it is always empty under helm template and on a fresh
install, where there is no StatefulSet to compare against yet. */}}
{{- define "seaweedfs.volumeResizeHookCommands" -}}
{{- $seaweedfsName := include "seaweedfs.fullname" $ }}
{{- $volumes := deepCopy .Values.volumes | mergeOverwrite (dict "" .Values.volume) }}
{{- $commands := list }}
{{- if .Values.volume.resizeHook.enabled }}
{{- range $vname, $volume := $volumes }}
{{- $volumeName := trimSuffix "-" (printf "volume-%s" $vname) }}
{{- $volume := mergeOverwrite (deepCopy $.Values.volume) (dict "enabled" true) $volume }}
{{- if $volume.enabled }}
{{- $replicas := int $volume.replicas }}
{{- $statefulsetName := printf "%s-%s" $seaweedfsName $volumeName }}
{{- $statefulset := (lookup "apps/v1" "StatefulSet" $.Release.Namespace $statefulsetName) }}
{{- /* Check for changes in volumeClaimTemplates */}}
{{- if $statefulset }}
{{- range $dir := $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) }}
{{- $commands = append $commands (printf "kubectl delete statefulset %s --cascade=orphan" $statefulsetName) }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- /* Check for the need for patching existing PVCs */}}
{{- range $dir := $volume.dataDirs }}
{{- if eq .type "persistentVolumeClaim" }}
{{- $desiredSize := .size }}
{{- range $i, $e := until $replicas }}
{{- $pvcName := printf "%s-%s-%s-%d" $dir.name $seaweedfsName $volumeName $e }}
{{- $currentPVC := (lookup "v1" "PersistentVolumeClaim" $.Release.Namespace $pvcName) }}
{{- if $currentPVC }}
{{- $oldSize := include "seaweedfs.resource-quantity" $currentPVC.spec.resources.requests.storage }}
{{- $newSize := include "seaweedfs.resource-quantity" $desiredSize }}
{{- if gt $newSize $oldSize }}
{{- $commands = append $commands (printf "kubectl patch pvc %s-%s-%s-%d -p '{\"spec\":{\"resources\":{\"requests\":{\"storage\":\"%s\"}}}}'" $dir.name $seaweedfsName $volumeName $e $desiredSize) }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- join "\n" $commands }}
{{- end -}}
{{/* S3 TLS cert/key arguments, using custom secret if s3.tlsSecret is set */}}
{{- define "seaweedfs.s3.tlsArgs" -}}
{{- $prefix := .prefix -}}
{{- $root := .root -}}
{{- if $root.Values.s3.tlsSecret -}}
-{{ $prefix }}cert.file=/usr/local/share/ca-certificates/s3/tls.crt \
-{{ $prefix }}key.file=/usr/local/share/ca-certificates/s3/tls.key \
{{- else -}}
-{{ $prefix }}cert.file=/usr/local/share/ca-certificates/client/tls.crt \
-{{ $prefix }}key.file=/usr/local/share/ca-certificates/client/tls.key \
{{- end -}}
{{- end -}}
{{/* S3 custom TLS volume mount */}}
{{- define "seaweedfs.s3.tlsVolumeMount" -}}
{{- if .Values.s3.tlsSecret }}
- name: s3-tls-cert
readOnly: true
mountPath: /usr/local/share/ca-certificates/s3/
{{- end }}
{{- end -}}
{{/* S3 custom TLS volume */}}
{{- define "seaweedfs.s3.tlsVolume" -}}
{{- if .Values.s3.tlsSecret }}
- name: s3-tls-cert
secret:
secretName: {{ .Values.s3.tlsSecret }}
{{- end }}
{{- end -}}
{{/* True when an enterprise license Secret is configured. */}}
{{- define "seaweedfs.licenseEnabled" -}}
{{- if ((.Values.global.seaweedfs).license).existingSecret -}}
true
{{- end -}}
{{- end -}}
{{/* Enterprise license volume. Projects just the license key. */}}
{{- define "seaweedfs.licenseVolume" -}}
{{- if include "seaweedfs.licenseEnabled" . -}}
- name: seaweedfs-license
secret:
secretName: {{ .Values.global.seaweedfs.license.existingSecret }}
defaultMode: 0444
items:
- key: {{ .Values.global.seaweedfs.license.secretKey | default "seaweed-license.json" | quote }}
path: {{ .Values.global.seaweedfs.license.secretKey | default "seaweed-license.json" | quote }}
{{- end }}
{{- end -}}
{{/* Enterprise license volume mount. Never a subPath: that is resolved once at
container start, so a renewed Secret would not reach a running master. */}}
{{- define "seaweedfs.licenseVolumeMount" -}}
{{- if include "seaweedfs.licenseEnabled" . -}}
- name: seaweedfs-license
readOnly: true
mountPath: {{ .Values.global.seaweedfs.license.mountPath | default "/etc/seaweedfs/license" | quote }}
{{- end }}
{{- end -}}
{{/* SEAWEED_LICENSE, set explicitly rather than relying on the binary's search
paths, which depend on the working directory. */}}
{{- define "seaweedfs.licenseEnv" -}}
{{- if include "seaweedfs.licenseEnabled" . -}}
- name: SEAWEED_LICENSE
value: {{ printf "%s/%s"
(.Values.global.seaweedfs.license.mountPath | default "/etc/seaweedfs/license")
(.Values.global.seaweedfs.license.secretKey | default "seaweed-license.json") | quote }}
{{- end }}
{{- end -}}
{{/* Name of the environment variable carrying one generated S3 credential
field, e.g. SEAWEEDFS_S3_ADMIN_ACCESS_KEY_ID. The generated identities file
names it in place of the key when the key lives in an existing Secret.
Usage: include "seaweedfs.s3.credentialEnvName" (list "admin" "accessKey") */}}
{{- define "seaweedfs.s3.credentialEnvName" -}}
{{- $identity := index . 0 -}}
{{- $field := index . 1 -}}
{{- printf "SEAWEEDFS_S3_%s_%s" (upper $identity) (ternary "ACCESS_KEY_ID" "SECRET_ACCESS_KEY" (eq $field "accessKey")) -}}
{{- end -}}
{{/* Environment for the S3 identities the chart generates from an existing
Secret. The gateway resolves the ${VAR} references the identities file
carries, so the keys never enter the rendered manifests and a dry run
renders the same as an install. */}}
{{- define "seaweedfs.s3.credentialEnv" -}}
{{- $creds := $.Values.s3.credentials | default dict -}}
{{- range $identity := list "admin" "read" -}}
{{- $identityCreds := index $creds $identity | default dict -}}
{{- if $identityCreds.existingSecret }}
- name: {{ include "seaweedfs.s3.credentialEnvName" (list $identity "accessKey") }}
valueFrom:
secretKeyRef:
name: {{ $identityCreds.existingSecret | quote }}
key: {{ default (printf "%s_access_key_id" $identity) $identityCreds.accessKeyKey | quote }}
- name: {{ include "seaweedfs.s3.credentialEnvName" (list $identity "secretKey") }}
valueFrom:
secretKeyRef:
name: {{ $identityCreds.existingSecret | quote }}
key: {{ default (printf "%s_secret_access_key" $identity) $identityCreds.secretKeyKey | quote }}
{{- end -}}
{{- end -}}
{{- end -}}
{{/* Generate a compatible trafficDistribution value due to "PreferClose" fast deprecation in k8s v1.35.
Accepts a dict with "value" (the trafficDistribution string) and "Capabilities". */}}
{{- define "seaweedfs.trafficDistribution" -}}
{{- if .value -}}
{{- and (eq .value "PreferClose") (semverCompare ">=1.35-0" .Capabilities.KubeVersion.GitVersion) | ternary "PreferSameZone" .value -}}
{{- end -}}
{{- end -}}
{{/*
Render LoadBalancer-specific service fields (loadBalancerClass, loadBalancerIP,
loadBalancerSourceRanges), only when the service type is LoadBalancer.
Usage: {{ include "seaweedfs.service.loadBalancerFields" .Values.s3.service }}
*/}}
{{- define "seaweedfs.service.loadBalancerFields" -}}
{{- if eq (.type | default "ClusterIP") "LoadBalancer" }}
{{- with .loadBalancerClass }}
loadBalancerClass: {{ . }}
{{- end }}
{{- with .loadBalancerIP }}
loadBalancerIP: {{ . }}
{{- end }}
{{- with .loadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- end -}}

View File

@@ -0,0 +1,36 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.global.seaweedfs.createClusterRole }}
#hack for delete pod master after migration
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "seaweedfs.fullname" . }}-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: {{ include "seaweedfs.fullname" . }}-rw-crb
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: {{ include "seaweedfs.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "seaweedfs.fullname" . }}-rw-cr
{{- end }}

View File

@@ -0,0 +1,267 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.networkPolicy.enabled }}
{{- $np := .Values.networkPolicy }}
{{- $egressCfg := $np.egress | default dict }}
{{- $overrides := $np.components | default dict }}
{{- /* One entry per rendered workload, keyed by its app.kubernetes.io/component
label. "ports" is everything the workload listens on, taken from the same
values the containerPorts are taken from, so a changed port cannot drift
out of the policy. "apiserver" marks the workloads that talk to the
Kubernetes API. "name" overrides the object name where the component
label already reads as a full name. */}}
{{- $targets := list }}
{{- /* allInOne.enabled does not turn the individual components off - their
templates only look at their own enabled flag - so the all-in-one pod is
an addition here, not an alternative. */}}
{{- if .Values.allInOne.enabled }}
{{- $ports := list .Values.master.port .Values.master.grpcPort .Values.volume.port .Values.volume.grpcPort .Values.filer.port .Values.filer.grpcPort }}
{{- if .Values.allInOne.metricsPort }}
{{- $ports = append $ports .Values.allInOne.metricsPort }}
{{- end }}
{{- if .Values.allInOne.s3.enabled }}
{{- $ports = append $ports (.Values.allInOne.s3.port | default .Values.s3.port) }}
{{- $https := .Values.allInOne.s3.httpsPort | default .Values.s3.httpsPort }}
{{- if and $https (gt (int $https) 0) }}
{{- $ports = append $ports $https }}
{{- end }}
{{- end }}
{{- if .Values.allInOne.sftp.enabled }}
{{- $ports = append $ports (.Values.allInOne.sftp.port | default .Values.sftp.port) }}
{{- end }}
{{- $targets = append $targets (dict "component" "seaweedfs-all-in-one" "name" "all-in-one" "ports" $ports) }}
{{- end }}
{{- if .Values.master.enabled }}
{{- $ports := list .Values.master.port .Values.master.grpcPort }}
{{- if .Values.master.metricsPort }}
{{- $ports = append $ports .Values.master.metricsPort }}
{{- end }}
{{- $targets = append $targets (dict "component" "master" "ports" $ports) }}
{{- end }}
{{- /* Every volume group carries its own component label and its own ports. */}}
{{- $volumes := deepCopy .Values.volumes | mergeOverwrite (dict "" .Values.volume) }}
{{- range $vname, $volume := $volumes }}
{{- $volumeName := trimSuffix "-" (printf "volume-%s" $vname) }}
{{- $volume := mergeOverwrite (deepCopy $.Values.volume) (dict "enabled" true) $volume }}
{{- if $volume.enabled }}
{{- $ports := list $volume.port $volume.grpcPort }}
{{- if $volume.metricsPort }}
{{- $ports = append $ports $volume.metricsPort }}
{{- end }}
{{- $targets = append $targets (dict "component" $volumeName "ports" $ports) }}
{{- end }}
{{- end }}
{{- if .Values.filer.enabled }}
{{- $ports := list .Values.filer.port .Values.filer.grpcPort }}
{{- if .Values.filer.metricsPort }}
{{- $ports = append $ports .Values.filer.metricsPort }}
{{- end }}
{{- if .Values.filer.s3.enabled }}
{{- $ports = append $ports .Values.filer.s3.port }}
{{- if and .Values.filer.s3.httpsPort (gt (int .Values.filer.s3.httpsPort) 0) }}
{{- $ports = append $ports .Values.filer.s3.httpsPort }}
{{- end }}
{{- end }}
{{- $targets = append $targets (dict "component" "filer" "ports" $ports) }}
{{- end }}
{{- if .Values.s3.enabled }}
{{- $ports := list .Values.s3.port }}
{{- if and .Values.s3.httpsPort (gt (int .Values.s3.httpsPort) 0) }}
{{- $ports = append $ports .Values.s3.httpsPort }}
{{- end }}
{{- if .Values.s3.icebergPort }}
{{- $ports = append $ports .Values.s3.icebergPort }}
{{- end }}
{{- if .Values.s3.lancePort }}
{{- $ports = append $ports .Values.s3.lancePort }}
{{- end }}
{{- if .Values.s3.metricsPort }}
{{- $ports = append $ports .Values.s3.metricsPort }}
{{- end }}
{{- $targets = append $targets (dict "component" "s3" "ports" $ports) }}
{{- end }}
{{- if .Values.sftp.enabled }}
{{- $ports := list .Values.sftp.port }}
{{- if .Values.sftp.metricsPort }}
{{- $ports = append $ports .Values.sftp.metricsPort }}
{{- end }}
{{- $targets = append $targets (dict "component" "sftp" "ports" $ports) }}
{{- end }}
{{- /* No seaweedfs binary speaks to the Kubernetes API - the repository has no
client-go dependency - so admin gets no apiserver rule. The pod-RW
ClusterRole under global.seaweedfs.createClusterRole is a leftover from a
migration and is not exercised by any component. */}}
{{- if .Values.admin.enabled }}
{{- $targets = append $targets (dict "component" "admin" "ports" (list .Values.admin.port .Values.admin.grpcPort)) }}
{{- end }}
{{- if .Values.worker.enabled }}
{{- $ports := list }}
{{- if .Values.worker.metricsPort }}
{{- $ports = append $ports .Values.worker.metricsPort }}
{{- end }}
{{- if and .Values.worker.lanceMetricsPort (include "seaweedfs.worker.lanceNamespaceUrl" .) }}
{{- $ports = append $ports .Values.worker.lanceMetricsPort }}
{{- end }}
{{- $targets = append $targets (dict "component" "worker" "ports" $ports) }}
{{- end }}
{{- if .Values.cosi.enabled }}
{{- /* The provisioner sidecar watches the COSI CRs, so it needs the API
server; nothing needs to reach the driver itself. */}}
{{- $targets = append $targets (dict "component" "objectstorage-provisioner" "ports" (list) "apiserver" true) }}
{{- end }}
{{- /* The hook Jobs. Nothing connects to either, but under a default-deny
namespace they need egress or they hang: the bucket hook waits on the
master and filer, the resize hook shells out to kubectl.
The bucket hook is post-install, and Helm applies the release manifest
before post-install hooks run, so a plain policy is already in place by
then. The resize hook is pre-install weight 0, which runs before the
manifest is applied at all, so its policy has to be a pre-install hook
itself, at a weight below the Job's. */}}
{{- if include "seaweedfs.bucketHookEnabled" . }}
{{- $targets = append $targets (dict "component" "bucket-hook" "ports" (list)) }}
{{- end }}
{{- /* Same cluster lookup the Job is gated on, so the policy appears on exactly
the upgrades that grow a PVC and never on the ones that do not. Helm does
not garbage-collect hook resources, so a policy rendered unconditionally
would be left in the namespace by every install that uninstalls again -
and would make egress.kubeApiServer.cidrs mandatory for every release,
for a Job most of them never run. */}}
{{- if include "seaweedfs.volumeResizeHookCommands" . | trim }}
{{- $targets = append $targets (dict "component" "volume-resize-hook" "ports" (list) "apiserver" true "hook" "pre-install,pre-upgrade" "hookWeight" "-10") }}
{{- end }}
{{- /* A key under networkPolicy.components that names no component would be
read as "these rules are applied" and silently do nothing. Check against
every component the chart can produce rather than the ones enabled here,
so one values file can still carry overrides for a component this release
leaves off. */}}
{{- $known := list "master" "filer" "s3" "sftp" "admin" "worker" "volume" "bucket-hook" "volume-resize-hook" "objectstorage-provisioner" "seaweedfs-all-in-one" }}
{{- range $vname, $_ := (.Values.volumes | default dict) }}
{{- $known = append $known (trimSuffix "-" (printf "volume-%s" $vname)) }}
{{- end }}
{{- range $name, $_ := $overrides }}
{{- if not (has $name $known) }}
{{- fail (printf "networkPolicy.components: %q is not a component of this chart, so its rules would never be applied. Known components: %s." $name (join ", " (sortAlpha $known))) }}
{{- end }}
{{- end }}
{{- range $target := $targets }}
{{- $component := $target.component }}
{{- $override := get $overrides $component | default dict }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ include "seaweedfs.componentName" (list $ ($target.name | default $component)) }}
namespace: {{ $.Release.Namespace }}
labels:
app.kubernetes.io/name: {{ include "seaweedfs.name" $ | quote }}
helm.sh/chart: {{ $.Chart.Name }}-{{ $.Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ $.Release.Service | quote }}
app.kubernetes.io/instance: {{ $.Release.Name | quote }}
app.kubernetes.io/component: {{ $component | quote }}
{{- if $target.hook }}
annotations:
{{- /* Only before-hook-creation: the policy has to outlive the Job it
covers, so it must not be deleted when the Job succeeds. That does
leave it behind on uninstall, the usual trade-off for Helm hook
resources. */}}
"helm.sh/hook": {{ $target.hook }}
"helm.sh/hook-weight": {{ $target.hookWeight | quote }}
"helm.sh/hook-delete-policy": before-hook-creation
{{- end }}
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: {{ include "seaweedfs.name" $ | quote }}
app.kubernetes.io/instance: {{ $.Release.Name | quote }}
app.kubernetes.io/component: {{ $component | quote }}
policyTypes:
- Ingress
{{- if $egressCfg.enabled }}
- Egress
{{- end }}
ingress:
{{- $extraIngress := concat ($np.extraIngress | default list) ($override.extraIngress | default list) }}
{{- if and (not $target.ports) (not $extraIngress) }}
[]
{{- end }}
{{- if $target.ports }}
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: {{ include "seaweedfs.name" $ | quote }}
app.kubernetes.io/instance: {{ $.Release.Name | quote }}
ports:
{{- range $port := $target.ports }}
- protocol: TCP
port: {{ $port }}
{{- end }}
{{- end }}
{{- with $extraIngress }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if $egressCfg.enabled }}
egress:
- to:
- podSelector:
matchLabels:
app.kubernetes.io/name: {{ include "seaweedfs.name" $ | quote }}
app.kubernetes.io/instance: {{ $.Release.Name | quote }}
{{- if $egressCfg.allowDNS }}
{{- /* Emit only the selectors that are set. An empty one has to be left out
rather than rendered as null: a missing podSelector means every pod in
the namespace, and a missing namespaceSelector means this namespace
instead of the one DNS runs in. */}}
{{- if not (or $egressCfg.dnsNamespaceSelector $egressCfg.dnsPodSelector) }}
{{- fail "networkPolicy: egress.allowDNS is on but both egress.dnsNamespaceSelector and egress.dnsPodSelector are empty, which would open port 53 to every pod in the release namespace. Set at least one of them, or turn allowDNS off and name the resolver in egress.extraEgress." }}
{{- end }}
- to:
{{- if and $egressCfg.dnsNamespaceSelector $egressCfg.dnsPodSelector }}
- namespaceSelector:
{{- toYaml $egressCfg.dnsNamespaceSelector | nindent 12 }}
podSelector:
{{- toYaml $egressCfg.dnsPodSelector | nindent 12 }}
{{- else if $egressCfg.dnsNamespaceSelector }}
- namespaceSelector:
{{- toYaml $egressCfg.dnsNamespaceSelector | nindent 12 }}
{{- else }}
- podSelector:
{{- toYaml $egressCfg.dnsPodSelector | nindent 12 }}
{{- end }}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
{{- end }}
{{- if and $target.apiserver ($egressCfg.kubeApiServer).enabled }}
{{- if not $egressCfg.kubeApiServer.cidrs }}
{{- fail (printf "networkPolicy: %s needs the Kubernetes API server, but networkPolicy.egress.kubeApiServer.cidrs is empty. Set it to your API server address(es), or disable networkPolicy.egress.kubeApiServer and allow it through networkPolicy.egress.extraEgress." $component) }}
{{- end }}
{{- /* An empty port list is not "no ports" in a NetworkPolicy, it is every
port, so refuse it rather than quietly opening the CIDR up. */}}
{{- if not $egressCfg.kubeApiServer.ports }}
{{- fail "networkPolicy: egress.kubeApiServer.ports is empty, which allows every port on the API server CIDR(s) rather than none. Set it (the default is [443, 6443]), or turn egress.kubeApiServer off and describe the access in egress.extraEgress." }}
{{- end }}
{{- range $cidr := $egressCfg.kubeApiServer.cidrs }}
- to:
- ipBlock:
cidr: {{ $cidr }}
ports:
{{- range $port := $egressCfg.kubeApiServer.ports }}
- protocol: TCP
port: {{ $port }}
{{- end }}
{{- end }}
{{- end }}
{{- with concat ($egressCfg.extraEgress | default list) ($override.extraEgress | default list) }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,19 @@
{{- if and .Values.filer.enabled .Values.filer.notificationConfig }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "seaweedfs.fullname" . }}-notification-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 }}
{{- if .Values.filer.annotations }}
annotations:
{{- toYaml .Values.filer.annotations | nindent 4 }}
{{- end }}
data:
notification.toml: |-
{{ .Values.filer.notificationConfig | nindent 4 }}
{{- end }}

View File

@@ -0,0 +1,253 @@
{{- include "seaweedfs.compat" . -}}
{{- /* Support bucket creation for both standalone filer.s3 and allInOne modes */}}
{{- $createBuckets := list }}
{{- $enableAuth := false }}
{{- $existingConfigSecret := "" }}
{{- $bucketsFolder := "/buckets" }}
{{- $bucketEnvVars := merge (dict) (.Values.global.seaweedfs.extraEnvironmentVars | default dict) }}
{{- if .Values.allInOne.enabled }}
{{- $bucketEnvVars = merge (.Values.allInOne.extraEnvironmentVars | default dict) $bucketEnvVars }}
{{- else }}
{{- $bucketEnvVars = merge (.Values.filer.extraEnvironmentVars | default dict) $bucketEnvVars }}
{{- end }}
{{- $bucketsFolder = default $bucketsFolder (get $bucketEnvVars "WEED_FILER_BUCKETS_FOLDER") }}
{{- $bucketsFolder = trimSuffix "/" $bucketsFolder }}
{{- $clusterAlias := default "sw" (get $bucketEnvVars "WEED_CLUSTER_DEFAULT") }}
{{- $clusterUpper := upper $clusterAlias }}
{{- $clusterMasterKey := printf "WEED_CLUSTER_%s_MASTER" $clusterUpper }}
{{- $clusterFilerKey := printf "WEED_CLUSTER_%s_FILER" $clusterUpper }}
{{- /* Check allInOne mode first */}}
{{- if .Values.allInOne.enabled }}
{{- if .Values.allInOne.s3.enabled }}
{{- if .Values.allInOne.s3.createBuckets }}
{{- $createBuckets = .Values.allInOne.s3.createBuckets }}
{{- end }}
{{- $enableAuth = or .Values.allInOne.s3.enableAuth .Values.s3.enableAuth .Values.filer.s3.enableAuth }}
{{- $existingConfigSecret = or .Values.allInOne.s3.existingConfigSecret .Values.s3.existingConfigSecret .Values.filer.s3.existingConfigSecret }}
{{- end }}
{{- else if .Values.master.enabled }}
{{- /* Check if embedded (in filer) or standalone S3 gateway is enabled */}}
{{- if or .Values.filer.s3.enabled .Values.s3.enabled }}
{{- if .Values.s3.createBuckets }}
{{- $createBuckets = .Values.s3.createBuckets }}
{{- $enableAuth = .Values.s3.enableAuth }}
{{- $existingConfigSecret = .Values.s3.existingConfigSecret }}
{{- else if .Values.filer.s3.createBuckets }}
{{- $createBuckets = .Values.filer.s3.createBuckets }}
{{- $enableAuth = .Values.filer.s3.enableAuth }}
{{- $existingConfigSecret = .Values.filer.s3.existingConfigSecret }}
{{- end }}
{{- end }}
{{- end }}
{{- /* Shared with networkpolicy.yaml, which renders this Job's policy exactly
when the Job itself renders. */}}
{{- if include "seaweedfs.bucketHookEnabled" . }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: "{{ $.Release.Name }}-bucket-hook"
labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/component: bucket-hook
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
template:
metadata:
name: "{{ .Release.Name }}"
labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/component: bucket-hook
spec:
restartPolicy: Never
{{- if .Values.filer.podSecurityContext.enabled }}
securityContext: {{- omit .Values.filer.podSecurityContext "enabled" | toYaml | nindent 8 }}
{{- end }}
{{- include "seaweedfs.imagePullSecrets" $ | nindent 6 }}
containers:
- name: post-install-job
image: {{ template "seaweedfs.master.image" . }}
imagePullPolicy: {{ $.Values.global.seaweedfs.imagePullPolicy | default "IfNotPresent" }}
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: "{{ include "seaweedfs.fullname" . }}"
{{- /* Carries the JWT signing keys when they are set as environment
overrides rather than in security.toml. */}}
{{- range $key := keys $bucketEnvVars | sortAlpha }}
{{- $value := index $bucketEnvVars $key }}
{{- if not (has $key (list "WEED_CLUSTER_DEFAULT" $clusterMasterKey $clusterFilerKey)) }}
- name: {{ $key }}
{{- if kindIs "string" $value }}
value: {{ tpl $value $ | quote }}
{{- else }}
valueFrom:
{{ toYaml $value | nindent 14 | trim }}
{{- end }}
{{- end }}
{{- end }}
{{- /* Computed, as in all-in-one: the values pick the cluster alias,
the chart still owns the endpoints the script waits on. */}}
- name: WEED_CLUSTER_DEFAULT
value: {{ $clusterAlias | quote }}
- name: {{ $clusterMasterKey }}
value: {{ include "seaweedfs.cluster.masterAddress" . | quote }}
- name: {{ $clusterFilerKey }}
value: {{ include "seaweedfs.cluster.filerAddress" . | quote }}
command:
- "/bin/sh"
- "-ec"
- |
set -o pipefail
wait_for_service() {
local url=$1
local max_attempts=60 # 5 minutes total (5s * 60)
local attempt=1
echo "Waiting for service at $url..."
while [ $attempt -le $max_attempts ]; do
if curl -sS -o /dev/null --max-time 5 "$url" >/dev/null 2>&1; then
echo "Service at $url is up!"
return 0
fi
echo "Attempt $attempt: Service not ready yet, retrying in 5s..."
sleep 5
attempt=$((attempt + 1))
done
echo "Service at $url failed to become ready within 5 minutes"
exit 1
}
{{- if .Values.allInOne.enabled }}
wait_for_service "http://${{ $clusterMasterKey }}{{ .Values.allInOne.readinessProbe.httpGet.path }}"
wait_for_service "http://${{ $clusterFilerKey }}{{ .Values.filer.readinessProbe.httpGet.path }}"
{{- else }}
wait_for_service "http://${{ $clusterMasterKey }}{{ .Values.master.readinessProbe.httpGet.path }}"
wait_for_service "http://${{ $clusterFilerKey }}{{ .Values.filer.readinessProbe.httpGet.path }}"
{{- end }}
{{- range $createBuckets }}
{{- $bucketName := .name }}
{{- $bucketLock := or .lock .objectLock .withLock }}
bucket_list=$(/bin/echo 's3.bucket.list' | /usr/bin/weed shell) || { echo "Error listing s3 buckets"; exit 1; }
if echo "$bucket_list" | awk '{print $1}' | grep -Fxq "{{ $bucketName }}"; then
echo "Bucket '{{ $bucketName }}' already exists, skipping creation."
else
echo "Creating bucket '{{ $bucketName }}'..."
/bin/echo 's3.bucket.create --name {{ $bucketName }}{{- if $bucketLock }} --withLock{{- end }}' | /usr/bin/weed shell
fi
{{- end }}
{{- range $createBuckets }}
{{- $bucketLock := or .lock .objectLock .withLock }}
{{- if $bucketLock }}
/bin/echo 's3.bucket.lock -name {{ .name }} -enable' | /usr/bin/weed shell
{{- end }}
{{- end }}
{{- range $createBuckets }}
{{- $bucketVersioning := "" }}
{{- if kindIs "bool" .versioning }}
{{- if .versioning }}
{{- $bucketVersioning = "Enabled" }}
{{- else }}
{{- $bucketVersioning = "Suspended" }}
{{- end }}
{{- else if kindIs "string" .versioning }}
{{- $versioningLower := lower .versioning }}
{{- if eq $versioningLower "enabled" "enable" "true" }}
{{- $bucketVersioning = "Enabled" }}
{{- else if eq $versioningLower "suspended" "disable" "false" }}
{{- $bucketVersioning = "Suspended" }}
{{- else if or (eq .versioning "Enabled") (eq .versioning "Suspended") }}
{{- $bucketVersioning = .versioning }}
{{- else }}
{{- fail (printf "Invalid versioning value for bucket %s: %s. Must be 'Enabled' or 'Suspended'" .name .versioning) }}
{{- end }}
{{- end }}
{{- if $bucketVersioning }}
/bin/echo 's3.bucket.versioning -name {{ .name }} -status {{ $bucketVersioning }}' | /usr/bin/weed shell
{{- end }}
{{- end }}
{{- range $createBuckets }}
{{- if .ttl }}
/bin/echo 'fs.configure -locationPrefix={{ $bucketsFolder }}/{{ .name }}/ -ttl={{ .ttl }} -apply' | /usr/bin/weed shell
{{- end }}
{{- end }}
{{- range $createBuckets }}
{{- if .anonymousRead }}
/bin/echo \
"s3.configure --user anonymous \
--buckets {{ .name }} \
--actions Read \
--apply true" |\
/usr/bin/weed shell
{{- end }}
{{- end }}
{{- if or $enableAuth (include "seaweedfs.securityConfigEnabled" .) }}
volumeMounts:
{{- if $enableAuth }}
- name: config-users
mountPath: /etc/sw
readOnly: true
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
readOnly: true
mountPath: /etc/seaweedfs/security.toml
subPath: security.toml
{{- end }}
{{- end }}
ports:
- containerPort: {{ .Values.master.port }}
name: swfs-master
{{- if and .Values.global.seaweedfs.monitoring.enabled .Values.master.metricsPort }}
- containerPort: {{ .Values.master.metricsPort }}
name: metrics
{{- end }}
- containerPort: {{ .Values.master.grpcPort }}
#name: swfs-master-grpc
{{- with coalesce .Values.allInOne.s3.createBucketsHook.resources .Values.s3.createBucketsHook.resources .Values.filer.s3.createBucketsHook.resources }}
resources:
{{- toYaml . | nindent 10 }}
{{- end }}
{{- if .Values.filer.containerSecurityContext.enabled }}
securityContext: {{- omit .Values.filer.containerSecurityContext "enabled" | toYaml | nindent 12 }}
{{- end }}
{{- if or $enableAuth (include "seaweedfs.securityConfigEnabled" .) }}
volumes:
{{- if $enableAuth }}
- name: config-users
secret:
defaultMode: 420
{{- if $existingConfigSecret }}
secretName: {{ $existingConfigSecret }}
{{- else }}
secretName: {{ include "seaweedfs.fullname" . }}-s3-secret
{{- end }}
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-security-config
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,20 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.global.seaweedfs.monitoring.enabled }}
{{- $files := .Files.Glob "dashboards/*.json" }}
{{- if $files }}
{{- range $path, $file := $files }}
{{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "seaweedfs.fullname" $ }}-{{ printf "%s" $dashboardName | lower | replace "_" "-" }}
namespace: {{ $.Release.Namespace }}
labels:
grafana_dashboard: "1"
data:
{{ $dashboardName }}.json: |-
{{ toString $file | indent 4 }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,20 @@
{{- if and .Values.filer.enabled (include "seaweedfs.filer.mysqlEnabled" .) }}
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: {{ include "seaweedfs.fullname" . }}-db-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 }}
stringData:
user: "YourSWUser"
# auto-generated password
password: {{ randAlphaNum 10 | sha256sum | b64enc | trunc 32 }}
{{- end }}

View File

@@ -0,0 +1,128 @@
{{- include "seaweedfs.compat" . -}}
{{- if include "seaweedfs.securityConfigEnabled" . }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "seaweedfs.fullname" . }}-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:
{{- $fullname := include "seaweedfs.fullname" . }}
{{- $securityConfigName := printf "%s-security-config" $fullname }}
{{- $existing := lookup "v1" "ConfigMap" .Release.Namespace $securityConfigName }}
{{- if not $existing }}
{{- $legacyName := printf "%s-%s" (include "seaweedfs.name" .) "security-config" }}
{{- $existing = lookup "v1" "ConfigMap" .Release.Namespace $legacyName }}
{{- end }}
{{- $securityConfig := fromToml (dig "data" "security.toml" "" $existing) }}
{{- $securityConfigValues := .Values.global.seaweedfs.securityConfig | default dict }}
{{- $jwtSigning := $securityConfigValues.jwtSigning | default dict }}
{{- $expiresAfterSeconds := $jwtSigning.expiresAfterSeconds | default dict }}
security.toml: |-
# this file is read by master, volume server, and filer
{{- if $jwtSigning.volumeWrite }}
# the jwt signing key is read by master and volume server
# the jwt defaults to expire after 10 seconds
[jwt.signing]
key = "{{ dig "jwt" "signing" "key" (randAlphaNum 10 | b64enc) $securityConfig }}"
{{- if gt (int $expiresAfterSeconds.volumeWrite) 0 }}
expires_after_seconds = {{ int $expiresAfterSeconds.volumeWrite }}
{{- end }}
{{- end }}
{{- if $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
# the jwt defaults to expire after 60 seconds
[jwt.signing.read]
key = "{{ dig "jwt" "signing" "read" "key" (randAlphaNum 10 | b64enc) $securityConfig }}"
{{- if gt (int $expiresAfterSeconds.volumeRead) 0 }}
expires_after_seconds = {{ int $expiresAfterSeconds.volumeRead }}
{{- end }}
{{- end }}
{{- if $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 = "{{ dig "jwt" "filer_signing" "key" (randAlphaNum 10 | b64enc) $securityConfig }}"
{{- if gt (int $expiresAfterSeconds.filerWrite) 0 }}
expires_after_seconds = {{ int $expiresAfterSeconds.filerWrite }}
{{- end }}
{{- end }}
{{- if $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 reading
# the jwt defaults to expire after 60 seconds
[jwt.filer_signing.read]
key = "{{ dig "jwt" "filer_signing" "read" "key" (randAlphaNum 10 | b64enc) $securityConfig }}"
{{- if gt (int $expiresAfterSeconds.filerRead) 0 }}
expires_after_seconds = {{ int $expiresAfterSeconds.filerRead }}
{{- end }}
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
# 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"
[grpc.admin]
cert = "/usr/local/share/ca-certificates/admin/tls.crt"
key = "/usr/local/share/ca-certificates/admin/tls.key"
[grpc.worker]
cert = "/usr/local/share/ca-certificates/worker/tls.crt"
key = "/usr/local/share/ca-certificates/worker/tls.key"
{{- /* S3 gRPC server identity (weed s3 -port.grpc, default httpPort+10000).
Without this section, LoadServerTLS("grpc.s3") returns nil and the S3
server serves its internal gRPC (IAM cache propagation, s3 lifecycle
delete RPCs) as plaintext, while peers dial it with mTLS credentials:
"tls: first record does not look like a TLS handshake".
Always uses the internal CA-signed client certificate (already mounted
on s3 pods by s3-deployment.yaml). Deliberately NOT s3.tlsSecret: that
secret is for the public HTTPS listener and may be issued by a public
CA which internal gRPC peers (trusting only grpc.ca) would reject. */}}
[grpc.s3]
cert = "/usr/local/share/ca-certificates/client/tls.crt"
key = "/usr/local/share/ca-certificates/client/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 }}
{{- end }}

View File

@@ -0,0 +1,16 @@
{{- include "seaweedfs.compat" . -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "seaweedfs.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- with .Values.global.seaweedfs.serviceAccountAnnotations }}
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 }}
automountServiceAccountToken: {{ .Values.global.seaweedfs.automountServiceAccountToken }}

View File

@@ -0,0 +1,59 @@
{{- /* Volume ingress works for both normal mode (volume.enabled) and all-in-one mode (allInOne.enabled) */}}
{{- $volumeEnabled := or .Values.volume.enabled .Values.allInOne.enabled }}
{{- if and $volumeEnabled .Values.volume.ingress.enabled }}
{{- /* Determine service name based on deployment mode */}}
{{- $serviceName := ternary (include "seaweedfs.componentName" (list . "all-in-one")) (include "seaweedfs.componentName" (list . "volume")) .Values.allInOne.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-{{ include "seaweedfs.fullname" . }}-volume
namespace: {{ .Release.Namespace }}
annotations:
{{- if and (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) .Values.volume.ingress.className }}
kubernetes.io/ingress.class: {{ .Values.volume.ingress.className }}
{{- end }}
{{- with .Values.volume.ingress.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: volume
{{- with .Values.volume.ingress.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) .Values.volume.ingress.className }}
ingressClassName: {{ .Values.volume.ingress.className | quote }}
{{- end }}
tls:
{{ .Values.volume.ingress.tls | default list | toYaml | nindent 6}}
rules:
- {{- if .Values.volume.ingress.host }}
host: {{ .Values.volume.ingress.host | quote }}
{{- end }}
http:
paths:
- path: {{ .Values.volume.ingress.path | quote }}
{{- if semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion }}
pathType: {{ .Values.volume.ingress.pathType | quote }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $serviceName }}
port:
number: {{ .Values.volume.port }}
{{- else }}
serviceName: {{ $serviceName }}
servicePort: {{ .Values.volume.port }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,83 @@
{{- $seaweedfsName := include "seaweedfs.fullname" $ }}
{{- /* Shared with networkpolicy.yaml, which renders this Job's policy exactly
when the Job itself renders. */}}
{{- /* trim: include returns a string, and a whitespace-only one is truthy. */}}
{{- $commands := include "seaweedfs.volumeResizeHookCommands" . | trim }}
{{- if $commands }}
apiVersion: batch/v1
kind: Job
metadata:
name: "{{ $seaweedfsName }}-volume-resize-hook"
labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/component: 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:
backoffLimit: 1
template:
metadata:
labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/component: volume-resize-hook
spec:
serviceAccountName: {{ $seaweedfsName }}-volume-resize-hook
restartPolicy: Never
containers:
- name: resize
image: {{ .Values.volume.resizeHook.image }}
command: ["sh", "-xec"]
args:
- |
{{ $commands | indent 14 }}
---
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 }}

View File

@@ -0,0 +1,46 @@
{{ $volumes := deepCopy .Values.volumes | mergeOverwrite (dict "" .Values.volume) }}
{{- range $vname, $volume := $volumes }}
{{- $volumeName := trimSuffix "-" (printf "volume-%s" $vname) }}
{{- $volume := mergeOverwrite (deepCopy $.Values.volume) (dict "enabled" true) $volume }}
{{- if $volume.enabled }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "seaweedfs.componentName" (list $ $volumeName) }}
namespace: {{ $.Release.Namespace }}
labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" $ }}
app.kubernetes.io/instance: {{ $.Release.Name }}
app.kubernetes.io/component: {{ $volumeName }}
helm.sh/chart: {{ $.Chart.Name }}-{{ $.Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ $.Release.Service }}
{{- if $volume.annotations }}
annotations:
{{- toYaml $volume.annotations | nindent 4 }}
{{- end }}
spec:
clusterIP: None
internalTrafficPolicy: {{ $volume.internalTrafficPolicy | default "Cluster" }}
ports:
- name: "swfs-volume"
port: {{ $volume.port }}
targetPort: {{ $volume.port }}
protocol: TCP
- name: "swfs-volume-18080"
port: {{ $volume.grpcPort }}
targetPort: {{ $volume.grpcPort }}
protocol: TCP
{{- if $volume.metricsPort }}
- name: "metrics"
port: {{ $volume.metricsPort }}
targetPort: {{ $volume.metricsPort }}
protocol: TCP
{{- end }}
selector:
app.kubernetes.io/name: {{ template "seaweedfs.name" $ }}
app.kubernetes.io/instance: {{ $.Release.Name }}
app.kubernetes.io/component: {{ $volumeName }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,42 @@
{{- include "seaweedfs.compat" . -}}
{{ $volumes := deepCopy .Values.volumes | mergeOverwrite (dict "" .Values.volume) }}
{{- range $vname, $volume := $volumes }}
{{- $volumeName := trimSuffix "-" (printf "volume-%s" $vname) }}
{{- $volume := mergeOverwrite (deepCopy $.Values.volume) (dict "enabled" true) $volume }}
{{- if $volume.enabled }}
{{- if $volume.metricsPort }}
{{- if $.Values.global.seaweedfs.monitoring.enabled }}
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "seaweedfs.fullname" $ }}-{{ $volumeName }}
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: {{ $volumeName }}
{{- with $.Values.global.seaweedfs.monitoring.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with $volume.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
endpoints:
- interval: 30s
port: metrics
scrapeTimeout: 5s
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" $ }}
app.kubernetes.io/instance: {{ $.Release.Name }}
app.kubernetes.io/component: {{ $volumeName }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,447 @@
{{- include "seaweedfs.compat" . -}}
{{ $volumes := deepCopy .Values.volumes | mergeOverwrite (dict "" .Values.volume) }}
{{- range $vname, $volume := $volumes }}
{{- $volumeName := trimSuffix "-" (printf "volume-%s" $vname) }}
{{- $volume := mergeOverwrite (deepCopy $.Values.volume) (dict "enabled" true) $volume }}
{{- if and $volume.idx (eq ($volume.idx.type | toString) "emptyDir") }}
{{- fail (printf "%s: idx.type \"emptyDir\" is not supported. An ephemeral index is wiped on every pod restart while the data persists, forcing a full index rebuild from the .dat on each start (a fatal crash on older versions). Use the default (idx: {}, kept next to the data) or a persistentVolumeClaim/hostPath/existingClaim for a separate persistent index." $volumeName) }}
{{- end }}
{{- if $volume.enabled }}
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "seaweedfs.componentName" (list $ $volumeName) }}
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: {{ $volumeName }}
{{- if $volume.annotations }}
annotations:
{{- toYaml $volume.annotations | nindent 4 }}
{{- end }}
spec:
serviceName: {{ include "seaweedfs.componentName" (list $ $volumeName) }}
replicas: {{ $volume.replicas }}
podManagementPolicy: {{ $volume.podManagementPolicy }}
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" $ }}
app.kubernetes.io/instance: {{ $.Release.Name }}
app.kubernetes.io/component: {{ $volumeName }}
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: {{ $volumeName }}
{{ with $.Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with $volume.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
annotations:
{{ with $.Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with $volume.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- if $volume.affinity }}
affinity:
{{ tpl (printf "{{ $volumeName := \"%s\" }}%s" $volumeName $volume.affinity) $ | indent 8 | trim }}
{{- end }}
{{- if $volume.topologySpreadConstraints }}
topologySpreadConstraints:
{{ tpl (printf "{{ $volumeName := \"%s\" }}%s" $volumeName $volume.topologySpreadConstraints) $ | nindent 8 | trim }}
{{- end }}
restartPolicy: {{ default $.Values.global.seaweedfs.restartPolicy $volume.restartPolicy }}
{{- if $volume.tolerations }}
tolerations:
{{ tpl (printf "{{ $volumeName := \"%s\" }}%s" $volumeName $volume.tolerations) $ | indent 8 | trim }}
{{- end }}
{{- include "seaweedfs.imagePullSecrets" $ | nindent 6 }}
terminationGracePeriodSeconds: 150
{{- if $volume.priorityClassName }}
priorityClassName: {{ $volume.priorityClassName | quote }}
{{- end }}
{{- if $volume.schedulerName }}
schedulerName: {{ $volume.schedulerName | quote }}
{{- end }}
enableServiceLinks: false
serviceAccountName: {{ $volume.serviceAccountName | default (include "seaweedfs.serviceAccountName" $) | quote }} # for deleting statefulset pods after migration
{{- $initContainers_exists := include "seaweedfs.volume.initContainers_exists" $ -}}
{{- if $initContainers_exists }}
initContainers:
{{- if $volume.idx }}
- name: seaweedfs-vol-move-idx
image: {{ template "seaweedfs.volume.image" $ }}
imagePullPolicy: {{ $.Values.global.seaweedfs.imagePullPolicy | default "IfNotPresent" }}
command: [ '/bin/sh', '-c' ]
args:
- |
for dir in {{ range $index, $dir := $volume.dataDirs }}{{ if ne $index 0 }} {{ end }}/{{ $dir.name }}{{ end }}; do
# Rebuild a .idx missing from both dirs (e.g. an index volume that lost files) from the .dat, else the server fatally exits on its idx check.
for dat in "$dir"/*.dat; do
[ -e "$dat" ] || continue
base=${dat##*/}; base=${base%.dat}
if [ ! -e "$dir/$base.idx" ] && [ ! -e "/idx/$base.idx" ]; then
echo "rebuilding missing idx in $dir (trigger: volume $base)"
weed fix "$dir"
break
fi
done
if ls "$dir"/*.idx >/dev/null 2>&1; then
mv "$dir"/*.idx /idx/
fi
done
volumeMounts:
- name: idx
mountPath: /idx
{{- range $dir := $volume.dataDirs }}
- name: {{ $dir.name }}
mountPath: /{{ $dir.name }}
{{- end }}
{{- with $volume.idxVolMoveResources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if $volume.containerSecurityContext.enabled }}
securityContext: {{- omit $volume.containerSecurityContext "enabled" | toYaml | nindent 12 }}
{{- end }}
{{- end }}
{{- if $volume.initContainers }}
{{ tpl (printf "{{ $volumeName := \"%s\" }}%s" $volumeName $volume.initContainers) $ | indent 8 | trim }}
{{- end }}
{{- end }}
{{- if $volume.podSecurityContext.enabled }}
securityContext: {{- omit $volume.podSecurityContext "enabled" | toYaml | nindent 8 }}
{{- end }}
containers:
- name: seaweedfs
image: {{ template "seaweedfs.volume.image" $ }}
imagePullPolicy: {{ default "IfNotPresent" $.Values.global.seaweedfs.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: "{{ include "seaweedfs.fullname" $ }}"
{{- $mergedExtraEnvironmentVars := dict }}
{{- include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" $.Values.global.seaweedfs "component" $volume "target" $mergedExtraEnvironmentVars) }}
{{- range $key := keys $mergedExtraEnvironmentVars | sortAlpha }}
{{- $value := index $mergedExtraEnvironmentVars $key }}
- name: {{ $key }}
{{- if kindIs "string" $value }}
value: {{ tpl $value $ | quote }}
{{- else }}
valueFrom:
{{ toYaml $value | nindent 16 | trim }}
{{- end -}}
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
{{- if $volume.rust }}
exec /usr/bin/weed-volume \
{{- else }}
exec /usr/bin/weed \
{{- if $volume.logs }}
-logdir=/logs \
{{- else }}
-logtostderr=true \
{{- end }}
{{- if $volume.loggingOverrideLevel }}
-v={{ $volume.loggingOverrideLevel }} \
{{- else }}
-v={{ $.Values.global.seaweedfs.loggingLevel }} \
{{- end }}
volume \
{{- end }}
-port={{ $volume.port }} \
{{- if $volume.metricsPort }}
-metricsPort={{ $volume.metricsPort }} \
{{- end }}
{{- if $volume.metricsIp }}
-metricsIp={{ $volume.metricsIp }} \
{{- end }}
-dir {{range $index, $dir := $volume.dataDirs }}{{if ne $index 0}},{{end}}/{{$dir.name}}{{end}} \
{{- if $volume.idx }}
-dir.idx=/idx \
{{- end }}
-max {{range $index, $dir := $volume.dataDirs }}{{if ne $index 0}},{{end}}
{{- if eq ($dir.maxVolumes | toString) "0" }}0{{ else if not $dir.maxVolumes }}7{{ else }}{{$dir.maxVolumes}}{{ end }}
{{- end }} \
{{- if $volume.rack }}
-rack={{ $volume.rack }} \
{{- end }}
{{- if $volume.dataCenter }}
-dataCenter={{ $volume.dataCenter }} \
{{- end }}
{{- if $volume.id }}
-id={{ $volume.id }} \
{{- end }}
-ip.bind={{ $volume.ipBind }} \
-readMode={{ $volume.readMode }} \
{{- if $volume.whiteList }}
-whiteList={{ $volume.whiteList }} \
{{- end }}
{{- if $volume.imagesFixOrientation }}
-images.fix.orientation \
{{- end }}
{{- if and $volume.pulseSeconds (not $volume.rust) }}
-pulseSeconds={{ $volume.pulseSeconds }} \
{{- end }}
{{- if $volume.index }}
-index={{ $volume.index }} \
{{- end }}
{{- if $volume.fileSizeLimitMB }}
-fileSizeLimitMB={{ $volume.fileSizeLimitMB }} \
{{- end }}
-minFreeSpacePercent={{ $volume.minFreeSpacePercent }} \
-ip=${POD_NAME}.{{ include "seaweedfs.componentName" (list $ $volumeName) }}.{{ $.Release.Namespace }} \
-compactionMBps={{ $volume.compactionMBps }} \
-master={{ include "seaweedfs.masterServerArg" $ }} \
{{- range $volume.extraArgs }}
{{ . }} \
{{- end }}
volumeMounts:
{{- range $dir := $volume.dataDirs }}
{{- if not ( eq $dir.type "custom" ) }}
- name: {{ $dir.name }}
mountPath: "/{{ $dir.name }}/"
{{- end }}
{{- end }}
{{- if $volume.logs }}
- name: logs
mountPath: "/logs/"
{{- end }}
{{- if $volume.idx }}
- name: idx
mountPath: "/idx/"
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" $ }}
- name: security-config
readOnly: true
mountPath: /etc/seaweedfs/security.toml
subPath: security.toml
{{- end }}
{{- if $.Values.global.seaweedfs.enableSecurity }}
- 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 (printf "{{ $volumeName := \"%s\" }}%s" $volumeName $volume.extraVolumeMounts) $ | indent 12 | trim }}
ports:
- containerPort: {{ $volume.port }}
name: swfs-vol
{{- if $volume.metricsPort }}
- containerPort: {{ $volume.metricsPort }}
name: metrics
{{- end }}
- containerPort: {{ $volume.grpcPort }}
name: swfs-vol-grpc
{{- if $volume.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: {{ $volume.readinessProbe.httpGet.path }}
port: {{ $volume.port }}
scheme: {{ $volume.readinessProbe.httpGet.scheme }}
initialDelaySeconds: {{ $volume.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ $volume.readinessProbe.periodSeconds }}
successThreshold: {{ $volume.readinessProbe.successThreshold }}
failureThreshold: {{ $volume.readinessProbe.failureThreshold }}
timeoutSeconds: {{ $volume.readinessProbe.timeoutSeconds }}
{{- end }}
{{- if $volume.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: {{ $volume.livenessProbe.httpGet.path }}
port: {{ $volume.port }}
scheme: {{ $volume.livenessProbe.httpGet.scheme }}
initialDelaySeconds: {{ $volume.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ $volume.livenessProbe.periodSeconds }}
successThreshold: {{ $volume.livenessProbe.successThreshold }}
failureThreshold: {{ $volume.livenessProbe.failureThreshold }}
timeoutSeconds: {{ $volume.livenessProbe.timeoutSeconds }}
{{- end }}
{{- with $volume.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if $volume.containerSecurityContext.enabled }}
securityContext: {{- omit $volume.containerSecurityContext "enabled" | toYaml | nindent 12 }}
{{- end }}
{{- if $volume.sidecars }}
{{- include "seaweedfs.tplvalues.render" (dict "value" (printf "{{ $volumeName := \"%s\" }}%s" $volumeName $volume.sidecars) "context" $) | nindent 8 }}
{{- end }}
volumes:
{{- range $dir := $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 $volume.idx }}
{{- if eq $volume.idx.type "hostPath" }}
- name: idx
hostPath:
path: {{ $volume.idx.hostPathPrefix }}/seaweedfs-volume-idx/
type: DirectoryOrCreate
{{- end }}
{{- if eq $volume.idx.type "existingClaim" }}
- name: idx
persistentVolumeClaim:
claimName: {{ $volume.idx.claimName }}
{{- end }}
{{- if eq $volume.idx.type "emptyDir" }}
- name: idx
emptyDir: {}
{{- end }}
{{- end }}
{{- if $volume.logs }}
{{- if eq $volume.logs.type "hostPath" }}
- name: logs
hostPath:
path: {{ $volume.logs.hostPathPrefix }}/logs/seaweedfs/volume
type: DirectoryOrCreate
{{- end }}
{{- if eq $volume.logs.type "existingClaim" }}
- name: logs
persistentVolumeClaim:
claimName: {{ $volume.logs.claimName }}
{{- end }}
{{- if eq $volume.logs.type "emptyDir" }}
- name: logs
emptyDir: {}
{{- end }}
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" $ }}
- name: security-config
configMap:
name: {{ include "seaweedfs.fullname" $ }}-security-config
{{- end }}
{{- if $.Values.global.seaweedfs.enableSecurity }}
- name: ca-cert
secret:
secretName: {{ include "seaweedfs.fullname" $ }}-ca-cert
- name: master-cert
secret:
secretName: {{ include "seaweedfs.fullname" $ }}-master-cert
- name: volume-cert
secret:
secretName: {{ include "seaweedfs.fullname" $ }}-volume-cert
- name: filer-cert
secret:
secretName: {{ include "seaweedfs.fullname" $ }}-filer-cert
- name: client-cert
secret:
secretName: {{ include "seaweedfs.fullname" $ }}-client-cert
{{- end }}
{{- if $volume.extraVolumes }}
{{ tpl $volume.extraVolumes $ | indent 8 | trim }}
{{- end }}
{{- if $volume.nodeSelector }}
nodeSelector:
{{ tpl (printf "{{ $volumeName := \"%s\" }}%s" $volumeName $volume.nodeSelector) $ | indent 8 | trim }}
{{- end }}
volumeClaimTemplates:
{{- range $dir := $volume.dataDirs }}
{{- if eq $dir.type "persistentVolumeClaim" }}
- apiVersion: v1
kind: 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 $volume.idx (eq $volume.idx.type "persistentVolumeClaim") }}
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: idx
{{- with $volume.idx.annotations }}
annotations:
{{- toYaml . | nindent 10 }}
{{- end }}
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: {{ $volume.idx.storageClass }}
resources:
requests:
storage: {{ $volume.idx.size }}
{{- end }}
{{- if and $volume.logs (eq $volume.logs.type "persistentVolumeClaim") }}
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: logs
{{- with $volume.logs.annotations }}
annotations:
{{- toYaml . | nindent 10 }}
{{- end }}
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: {{ $volume.logs.storageClass }}
resources:
requests:
storage: {{ $volume.logs.size }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,365 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.worker.enabled }}
{{- if and (not .Values.worker.adminServer) (not .Values.admin.enabled) }}
{{- fail "worker.adminServer must be set if admin.enabled is false within the same release" -}}
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "seaweedfs.fullname" . }}-worker
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: worker
{{- if .Values.worker.annotations }}
annotations:
{{- toYaml .Values.worker.annotations | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.worker.replicas }}
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: worker
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: worker
{{ with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.worker.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
annotations:
{{ with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.worker.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
restartPolicy: {{ default .Values.global.seaweedfs.restartPolicy .Values.worker.restartPolicy }}
{{- if .Values.worker.affinity }}
affinity:
{{ tpl .Values.worker.affinity . | nindent 8 | trim }}
{{- end }}
{{- if .Values.worker.topologySpreadConstraints }}
topologySpreadConstraints:
{{ tpl .Values.worker.topologySpreadConstraints . | nindent 8 | trim }}
{{- end }}
{{- if .Values.worker.tolerations }}
tolerations:
{{ tpl .Values.worker.tolerations . | nindent 8 | trim }}
{{- end }}
{{- include "seaweedfs.imagePullSecrets" . | nindent 6 }}
terminationGracePeriodSeconds: 60
{{- if .Values.worker.priorityClassName }}
priorityClassName: {{ .Values.worker.priorityClassName | quote }}
{{- end }}
{{- if .Values.worker.schedulerName }}
schedulerName: {{ .Values.worker.schedulerName | quote }}
{{- end }}
enableServiceLinks: false
{{- if .Values.worker.serviceAccountName }}
serviceAccountName: {{ .Values.worker.serviceAccountName | quote }}
{{- end }}
{{- if .Values.worker.initContainers }}
initContainers:
{{ tpl .Values.worker.initContainers . | nindent 8 | trim }}
{{- end }}
{{- if .Values.worker.podSecurityContext.enabled }}
securityContext: {{- omit .Values.worker.podSecurityContext "enabled" | toYaml | nindent 8 }}
{{- end }}
containers:
- name: seaweedfs
image: {{ template "seaweedfs.worker.image" . }}
imagePullPolicy: {{ default "IfNotPresent" .Values.global.seaweedfs.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: "{{ include "seaweedfs.fullname" . }}"
{{- $mergedExtraEnvironmentVars := dict }}
{{- include "seaweedfs.mergeExtraEnvironmentVars" (dict "global" .Values.global.seaweedfs "component" .Values.worker "target" $mergedExtraEnvironmentVars) }}
{{- range $key := keys $mergedExtraEnvironmentVars | sortAlpha }}
{{- $value := index $mergedExtraEnvironmentVars $key }}
- name: {{ $key }}
{{- if kindIs "string" $value }}
value: {{ tpl $value $ | quote }}
{{- else }}
valueFrom:
{{ toYaml $value | nindent 16 | trim }}
{{- end -}}
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
exec /usr/bin/weed \
{{- if or (eq .Values.worker.logs.type "hostPath") (eq .Values.worker.logs.type "emptyDir") (eq .Values.worker.logs.type "existingClaim") }}
-logdir=/logs \
{{- else }}
-logtostderr=true \
{{- end }}
{{- if .Values.worker.loggingOverrideLevel }}
-v={{ .Values.worker.loggingOverrideLevel }} \
{{- else }}
-v={{ .Values.global.seaweedfs.loggingLevel }} \
{{- end }}
worker \
{{- if .Values.worker.adminServer }}
-admin={{ .Values.worker.adminServer }} \
{{- else }}
-admin={{ template "seaweedfs.fullname" . }}-admin.{{ .Release.Namespace }}:{{ .Values.admin.port }}{{ if .Values.admin.grpcPort }}.{{ .Values.admin.grpcPort }}{{ end }} \
{{- end }}
-jobType={{ .Values.worker.jobType }} \
-maxDetect={{ .Values.worker.maxDetect }} \
-maxExecute={{ .Values.worker.maxExecute }} \
-workingDir={{ .Values.worker.workingDir }}{{- if or .Values.worker.metricsPort .Values.worker.metricsIp .Values.worker.extraArgs }} \{{ end }}
{{- if .Values.worker.metricsPort }}
-metricsPort={{ .Values.worker.metricsPort }}{{- if or .Values.worker.metricsIp .Values.worker.extraArgs }} \{{ end }}
{{- end }}
{{- if .Values.worker.metricsIp }}
-metricsIp={{ .Values.worker.metricsIp }}{{- if .Values.worker.extraArgs }} \{{ end }}
{{- end }}
{{- range $index, $arg := .Values.worker.extraArgs }}
{{ $arg }}{{- if lt $index (sub (len $.Values.worker.extraArgs) 1) }} \{{ end }}
{{- end }}
volumeMounts:
{{- if or (eq .Values.worker.data.type "hostPath") (eq .Values.worker.data.type "emptyDir") (eq .Values.worker.data.type "existingClaim") }}
- name: worker-data
mountPath: {{ .Values.worker.workingDir }}
{{- end }}
{{- if or (eq .Values.worker.logs.type "hostPath") (eq .Values.worker.logs.type "emptyDir") (eq .Values.worker.logs.type "existingClaim") }}
- name: worker-logs
mountPath: /logs
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
readOnly: true
mountPath: /etc/seaweedfs/security.toml
subPath: security.toml
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- 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/
- name: worker-cert
readOnly: true
mountPath: /usr/local/share/ca-certificates/worker/
{{- end }}
{{ tpl .Values.worker.extraVolumeMounts . | nindent 12 | trim }}
ports:
{{- if .Values.worker.metricsPort }}
- containerPort: {{ .Values.worker.metricsPort }}
name: metrics
{{- end }}
{{- with .Values.worker.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.worker.livenessProbe.enabled }}
livenessProbe:
{{- if .Values.worker.livenessProbe.httpGet }}
httpGet:
path: {{ .Values.worker.livenessProbe.httpGet.path }}
port: {{ .Values.worker.livenessProbe.httpGet.port }}
{{- else if .Values.worker.livenessProbe.tcpSocket }}
tcpSocket:
port: {{ .Values.worker.livenessProbe.tcpSocket.port }}
{{- end }}
initialDelaySeconds: {{ .Values.worker.livenessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.worker.livenessProbe.periodSeconds }}
successThreshold: {{ .Values.worker.livenessProbe.successThreshold }}
failureThreshold: {{ .Values.worker.livenessProbe.failureThreshold }}
timeoutSeconds: {{ .Values.worker.livenessProbe.timeoutSeconds }}
{{- end }}
{{- if .Values.worker.readinessProbe.enabled }}
readinessProbe:
{{- if .Values.worker.readinessProbe.httpGet }}
httpGet:
path: {{ .Values.worker.readinessProbe.httpGet.path }}
port: {{ .Values.worker.readinessProbe.httpGet.port }}
{{- else if .Values.worker.readinessProbe.tcpSocket }}
tcpSocket:
port: {{ .Values.worker.readinessProbe.tcpSocket.port }}
{{- end }}
initialDelaySeconds: {{ .Values.worker.readinessProbe.initialDelaySeconds }}
periodSeconds: {{ .Values.worker.readinessProbe.periodSeconds }}
successThreshold: {{ .Values.worker.readinessProbe.successThreshold }}
failureThreshold: {{ .Values.worker.readinessProbe.failureThreshold }}
timeoutSeconds: {{ .Values.worker.readinessProbe.timeoutSeconds }}
{{- end }}
{{- if .Values.worker.containerSecurityContext.enabled }}
securityContext: {{- omit .Values.worker.containerSecurityContext "enabled" | toYaml | nindent 12 }}
{{- end }}
{{- if include "seaweedfs.worker.lanceNamespaceUrl" . }}
- name: worker-lance
image: {{ template "seaweedfs.worker.image" . }}
imagePullPolicy: {{ default "IfNotPresent" .Values.global.seaweedfs.imagePullPolicy }}
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
{{- /* the URL crosses a shell line; metacharacters must arrive as data, not syntax */}}
- name: LANCE_NAMESPACE_URL
value: {{ include "seaweedfs.worker.lanceNamespaceUrl" . | quote }}
command:
- "/bin/sh"
- "-ec"
- |
{{- /* the armv7/386 placeholder is empty; exec of it becomes the shell and exits 0 */}}
if [ ! -s /usr/bin/weed-worker ]; then
echo "the Rust worker is not available on this platform ($(uname -m)); it ships for amd64 and arm64" >&2
exit 1
fi
exec /usr/bin/weed-worker \
--id="$POD_NAME" \
{{- if .Values.worker.adminServer }}
--admin={{ .Values.worker.adminServer }} \
{{- else }}
--admin={{ template "seaweedfs.fullname" . }}-admin.{{ .Release.Namespace }}:{{ .Values.admin.port }}{{ if .Values.admin.grpcPort }}.{{ .Values.admin.grpcPort }}{{ end }} \
{{- end }}
--namespace="$LANCE_NAMESPACE_URL" \
{{- if .Values.global.seaweedfs.enableSecurity }}
--tls-ca=/usr/local/share/ca-certificates/ca/tls.crt \
--tls-cert=/usr/local/share/ca-certificates/worker/tls.crt \
--tls-key=/usr/local/share/ca-certificates/worker/tls.key \
{{- end }}
{{- if .Values.worker.lanceMetricsPort }}
--metrics-port={{ .Values.worker.lanceMetricsPort }} \
--metrics-ip=0.0.0.0 \
{{- end }}
--max-concurrency={{ .Values.worker.maxExecute }}
{{- if .Values.global.seaweedfs.enableSecurity }}
volumeMounts:
- name: ca-cert
readOnly: true
mountPath: /usr/local/share/ca-certificates/ca/
- name: worker-cert
readOnly: true
mountPath: /usr/local/share/ca-certificates/worker/
{{- end }}
{{- if .Values.worker.lanceMetricsPort }}
ports:
- containerPort: {{ .Values.worker.lanceMetricsPort }}
name: lance-metrics
livenessProbe:
httpGet:
path: /health
port: lance-metrics
initialDelaySeconds: 30
periodSeconds: 60
successThreshold: 1
failureThreshold: 5
timeoutSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: lance-metrics
initialDelaySeconds: 20
periodSeconds: 15
successThreshold: 1
failureThreshold: 3
timeoutSeconds: 10
{{- end }}
{{- if .Values.worker.containerSecurityContext.enabled }}
securityContext: {{- omit .Values.worker.containerSecurityContext "enabled" | toYaml | nindent 12 }}
{{- end }}
{{- end }}
{{- if .Values.worker.sidecars }}
{{- include "seaweedfs.tplvalues.render" (dict "value" .Values.worker.sidecars "context" $) | nindent 8 }}
{{- end }}
volumes:
{{- if eq .Values.worker.data.type "hostPath" }}
- name: worker-data
hostPath:
path: {{ .Values.worker.data.hostPathPrefix }}/seaweedfs-worker-data
type: DirectoryOrCreate
{{- end }}
{{- if eq .Values.worker.data.type "emptyDir" }}
- name: worker-data
emptyDir: {}
{{- end }}
{{- if eq .Values.worker.data.type "existingClaim" }}
- name: worker-data
persistentVolumeClaim:
claimName: {{ .Values.worker.data.claimName }}
{{- end }}
{{- if eq .Values.worker.logs.type "hostPath" }}
- name: worker-logs
hostPath:
path: {{ .Values.worker.logs.hostPathPrefix }}/logs/seaweedfs/worker
type: DirectoryOrCreate
{{- end }}
{{- if eq .Values.worker.logs.type "emptyDir" }}
- name: worker-logs
emptyDir: {}
{{- end }}
{{- if eq .Values.worker.logs.type "existingClaim" }}
- name: worker-logs
persistentVolumeClaim:
claimName: {{ .Values.worker.logs.claimName }}
{{- end }}
{{- if include "seaweedfs.securityConfigEnabled" . }}
- name: security-config
configMap:
name: {{ include "seaweedfs.fullname" . }}-security-config
{{- end }}
{{- if .Values.global.seaweedfs.enableSecurity }}
- name: ca-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-ca-cert
- name: master-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-master-cert
- name: volume-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-volume-cert
- name: filer-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-filer-cert
- name: client-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-client-cert
- name: worker-cert
secret:
secretName: {{ include "seaweedfs.fullname" . }}-worker-cert
{{- end }}
{{ tpl .Values.worker.extraVolumes . | indent 8 | trim }}
{{- if .Values.worker.nodeSelector }}
nodeSelector:
{{ tpl .Values.worker.nodeSelector . | indent 8 | trim }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,35 @@
{{- if .Values.worker.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "seaweedfs.componentName" (list . "worker") }}
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: worker
spec:
clusterIP: None # Headless service
{{- $lanceMetrics := and .Values.worker.lanceMetricsPort (include "seaweedfs.worker.lanceNamespaceUrl" .) }}
{{- if or .Values.worker.metricsPort $lanceMetrics }}
ports:
{{- if .Values.worker.metricsPort }}
- name: "metrics"
port: {{ .Values.worker.metricsPort }}
targetPort: {{ .Values.worker.metricsPort }}
protocol: TCP
{{- end }}
{{- if $lanceMetrics }}
- name: "lance-metrics"
port: {{ .Values.worker.lanceMetricsPort }}
targetPort: {{ .Values.worker.lanceMetricsPort }}
protocol: TCP
{{- end }}
{{- end }}
selector:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: worker
{{- end }}

View File

@@ -0,0 +1,43 @@
{{- include "seaweedfs.compat" . -}}
{{- if .Values.worker.enabled }}
{{- $lanceMetrics := and .Values.worker.lanceMetricsPort (include "seaweedfs.worker.lanceNamespaceUrl" .) }}
{{- if or .Values.worker.metricsPort $lanceMetrics }}
{{- if .Values.global.seaweedfs.monitoring.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "seaweedfs.fullname" . }}-worker
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: worker
{{- with .Values.global.seaweedfs.monitoring.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.worker.serviceMonitor.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
endpoints:
{{- if .Values.worker.metricsPort }}
- interval: 30s
port: metrics
scrapeTimeout: 5s
{{- end }}
{{- if $lanceMetrics }}
- interval: 30s
port: lance-metrics
scrapeTimeout: 5s
{{- end }}
selector:
matchLabels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: worker
{{- end }}
{{- end }}
{{- end }}

File diff suppressed because it is too large Load Diff