关于腾讯云:istio-常见的-10-个异常

48次阅读

共计 6689 个字符,预计需要花费 17 分钟才能阅读完成。

总结应用 istio 常见的 10 个异样:

  1. Service 端口命名束缚
  2. 流控规定下发程序问题
  3. 申请中断剖析
  4. sidecar 和 user container 启动程序
  5. Ingress Gateway 和 Service 端口联动
  6. VirtualService 作用域
  7. VirtualService 不反对 host fragment
  8. 全链路跟踪并非齐全通明接入
  9. mTLS 导致连贯中断
  10. 用户服务监听地址限度

1. Service 端口命名束缚

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 须要用户显式提供。

istio 的解决方案:Protocol sniffing

协定嗅探概要:

  • 检测 TLS CLIENT_HELLO 提取 SNI、ALPN、NPN 等信息
  • 基于常见协定的已知典型构造,尝试检测应用层 plaintext 内容 a. 基于 HTTP2 spec: Connection Preface,, 判断是否为 HTTP/2 b. 基于 HTTP header 构造,判断是否是 HTTP/1.x
  • 过程中会设置超时管制和检测包大小限度,默认依照协定 TCP 解决

最佳实际

Protocol sniffing 缩小了老手应用 istio 所需的配置,然而可能会带来不确定的行为。不确定的行为在生产环境中是应该尽量避免的。

一些嗅探生效的例子:

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

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

2. 流控规定下发程序问题

异样形容

在批量更新流量规定的过程中,偶然会呈现流量异样(503),envoy 日志中 RESPONSE_FLAGS 蕴含「NR」标记(No route configured),持续时间不长,会主动复原。

起因剖析

当用户应用 kubectl apply -f multiple-virtualservice-destinationrule.yaml时,这些对象的流传和失效先后顺序是不保障的,所谓最终一致性,比方 VirtualService 中援用了某一个 DestinationRule 定义的子版本,然而这个 DestinationRule 资源的流传和失效可能在工夫上落后于 该 VirtualService 资源。

最佳实际:make before break

将更新过程从批量单步拆分为多步骤,确保整个过程中不会援用不存在的 subset:

当新增 DestinationRule subset 时,应该先 apply DestinationRule subset,期待 subset 失效后,再 apply 援用了该 subset 的 VirtualService。

当删除 DestinationRule subset 时,应该先 删除 VirtualService 中对 该 subset 的援用,期待 VirtualService 的批改失效后,在执行删除 DestinationRule subset。

3. 申请中断剖析

申请异样,到底是 istio 流控规定导致,还是业务利用的返回,流量断点呈现在哪个具体的 pod?

这是应用 mesh 最常见的窘境,在微服务中引入 envoy 作为代理后,当流量拜访和预期行为不符时,用户很难疾速确定问题是出在哪个环节。客户端收到的异样响应,诸如 403、404、503 或者连贯中断等,可能是链路中任一 sidecar 执行流量管控的后果,但也有可能是来自某个服务的正当逻辑响应。

envoy 流量模型

Envoy 承受申请流量叫做 Downstream,Envoy 发出请求流量叫做 Upstream。在解决 Downstream 和 Upstream 过程中,别离会波及 2 个流量端点,即申请的发动端和接收端:

在这个过程中,envoy 会依据用户规定,计算出符合条件的转发目标主机汇合,这个汇合叫做 UPSTREAM_CLUSTER, 并依据负载平衡规定,从这个汇合中抉择一个 host 作为流量转发的接收端点,这个 host 就是 UPSTREAM_HOST。

以上就是 envoy 申请解决的 流量五元组信息,这是 envoy 日志里最重要的局部,通过这个五元组咱们能够精确的观测流量「从哪里来」和「到哪里去」。

  • UPSTREAM_CLUSTER
  • DOWNSTREAM_REMOTE_ADDRESS
  • DOWNSTREAM_LOCAL_ADDRESS
  • UPSTREAM_LOCAL_ADDRESS
  • UPSTREAM_HOST

日志剖析示例

通过日志重点观测 2 个信息:

  • 断点是在哪里?
  • 起因是什么?

示例一:一次失常的 client-server 申请

能够看到 2 端日志蕴含雷同的 request ID,因而能够将流量剖析串联起来。

示例二:no healthy upstream, 比方指标 deployment 衰弱正本数为 0

日志中 flag「UH」示意 upstream cluster 中没有衰弱的 host。

示例三:No route configured , 比方 DestinationRule 不足对应的 subset

日志中 flag「NR」示意找不到路由。

