Istio注入场景下K8s RabbitMQ StatefulSet对等发现故障咨询
问题现象
- 在Kubernetes环境部署RabbitMQ集群,未启用Istio sidecar注入时集群运行状态符合预期
- 开启命名空间
istio-injection注入后,RabbitMQ集群在启动阶段因对等发现失败发生崩溃,Pod日志输出如下错误:
2022-06-23 12:39:59.907 [error] <0.249.0> CRASH REPORT Process <0.249.0> with 0 neighbours exited with reason: no match of right hand value {error,eacces} in rabbit_peer_discovery_k8s:make_request/0 line 110 in application_master:init/4 line 138
已尝试的修复操作
尝试为每个RabbitMQ Pod创建ServiceEntry,暴露所有服务端口以告知Istio对应端点属于服务网格内部,使用的ServiceEntry配置示例如下,配置后相同错误仍然出现:
apiVersion: networking.istio.io/v1alpha3 kind: ServiceEntry metadata: labels: app: rabbitmq-ha chart: rabbitmq-ha-1.12.1 heritage: Tiller release: rabbitmq name: rabbitmq namespace: rabbitns spec: hosts: - rabbitmq-0.rabbitmq-discovery.rabbitns.svc.cluster.local - rabbitmq-1.rabbitmq-discovery.rabbitns.svc.cluster.local location: MESH_INTERNAL ports: - name: http number: 15672 protocol: TCP - name: amqp number: 5672 protocol: TCP - name: epmd number: 4369 protocol: TCP - name: amqps number: 5671 protocol: TCP - name: exporter number: 9419 protocol: TCP - name: inter-node number: 25672 protocol: TCP resolution: NONE
环境信息
当前环境组件版本如下:
$ istioctl version client version: 1.14.0 control plane version: 1.14.0 data plane version: 1.14.0 (3 proxies) $ kubectl version --short Client Version: v1.21.5 Server Version: v1.22.4
已确认的排查线索
- 执行
istioctl bug-report生成的分析报告抛出如下配置校验错误:
Error [IST0106] (ServiceEntry rabbitns/rabbitmq) Schema validation error: multiple hosts provided with non-HTTP, non-TLS ports
- Istio可正常识别常规Service资源(单DNS关联所有后端Pod,轮询转发流量的模式),但无法识别StatefulSet生成的Pod独立DNS,对应配置会被直接拒绝
- 问题与mTLS配置无关,无论启用或禁用mTLS均可稳定复现相同错误
根因分析与解决方案
根因
- 编写的ServiceEntry不符合Istio配置规则:当ServiceEntry配置
resolution: NONE、端口为非HTTP/非TLS的普通TCP协议时,仅支持配置单个host,多host配置会触发IST0106校验错误,配置完全不会被Istio下发生效。 - 核心故障原因是sidecar启动顺序竞争:RabbitMQ对等发现插件启动时会优先请求Kubernetes API获取集群节点列表,此时Envoy sidecar尚未完成初始化,出向流量被iptables规则拦截后无可用代理路径,直接返回
EACCES错误,和ServiceEntry配置无直接关联。
可落地修复方案
- 方案1(无侵入,优先推荐):配置业务容器等待Envoy代理启动完成后再启动,彻底规避启动阶段的流量拦截问题。为RabbitMQ工作负载添加如下Pod注解:
annotations: proxy.istio.io/config: | holdApplicationUntilProxyStarts: true
- 方案2:豁免RabbitMQ对等发现、节点间通信的出向流量,使其不经过Envoy代理。为RabbitMQ工作负载添加如下Pod注解:
annotations: traffic.sidecar.istio.io/excludeOutboundPorts: "443,4369,25672"
其中443为访问Kubernetes API Server的默认端口,4369为epmd端口,25672为RabbitMQ节点间数据同步端口,上述端口流量绕过sidecar后,对等发现流程可正常执行。
- 如果确实需要通过ServiceEntry注册StatefulSet Pod的独立域名,不要在同一个TCP类型ServiceEntry中配置多个host,为每个Pod的独立DNS创建单独的ServiceEntry资源即可通过Istio schema校验。
内容的提问来源于stack exchange,提问作者Yiadh TLIJANI
相关产品推荐
相关产品推荐

