腾讯云-Istio案例分析: 端口命名不满足约束导致流量异常

2020-11-13 16:51:46 浏览数 (1)

问题背景

istio 支持多平台,不过 Istio 和 k8s 的兼容性是最优的,不管是设计理念,核心团队还是社区, 都有一脉相承的意思。但 istio 和 k8s 的适配并非完全没有冲突, 一个典型问题就是 istio 需要 k8s service 按照协议进行端口命名(port naming)。

端口命名不满足约束而导致的流量异常,是使用 mesh 过程中最常见的问题,其现象是协议相关的流控规则不生效,这通常可以通过检查该 port LDS 中 filter 的类型来定位。

原因

k8s 的网络对应用层是无感知的,k8s 的主要流量转发逻辑发生在 node 上,由 iptables/ipvs 来实现,这些规则并不关心应用层里是什么协议。

istio 的核心能力是对 7层流量进行管控,但前提条件是 istio 必须知道每个受管控的服务是什么协议,istio 会根据端口协议的不同,下发不同的流控功能(envoy filter),而 k8s 资源定义里并不包括七层协议信息,所以 istio 需要用户显式提供。

image.pngimage.png

istio 的解决方案:Protocol sniffing

协议嗅探简要流程:

  1. envoy 在 inbound 连接上等待接收包,过程会设置超时控制:
  2. 如果触发超时,协议将按照默认协议 TCP 处理
  3. 如果是 server 端先发包,协议将按照 TCP 处理
  4. 检测 TLS CLIENT_HELLO
  5. 如果不是 terminating TLS (通常是应用本身发起的tls/https), 按照 TLS 处理,提取 TLS 中的 SNI 作为 virtual host,进行路由控制
  6. 如果 terminating 连接(通常是sidecar 间的 mtls),尝试从 ALPN/NPN 中提取应用层协议
  7. 如果没有 ALPN/NPN 信息,会进行下一步,尝试读取应用层的数据,见下
  8. 基于常见协议的已知典型结构,尝试检测应用层 plaintext 内容,过程中会设置超时控制和检测包大小限制:
  • 基于HTTP2 spec: Connection Preface,,判断是否为 HTTP/2
  • 基于 HTTP header 结构,判断是否是 HTTP/1.x

最佳实践

Protocol sniffing 减少了新手使用 istio 所需的配置,但是可能会带来不确定的行为。不确定的行为在生产环境中是应该尽量避免的。

一些嗅探失效的例子:

  • 客户端和服务端使用着某类非标准的七层协议,客户端和服务端都可以正确解析,但是不能确保 istio 自动嗅探逻辑认可这类非标准协议。比如对于 http 协议,标准的换行分隔是用CRLF (0x0d 0x0a), 但是大部分 http 类库会使用并认可LF (0x0a)作为分隔。
  • 某些自定义私有协议,数据流的起始格式和 http 报文格式类似,但是后续数据流是自定义格式: 未开启嗅探时:数据流按照 L4 TCP 进行路由,符合用户期望 如果开启嗅探:数据流最开始会被认定为 L7 http 协议,但是后续数据不符合 http 格式,流量将被中断

建议生产环境不使用协议嗅探, 接入 mesh 的 service 应该按照约定使用协议前缀进行命名。

0 人点赞