diff --git a/README.md b/README.md index 75bfcd4..da0116e 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ There you will also find some helper scripts to test out creating the replica se | Environment Variable | Required | Default | Description | | --- | --- | --- | --- | | KUBE_NAMESPACE | NO | | The namespace to look up pods in. Not setting it will search for pods in all namespaces. | -| MONGO_SIDECAR_POD_LABELS | YES | | This should be a be a comma separated list of key values the same as the podTemplate labels. See above for example. | +| MONGO_SIDECAR_POD_LABELS | YES | | This should be a comma separated list of key values the same as the podTemplate labels. See above for example. | +| MONGO_SIDECAR_POD_LABELS_ARBITER | NO | | This should be a comma separated list of key values the same as the podTemplate labels. Nodes with the selected labels will be added to the replicaSet as Arbiters to participate in elections but without storing data. | MONGO_SIDECAR_SLEEP_SECONDS | NO | 5 | This is how long to sleep between work cycles. | | MONGO_SIDECAR_UNHEALTHY_SECONDS | NO | 15 | This is how many seconds a replica set member has to get healthy before automatically being removed from the replica set. | | MONGO_PORT | NO | 27017 | Configures the mongo port, allows the usage of non-standard ports. | diff --git a/src/lib/config.js b/src/lib/config.js index b2fb0d2..7738250 100644 --- a/src/lib/config.js +++ b/src/lib/config.js @@ -4,12 +4,23 @@ var getMongoPodLabels = function() { return process.env.MONGO_SIDECAR_POD_LABELS || false; }; +var getMongoPodLabelsArbiter = function() { + return process.env.MONGO_SIDECAR_POD_LABELS_ARBITER || false; +}; + var getMongoPodLabelCollection = function() { - var podLabels = getMongoPodLabels(); - if (!podLabels) { + return parseLabelCollection(getMongoPodLabels()); +}; + +var getMongoPodLabelCollectionArbiter = function() { + return parseLabelCollection(getMongoPodLabelsArbiter()); +}; + +var parseLabelCollection = function(labelString) { + if (!labelString) { return false; } - var labels = process.env.MONGO_SIDECAR_POD_LABELS.split(','); + var labels = labelString.split(','); for (var i in labels) { var keyAndValue = labels[i].split('='); labels[i] = { @@ -115,6 +126,8 @@ module.exports = { mongoSSLAllowInvalidHostnames: stringToBool(process.env.MONGO_SSL_ALLOW_INVALID_HOSTNAMES), env: process.env.NODE_ENV || 'local', mongoPodLabels: getMongoPodLabels(), + mongoPodLabelsArbiter: getMongoPodLabelsArbiter(), + mongoPodLabelCollectionArbiter: getMongoPodLabelCollectionArbiter(), mongoPodLabelCollection: getMongoPodLabelCollection(), k8sROServiceAddress: getk8sROServiceAddress(), k8sMongoServiceName: getK8sMongoServiceName(), diff --git a/src/lib/k8s.js b/src/lib/k8s.js index daa45df..fbfb0be 100644 --- a/src/lib/k8s.js +++ b/src/lib/k8s.js @@ -50,5 +50,6 @@ var podContainsLabels = function podContainsLabels(pod, labels) { }; module.exports = { - getMongoPods: getMongoPods + getMongoPods: getMongoPods, + podContainsLabels: podContainsLabels }; diff --git a/src/lib/mongo.js b/src/lib/mongo.js index 2766b97..fb7026d 100644 --- a/src/lib/mongo.js +++ b/src/lib/mongo.js @@ -2,6 +2,7 @@ var Db = require('mongodb').Db; var MongoServer = require('mongodb').Server; var async = require('async'); var config = require('./config'); +var k8s = require('./k8s'); var localhost = '127.0.0.1'; //Can access mongo as localhost from a sidecar @@ -160,9 +161,14 @@ var addNewMembers = function(rsConfig, addrsToAdd) { var cfg = { _id: ++max, - host: addrToAdd + host: addrsToAdd[i].host }; + // check if we want to add the pod as an arbiter only based on its labels + if (k8s.podContainsLabels(addrsToAdd[i].pod, config.mongoPodLabelCollectionArbiter)) { + cfg.arbiterOnly = true; + } + rsConfig.members.push(cfg); } }; diff --git a/src/lib/worker.js b/src/lib/worker.js index 05b1de1..d265ff3 100644 --- a/src/lib/worker.js +++ b/src/lib/worker.js @@ -216,7 +216,10 @@ var invalidReplicaSet = function(db, pods, status, done) { var podElection = function(pods) { //Because all the pods are going to be running this code independently, we need a way to consistently find the same //node to kick things off, the easiest way to do that is convert their ips into longs and find the highest - pods.sort(function(a,b) { + + var filtered_pods = pods.filter(function(pod) { return !k8s.podContainsLabels(pod, config.mongoPodLabelCollectionArbiter); }) + + filtered_pods.sort(function(a,b) { var aIpVal = ip.toLong(a.status.podIP); var bIpVal = ip.toLong(b.status.podIP); if (aIpVal < bIpVal) return -1; @@ -225,7 +228,7 @@ var podElection = function(pods) { }); //Are we the lucky one? - return pods[0].status.podIP == hostIp; + return filtered_pods[0].status.podIP == hostIp; }; var addrToAddLoop = function(pods, members) { @@ -253,7 +256,8 @@ var addrToAddLoop = function(pods, members) { if (!podInRs) { // If the node was not present, we prefer the stable network ID, if present. var addrToUse = podStableNetworkAddr || podIpAddr; - addrToAdd.push(addrToUse); + var obj = { host: addrToUse, pod: pod }; + addrToAdd.push(obj); } } return addrToAdd;