(O+P)ut

アウトプット



(O+P)ut

エンジニアのアウトプット

【MongoDB/Kubernetes】レプリカセットの初期設定

スポンサーリンク

はじめに

KubernetesのStatefulsetを利用して3つのMongoDBを用意し、PrimaryとSecondaryとArbiterにてレプリケーションを組む手順について解説します。

環境情報
  • MongoDB v4.4
  • kubectl v1.18

事前準備

以下のyamlを展開することで3台もMongoDBがレプリカセット名repltestという名前で作成されます。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongod
spec:
  serviceName: mongodb-service
  replicas: 3
  selector:
    matchLabels:
      role: mongo
  template:
    metadata:
      labels:
        role: mongo
        replicaset: MainRepSet
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: mongod-container
          image: mongo
          command:
            - "mongod"
            - "--bind_ip"
            - "0.0.0.0"
            - "--replSet"
            - "repltest"
          ports:
            - containerPort: 27017
apiVersion: v1
kind: Service
metadata:
  name: mongodb-service
  labels:
    name: mongo
spec:
  ports:
  - port: 27017
    targetPort: 27017
  selector:
    role: mongo


以下のようになれば全Podが正常に起動しています。

$ kubectl get pod
NAME                             READY   STATUS      RESTARTS   AGE
mongod-0                         1/1     Running     0          ..
mongod-1                         1/1     Running     0          ..
mongod-2                         1/1     Running     0          ..

レプリカセットの設定(プライマリー)

mongo-0に入ってレプリカセットの状態を確認するとno replset config has been receivedと表示されます。

> rs.status()
{
        "operationTime" : Timestamp(0, 0),
        "ok" : 0,
        "errmsg" : "no replset config has been received",
        "code" : 94,
        "codeName" : "NotYetInitialized",
        "$clusterTime" : {
                "clusterTime" : Timestamp(0, 0),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

よって以下にて初期化を行いレプリカセットに加えるDBサーバを指定します。引数としてはPod_Name.Service_Nameです。

> rs.initiate({_id: "repltest",members: [{_id:0,host:"mongod-0.mongodb-service:27017"}]})
{
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1603700291, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        },
        "operationTime" : Timestamp(1603700291, 1)
}

同設定が完了するとmembersとして_idが0のPodが追加されています。

> rs.status()
{
        "set" : "repltest",
        "date" : ISODate("xx"),
        "myState" : 1,
        "term" : NumberLong(1),
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "heartbeatIntervalMillis" : NumberLong(2000),
        "majorityVoteCount" : 1,
        "writeMajorityCount" : 1,
        "votingMembersCount" : 1,
        "writableVotingMembersCount" : 1,
        "optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1603700291, 8),
                        "t" : NumberLong(1)
                },
                "lastCommittedWallTime" : ISODate("xx"),
                "readConcernMajorityOpTime" : {
                        "ts" : Timestamp(1603700291, 8),
                        "t" : NumberLong(1)
                },
                "readConcernMajorityWallTime" : ISODate("xx"),
                "appliedOpTime" : {
                        "ts" : Timestamp(1603700291, 8),
                        "t" : NumberLong(1)
                },
                "durableOpTime" : {
                        "ts" : Timestamp(1603700291, 8),
                        "t" : NumberLong(1)
                },
                "lastAppliedWallTime" : ISODate("xx"),
                "lastDurableWallTime" : ISODate("xx")
        },
        "lastStableRecoveryTimestamp" : Timestamp(1603700291, 7),
        "electionCandidateMetrics" : {
                "lastElectionReason" : "electionTimeout",
                "lastElectionDate" : ISODate("xx"),
                "electionTerm" : NumberLong(1),
                "lastCommittedOpTimeAtElection" : {
                        "ts" : Timestamp(0, 0),
                        "t" : NumberLong(-1)
                },
                "lastSeenOpTimeAtElection" : {
                        "ts" : Timestamp(1603700291, 1),
                        "t" : NumberLong(-1)
                },
                "numVotesNeeded" : 1,
                "priorityAtElection" : 1,
                "electionTimeoutMillis" : NumberLong(10000),
                "newTermStartDate" : ISODate("2020-10-26T08:18:11.338Z"),
                "wMajorityWriteAvailabilityDate" : ISODate("2020-10-26T08:18:11.372Z")
        },
        "members" : [
                {
                        "_id" : 0,
                        "name" : "mongod-0.mongodb-service:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 174,
                        "optime" : {
                                "ts" : Timestamp(1603700291, 8),
                                "t" : NumberLong(1)
                        },
                        "optimeDate" : ISODate("xx"),
                        "syncSourceHost" : "",
                        "syncSourceId" : -1,
                        "infoMessage" : "Could not find member to sync from",
                        "electionTime" : Timestamp(1603700291, 2),
                        "electionDate" : ISODate("xx"),
                        "configVersion" : 1,
                        "configTerm" : 1,
                        "self" : true,
                        "lastHeartbeatMessage" : ""
                }
        ],
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1603700291, 8),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        },
        "operationTime" : Timestamp(1603700291, 8)
}

プロンプトも以下のように変化しプライマリーであることが分かります。

repltest:PRIMARY>

セカンダリーを追加する

以下で2つ目のPodをSecondaryとして追加できます。

repltest:PRIMARY> rs.add("mongod-1.mongodb-service:27017")
{
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1603702008, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        },

同じく以下で3つ目のPodも追加できます。
(本コマンドはPrimary選出のみを行うARBITERとして追加していますがaddとすればSecondaryとして追加されます。)

rs.addArb("mongod-2.mongodb-service:27017")

これの状態で改めてレプリカセットの状態を確認するとPrimaryが一つとSecondaryが二つの構成であることが確認できます。

repltest:PRIMARY> rs.status()
...
        "members" : [
                {
                        "_id" : 0,
                        "name" : "mongod-0.mongodb-service:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
...
                {
                        "_id" : 1,
                        "name" : "mongod-1.mongodb-service:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
....
                        "_id" : 2,
                        "name" : "mongod-2.mongodb-service:27017",
                        "health" : 1,
                        "state" : 7,
                        "stateStr" : "ARBITER",
 ...

終わりに

MongoDBにてレプリケーションを行う上での初期設定について説明しました。
尚、よくあるミスとしてメンバーを追加する際にサーバ名の指定に失敗すると以下メッセージでエラーとなるのでご注意ください。

SocketException: Host not found (authoritative)",
        "code" : 74,
        "codeName" : "NodeNotFound",

以上、ご参考になれば幸いです。