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 that can mount object storage or databases as a local filesystem.
The JUICE module depends on NODE for infrastructure and package repo, and typically uses PGSQL as the metadata engine.
Data storage can be PostgreSQL (in a jfs_blob table) or Silo / S3-compatible object storage provided by the MINIO module. Monitoring relies on INFRA VictoriaMetrics.
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:#fff
Features
- 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.
In the current version, meta is passed through to juicefs as the metadata engine URL, and PostgreSQL is typically used in production.
Data storage is defined by data options passed to juicefs format.
JUICE module core commands:
Notes:
--no-updateensures existing filesystems are not overwritten.datais only used for initial format; it does not affect existing filesystems.mountis only used during mount, you can 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 dict, key is filesystem name; an empty dict means no instances are managed
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 |
- It’s recommended to explicitly set
dataon first format to make the storage backend clear. - Multiple instances on the same node must use different
portvalues.
Example:
Storage Backends
data is appended to juicefs format, any supported backend works. Common examples:
PostgreSQL Data Backend
JuiceFS creates a jfs_blob table in the database selected by --bucket for file data. This PostgreSQL data backend and the meta metadata engine are separate roles; they may use one database or be deployed separately. 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; others will skip via --no-update.
Notes
portis exposed on0.0.0.0. Use firewall or security group to restrict access.- Changing
datawill not update an existing filesystem; handle migration manually. metaanddatamay contain database or object-storage credentials. Restrict access topigsty.yml, use dedicated least-privilege accounts, and never keep example passwords in production.
2 - Parameters
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
Instance definition dict, usually defined at instance level. Default is an empty dict (meaning no instances are deployed). Key is filesystem name, value is instance config 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 |
datais only used byjuicefs format, it will not update an existing filesystem.- Multiple instances on the same node must use different
portvalues.
3 - Playbook
JUICE module provides 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 includes stopping the service, lazy unmounting, removing systemd unit and environment files, and reloading systemd. juice_register then rewrites the node’s target file and removes stale scrape endpoints. Running only juice_clean does not update monitoring targets.
PostgreSQL metadata, PostgreSQL jfs_blob data tables, and object-storage data are not deleted.
Monitoring Registration
juice_register writes target file on 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 changing config, it’s recommended to run (update config and ensure service is online):
Render config without touching service state:
Notes:
juice_config,juice_launchensures service isstarted, but does not force-restart an already running instancedataonly 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.
Running only -t juice_clean does not update monitoring targets and temporarily leaves stale scrape endpoints for removed instances. The commands above therefore run juice_register as well.
Add New Instance
Add a new instance in config, ensure 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; others will skip via --no-update.
PITR Recovery
JuiceFS metadata and data must be restored to a mutually consistent state. Before any restore, stop every writer and unmount/stop the corresponding JuiceFS service on every client, identify the exact PostgreSQL cluster and target time, and confirm an available backup:
Only after confirming the exact cluster name, a recent backup, the recovery target, and a rollback plan should you follow the PostgreSQL PITR tutorial to stop Patroni/PostgreSQL and perform the restore. pg-pitr 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 are in the same restored PostgreSQL database, database PITR can return both to one point in time. If they reside in different databases or clusters, design a coordinated recovery point for both.
If file data is in Silo/S3, PostgreSQL PITR rolls back metadata only, not objects. Newer objects may remain, while old objects that were deleted or collected may be unavailable. Recoverability 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, metrics listen on 0.0.0.0:<port>, default port 9567.
Monitoring Architecture
If INFRA is deployed, juice_register writes scrape targets to:
The current source includes the Node JuiceFS dashboard (UID: node-juice) for capacity, cache, object-storage, metadata-transaction, and client-resource metrics across 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?
data is only used by juicefs format --no-update. After filesystem creation it will not change.
To switch backend, migrate 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 refreshes the target file; running only juice_clean leaves a stale monitoring scrape endpoint.
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
Metadata is stored in the metadata engine defined by meta (in Pigsty production scenarios, this is usually PostgreSQL).
Multi-node mount notes?
- Use the same
metaand instance name on all nodes - Only one node needs to format; others will skip
- 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 updating mount in the instance, refresh config first and then manually restart the service: