Как настроить Монго реплики на Кубернете?
Я хотел бы установить набор реплик Mongo на Kubernetes. Я хотел бы иметь три реплики. Это означает, что мне нужно запустить 3 экземпляра.
Должен ли я запускать три контейнера, с Mongo в каждом из них, и использовать сервис для основного? Или я должен каким-то образом использовать контроллер репликации?
Ответы
Ответ 1
Этот ответ устарел. Я написал подробный пошаговый учебник здесь, используя более современные методы. Я настоятельно рекомендую прочитать все это.
В двух словах вы запустите приложение sidecar, чтобы настроить набор реплик для вас, и либо используйте службу на один экземпляр, либо выполните ping API K8s для IP-адресов pod.
Пример:. Это будет работать только в облаке Google. Вам нужно будет внести изменения для других платформ, особенно вокруг томов:
- Следуйте примеру https://github.com/leportlabs/mongo-k8s-sidecar.git
-
git clone https://github.com/leportlabs/mongo-k8s-sidecar.git
-
cd mongo-k8s-sidecar/example/
-
make add-replica ENV=GoogleCloudPlatform
(сделайте это три раза)
- Подключиться к набору реплик через службы.
-
mongodb://mongo-1,mongo-2,mongo-3:27017/dbname_?
- Вы также можете использовать IP-адреса raw pod вместо создания службы на каждый блок
Ответ 2
Как правило, для создания кластерного набора таких узлов, как mongo с наборами реплик, вы создадите Service
, который отслеживает содержимое под именем службы (например, создайте контроллер репликации MongoDB с тегом mongodb
, и Service
отслеживание этих экземпляров)
Затем сервис может быть запрошен для своих членов (используя сервер API, вы можете искать узлы с помощью
curl -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://kubernetes/api/v1/namespaces/default/endpoints/mongodb
где mongodb - ваш селектор имени службы.
который возвращает объект JSON с кучей полей, поэтому хороший способ легко проанализировать это - использовать jq https://stedolan.github.io/jq/
соединение команды curl с запросом jq, например
jq '.subsets[].addresses[]' | jq '{ip: .ip, host:.targetRef.name}'
вернет IP и имена хостов экземпляров mongodb в вашем кластере.
Итак, теперь вы знаете, кто находится в кластере, и вы можете создать набор реплик в своем init script.
Очевидно, здесь это означает, что вам нужно сначала запустить Service
, ваш запуск script должен ждать, пока все узлы будут вставлены и зарегистрированы в службе, а затем вы можете продолжить.
Если вы используете одно изображение с одним script, оно будет запускать n каждый node, поэтому вам нужно проверить, что набор реплик уже не существует или обрабатывает ошибки. Первый блок для регистрации должен выполнять работу.
Другой вариант - запустить все узлы как отдельные узлы, затем запустить отдельный загрузочный файл script, который создаст набор реплик.
Наконец, вы вызываете кластер mongodb, вам нужно будет указать URL-адрес с именем набора реплик в качестве опции:
mongodb://mongodb:27017/database?replicaSet=replicaSetName
Поскольку вы не знаете IP-адрес ведущего устройства, вы вызываете его через службу mongodb
, которая будет загружать баланс для одного из узлов, и если вы не укажете имя набора реплик, вы закончится ошибками подключения, так как только мастер может получить запросы на запись.
Очевидно, что это не пошаговое руководство, но я надеюсь, что вы начнете.
Ответ 3
Это пример, который я сейчас выполняю.
apiVersion: v1
kind: Service
metadata:
labels:
name: mongo
name: mongo-svc1
spec:
ports:
- port: 27017
targetPort: 27017
selector:
type: mongo-rs-A
---
apiVersion: v1
kind: Service
metadata:
labels:
name: mongo
name: mongo-svc2
spec:
ports:
- port: 27017
targetPort: 27017
selector:
type: mongo-rs-B
---
apiVersion: v1
kind: Service
metadata:
labels:
name: mongo
name: mongo-svc3
spec:
ports:
- port: 27017
targetPort: 27017
selector:
type: mongo-rs-C
---
apiVersion: v1
kind: ReplicationController
metadata:
name: mongo
spec:
replicas: 1
selector:
name: mongo-nodea
role: mongo
environment: test
template:
metadata:
labels:
name: mongo-nodea
role: mongo
environment: test
type: mongo-rs-A
spec:
containers:
- name: mongo-nodea
image: mongo
command:
- mongod
- "--replSet"
- rsABC
- "--smallfiles"
- "--noprealloc"
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-persistent-storage
mountPath: /data/db
volumes:
- name: mongo-persistent-storage
flocker:
datasetName: FlockerMongoVolSetA
---
apiVersion: v1
kind: ReplicationController
metadata:
name: mongo-1
spec:
replicas: 1
selector:
name: mongo-nodeb
role: mongo
environment: test
template:
metadata:
labels:
name: mongo-nodeb
role: mongo
environment: test
type: mongo-rs-B
spec:
containers:
- name: mongo-nodeb
image: mongo
command:
- mongod
- "--replSet"
- rsABC
- "--smallfiles"
- "--noprealloc"
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-persistent-storage
mountPath: /data/db
volumes:
- name: mongo-persistent-storage
flocker:
datasetName: FlockerMongoVolSetB
---
apiVersion: v1
kind: ReplicationController
metadata:
name: mongo-2
spec:
replicas: 1
selector:
name: mongo-nodec
role: mongo
environment: test
template:
metadata:
labels:
name: mongo-nodec
role: mongo
environment: test
type: mongo-rs-C
spec:
containers:
- name: mongo-nodec
image: mongo
command:
- mongod
- "--replSet"
- rsABC
- "--smallfiles"
- "--noprealloc"
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-persistent-storage
mountPath: /data/db
volumes:
- name: mongo-persistent-storage
flocker:
datasetName: FlockerMongoVolSetC
kubectl --kubeconfig=clusters/k8s-mongo/kubeconfig get po,svc -L type,role,name
NAME READY STATUS RESTARTS AGE TYPE ROLE NAME
mongo-1-39nuw 1/1 Running 0 1m mongo-rs-B mongo mongo-nodeb
mongo-2-4tgho 1/1 Running 0 1m mongo-rs-C mongo mongo-nodec
mongo-rk9n8 1/1 Running 0 1m mongo-rs-A mongo mongo-nodea
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR AGE TYPE ROLE NAME
kubernetes 10.3.0.1 <none> 443/TCP <none> 21h <none> <none> <none>
mongo-svc1 10.3.0.28 <none> 27017/TCP type=mongo-rs-A 1m <none> <none> mongo
mongo-svc2 10.3.0.56 <none> 27017/TCP type=mongo-rs-B 1m <none> <none> mongo
mongo-svc3 10.3.0.47 <none> 27017/TCP type=mongo-rs-C 1m <none> <none> mongo
В Primary node я собираюсь в оболочку mongo
rs.status() rs.initiate() rs.add( "10.3.0.56:27017" )
В настоящее время я сталкиваюсь с этой проблемой, когда я застрял в статусах Secondary и Startup для двух узлов без первичного.
rs.status()
{
"set" : "rsABC",
"date" : ISODate("2016-01-21T22:51:33.216Z"),
"myState" : 2,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 0,
"name" : "mongo-rk9n8:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 242,
"optime" : {
"ts" : Timestamp(1453416638, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2016-01-21T22:50:38Z"),
"infoMessage" : "could not find member to sync from",
"configVersion" : 2,
"self" : true
},
{
"_id" : 1,
"name" : "10.3.0.56:27017",
"health" : 1,
"state" : 0,
"stateStr" : "STARTUP",
"uptime" : 45,
"optime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2016-01-21T22:51:28.639Z"),
"lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
"pingMs" : NumberLong(40),
"configVersion" : -2
}
],
"ok" : 1
}
Ответ 4
Посмотрите здесь по ссылке ниже. В кубернетах создайте служебные адреса, тогда контроллеры и инициация репликации могут быть легко сгенерированы.... https://www.mongodb.com/blog/post/running-mongodb-as-a-microservice-with-docker-and-kubernetes
Ответ 5
@Стефен Нгуен
Я просто копирую ваше дело и создаю для него тест пространства имен (я соответствующим образом меняю ваш файл yaml) и инициализирую свои mongo rs:
rs.initiate({
"_id" : "rsABC",
"members" : [
{
"_id" : 0,
"host" : "mongo-svc1.test:27017",
"priority" : 10
},
{
"_id" : 1,
"host" : "mongo-svc2.test:27017",
"priority" : 9
},
{
"_id" : 2,
"host" : "mongo-svc3.test:27017",
"arbiterOnly" : true
}
]
})
Кажется, он работает:
> rs.status()
{
"set" : "rsABC",
"date" : ISODate("2016-05-10T07:45:25.975Z"),
"myState" : 2,
"term" : NumberLong(2),
"syncingTo" : "mongo-svc1.test:27017",
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 0,
"name" : "mongo-svc1.test:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 657,
"optime" : {
"ts" : Timestamp(1462865715, 2),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2016-05-10T07:35:15Z"),
"lastHeartbeat" : ISODate("2016-05-10T07:45:25.551Z"),
"lastHeartbeatRecv" : ISODate("2016-05-10T07:45:25.388Z"),
"pingMs" : NumberLong(0),
"electionTime" : Timestamp(1462865715, 1),
"electionDate" : ISODate("2016-05-10T07:35:15Z"),
"configVersion" : 1
},
{
"_id" : 1,
"name" : "mongo-svc2.test:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 1171,
"optime" : {
"ts" : Timestamp(1462865715, 2),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2016-05-10T07:35:15Z"),
"syncingTo" : "mongo-svc1.test:27017",
"configVersion" : 1,
"self" : true
},
{
"_id" : 2,
"name" : "mongo-svc3.test:27017",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 657,
"lastHeartbeat" : ISODate("2016-05-10T07:45:25.549Z"),
"lastHeartbeatRecv" : ISODate("2016-05-10T07:45:23.969Z"),
"pingMs" : NumberLong(0),
"configVersion" : 1
}
],
"ok" : 1
}
Я добавляю mongo node именем службы.
Ответ 6
Как хэдз-ап. Не используйте подход mongo-k8s-sidecar в Production, поскольку он имеет потенциально опасные последствия. Для более актуального подхода к использованию MongoDB с помощью statefulSets k8s см.:
Дополнительная информация о MongoDB и Kubernetes доступна по адресу: http://k8smongodb.net/
Ответ 7
Я использую это как решение. Его продукция НЕ готова.
Настройка репликации MongoDB
Получите весь модуль MongoDB IP kubectl describe pod <PODNAME> | grep IP | sed -E 's/IP:[[:space:]]+//'
и...
Выполнить kubectl exec -i <POD_1_NAME> mongo
и...
rs.initiate({
"_id" : "cloudboost",
"version":1,
"members" : [
{
"_id" : 0,
"host" : "<POD_1_IP>:27017",
"priority" : 10
},
{
"_id" : 1,
"host" : "<POD_2_IP>:27017",
"priority" : 9
},
{
"_id" : 2,
"host" : "<POD_3_IP>:27017",
"arbiterOnly" : true
}
]
});
Пример:
rs.initiate({
"_id" : "cloudboost",
"version":1,
"members" : [
{
"_id" : 0,
"host" : "10.244.1.5:27017",
"priority" : 10
},
{
"_id" : 1,
"host" : "10.244.2.6:27017",
"priority" : 9
},
{
"_id" : 2,
"host" : "10.244.3.5:27017",
"arbiterOnly" : true
}
]
});
Обратите внимание: IP может отличаться для вашего кластера.
TODO: Создайте службу безглавых, чтобы автоматически обнаружить узлы и инициализировать репликацию.