Merge pull request #22 from sameersbn/support-replicaset-config

adds support for configuring a replicaSet
This commit is contained in:
Sameer Naik 2016-07-11 20:23:32 +05:30 committed by GitHub
commit 5b0ed93afe
3 changed files with 199 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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"' ]]
}