示例四,Upstream connection failure,比方服务未失常监听端口。

日志中 flag「UF」示意 Upstream 连贯失败,据此能够判断出流量断点地位。

4. sidecar 和 user container 启动程序

异样形容

Sidecar 模式在 kubernetes 世界很风行,但对目前的 k8s(V1.17)来说,并没有 sidecar 的概念,sidecar 容器的角色是用户主观赋予的。

对 Istio 用户来说,一个常见的困扰是:sidecar 和用户容器的启动程序:

sidecar(envoy)和用户容器的启动程序是不确定的,如果用户容器先启动了,envoy 还未实现启动,这时候用户容器往外发送申请,申请依然会被拦挡,发往未启动的 envoy,申请异样。

在 Pod 终止阶段,也会有相似的异样,本源依然是 sidecar 和一般容器的生命周期的不确定性。

解决方案

目前惯例的躲避计划次要是有这样几种:

  • 业务容器提早几秒启动, 或者失败重试
  • 启动脚本中被动探测 envoy 是否 ready,如 127.0.0.1:15020/ healthz/ready

无论哪种计划都显得很糟糕,为了彻底解决上述痛点,从 kubernets 1.18 版本开始,k8s 内置的 Sidecar 性能将确保 sidecar 在失常业务流程开始之前就启动并运行,即通过更改 pod 的启动生命周期,在 init 容器实现后启动 sidecar 容器,在 sidecar 容器就绪后启动业务容器,从启动流程上保障程序性。而 Pod 终止阶段,只有当所有一般容器都已达到终止状态, 才会向 sidecar 容器发送 SIGTERM 信号。

5. Ingress Gateway 和 Service 端口联动

Ingress Gateway 规定不失效的一个常见起因是:Gateway 的监听端口在对应的 k8s Service 上没有开启,首先咱们须要了解 Istio Ingress Gateway 和 k8s Service 的关系:

上图中,尽管 gateway 定义冀望管控端口 b 和 c,然而它对应的 service(通过腾讯云 CLB)只开启了端口 a 和 b,因而最终从 LB 端口 b 进来的流量能力被 istio gateway 管控。

  • Istio Gateway 和 k8s Service 没有间接的关联,二者都是通过 selector 去绑定 pod,实现间接关联
  • Istio CRD Gateway 只实现了将用户流控规定下发到网格边缘节点,流量仍须要通过 LB 管制能力进入网格
  • 腾讯云 tke mesh 实现了 Gateway-Service 定义中的 Port 动静联动,让用户聚焦在网格内的配置。

6. VirtualService 作用域

VirtualService 蕴含了大部分 outbound 端的流量规定,它既能够利用到网格外部数据面代理中,也能够利用到网格边缘的代理中。

VirtualService 的属性 gateways 用于指定 VirtualService 的失效范畴:

  • 如果 VirtualService.gateways为空,则 istio 为其赋默认值 mesh, 代表失效范畴为网格外部
  • 如果心愿 VirtualService 利用到具体边缘网关上,则须要显示为其赋值:gateway-name1,gateway-name2...
  • 如果心愿 VirtualService 同时利用到网格外部和边缘网关上,则须要显示地把 mesh 值退出 VirtualService.gateways,如 mesh,gateway-name1,gateway-name2... 一个常见的问题是以上的第三种状况,VirtualService 最开始作用于网关外部,后续要将其规定扩大到边缘网关上,用户往往只会增加具体 gateway name,而脱漏 mesh:

Istio 主动给 VirtualService.gateways 设置默认值,本意是为了简化用户的配置,然而往往会导致用户利用不当,一个 feature 一不小心会被用成了 bug。

7. VirtualService 不反对 host fragment

异样案例

对某一 host 新增、批改 VirtualService,发现规定始终无奈失效,排查发现存在其余 VirtualService 也对该 host 利用了其余规定,规定内容可能不抵触,但还是可能呈现其中一些规定无奈失效的状况。

背景

  • VirtualService 里的规定,依照 host 进行聚合
  • 随着业务的增长,VirtualService 的内容会快速增长,一个 host 的流控规定,可能会由不同的团队散布保护。如平安规定和业务规定离开,不同业务依照子 path 离开

目前 istio 对 cross-resource VirtualService 的反对状况:

  • 在网格边缘(gateway),同一个 host 的流控规定,反对散布到多个 VirtualService 对象中,istio 主动聚合,但依赖定义程序以及用户自行防止抵触。
  • 在网格外部(for sidecar),同一个 host 的流控规定,不反对散布到多个 VirtualService 对象中,如果同一个 host 存在多个 VirtualService,只有第一个 VirtualService 失效,且没有冲突检测。

