В продовження попереднього посту Valkey: запуск в Kubernetes – Helm, monitoring, ACL – там підняли Valkey/Redis, тепер треба додати MongoDB.
Робиться для нашого нового сервісу, який ще в експерементальній/PoC фазі, але скоріш за все піде в продакшен, тому сетап такий собі “недо-production” – робимо з розрахунком на те, що потім це все діло будемо повноцінно менеджити і моніторити, але поки і не сильно заморочуємось зі всякими security-задачами.
Як і Valkey, запускати MongoDB будемо в Kubernetes, але на відміну з Valkey тут трохи більш і складно і печально, бо:
- для MongoDB є ентерпрайз-версія, і частина компонентів та документації заточено під неї, що трохи заплутує – бо документації багато
- нема адекватного і простого Helm-чарту – бо і сама система трохи складніша за Redis (ну – якщо не розгортати Redis Cluster)
- є чарт Bitnami – але ж ми не вороги собі 🙂
Тому для запуску в Kubernetes вибрав підхід з MCK – MongoDB Controllers for Kubernetes (MCK).
Отже, що будемо робити:
- у власному Kubernetes Namespace встановимо сам MongoDB Operator
- в окремому Namespace створимо тестовий MongoDB Replica Set “cluster” – але з одною нодою
Так як для MongoDB будемо використовувати Kubernetes Operator та CRD – то рекомендую почитати пости про те, як воно працює “під капотом” – Kubernetes: Kubernetes API, API Groups, CRD та etcd та Kubernetes: що таке Kubernetes Operator та CustomResourceDefinition.
Зміст
Install MongoDB Operator
Всі values чудово задокументовані в MongoDB Controllers for Kubernetes Operator Helm Installation Settings.
Всі дефолтні значення можна глянути в репозиторії mongodb/helm-charts/main/charts/mongodb-kubernetes/values.yaml.
Ще може бути цікавим глянути маніфест mongodb-kubernetes.yaml – по суті тут всі ресурси, які створить Helm chart самого оператора.
Поки робимо установку оператора руками в тестовий Kubernetes Namespace – потім перенесемо в автоматизацію Kubernetes.
Додаємо репозиторій:
$ helm repo add mongodb https://mongodb.github.io/helm-charts
Пишемо простий values:
operator:
env: dev
watchNamespace: test-mongodb-service-ns
watchedResources:
- mongodbcommunity
replicas: 1
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
createOperatorServiceAccount: true
createResourcesServiceAccountsAndRoles: true
enableClusterMongoDBRoles: false
enablePVCResize: true
Тут:
env: від значення вenvзадається log levelwatchNamespace: вказуємо Kubernetes Namespace, де буде потім буде MongoDBCommunity – оператор тут створить Roles && RoleBindings, і тільки в цих NS буде моніторити свої Custom ResourceswatchedResources: будемо користуватись тільки MongoDBCommunity CRD, без Enterprise, Ops Manager, Search тощо – тому тут обмежуємо ресурсиenableClusterMongoDBRoles: CRD ClusterMongoDBRole не використовуємо, ролі для MongoDB будемо задавати на рівні MongoDBCommunityenablePVCResize: включаємо можливість збільшення PVC (StorageClass має бути зallowVolumeExpansion)resources: відразу додамо, потім в production підтюнимо значення
Helm-чарт оператора встановить потрібні CRD, ClusterRole та RoleBinding самого оператора в його власному неймспейсі – та RoleBinding і потрібні ServiceAccounts в неймспейсі нашого тестового інстансу MongoDB.
Створюємо неймспейси:
$ kk create ns test-mongodb-operator-ns $ kk create ns test-mongodb-service-ns
Деплоїмо оператор:
$ helm upgrade --install mongodb-kubernetes-operator \ mongodb/mongodb-kubernetes \ --namespace test-mongodb-operator-ns \ --create-namespace \ -f operator-values.yaml
Перевіряємо поди:
$ kk get pod NAME READY STATUS RESTARTS AGE mongodb-kubernetes-operator-6b4cb5955b-wk9q5 1/1 Running 0 28s
Для створення інстансів MongoDB у watchNamespace оператор створює там ServiceAccount – перевіряємо, що він є і з цим ServiceAccount є права на створення Kubernetes StatefulSet:
$ kk auth can-i create statefulsets.apps \ --namespace test-mongodb-service-ns \ --as system:serviceaccount:test-mongodb-operator-ns:mongodb-kubernetes-operator yes
Перевіряємо MongoDBCommunity CustomResourceDefinition:
$ kk get crd mongodbcommunity.mongodbcommunity.mongodb.com NAME CREATED AT mongodbcommunity.mongodbcommunity.mongodb.com 2026-07-22T13:36:50Z
По-дефолту Operator шле MongoDB product telemetry – можна відключити з:
operator:
telemetry:
enabled: false
Оператор готовий – можемо запускати саму MongoDB.
Деплой MongoDB Community instance
Сам CRD можна подивитись тут – mongodbcommunity.mongodb.com_mongodbcommunity.yaml.
З ним ми вже власне описуємо саме наш MongoDB, тому це вже робимо в іншому неймспейсі test-mongodb-service-ns, в якому буде сам наш сервіс, який буде цю MongoDB використовувати.
Kubernetes Secrets та паролі поки робимо руками, потім вже нормально – з AWS Secrets Manager та External Secrets Operator.
Створюємо сікрет з паролем для root на цьому інстансі MongoDB:
$ kk -n test-mongodb-service-ns create secret generic agents-mainframe-mongodb-admin-password \ --from-literal=password='test-mongodb-admin-password'
Створюємо маніфест mongodb-community.yaml:
apiVersion: mongodbcommunity.mongodb.com/v1
kind: MongoDBCommunity
metadata:
name: agents-mainframe-mongodb
spec:
type: ReplicaSet
members: 1
version: "8.0.13"
security:
authentication:
modes:
- SCRAM
users:
- name: admin
db: admin
passwordSecretRef:
name: agents-mainframe-mongodb-admin-password
scramCredentialsSecretName: agents-mainframe-mongodb-admin-scram
roles:
- name: root
db: admin
Тут:
members: кількість MongoDB-процесів у MongoDB Replica Set (не плутати з Kubernetes ReplicaSet)authentication.modes: SCRAM – стандартна аутентифікація по логіну-паролюusers: описуємо RBAC – задаємо ім’я root user- в
passwordSecretRefпередаємо та ім’я Kubernetes Secret, в якому зберігається його пароль (той, що створили вище) scramCredentialsSecretName: ім’я Kubernetes Secret для MongoDB Operator, див. нижче- в
roles– задаємо значення root, всі ролі є в документації Built-In Roles
- в
Деплоїмо:
$ kk -n test-mongodb-service-ns apply -f mongodb-community.yaml mongodbcommunity.mongodbcommunity.mongodb.com/agents-mainframe-mongodb created
Перевіряємо Pods:
$ kk -n test-mongodb-service-ns get pod NAME READY STATUS RESTARTS AGE agents-mainframe-mongodb-0 2/2 Running 0 2m30s
Перевіряємо стан CustomResource:
$ kk -n test-mongodb-service-ns get mongodbcommunity agents-mainframe-mongodb NAME PHASE VERSION agents-mainframe-mongodb Running 8.0.13
Перевіряємо аутентифікацію:
$ kk -n test-mongodb-service-ns exec -it \ agents-mainframe-mongodb-0 \ -c mongod \ -- mongosh \ --username admin \ --password \ --authenticationDatabase admin Enter password: *************************** Warning: Could not access file: EACCES: permission denied, mkdir '/data/db/.mongodb' Current Mongosh Log ID: 6a60ce6f6671cfc48fce5f46 Connecting to: mongodb://<credentials>@127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&authSource=admin&appName=mongosh+2.5.8 ... Error: Could not open history file. REPL session history will not be persisted. ... agents-mainframe-mongodb [direct: primary] test>
В логах є помилка “EACCES: permission denied, mkdir ‘/data/db/.mongodb‘” – але це від MongoDB Shell, не самого демона mongod: далі і є як раз “Error: Could not open history file.“.
Тому ігноруємо.
І через db.runCommand() пробуємо запустити якусь команду, наприклад – connectionStatus:
agents-mainframe-mongodb [direct: primary] test> db.runCommand({ connectionStatus: 1 })
{
authInfo: {
authenticatedUsers: [ { user: 'admin', db: 'admin' } ],
authenticatedUserRoles: [ { role: 'root', db: 'admin' } ]
},
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1784729214, i: 1 }),
signature: {
hash: Binary.createFromBase64('cVOqP4fgjvw/kg8m6SnhJ03AB1A=', 0),
keyId: Long('7665352957805723654')
}
},
operationTime: Timestamp({ t: 1784729214, i: 1 })
}
Все працює.
MongoDB Operator та Kubernetes Secrets для MongoDBCommunity
Ще з цікавого, що можна глянути і корисно знати – Kubernetes Secrets, які створюються самим MongoDB Operator, коли ми деплоїмо ресурс MongoDBCommunity:
$ kk -n test-mongodb-service-ns get secret NAME TYPE DATA AGE agents-mainframe-mongodb-admin-admin Opaque 4 19m agents-mainframe-mongodb-admin-password Opaque 1 26m agents-mainframe-mongodb-admin-scram-scram-credentials Opaque 6 21m agents-mainframe-mongodb-agent-password Opaque 1 21m agents-mainframe-mongodb-config Opaque 1 21m agents-mainframe-mongodb-keyfile Opaque 1 21m
Тут agents-mainframe-mongodb-admin-password ми робили руками і передавали в CR manifest в полі passwordSecretRef, а інші:
agents-mainframe-mongodb-admin-scram-scram-credentials: це Secret для самого оператору – salt, sha-ключі- ім’я створюється зі значення в
scramCredentialsSecretNameнашого маніфесту CR, до якого оператор додає суфікс “-scram-credentials“
- ім’я створюється зі значення в
agents-mainframe-mongodb-admin-admin: тут Operator генерує connection string для підключення в форматіmongodb://<username>:<password>@<host>:<port>/<database>?<options>"- ім’я генерується з
<MongoDBCommunity name>-<auth database>-<username> - містить дві connection sring –
connectionString.standardтаconnectionString.standardSrv: другий використовує Kubernetes DNS замість імен подів – користуємось ним
- ім’я генерується з
agents-mainframe-mongodb-agent-password: внутрішній пароль MongoDB Agent, створений оператором – агент використовує цей пароль для керуванняmongodна цьому інстансі MongoDB, нам не цікавийagents-mainframe-mongodb-config: automation configuration для MongoDB Agent – бажаний стан deployment, replica set, users та інші параметри – оновлюється оператором при змінах в MongoDBCommunity, нам, в принципі, не цікавий
Власне – на цьому і все.
Можна готуватись до запуску в Dev/Staging/Prod:
- додати
podAntiAffinity,topologySpreadConstraints(див. Kubernetes: Pods та WorkerNodes – контроль розміщення подів на нодах) - включити PodDisruptionBudget для тих оточень, де реплік > 1
- налаштувати PVC з retention policy == Retain
- додати
resources.requests/limitsокремо для контейнерівmongodіmongodb-agent - налаштувати бекапи
- налаштувати моніторинг (є приклад mongodb-prometheus-sample.yaml)
По бекапам – просто EBS snapshots недостатньо/ненадійно, варіанти:
mongodump/mongorestore+ AWS S3 (див. The MongoDB Database Tools Documentation)- EBS snapshots – але на окремому інстансі MongoDB із запуском
db.fsyncLock()таdb.fsyncUnlock()(див. Back Up a Self-Managed Deployment with Filesystem Snapshots) - або налаштувати Percona Backup for MongoDB
![]()