K8s中Mongo副本集出现随机NotPrimaryError的技术咨询
MongoDB副本集写入NotPrimaryError问题排查与解决
环境信息
通过Helm Mongo Chart以--set architecture=replicaset部署Mongo副本集,当前运行Pod:
pod/mongo-mongodb-0 1/1 Running 0 6h15m pod/mongo-mongodb-1 1/1 Running 0 6h15m pod/mongo-mongodb-arbiter-0 1/1 Running 0 6h15m
对应的服务:
service/mongo-mongodb-arbiter-headless service/mongo-mongodb-headless
遇到的异常
执行find_one_and_update等写入操作时随机触发:
pymongo.errors.NotPrimaryError: not primary, full error: {'errorLabels': ['RetryableWriteError'], 'topologyVersion': {'processId': ObjectId('638f137760787a4a2c889597'), 'counter': 3}, 'ok': 0.0, 'errmsg': 'not primary', 'code': 10107, 'codeName': 'NotWritablePrimary', '$clusterTime': {'clusterTime': Timestamp(1670343147, 130), 'signature': {'hash': b'\xce\xa6_4\xe8H_G\xa5\x06\xf1\xe1\x1a?\x88\xd1\x01\x7f,\xa5', 'keyId': 7173973884128422279}}, 'operationTime': Timestamp(1670343147, 130)}
问题解答
1. 是否是写入只读副本?是否应该连接仲裁节点服务?
- 该错误确实是因为请求被路由到了只读副本节点。
mongo-mongodb-headless是副本集的无头服务,会解析到所有数据节点(主节点+从节点),客户端随机连接到从节点时,写入操作就会触发NotPrimaryError。 - 绝对不能连接
mongo-mongodb-arbiter-headless:仲裁节点不存储任何数据,仅参与副本集选举,无法处理任何读写请求,连接它只会引发更多错误。
2. 如何确保写入仅使用主节点?
有两种可靠方案:
方案一:利用pymongo副本集自动发现机制
连接时指定副本集名称(Helm默认部署的副本集名称为mongodb),将mongo-mongodb-headless作为种子地址传入,pymongo会自动发现主节点,后续所有写入请求都会路由到主节点。同时开启重试机制,可自动处理主节点切换导致的可重试错误:from pymongo import MongoClient client = MongoClient( "mongodb://mongo-mongodb-headless:27017/", replicaSet="mongodb", retryWrites=True )方案二:使用主节点专属服务(若Chart支持)
部分Mongo Helm Chart会提供专门指向主节点的服务(通常命名为mongo-mongodb-primary),可直接连接该服务,所有请求将直接发送到主节点。可通过helm status mongo查看是否存在此类服务,若有则直接替换连接地址即可。
内容的提问来源于stack exchange,提问作者JasonGenX
相关产品推荐
相关产品推荐