VirtualService 不能很好反对 host 规定分片,使得团队的保护职责不能很好的解耦,配置人员须要知悉指标 host 的所有流控规定,才有信念去批改 VirtualService。

Istio 解决方案:Virtual Service chaining(plan in 1.6)

Istio 打算在 1.6 中反对 Virtual Service 代理链:

  • Virtual Service 反对分片定义 + 代理链
  • 反对团队对同一 host 的 Virtual Service 进行灵便分片,比方依照 SecOps/Netops/Business 个性拆散,各团队保护各种独立的 Virtual Service

8. 全链路跟踪并非齐全通明接入

异样案例

微服务接入后 service mesh 后,链路跟踪数据没有造成串联。

起因

service mesh 遥测零碎中,对调用链跟踪的实现,并非齐全的零入侵,须要用户业务作出大量的批改能力反对,具体地,在用户收回(http/grpc)RPC 时,须要被动将上游申请中存在的 B3 trace headers写入上游 RPC 申请头中,这些 headers 包含:

有局部用户难以了解:既然 inbound 流量和 outbound 流量曾经齐全被拦挡到 envoy,envoy 能够实现齐全的流量管控和批改,为什么还须要利用显示第传递 headers?

对于 envoy 来说,inbound 申请和 outbound 申请齐全是独立的,envoy 无奈感知申请之间的关联。实际上这些申请到底有无上下级关联,齐全由利用本人决定。举一个非凡的业务场景,如果 Pod X 接管到 申请 A,触发的业务逻辑是:每隔 10 秒 发送一个申请到 Pod Y,如 B1,B2,B3,那么这些扇出的申请 Bx(x=1,2,3…),和申请 A 是什么关系?业务可能有不同的决策:认为 A 是 Bx 的父申请,或者认为 Bx 是独立的顶层申请。

9. mTLS 导致连贯中断

在开启 istio mTLS 的用户场景中,拜访呈现 connection termination 是一个高频的异样:

这个异样的起因和 DestinationRule 中的 mTLS 配置无关,是 istio 中一个不强壮的接口设计。

  • 当通过 MeshPolicy 开启全局 mTLS,如果网格中没有定义其余的 DestinationRule,mTLS 失常运行
  • 如果后续网格中新增了 DestinationRule,而 DestinationRule 中能够笼罩子版本的 mTLS 值(默认是不开启!), 用户在应用 DestinationRule 时,往往很少去关注 mTLS 属性(留空)。最终导致增 DestinationRule 后 mTLS 变成了不开启,导致connection termination
  • 为了修复以上问题,用户不得不在所有 DestinationRule 中减少 mTLS 属性并设置为开启

这种 istio mtls 用户接口极度不敌对,尽管 mtls 默认做到了全局通明,业务感知不到 mtls 的存在,然而一旦业务定义了 DestinationRule,就必须要晓得以后 mtls 是否开启,并作出调整。试想 mtls 配置交由平安团队负责,而业务团队负责各自的 DestinationRule,团队间的耦合会十分重大。

10. 用户服务监听地址限度

异样形容

如果用户容器中业务过程监听的地址是具体 ip (pod ip),而不是0.0.0.0, 该用户容器无奈失常接入 istio,流量路由失败。这是又一个挑战 Istio 最大透明化(Maximize Transparency)设计指标 的场景。

起因剖析

Istio-proxy 中的一段 iptables:

其中,ISTIO_IN_REDIRECT 是 virtualInbound, 端口 15006;ISTIO_REDIRECT 是 virtualOutbound,端口 15001。

关键点是规定二:如果 destination 不是 127.0.0.1/32, 转给 15006 (virtualInbound, envoy 监听),这里导致了对 pod ip 的流量始终会回到 envoy。

对该规定的解释:

# Redirect app calls back to itself via Envoy when using the service VIP or endpoint # address, e.g. appN => Envoy (client) => Envoy (server) => appN.

该规定是心愿在这里起作用: 假如以后 Pod a 属于 service A, Pod 中用户容器通过服务名拜访服务 A, envoy 中负载平衡逻辑将这次拜访转发到了以后的 pod ip, istio 心愿这种场景服务端依然有流量管控能力. 如图示:

革新倡议

倡议利用在接入 istio 之前,调整服务监听地址,应用 0.0.0.0 而不是具体 IP。如果业务方认为革新难度大,能够参考之前分享的一个解决方案:服务监听 pod ip 在 istio 中路由异样剖析

【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

正文完
 0