解决ASM中Server First协议应用连接问题

在 ASM 中运行 MySQL 等 Server First 协议应用时,为避免因 Sidecar 协议检测引发连接超时,可根据服务部署场景,通过修改端口名、配置 ServiceEntry 或禁用 mTLS 的方式显式声明 TCP 协议,以绕过检测,解决服务连接超时问题。

超时原理分析

Server First协议(如SMTP、MySQL、DNS)的特征是TCP连接建立后,服务端先于客户端发送数据。

ASMSidecar代理默认启用协议自动检测。自动检测与Server First协议连接过程存在冲突,如下:

  • 服务端:服务端的 Sidecar 代理必须拦截客户端的首个数据包以识别协议。在识别完成前,不会将连接转发至服务端。

  • 客户端:在TCP握手后,等待服务端首先发送数据,自身不发送任何业务数据。

Sidecar代理等待客户端发送数据以识别协议,而客户端等待被Sidecar代理阻塞的服务端数据,双方陷入相互等待,最终导致客户端连接超时。

场景一:客户端和服务端均在网格内

服务端未使用标准端口

  • 方式一:启用服务端标准端口,此时ASM会进行特殊处理,Sidecar代理不会阻塞连接。常见Server First协议应用的标准端口如下。

    协议

    标准端口

    MySQL

    3306

    SMTP

    25

    DNS

    53

    MongoDB

    27017

  • 方式二:修改服务端YAML配置,在ports.name添加tcp-前缀。以下YAML示例为运行在3307非标准端口的MySQL服务。

    apiVersion: v1
    kind: Service
    metadata:
      name: my-mysql-svc
    spec:
      ports:
      - name: tcp-mysql-port
        port: 3307
        targetPort: 3307
      selector:
        app: my-mysql-server

服务端未使用TLS连接

为服务端启用TLS连接,由于TLS协议握手过程需要客户端先发送ClientHello消息,满足了Sidecar代理的协议检测需求,因此Sidecar代理不会阻塞连接。

场景二:客户端在网格内,服务端在网格外

  1. ASM中开启DNS代理功能,并重启所有需要访问外部服务的客户端Pod使代理生效。

  2. 为外部服务创建ServiceEntry资源,并在端口定义中将protocol显式声明为TCP

    此配置会指示Sidecar代理将发往该外部服务的流量作为纯TCP流量处理,从而避免协议检测。

    示例:为外部RDS for MySQL实例创建ServiceEntry

    目标服务域名为rm-xxxx.mysql.rds.aliyuncs.com,端口为3306

    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: external-mysql-rds
    spec:
      # 1. 填入外部服务域名
      hosts:
      - rm-xxxx.mysql.rds.aliyuncs.com
      location: MESH_EXTERNAL
      ports:
      # 2. 声明端口,并将协议指定为TCP
      - name: tcp-mysql
        number: 3306
        protocol: TCP # 关键:显式声明为TCP协议
      # 3. 使用DNS进行服务发现
      resolution: DNS

    创建此ServiceEntry资源后,客户端即可正常访问该外部数据库。

场景三:客户端在网格外,网格内服务端不使用TLS连接

为服务端的工作负载禁用该端口的mTLS。请参考示例四-禁用8080端口mTLS

说明

服务端不使用TLS连接且直接对外暴露,可能会带来安全隐患,建议为服务端启用TLS连接。