Remove Shards from a Sharded Cluster
On this page
To remove a shard you must ensure the shard's data is migrated to the remaining shards in the cluster. This procedure describes how to safely migrate data and remove a shard.
About this Task
Creating, sharding, or moving collections while performing this procedure may cause interruptions and lead to unexpected results.
Do not use this procedure to migrate an entire cluster to new hardware. To migrate, see Migrate a Self-Managed Sharded Cluster to Different Hardware.
When you remove a shard in a cluster with an uneven chunk distribution, the balancer first removes the chunks from the draining shard and then balances the remaining uneven chunk distribution.
Removing a shard may cause an open change stream cursor to close, and the closed change stream cursor may not be fully resumable.
You can safely restart a cluster during a shard removal process. If you restart a cluster during an ongoing draining process, draining continues automatically after the cluster components restart. MongoDB records the shard draining status in the
config.shards
collection.
Before you Begin
This procedure uses the
sh.moveCollection()
method to move collections off of the removed shard. Before you begin this procedure, review themoveCollection
considerations and requirements to understand the command behavior.To remove a shard, first connect to one of the cluster's
mongos
instances usingmongosh
.
Steps
Ensure the balancer is enabled
To migrate data from a shard, the balancer process must
be enabled. To check the balancer state, use the
sh.getBalancerState()
method:
sh.getBalancerState()
If the operation returns true
, the balancer is enabled.
If the operation returns false
, see
Enable the Balancer.
Determine the name of the shard to remove
To find the name of the shard, run the listShards
command:
db.adminCommand( { listShards: 1 } )
The shards._id
field contains the shard name.
Migrate sharded collection data with the balancer
Run the removeShard
command for the shard you want to
remove:
db.adminCommand( { removeShard: "<shardName>" } )
Note
mongos
converts the
write concern of the
removeShard
command to "majority"
.
The removeShard
operation returns:
{ "msg" : "draining started successfully", "state" : "started", "shard" : "<shardName>", "note" : "you need to call moveCollection for collectionsToMove and afterwards movePrimary for the dbsToMove", "dbsToMove" : [ "db1", "db2" ], collectionsToMove: ["db1.collA"] "ok" : 1, "operationTime" : Timestamp(1575398919, 2), "$clusterTime" : { "clusterTime" : Timestamp(1575398919, 2), "signature" : { "hash" : BinData(0,"Oi68poWCFCA7b9kyhIcg+TzaGiA="), "keyId" : NumberLong("6766255701040824328") } }
The shard enters the draining
state and the balancer begins
migrating chunks from the removed shard to other shards in the
cluster. These migrations happens slowly to avoid severe impact on
the overall cluster. Depending on your network capacity and the
amount of data, this operation can take from a few minutes to
several days to complete.
Tip
While the shard is in the draining
state, you can use the
reshardCollection command to redistribute
data off of the removed shard.
Moving data with reshardCollection
can be faster than
waiting for the balancer to migrate chunks. The cluster ensures
that data is not placed on any draining shards. You can't run
moveCollection
and reshardCollection
operations
simultaneously.
Move unsharded collections to another shard
Determine what collections need to be moved
To list the unsharded collections on the shard, use the aggregation stage
$listClusterCatalog
:use admin db.aggregate([ { $listClusterCatalog: { shards: true } }, { $match: { $and: [ { sharded: false }, { shards: '<shard_to_remove>' }, { type: { $nin: ["timeseries","view"] } }, { ns: { $not: { $regex: "^enxcol_\..*(\.esc|\.ecc|\.ecoc|\.ecoc\.compact)$" }}}, { $or: [{ns: {$not: { $regex: "\.system\." }}}, {ns: {$regex: "\.system\.buckets\."}}]}, { db: { $ne: 'config' } }, { db: { $ne: 'admin' } } ]}}, { $project: { _id: 0, ns: { $cond: [ "$options.timeseries", { $replaceAll: { input: "$ns", find: ".system.buckets", replacement: "" } }, "$ns" ] } }} ]) Move the collections one by one
To move the collection, run
sh.moveCollection()
:sh.moveCollection( "<database>.<collection>", "<ID of recipient shard>" ) Note
moveCollection
fails if you run the command on a namespace that is sharded. If you receive this error message, ignore it and return to step1
for the next collection.Return to step
1
to check that there are no remaining unsharded collections on the draining shard.
Change primary shard
Run the db.printShardingStatus()
method:
db.printShardingStatus()
In the databases
section of the command output, check the
database.primary
field. If the primary
field is the
removed shard, you must move that database's primary to a
different shard.
To change a database's primary shard, run the movePrimary
command.
Warning
When you run movePrimary
, any collections that were not
moved in the Move collections off of the shard step
are unavailable during the movePrimary
process.
db.adminCommand( { movePrimary: <dbName>, to: <shardName> } )
Check migration status
To check the progress of the migration, run
removeShard
from the admin
database again:
db.adminCommand( { removeShard: "<shardName>" } )
In the output, the remaining
field includes these fields:
Field | Description |
---|---|
| Number of chunks currently remaining on the shard |
| Number of databases whose primary shard is the shard. These databases are specified in
the |
| Of the total number of If After the |
Continue checking the status of the removeShard
command until the
number of chunks remaining is 0.
db.adminCommand( { removeShard: "<shardName>" } )
Finalize shard removal
To finalize the shard removal process, re-run the removeShard
command:
db.adminCommand( { removeShard: <shardName> } )
Note
DDL Operations
If you remove a shard while your cluster executes a DDL
operation (an operation that modifies a collection such as
reshardCollection
), the removeShard
operation
runs after the concurrent DDL operation finishes.
If the shard is removed, the command output resembles the following:
{ msg: 'removeshard completed successfully', state: 'completed', shard: '<shardName>', ok: 1, '$clusterTime': { clusterTime: Timestamp({ t: 1721941519, i: 7 }), signature: { hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0), keyId: Long('0') } }, operationTime: Timestamp({ t: 1721941519, i: 7 }) }