我们目前正在对 ElasticSearch 集群的特定 Kubernetes 服务 (LoadBalancer) 的问题进行故障排除,该问题似乎在客户端随机提供 ECONNRESET 变得不可用。设置如下:
- 使用 Kops 部署的 AWS 上的 Kubernetes 1.6
- Elasticsearch 2.4 集群(Fabric8 发现插件部署)。它将自己暴露为 Service / LoadBalancer
- NodeJS API部署作为客户端,使用
request
模块连接到上述Elasticsearch服务
在运行足够长的时间(不多,大约 10-15 分钟)后,不一定在大量负载下(大约每秒 1 个请求),ElasticSearch 服务似乎变得不可用,这是来自 API 端的 ECONNRESET 错误症状:
{ Error: connect ECONNRESET 100.69.12.100:9200 at
Object.exports._errnoException (util.js:953:11) at
exports._exceptionWithHostPort (util.js:976:20) at
TCPConnectWrap.afterConnect [as oncomplete] (net.js:1080:14) cause: {
Error: connect ECONNRESET 100.69.12.100:9200 at
Object.exports._errnoException (util.js:953:11) at
exports._exceptionWithHostPort (util.js:976:20) at
TCPConnectWrap.afterConnect [as oncomplete] (net.js:1080:14) code:
'ECONNRESET', errno: 'ECONNRESET', syscall: 'connect', address:
'100.69.12.100', port: 9200 }, isOperational: true, code:
'ECONNRESET', errno: 'ECONNRESET', syscall: 'connect', address:
'100.69.12.100', port: 9200 }
这个错误是随机发生的,不需要高负载,而不是定义的时间段。在这些 ECONNRESET 的确切时间,kube-dns
ElasticSearch 服务(和其他服务)的插件日志创建(重新创建?):
I0515 08:11:49.941166 1 dns.go:264] New service: elasticsearch
I0515 08:11:49.941226 1 dns.go:462] Added SRV record &{Host:elasticsearch.prod.svc.cluster.local. Port:9200 Priority:10 Weight:10 Text: Mail:false Ttl:30 TargetStrip:0 Group: Key:}
I0515 08:11:49.941275 1 dns.go:462] Added SRV record &{Host:elasticsearch.prod.svc.cluster.local. Port:9300 Priority:10 Weight:10 Text: Mail:false Ttl:30 TargetStrip:0 Group: Key:}
对于每个 Kubernetes 服务,这些行几乎每 5 分钟连续重复一次。如果这是正常行为或与我们观察到的故障绝对相关,我完全不知道它们的含义。
API 和 ElasticSearch 在网络上的交互基本上是一组搜索查询(最多 30/50 并行)。在交互过程中,在 ElasticSearch 端没有观察到错误日志。
这在几个月前运行良好,变化是:
- Kubernetes 使用 Kops 从版本 1.4 升级到 1.6
- 为 ElasticSearch 集群添加了 CPU / 内存限制。遵循 Elastic 建议
- 向 Elastic 添加了额外的初始 30 次调用,这些调用在第一次调用后被缓存
尝试的操作:
- 减少和增加 ElasticSearch 端的资源限制(CPU/内存)以查看行为的任何变化。对 ECONNRESET 没有影响
- 增加了 ElasticSearch 端搜索的线程池和队列大小。它处理更多负载,但问题本身在低负载下表现出来。
考虑回滚到 Kubernetes 1.4,并取消任何限制。任何指针或信息都将受到高度赞赏。
更新 1:有关服务的一些额外信息elasticsearch
:
$ kubectl get svc elasticsearch
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elasticsearch 100.65.113.208 [AWS ELB] 9200:30295/TCP,9300:32535/TCP 6d
$ kubectl describe svc elasticsearch
Name: elasticsearch
Namespace: ppe
Labels: <none>
Annotations: kubernetes.io/change-cause=kubectl create --filename=app/elasticsearch/manifest/ --recursive=true --record=true --namespace=ppe --context=
Selector: component=elasticsearch,provider=fabric8,type=client
Type: LoadBalancer
IP: 100.65.113.208
LoadBalancer Ingress: [AWS ELB]
Port: http 9200/TCP
NodePort: http 30295/TCP
Endpoints: 100.96.1.25:9200,100.96.1.26:9200,100.96.2.24:9200 + 5 more...
Port: transport 9300/TCP
NodePort: transport 32535/TCP
Endpoints: 100.96.1.25:9300,100.96.1.26:9300,100.96.2.24:9300 + 5 more...
Session Affinity: None
Events: <none>
更新 2
我现在能够通过使用官方 ElasticSearch NodeJS 客户端进行搜索查询并与服务通信来缓解这个问题。API 上的代码使用request
模块直接调用 ElasticSearch REST API。
我仍在调查这个问题,因为问题仍然存在,但似乎在使用具有以下配置的 NodeJS 客户端时它并没有表现出来:
const elasticSearchClient = elasticSearch.Client({host: config.endpoints.elasticsearch, apiVersion: '2.3',
maxRetries: 5, requestTimeout: 15000, deadTimeout: 30000, keepAlive: true});
更新 3
我们不仅通过与 Elastic 通信的 NodeJS API 观察到这种行为,还观察到与kibana-logging
Kubernetes 服务和elasticdump
:
Mon, 15 May 2017 13:32:31 GMT | sent 1000 objects to destination
elasticsearch, wrote 1000
Mon, 15 May 2017 13:32:42 GMT | got 1000 objects from source
elasticsearch (offset: 24000)
Mon, 15 May 2017 13:32:44 GMT | Error Emitted => failed to parse json
(message: "Unexpected token E in JSON at position 0") - source: "Error:
'read tcp 172.20.33.123:46758->100.96.4.15:9200: read: connection reset
by peer'\nTrying to reach: 'http://100.96.4.15:9200/ghs.products-2017-
05-13/_bulk'"
这两个模块和原始的 NodeJS API 都使用request
NPM 模块与 ElasticSearch 进行通信。有趣的是,ElasticSearch NodeJS 客户端(https://github.com/elastic/elasticsearch-js)似乎没有使用request
.
仍在调查,但这可能最终成为 Elastic Kubernetes Service 暴露 + NodeJSrequest
模块之间的问题/不兼容