Istio 为服务指定协议
1、背景
Istio 默认支持代理所有 TCP 流量。包括 HTTP、HTTPS、gRPC 以及原始 TCP 协议。但为了提供额外的能力,比如路由和丰富的指标,必须确定协议。协议可以被自动检测或者手动声明。
使用非基于 TCP 的协议时,如 UDP,不会被 Istio 代理拦截,可以继续正常工作。但是不能在仅代理的组件中使用,如 Ingress 或 Egress Gateway。
2、协议选择
2.1 自动协议选择
istio 需要知道服务提供什么七层协议,从而来为其配置相应协议的 filter chain,通常最好是显式声明协议,如果没有声明,istio 会自动探测,这个探测能力比较有限(可以自动检测出 HTTP 和 HTTP/2 流量),如果未自动检测出协议,流量将会视为普通 TCP 流量。
2.2 手动协议选择
协议可以在 Service 定义中手动指定。
可以通过以下两种方式配置:
- 通过端口名称配置:
name: <protocol>[-<suffix>]
。 - 在版本 1.18+ 的Kubernetes,通过
appProtocol
字段配置:appProtocol: <protocol>
。
支持以下协议:
协议 | 边车用途 | 网关目的 |
---|---|---|
http |
明文 HTTP/1.1 流量 | 明文 HTTP(1.1 或 2)流量 |
http2 |
明文 HTTP/2 流量 | 明文 HTTP(1.1 或 2)流量 |
https |
TLS 加密数据。因为 Sidecar 不会解密 TLS 流量,所以这与tls |
TLS 加密 HTTP(1.1 或 2)流量 |
tcp |
不透明的TCP数据流 | 不透明的TCP数据流 |
tls |
TLS 加密数据 | TLS 加密数据 |
grpc ,grpc-web |
与...一样http2 |
与...一样http2 |
mongo , mysql ,redis |
实验应用协议支持。要启用它们,请配置相应的 Pilot环境变量。如果未启用,则视为不透明 TCP 数据流 | 实验应用协议支持。要启用它们,请配置相应的 Pilot环境变量。如果未启用,则视为不透明 TCP 数据流 |
注意 1:网关的行为在某些情况下会有所不同,因为网关可以终止 TLS 并且可以协商协议。
2.2.1 方式一:使用服务端口名称时指定协议类型
在 Service 的 ports 中,port 的 name 需设置为 {协议名称}或{协议名称}-{自定义后缀}
。例如:服务的 9090 端口是 gRPC 协议类型,可以设置 port 的 name 为 grpc-demo
;服务的 3306 端口是 MySQL 数据库协议,可以设置 port 的 name 为 mysql。
YAML 示例如下:
kind: Service metadata: name: svc-v1 spec: ports: - port: 9090 name: grpc-demo # 指定该端口提供 grpc 协议的服务 - port: 3306 name: mysql # 指定该端口提供 mysql 协议的服务
2.2.2 方式二:使用服务端口的appProtocol指定协议类型
可以使用 Service 的 appProtocol 指定协议类型。
指定协议类型为 HTTPS 的 YAML 示例如下:
kind: Service metadata: name: svc-v2 spec: ports: -port: 3306 name: database appProtocol: https # 指定该端口提供 https 协议的服务
注意 1:
ports.appProtocol
的生效优先级高于ports.name
。
3、HTTP网关协议选择
与 sidecar 不同,网关默认无法自动检测将请求转发到后端服务时使用的特定 HTTP 协议。因此,除非使用显式协议选择来指定 HTTP/1.1 ( http
) 或 HTTP/2 (http2
或grpc
),否则网关将使用 HTTP/1.1 转发所有传入 HTTP 请求。
您可以通过设置服务选项来指示网关使用与传入请求相同的协议来转发请求,而不是使用显式协议选择useClientProtocol
。但请注意,将此选项与不支持 HTTP/2 的服务一起使用可能存在风险,因为 HTTPS 网关始终通告对 HTTP/1.1 和 HTTP/2 的支持。因此,即使后端服务不支持 HTTP/2,现代客户端也会认为它支持并经常选择使用它。
参考:协议选择