<a id="cluster-placement-groups"></a>

# How to use placement groups

Placement groups allow you to control how instances are distributed across cluster members.
You can either spread instances across different members for high availability, or compact them onto the same member(s) for performance and locality.

#### NOTE
Placement groups are only available in clustered LXD deployments and are scoped to individual projects.

## Create a placement group

Placement groups require two configuration keys: `policy` and `rigor`.

### Policy options

**Spread policy**
: Distributes instances across different cluster members to maximize availability and distribute load.

**Compact policy**
: Co-locates instances on the same cluster member to minimize network latency and maximize resource sharing.

### Rigor options

**Strict rigor**
: Enforces the placement policy strictly. Instance creation fails if the policy cannot be satisfied.

**Permissive rigor**
: Attempts to follow the placement policy but allows fallback if constraints cannot be met.

### Create with spread policy

CLI

To create a placement group with a strict spread policy:

```none
lxc placement-group create my-pg-spread policy=spread rigor=strict
```

To create a placement group with a permissive spread policy that allows fallback:

```none
lxc placement-group create my-pg-spread policy=spread rigor=permissive
```

API

To create a placement group with a strict spread policy, send a POST request:

```none
lxc query --request POST /1.0/placement-groups --data '{
  "name": "my-pg-spread",
  "config": {
    "policy": "spread",
    "rigor": "strict"
  }
}'
```

To create a placement group with a permissive spread policy:

```none
lxc query --request POST /1.0/placement-groups --data '{
  "name": "my-pg-spread",
  "config": {
    "policy": "spread",
    "rigor": "permissive"
  }
}'
```

### Create with compact policy

CLI

To create a placement group with a strict compact policy:

```none
lxc placement-group create my-pg-compact policy=compact rigor=strict
```

To create a placement group with a permissive compact policy that allows fallback:

```none
lxc placement-group create my-pg-compact policy=compact rigor=permissive
```

API

To create a placement group with a strict compact policy, send a POST request:

```none
lxc query --request POST /1.0/placement-groups --data '{
  "name": "my-pg-compact",
  "config": {
    "policy": "compact",
    "rigor": "strict"
  }
}'
```

To create a placement group with a permissive compact policy:

```none
lxc query --request POST /1.0/placement-groups --data '{
  "name": "my-pg-compact",
  "config": {
    "policy": "compact",
    "rigor": "permissive"
  }
}'
```

## Assign instances to a placement group

### During instance creation

CLI

Specify the placement group when creating an instance:

```none
lxc launch ubuntu:24.04 my-instance -c placement.group=my-pg-spread
```

API

To create an instance with a placement group, send a POST request:

```none
lxc query --request POST /1.0/instances --data '{
  "name": "my-instance",
  "image": "ubuntu:24.04",
  "config": {
    "placement.group": "my-pg-spread"
  }
}'
```

### For existing instances

CLI

Add a placement group to an existing instance:

```none
lxc config set my-instance placement.group=my-pg-spread
```

API

To add a placement group to an existing instance, send a PATCH request:

```none
lxc query --request PATCH /1.0/instances/my-instance --data '{
  "config": {
    "placement.group": "my-pg-spread"
  }
}'
```

#### NOTE
Changing the placement group of an existing instance does not move the instance.
The new placement policy applies only to future LXD scheduling events (e.g., evacuation).

### Using profiles

CLI

Apply a placement group to all instances using a profile:

```none
lxc profile set default placement.group=my-pg-spread
```

API

To set a placement group on a profile, send a PATCH request:

```none
lxc query --request PATCH /1.0/profiles/default --data '{
  "config": {
    "placement.group": "my-pg-spread"
  }
}'
```

## View placement groups

### List placement groups

CLI

List all placement groups in the current project:

```none
lxc placement-group list
```

List placement groups from all projects:

```none
lxc placement-group list --all-projects
```

API

To retrieve all placement groups in a project, send a GET request:

```none
lxc query --request GET /1.0/placement-groups
```

To retrieve placement groups from all projects, send a GET request:

```none
lxc query --request GET /1.0/placement-groups?recursion=1&all-projects=true
```

### Show details of a placement group

CLI

View details of a specific placement group:

```none
lxc placement-group show my-pg-spread
```

The `used_by` field shows all instances and profiles referencing this placement group.

API

To retrieve details of a specific placement group, send a GET request:

```none
lxc query --request GET /1.0/placement-groups/my-pg-spread
```

