Merge pull request #22 from sameersbn/support-replicaset-config
adds support for configuring a replicaSet
This commit is contained in:
commit
5b0ed93afe
|
|
@ -119,6 +119,76 @@ myapp:
|
|||
|
||||
Inside `myapp`, use `mongodb` as the hostname for the MongoDB server.
|
||||
|
||||
## Setting up a replicaSet
|
||||
|
||||
A [replica set](https://docs.mongodb.com/manual/replication/) can easily be setup with the Bitnami MongoDB Docker Image using the following environment variables:
|
||||
|
||||
- `MONGODB_REPLICASET_MODE`: MongoDB replica set mode. Possible values `primary`,`secondary` or `arbiter`. No defaults.
|
||||
- `MONGODB_REPLICASET_NAME`: MongoDB replica set name. Defaults to `replicaset`.
|
||||
- `MONGODB_PRIMARY_HOST`: MongoDB primary host. No defaults.
|
||||
- `MONGODB_PRIMARY_PORT`: MongoDB primary port. Defaults to `27017`
|
||||
- `MONGODB_PRIMARY_USER`: MongoDB primary user. Defaults to `root`.
|
||||
- `MONGODB_PRIMARY_PASSWORD`: MongoDB primary user password. No defaults.
|
||||
|
||||
In a replica set you can have one primary and zero or more secondary nodes.
|
||||
|
||||
### Step 1: Create the primary node
|
||||
|
||||
The first step is to start the MongoDB primary node.
|
||||
|
||||
```bash
|
||||
docker run --name mongodb-primary \
|
||||
-e MONGODB_REPLICASET_MODE=primary \
|
||||
bitnami/mongodb:latest
|
||||
```
|
||||
|
||||
In the above command the container is configured as the `primary` node using the `MONGODB_REPLICASET_MODE` parameter.
|
||||
|
||||
### Step 2: Create the secondary node
|
||||
|
||||
Next we start a MongoDB secondary node.
|
||||
|
||||
```bash
|
||||
docker run --name mongodb-secondary \
|
||||
--link mongodb-primary:primary \
|
||||
-e MONGODB_REPLICASET_MODE=secondary \
|
||||
-e MONGODB_PRIMARY_HOST=primary \
|
||||
-e MONGODB_PRIMARY_PORT=27017 \
|
||||
bitnami/mongodb:latest
|
||||
```
|
||||
|
||||
In the above command the container is configured as a `secondary` using the `MONGODB_REPLICASET_MODE` parameter. The `MONGODB_PRIMARY_HOST` and `MONGODB_PRIMARY_PORT` parameters are used connect to the MongoDB primary.
|
||||
|
||||
You now have a two node MongoDB replica set which can be scaled by adding/removing secondary nodes.
|
||||
|
||||
With Docker Compose the replica set can be setup using:
|
||||
|
||||
```yaml
|
||||
primary:
|
||||
image: bitnami/mongodb:latest
|
||||
environment:
|
||||
- MONGODB_REPLICASET_MODE=primary
|
||||
|
||||
secondary:
|
||||
image: bitnami/mongodb:latest
|
||||
links:
|
||||
- primary:primary
|
||||
environment:
|
||||
- MONGODB_REPLICASET_MODE=secondary
|
||||
- MONGODB_PRIMARY_HOST=primary
|
||||
- MONGODB_PRIMARY_PORT=6379
|
||||
```
|
||||
|
||||
Scale the number of secondary nodes using:
|
||||
|
||||
```bash
|
||||
docker-compose scale primary=1 secondary=3
|
||||
```
|
||||
|
||||
The above command scales up the number of secondary nodes to `3`. You can scale down in the same way.
|
||||
|
||||
> **Note**: You should not scale up/down the number of primary nodes. Always have only one primary node running.
|
||||
|
||||
# Configuration
|
||||
|
||||
## Setting the root password on first run
|
||||
|
|
|
|||
|
|
@ -8,7 +8,13 @@ if [[ "$1" == "harpoon" && "$2" == "start" ]]; then
|
|||
${MONGODB_ROOT_PASSWORD:+--rootPassword $MONGODB_ROOT_PASSWORD} \
|
||||
${MONGODB_USER:+--username $MONGODB_USER} \
|
||||
${MONGODB_PASSWORD:+--password $MONGODB_PASSWORD} \
|
||||
${MONGODB_DATABASE:+--database $MONGODB_DATABASE}
|
||||
${MONGODB_DATABASE:+--database $MONGODB_DATABASE} \
|
||||
${MONGODB_REPLICASET_MODE:+--replicaSetMode $MONGODB_REPLICASET_MODE} \
|
||||
${MONGODB_REPLICASET_NAME:+--replicaSetName $MONGODB_REPLICASET_NAME} \
|
||||
${MONGODB_PRIMARY_HOST:+--primaryHost $MONGODB_PRIMARY_HOST} \
|
||||
${MONGODB_PRIMARY_PORT:+--primaryPort $MONGODB_PRIMARY_PORT} \
|
||||
${MONGODB_PRIMARY_USER:+--primaryUser $MONGODB_PRIMARY_USER} \
|
||||
${MONGODB_PRIMARY_PASSWORD:+--primaryPassword $MONGODB_PRIMARY_PASSWORD}
|
||||
fi
|
||||
chown $BITNAMI_APP_USER: /bitnami/$BITNAMI_APP_NAME || true
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ MONGODB_PASSWORD=test_password
|
|||
APP_NAME=mongodb
|
||||
VOL_PREFIX=/bitnami/$APP_NAME
|
||||
VOLUMES=$VOL_PREFIX
|
||||
SLEEP_TIME=30
|
||||
SLEEP_TIME=60
|
||||
load tests/docker_helper
|
||||
|
||||
# Link to container and execute mongo client
|
||||
|
|
@ -21,6 +21,7 @@ mongo_client() {
|
|||
# Cleans up all running/stopped containers and host mounted volumes
|
||||
cleanup_environment() {
|
||||
container_remove_full default
|
||||
container_remove_full secondary
|
||||
}
|
||||
|
||||
# Teardown called at the end of each test
|
||||
|
|
@ -168,3 +169,123 @@ cleanup_environment
|
|||
run mongo_client default -u $MONGODB_USER -p $MONGODB_PASSWORD $MONGODB_DATABASE --eval "printjson(db.getCollectionNames())"
|
||||
[[ "$output" =~ '"users"' ]]
|
||||
}
|
||||
|
||||
@test "Can't create replicaSet with authentication" {
|
||||
run container_create default \
|
||||
-e MONGODB_REPLICASET_MODE=primary \
|
||||
-e MONGODB_PASSWORD=$MONGODB_PASSWORD
|
||||
[[ "$output" =~ "Not possible to configure replica set scenario using authentication" ]]
|
||||
}
|
||||
|
||||
@test "Can't create secondary replicaSet node without specifying MONGODB_PRIMARY_HOST" {
|
||||
run container_create secondary \
|
||||
-e MONGODB_REPLICASET_MODE=secondary
|
||||
[[ "$output" =~ "provide the --primaryHost property" ]]
|
||||
}
|
||||
|
||||
@test "Can create replicaSet without authentication" {
|
||||
container_create default -d \
|
||||
-e MONGODB_REPLICASET_MODE=primary
|
||||
|
||||
container_create secondary -d \
|
||||
$(container_link default $CONTAINER_NAME) \
|
||||
-e MONGODB_REPLICASET_MODE=secondary \
|
||||
-e MONGODB_PRIMARY_HOST=$CONTAINER_NAME
|
||||
|
||||
run mongo_client default $MONGODB_DATABASE --eval "printjson(db.createCollection('users'))"
|
||||
[[ "$output" =~ '"ok" : 1' ]]
|
||||
|
||||
sleep 3
|
||||
run mongo_client secondary $MONGODB_DATABASE --eval "rs.slaveOk(); printjson(db.getCollectionNames())"
|
||||
[[ "$output" =~ '"users"' ]]
|
||||
}
|
||||
|
||||
@test "Secondary node in replicaSet synchronizes with the primary (delayed start)" {
|
||||
container_create default -d \
|
||||
-e MONGODB_REPLICASET_MODE=primary
|
||||
|
||||
run mongo_client default $MONGODB_DATABASE --eval "printjson(db.createCollection('users'))"
|
||||
[[ "$output" =~ '"ok" : 1' ]]
|
||||
|
||||
container_create secondary -d \
|
||||
$(container_link default $CONTAINER_NAME) \
|
||||
-e MONGODB_REPLICASET_MODE=secondary \
|
||||
-e MONGODB_PRIMARY_HOST=$CONTAINER_NAME
|
||||
|
||||
run mongo_client secondary $MONGODB_DATABASE --eval "rs.slaveOk(); printjson(db.getCollectionNames())"
|
||||
[[ "$output" =~ '"users"' ]]
|
||||
}
|
||||
|
||||
@test "replicaSet setup and state is preserved after restart" {
|
||||
container_create default -d \
|
||||
-e MONGODB_REPLICASET_MODE=primary
|
||||
|
||||
run mongo_client default $MONGODB_DATABASE --eval "printjson(db.createCollection('users'))"
|
||||
[[ "$output" =~ '"ok" : 1' ]]
|
||||
|
||||
container_create secondary -d \
|
||||
$(container_link default $CONTAINER_NAME) \
|
||||
-e MONGODB_REPLICASET_MODE=secondary \
|
||||
-e MONGODB_PRIMARY_HOST=$CONTAINER_NAME
|
||||
|
||||
container_restart secondary
|
||||
container_restart default
|
||||
|
||||
run mongo_client default $MONGODB_DATABASE --eval "printjson(db.createCollection('networks'))"
|
||||
[[ "$output" =~ '"ok" : 1' ]]
|
||||
|
||||
sleep 3
|
||||
run mongo_client secondary $MONGODB_DATABASE --eval "rs.slaveOk(); printjson(db.getCollectionNames())"
|
||||
[[ "$output" =~ '"users"' ]]
|
||||
[[ "$output" =~ '"networks"' ]]
|
||||
}
|
||||
|
||||
@test "replicaSet setup and state is preserved after deletion" {
|
||||
container_create_with_host_volumes default -d \
|
||||
-e MONGODB_REPLICASET_MODE=primary
|
||||
|
||||
run mongo_client default $MONGODB_DATABASE --eval "printjson(db.createCollection('users'))"
|
||||
[[ "$output" =~ '"ok" : 1' ]]
|
||||
|
||||
container_create_with_host_volumes secondary -d \
|
||||
$(container_link default $CONTAINER_NAME) \
|
||||
-e MONGODB_REPLICASET_MODE=secondary \
|
||||
-e MONGODB_PRIMARY_HOST=$CONTAINER_NAME
|
||||
|
||||
container_remove secondary
|
||||
container_remove default
|
||||
|
||||
container_create_with_host_volumes default -d
|
||||
container_create_with_host_volumes secondary -d $(container_link default $CONTAINER_NAME)
|
||||
|
||||
run mongo_client default $MONGODB_DATABASE --eval "printjson(db.createCollection('networks'))"
|
||||
[[ "$output" =~ '"ok" : 1' ]]
|
||||
|
||||
sleep 3
|
||||
run mongo_client secondary $MONGODB_DATABASE --eval "rs.slaveOk(); printjson(db.getCollectionNames())"
|
||||
[[ "$output" =~ '"users"' ]]
|
||||
[[ "$output" =~ '"networks"' ]]
|
||||
}
|
||||
|
||||
@test "Slave recovers if master is temporarily offine" {
|
||||
container_create_with_host_volumes default -d \
|
||||
-e MONGODB_REPLICASET_MODE=primary
|
||||
|
||||
run mongo_client default $MONGODB_DATABASE --eval "printjson(db.createCollection('users'))"
|
||||
[[ "$output" =~ '"ok" : 1' ]]
|
||||
|
||||
container_create_with_host_volumes secondary -d \
|
||||
$(container_link default $CONTAINER_NAME) \
|
||||
-e MONGODB_REPLICASET_MODE=secondary \
|
||||
-e MONGODB_PRIMARY_HOST=$CONTAINER_NAME
|
||||
|
||||
container_restart default
|
||||
|
||||
run mongo_client default $MONGODB_DATABASE --eval "printjson(db.createCollection('networks'))"
|
||||
[[ "$output" =~ '"ok" : 1' ]]
|
||||
|
||||
sleep 3
|
||||
run mongo_client secondary $MONGODB_DATABASE --eval "rs.slaveOk(); printjson(db.getCollectionNames())"
|
||||
[[ "$output" =~ '"users"' ]]
|
||||
[[ "$output" =~ '"networks"' ]]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue