Links#
https://www.mongodb.com/docs/manual/installation/
https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/
https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-red-hat/
https://hub.docker.com/_/mongo
https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/
https://www.mongodb.com/docs/manual/tutorial/enforce-keyfile-access-control-in-existing-replica-set/
https://github.com/mongodb/helm-charts
https://github.com/percona/percona-helm-charts
https://github.com/bitnami/charts/tree/main/bitnami/mongodb
1. Linux VM With systemd#
install#
example:
Ubuntu 24.04
MongoDB Community 8.0
systemd service: mongod
note:
production should follow the exact official repository for your OS version
do not install random mongodb packages from old distro repo
sudo apt-get update
sudo apt-get install -y gnupg curl
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc \
| sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" \
| sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
sudo apt-get update
sudo apt-get install -y mongodb-org
directories#
sudo mkdir -p /var/lib/mongo /var/log/mongodb /etc/mongodb/tls
sudo chown -R mongodb:mongodb /var/lib/mongo /var/log/mongodb
sudo chmod 0755 /var/lib/mongo /var/log/mongodb
config#
# /etc/mongod.conf
storage:
dbPath: /var/lib/mongo
journal:
enabled: true
systemLog:
destination: file
path: /var/log/mongodb/mongod.log
logAppend: true
net:
port: 27017
bindIp: 127.0.0.1,10.0.1.10
processManagement:
timeZoneInfo: /usr/share/zoneinfo
security:
authorization: enabled
keyFile: /etc/mongodb/keyfile
replication:
replSetName: rs0
operationProfiling:
slowOpThresholdMs: 100
keyfile#
openssl rand -base64 756 | sudo tee /etc/mongodb/keyfile > /dev/null
sudo chown mongodb:mongodb /etc/mongodb/keyfile
sudo chmod 0400 /etc/mongodb/keyfile
keyfile notes:
same content on every replica set member
owner should be mongodb
permission should be strict
rotate with a planned maintenance procedure
systemd#
sudo systemctl daemon-reload
sudo systemctl enable mongod
sudo systemctl start mongod
sudo systemctl status mongod
journalctl -u mongod -f
tail -f /var/log/mongodb/mongod.log
initialize replica set#
mongosh
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "mongo-1.example.internal:27017" },
{ _id: 1, host: "mongo-2.example.internal:27017" },
{ _id: 2, host: "mongo-3.example.internal:27017" }
]
})
create admin user#
use admin
db.createUser({
user: "root_admin",
pwd: passwordPrompt(),
roles: [
{ role: "root", db: "admin" }
]
})
create application user#
use admin
db.createUser({
user: "order_app",
pwd: passwordPrompt(),
roles: [
{ role: "readWrite", db: "order" }
]
})
firewall#
allow:
app subnet -> mongo nodes tcp/27017
mongo nodes -> mongo nodes tcp/27017
bastion/admin subnet -> mongo nodes tcp/27017, if required
deny:
public internet -> tcp/27017
2. Docker#
standalone for local dev#
docker network create mongo-net
docker run -d \
--name mongo \
--network mongo-net \
-p 27017:27017 \
-e MONGO_INITDB_ROOT_USERNAME=root \
-e MONGO_INITDB_ROOT_PASSWORD=change-me \
-v mongo-data:/data/db \
mongo:8
mongosh "mongodb://root:change-me@localhost:27017/admin"
docker compose replica set#
services:
mongo-1:
image: mongo:8
command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--keyFile", "/etc/mongo/keyfile"]
ports:
- "27017:27017"
volumes:
- mongo-1-data:/data/db
- ./keyfile:/etc/mongo/keyfile:ro
mongo-2:
image: mongo:8
command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--keyFile", "/etc/mongo/keyfile"]
ports:
- "27018:27017"
volumes:
- mongo-2-data:/data/db
- ./keyfile:/etc/mongo/keyfile:ro
mongo-3:
image: mongo:8
command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--keyFile", "/etc/mongo/keyfile"]
ports:
- "27019:27017"
volumes:
- mongo-3-data:/data/db
- ./keyfile:/etc/mongo/keyfile:ro
volumes:
mongo-1-data:
mongo-2-data:
mongo-3-data:
openssl rand -base64 756 > keyfile
chmod 0400 keyfile
docker compose up -d
mongosh "mongodb://localhost:27017"
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "mongo-1:27017" },
{ _id: 1, host: "mongo-2:27017" },
{ _id: 2, host: "mongo-3:27017" }
]
})
docker notes:
good for local dev / lab
production needs persistent volume, backup, monitoring, TLS, resource limits
container memory limit should match WiredTiger cache configuration
3. K8S With Helm#
option#
MongoDB official helm-charts repo:
includes community-operator chart
community charts are not officially supported by MongoDB
good for lab / learning
Percona Operator for MongoDB:
open-source operator
production-oriented HA / backup / TLS / users
recommended for self-managed OSS production if your team accepts Percona stack
Bitnami MongoDB chart:
simple Helm chart
supports standalone / replicaset
good for quick setup
production needs careful values review
percona operator#
helm repo add percona https://percona.github.io/percona-helm-charts/
helm repo update
kubectl create namespace mongodb
helm install psmdb-operator percona/psmdb-operator \
--namespace mongodb
helm install psmdb-db percona/psmdb-db \
--namespace mongodb \
--set finalizers.deletePvc=false \
--set replsets.rs0.size=3 \
--set replsets.rs0.volumeSpec.persistentVolumeClaim.resources.requests.storage=100Gi
check:
kubectl -n mongodb get pods
kubectl -n mongodb get psmdb
kubectl -n mongodb get pvc
bitnami replicaset#
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
kubectl create namespace mongodb
helm install mongodb bitnami/mongodb \
--namespace mongodb \
--set architecture=replicaset \
--set replicaCount=3 \
--set auth.enabled=true \
--set auth.rootPassword='change-me' \
--set auth.replicaSetKey='change-me-replica-key' \
--set persistence.enabled=true \
--set persistence.size=100Gi
production values should include:
resource requests / limits
storageClass
pod anti-affinity
TLS
backup
monitoring exporter
network policy
secret management
network policy#
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mongodb-allow-app
namespace: mongodb
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: mongodb
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: app
ports:
- protocol: TCP
port: 27017
4. High Availability#
replica set#
recommended:
3 data-bearing nodes across different AZs
odd number of voting members
majority writeConcern for critical write
app connection string includes all nodes and replicaSet name
example:
mongo-1: primary or secondary
mongo-2: primary or secondary
mongo-3: primary or secondary
connection string:
mongodb://order_app:<password>@mongo-1:27017,mongo-2:27017,mongo-3:27017/order?replicaSet=rs0&authSource=admin
election:
primary unavailable -> secondaries elect new primary
writes fail during short election window
application driver must retry retryable writes
tune timeout and retry policy
arbiter#
arbiter:
votes in election
does not store data
cannot become primary
use only when:
cost is constrained
two data-bearing nodes are unavoidable
avoid when:
you need strong durability across AZs
writeConcern majority should represent data-bearing majority
hidden / delayed secondary#
hidden secondary:
not visible to application read preference
useful for backup / analytics / reporting
delayed secondary:
intentionally lags
can help recover from accidental delete / bad write
not a replacement for real backup
sharded cluster HA#
sharded cluster components:
shard replica sets
config server replica set
mongos routers
HA requirements:
each shard is a replica set
config servers run as replica set
multiple mongos behind app / service discovery
distribute pods / VMs across AZs
use sharding when:
one replica set cannot handle data size or throughput
shard key has been carefully tested
backup and restore#
HA is not backup:
replica set protects node failure
backup protects data corruption / accidental delete / ransomware / bad deploy
must have:
scheduled backup
tested restore
offsite copy
documented RPO / RTO
5. Operations#
rolling restart#
order:
restart secondary first
wait until healthy and caught up
step down primary
restart old primary
verify new primary and replication lag
rs.status()
rs.stepDown()
upgrade#
upgrade checklist:
read official release notes
check driver compatibility
backup before upgrade
upgrade secondaries first
step down primary
upgrade old primary
only change featureCompatibilityVersion after rollback window
maintenance commands#
db.adminCommand({ ping: 1 })
rs.status()
rs.printReplicationInfo()
rs.printSecondaryReplicationInfo()
db.serverStatus()
db.currentOp()