The `used_by` field shows all instances and profiles referencing this placement group.

## Modify a placement group

### Edit interactively

CLI

Open the placement group configuration in your default editor:

```none
lxc placement-group edit my-pg-spread
```

API

To update the full placement group configuration, send a PUT request:

```none
lxc query --request PUT /1.0/placement-groups/my-pg-spread --data '<placement_group_configuration>'
```

### Update specific keys

CLI

Change the policy:

```none
lxc placement-group set my-pg-spread policy=compact
```

Change the rigor:

```none
lxc placement-group set my-pg-spread rigor=permissive
```

Get a configuration value:

```none
lxc placement-group get my-pg-spread policy
```

API

To update specific keys in a placement group, send a PATCH request:

```none
lxc query --request PATCH /1.0/placement-groups/my-pg-spread --data '{
  "config": {
    "policy": "compact",
    "rigor": "permissive"
  }
}'
```

To retrieve a specific configuration value, send a GET request and parse the response:

```none
lxc query --request GET /1.0/placement-groups/my-pg-spread
```

### Add user metadata

CLI

Add custom metadata to a placement group:

```none
lxc placement-group set my-pg-spread user.department=engineering
lxc placement-group set my-pg-spread user.cost-center=12345
```

API

To add custom metadata to a placement group, send a PATCH request:

```none
lxc query --request PATCH /1.0/placement-groups/my-pg-spread --data '{
  "config": {
    "user.department": "engineering",
    "user.cost-center": "12345"
  }
}'
```

## Rename a placement group

CLI

```bash
lxc placement-group rename my-pg-spread my-pg-ha
```

API

To rename a placement group, send a POST request:

```none
lxc query --request POST /1.0/placement-groups/my-pg-spread --data '{
  "name": "my-pg-ha"
}'
```

## Delete a placement group

CLI

```none
lxc placement-group delete my-pg-spread
```

To find what’s using a placement group before deletion:

```none
lxc placement-group show my-pg-spread | grep used_by
```

API

To delete a placement group, send a DELETE request:

```none
lxc query --request DELETE /1.0/placement-groups/my-pg-spread
```

To find what’s using a placement group before deletion:

```none
lxc query --request GET /1.0/placement-groups/my-pg-spread
```

#### NOTE
You cannot delete a placement group that is in use. Remove it from all instances and profiles first.

## Placement behavior

### During instance creation

When you create an instance with a placement group:

1. LXD filters cluster members according to the placement policy
2. From the filtered members, LXD selects the member with the fewest instances
3. If strict rigor is set and filtering returns no eligible members, instance creation fails
4. If permissive rigor is set and filtering returns no eligible members, LXD uses all available members

### Spread policy behavior

**Strict spread**
: Places at most one instance per cluster member

: Fails if there aren’t enough eligible members

**Permissive spread**
: Spreads instances as evenly as possible

: Ensures instance count per member differs by at most one

### Compact policy behavior

**Strict compact**
: Places all instances on the same cluster member

: When instances already exist, new instances are placed on the member with the most instances from the placement group

: Fails if the preferred member is unavailable

**Permissive compact**
: Prefers to place all instances on the same cluster member

: When instances already exist, new instances are placed on the member with the most instances from the placement group

: Allows fallback to other members if the preferred member is unavailable

#### NOTE
If instances in a compact placement group are distributed across multiple members (for example, due to manual placement with `--target`), LXD will prefer the member with the most instances from that placement group when placing new instances.

### During cluster evacuation

When evacuating a cluster member, LXD respects placement groups:

- **Spread policy**: Distributes evacuated instances across remaining members
- **Compact policy**: Attempts to keep instances from the same placement group together

If strict placement cannot be satisfied during evacuation, LXD falls back to the least-loaded member (unlike instance creation, which would fail).

## Troubleshooting

### Instance creation fails with strict rigor

If instance creation fails with a strict placement group:

1. Check available cluster members: `lxc cluster list`
2. Check instance distribution: `lxc list -c nL`
3. Consider using permissive rigor or adding more cluster members

## Related topics

- [Automatic placement of instances](https://canonical.com/lxd/docs/latest/explanation/clusters/index.html.md#clustering-instance-placement)
- [Placement group configuration](https://canonical.com/lxd/docs/latest/reference/placement_groups/index.html.md#ref-placement-groups)
- [`placement.group`](https://canonical.com/lxd/docs/latest/reference/instance_options/index.html.md#instance-placement:placement.group)
