This is the multi-page printable view of this section. .
Module: JUICE
- 1: Configuration
- 2: Parameters
- 3: Playbook
- 4: Administration
- 5: Monitoring
- 6: FAQ
JuiceFS is a high-performance, POSIX-compatible distributed filesystem. It can mount object storage or databases as a local filesystem.
The JUICE module depends on NODE for infrastructure and the package repository. It typically uses PGSQL as the metadata engine.
File data can reside in a PostgreSQL jfs_blob table. It can also reside in Silo or S3-compatible object storage from the MINIO module. Monitoring uses VictoriaMetrics from INFRA.
flowchart LR
subgraph Client["App/User"]
app["POSIX Access"]
end
subgraph JUICE["JUICE"]
jfs["JuiceFS Mount"]
end
subgraph PGSQL["PGSQL"]
meta["Metadata DB"]
blob["Data DB / jfs_blob (optional)"]
end
subgraph Object["Object Storage (optional)"]
s3["Silo / S3"]
end
subgraph INFRA["INFRA (optional)"]
vm["VictoriaMetrics"]
end
app --> jfs
jfs --> meta
jfs -.->|alternative data backend| blob
jfs -.->|alternative data backend| s3
jfs -->|/metrics| vm
style JUICE fill:#5B9CD5,stroke:#4178a8,color:#fff
style PGSQL fill:#3E668F,stroke:#2d4a66,color:#fff
style Object fill:#FCDB72,stroke:#d4b85e,color:#333
style INFRA fill:#999,stroke:#666,color:#fffFeatures
- PostgreSQL metadata: Metadata stored in PostgreSQL for easy management and backup
- Multi-instance: One node can mount multiple independent filesystem instances
- Multiple data backends: PostgreSQL, Silo/MinIO, S3, and more. Metadata and file data remain separate roles.
- Monitoring integration: Each instance exposes Prometheus / Victoria-format metrics port
- Simple config: Describe instances with the
juice_instancesdict
Quick Start
Minimal config example (single instance):
Deploy:
1 - Configuration
Concepts and Implementation
JuiceFS consists of a metadata engine and data storage.
The current version passes meta to juicefs as the metadata engine URL. Production deployments typically use PostgreSQL.
Data storage is defined by data options passed to juicefs format.
JUICE module core commands:
Notes:
--no-updateensures existing filesystems are not overwritten.dataapplies only to the initial format. It does not affect existing filesystems.mountapplies only during mounting. Use it to pass cache and concurrency options.
Module Parameters
JUICE module has only two parameters:
| Parameter | Type | Level | Description |
|---|---|---|---|
juice_cache | path | C | JuiceFS shared cache directory |
juice_instances | dict | I | JuiceFS instance dict (can be empty) |
juice_cache: shared local cache directory for all instances, default/data/juicejuice_instances: Instance-level dictionary. Each key is a filesystem name. An empty dictionary means that the module manages no instances.
Instance Configuration
Each entry in juice_instances represents a JuiceFS instance:
| Field | Required | Default | Description |
|---|---|---|---|
path | Yes | - | Mount point path, e.g. /fs |
meta | Yes | - | Metadata engine URL (PostgreSQL recommended) |
data | No | '' | juicefs format options (storage backend) |
unit | No | juicefs-<name> | systemd service name |
mount | No | '' | Extra juicefs mount options |
port | No | 9567 | Metrics port (unique per node) |
owner | No | root | Mount point owner |
group | No | root | Mount point group |
mode | No | 0755 | Mount point permissions |
state | No | create | create / absent |
- We recommend that you explicitly set
dataon the first format. This makes the storage backend clear. - Multiple instances on the same node must use different
portvalues.
Example:
Storage Backends
The module appends data to juicefs format. You can use any supported backend. Common examples follow.
PostgreSQL Data Backend
JuiceFS creates a jfs_blob table in the database selected by --bucket for file data. The PostgreSQL data backend and the meta metadata engine have separate roles. They can use one database or separate deployments. The database and a user with read/write privileges must already exist.
Silo / MinIO-Compatible Object Storage
S3-Compatible Storage
Typical Configurations
Multi-Instance (Same Node)
Shared Mount Across Nodes
Mount the same JuiceFS on multiple nodes:
Only one node needs to format the filesystem. Other nodes skip this operation because of --no-update.
Notes
portis exposed on0.0.0.0. Use firewall or security group to restrict access.- A change to
datadoes not update an existing filesystem. Migrate the data manually. metaanddatacan contain database or object-storage credentials. Restrict access topigsty.yml. Use dedicated accounts with the minimum required privileges. Never keep example passwords in production.
2 - Parameters
The JUICE module has 2 parameters:
juice_cache: shared cache directoryjuice_instances: instance definition dict
Parameter Overview
| Parameter | Type | Level | Description |
|---|---|---|---|
juice_cache | path | C | JuiceFS shared cache directory |
juice_instances | dict | I | JuiceFS instance definition dict (can be empty) |
Level:
C= cluster level,I= instance level.
Default Parameters
Defined in roles/juice/defaults/main.yml:
juice_cache
Parameter: juice_cache, type: path, level: C
Shared local cache directory for all JuiceFS instances, default /data/juice.
JuiceFS isolates caches by filesystem UUID under this directory.
juice_instances
Parameter: juice_instances, type: dict, level: I
Dictionary of instance definitions, usually set at the instance level. The default is an empty dictionary, which deploys no instances. Each key is a filesystem name. Each value is an instance configuration object.
Instance fields:
| Field | Required | Default | Description |
|---|---|---|---|
path | Yes | - | Mount point path |
meta | Yes | - | Metadata engine URL (PostgreSQL recommended) |
data | No | '' | juicefs format options (only effective on first creation) |
unit | No | juicefs-<name> | systemd service name |
mount | No | '' | Extra juicefs mount options |
port | No | 9567 | Metrics port (unique per node) |
owner | No | root | Mount point owner |
group | No | root | Mount point group |
mode | No | 0755 | Mount point permissions |
state | No | create | create / absent |
- Only
juicefs formatusesdata. It does not update an existing filesystem. - Multiple instances on the same node must use different
portvalues.
3 - Playbook
The JUICE module provides the juice.yml playbook to deploy and remove JuiceFS instances.
juice.yml
Task structure in juice.yml:
Scope
| Scope | Limit | Description |
|---|---|---|
| Node | -l <host> | Deploy all instances on the node |
| Instance | -l <host> -e fsname=<name> | Only handle specified instance |
Examples:
Common Tags
| Tag | Description |
|---|---|
juice_id | Validate juice_instances and port conflicts |
juice_install | Install juicefs package |
juice_cache | Create shared cache dir |
juice_clean | Remove instance (state=absent) |
juice_instance | Create instance (umbrella tag) |
juice_init | Format filesystem |
juice_dir | Create mount dir |
juice_config | Render config files |
juice_launch | Start service |
juice_register | Write VictoriaMetrics target file |
Config Updates
Render config only (no restart):
Update config and ensure service is online (without force restart):
If you need new mount options to take effect immediately, manually restart the instance service:
Remove Instance
Removal flow:
- Set instance
statetoabsent - Run
juice_clean
Removal stops the service and performs a lazy unmount. It removes the systemd unit and environment files, then reloads systemd. The juice_register task then rewrites the node’s target file and removes stale scrape endpoints. If you run only juice_clean, monitoring targets remain unchanged.
PostgreSQL metadata, PostgreSQL jfs_blob data tables, and object-storage data are not deleted.
Monitoring Registration
juice_register writes the target file on the infra node:
To re-register manually:
4 - Administration
Common operations:
- Initialize Instance
- Reconfigure
- Remove Instance
- Add New Instance
- Shared Mount Across Nodes
- PITR Recovery
- Troubleshooting
- Performance Tuning
See FAQ for more.
Initialize Instance
Initialization steps:
- Install
juicefspackage - Create shared cache dir (default
/data/juice) - Run
juicefs format --no-update(only effective on first creation) - Create mount point and set permissions
- Render systemd unit and env files
- Start service and wait for metrics port
- Register to VictoriaMetrics (if infra node exists)
Reconfigure
After configuration changes, we recommend this command to update the configuration and make sure the service is running:
To generate the configuration without changing the service state:
Notes:
juice_config,juice_launchsets the service state tostarted. It does not force a restart of a running instance.dataonly takes effect on the firstformat- After changing
mountoptions, manually restart the instance service (systemctl restart juicefs-<name>)
Remove Instance
- Set instance
statetoabsent - Run
juice_clean
Removal actions:
- Stop systemd service
umount -llazy unmount- Remove unit and env files
- Reload systemd
- Rewrite this node’s VictoriaMetrics target file, removing instances with
state=absent
PostgreSQL metadata, PostgreSQL jfs_blob data tables, and object-storage data are not deleted.
If you run only -t juice_clean, monitoring targets remain unchanged. Removed instances temporarily retain stale scrape endpoints. The commands above also run juice_register to update these targets.
Add New Instance
Add a new instance to the configuration. Give it a unique port:
Deploy:
Shared Mount Across Nodes
Configure the same meta and instance name on multiple nodes:
Only one node needs to format the filesystem. Other nodes skip this operation because of --no-update.
PITR Recovery
Restore JuiceFS metadata and data to a mutually consistent state. Before any restore, stop every writer. Unmount or stop the corresponding JuiceFS service on every client. Identify the exact PostgreSQL cluster and target time. Confirm that a backup is available:
First, confirm the exact cluster name, a recent backup, the recovery target, and a rollback plan. Only then follow the PostgreSQL PITR tutorial to stop Patroni/PostgreSQL and restore the data. The pg-pitr command does not stop services, repair Patroni/DCS, validate data, or rebuild replicas. The command above is not a complete recovery procedure.
If metadata and the --storage postgres jfs_blob table share the restored PostgreSQL database, PITR can restore both to the same time. If they reside in different databases or clusters, design a coordinated recovery point for both.
If file data resides in Silo/S3, PostgreSQL PITR rolls back metadata only. It does not restore objects. Newer objects can remain. Older objects can be unavailable if they were deleted or removed by garbage collection.
Recovery depends on object versioning, trash, and lifecycle policies. Do not run garbage collection until validation is complete.
Troubleshooting
Mount Fails
Metadata Connection Issues
Metrics Port Check
Performance Tuning
Pass juicefs mount options via mount:
Key metrics to watch:
juicefs_blockcache_hits/juicefs_blockcache_miss: cache hit ratiojuicefs_object_request_durations_histogram_seconds: object storage latencyjuicefs_transaction_durations_histogram_seconds: metadata transaction latency
5 - Monitoring
JuiceFS instances expose Prometheus metrics via juicefs mount --metrics.
In JUICE, the metrics endpoint listens on 0.0.0.0:<port>. The default port is 9567.
Monitoring Architecture
If INFRA is deployed, juice_register writes scrape targets to:
The current source includes the Node JuiceFS dashboard (UID: node-juice). It shows capacity, cache, object-storage, metadata-transaction, and client-resource metrics for JuiceFS mounts on a node.
Target File Example
To register manually:
Key Metrics
Object Storage
| Metric | Type | Description |
|---|---|---|
juicefs_object_request_durations_histogram_seconds | histogram | Object storage request latency |
juicefs_object_request_errors | counter | Object storage errors |
Cache
| Metric | Type | Description |
|---|---|---|
juicefs_blockcache_hits | counter | Cache hits |
juicefs_blockcache_miss | counter | Cache misses |
Metadata Transactions
| Metric | Type | Description |
|---|---|---|
juicefs_transaction_durations_histogram_seconds | histogram | Metadata transaction latency (histogram) |
juicefs_transaction_durations_histogram_seconds_count | counter | Metadata transaction request count |
Common PromQL
Cache hit ratio:
Object storage P99 latency:
6 - FAQ
Port Conflicts?
Multiple instances on the same node must use different port values. Example:
Why does changing data not take effect?
Only juicefs format --no-update uses data. This setting does not change the filesystem after creation. To change the backend, migrate the data and reformat manually.
How to add a new instance?
- Add instance definition in config
- Run:
How to remove an instance?
- Set instance
statetoabsent - Run:
Removal does not delete PostgreSQL metadata or object storage data.
juice_register updates the target file. If you run only juice_clean, a stale monitoring scrape endpoint remains.
Where is file data stored?
Depends on data:
--storage postgres: JuiceFS creates ajfs_blobtable in the PostgreSQL database selected by--bucket--storage minio/s3: data is stored in a Silo/S3-compatible object-storage bucket
meta specifies the metadata engine. Pigsty production deployments usually use PostgreSQL for this role.
Multi-node mount notes?
- Use the same
metaand instance name on all nodes - Only one node needs to format the filesystem. Other nodes skip this operation.
- Ensure
portdoes not conflict on each node
Monitoring target not generated?
juice_register only writes /infra/targets/juice/ when infra group exists.
You can run manually:
How to change mount options?
After you update mount in the instance, refresh the configuration. Then restart the service manually: