diff --git a/docs/book/getting-started/deploying-zenml/deploy-with-helm.md b/docs/book/getting-started/deploying-zenml/deploy-with-helm.md index b28a8ddb518..3df409bd92c 100644 --- a/docs/book/getting-started/deploying-zenml/deploy-with-helm.md +++ b/docs/book/getting-started/deploying-zenml/deploy-with-helm.md @@ -147,6 +147,30 @@ zenml login http://localhost:8080 This is just a simple example only fit for testing and evaluation purposes. For production deployments, you should use an external database and an Ingress service with TLS certificates to secure and expose the ZenML server to the internet. +### Deployment with persistent local database + +When using a local SQLite database with persistence enabled, you need to configure proper volume permissions. The ZenML Helm chart sets `podSecurityContext.fsGroup: 1000` by default to ensure the ZenML container (running as UID 1000) can write to the persistent volume. + +Example configuration: + +```yaml +zenml: + database: + persistence: + enabled: true + size: "10Gi" + # storageClassName: "" # Optional: use default storage class if not specified + +# podSecurityContext.fsGroup is set to 1000 by default +# This ensures the container can write to the persistent volume +``` + +{% hint style="warning" %} +If you override `podSecurityContext` in your custom values, ensure that `fsGroup: 1000` is included. Without this setting, the persistent volume will be mounted with root:root ownership, causing permission errors and preventing the ZenML server from starting. +{% endhint %} + +This configuration is also required when using persistent volumes for database backup dumps. See the [Database backup and recovery](deploy-with-helm.md#database-backup-and-recovery) section for more details. + ### Basic deployment with local database This deployment use-case still uses a local database, but it exposes the ZenML server to the internet using an Ingress service with TLS certificates generated by the cert-manager and signed by Let's Encrypt. diff --git a/helm/README.md b/helm/README.md index 5a1d0eaeab8..a01d0145fc9 100644 --- a/helm/README.md +++ b/helm/README.md @@ -92,6 +92,26 @@ You can add additional exclusions using the `additionalNoProxy` list. The NO_PRO - IPv6 addresses (e.g., "::1") - IPv6 ranges in CIDR notation (e.g., "fe80::/10") +### Database Persistence + +When using database persistence with a local SQLite database, the chart automatically configures the necessary permissions. The `podSecurityContext.fsGroup` is set to 1000 by default to ensure the ZenML container (running as UID 1000) can write to the persistent volume. + +Example configuration: + +```yaml +zenml: + database: + persistence: + enabled: true + size: "10Gi" + # storageClassName: "" # Optional: use default storage class if not specified + +# podSecurityContext.fsGroup is set to 1000 by default +# This ensures the container can write to the persistent volume +``` + +If you override `podSecurityContext`, ensure that `fsGroup: 1000` is set when using persistent volumes, otherwise the container will not be able to write to the mounted volume and will crash. + ## Telemetry The ZenML server collects anonymous usage data to help us improve the product. You can opt out by setting `zenml.analyticsOptIn` to false. diff --git a/helm/values.yaml b/helm/values.yaml index 326b632e4fe..2b92c5cef1a 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -314,6 +314,10 @@ zenml: # If set to true, path where the local database is created will be # mounted as a persistent volume so the data is not lost on pod restarts. # Only relevant for local sqlite database. + # When persistence is enabled, ensure that podSecurityContext.fsGroup + # is set to 1000 (this is the default) so that the ZenML container can write to + # the persistent volume. The container runs as UID 1000, and without fsGroup + # set, the PVC will be mounted with root:root ownership, causing permission errors. persistence: enabled: false size: 1Gi @@ -1173,8 +1177,14 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} - # fsGroup: 1000 # if you're using a PVC for backup, this should necessarily be set. +podSecurityContext: + # fsGroup must be set to 1000 when using persistent volumes (database persistence or backup PVCs) + # to ensure the ZenML container (running as UID 1000) can write to the mounted volumes. + # This is set by default to prevent permission issues. + fsGroup: 1000 + # fsGroupChangePolicy controls when fsGroup ownership changes are applied. + # "OnRootMismatch" only changes ownership if the root of the volume doesn't match the fsGroup. + fsGroupChangePolicy: "OnRootMismatch" securityContext: runAsNonRoot: true