Istio 网络常见问题

1,011 阅读3分钟
  1. 请求被 Envoy 拒绝
  2. 路线规则似乎不会影响交通流量
  3. 设置目标规则后出现 503 错误
  4. 路由规则对入口网关请求没有影响
  5. 无头 TCP 服务失去连接
  6. Envoy 在负载下崩溃
  7. Envoy 无法连接到我的 HTTP/1.0 服务

本节介绍常见问题以及解决与流量管理相关问题的工具和技术。

请求被 Envoy 拒绝

请求可能会因各种原因被拒绝。了解请求被拒绝原因的最佳方法是检查 Envoy 的访问日志。默认情况下,访问日志输出到容器的标准输出。运行以下命令查看日志:

$ kubectl logs PODNAME -c istio-proxy -n NAMESPACE

在默认访问日志格式中,Envoy 响应标志和 Mixer 策略状态位于响应代码之后,如果您使用自定义日志格式,请确保包含%RESPONSE_FLAGS%%DYNAMIC_METADATA(istio.mixer:status)%

有关响应标志的详细信息,请参阅Envoy 响应标志

常见的响应标志有:

  • NR:未配置路由,请检查您的DestinationRuleVirtualService
  • UO:上游溢出并断路,请检查 中的断路器配置DestinationRule
  • UF:无法连接到上游,如果您使用 Istio 身份验证,请检查 相互 TLS 配置冲突

UAEX如果响应标志为且 Mixer 策略状态不是 ,则请求将被 Mixer 拒绝-

常见的 Mixer 策略状态有:

  • UNAVAILABLE:Envoy 无法连接到 Mixer,并且策略配置为失败关闭。
  • UNAUTHENTICATED:Mixer 身份验证拒绝请求。
  • PERMISSION_DENIED:请求被 Mixer 授权拒绝。
  • RESOURCE_EXHAUSTED:请求被 Mixer 配额拒绝。
  • INTERNAL:由于 Mixer 内部错误,请求被拒绝。

路线规则似乎不会影响交通流量

在当前的 Envoy sidecar 实现中,可能需要最多 100 个请求才能观察到加权版本分布。

如果路由规则对于Bookinfo示例运行良好,但类似版本的路由规则对您自己的应用程序没有影响,则可能是您的 Kubernetes 服务需要稍作更改。Kubernetes 服务必须遵守某些限制才能利用 Istio 的 L7 路由功能。有关详细信息,请参阅Pod 和服务的要求

另一个潜在的问题是,路线规则的生效速度可能很慢。Kubernetes 上的 Istio 实现利用最终一致的算法来确保所有 Envoy sidecar 都具有正确的配置,包括所有路由规则。配置更改需要一些时间才能传播到所有 sidecar。对于大型部署,传播将需要更长的时间,并且可能会有秒级的延迟时间。

设置目标规则后出现 503 错误

如果在您应用 a 之后,对服务的请求立即开始生成 HTTP 503 错误,DestinationRule 并且错误一直持续到您删除或恢复 a 为止DestinationRule,则DestinationRule可能会导致该服务发生 TLS 冲突。

例如,如果您在集群中全局配置相互 TLS,则DestinationRule必须包括以下内容trafficPolicy

trafficPolicy:
  tls:
    mode: ISTIO_MUTUAL

否则,该模式默认DISABLE导致客户端代理 sidecar 发出纯 HTTP 请求,而不是 TLS 加密请求。因此,请求与服务器代理冲突,因为服务器代理期望加密的请求。

要确认是否存在冲突,请检查命令STATUS输出中的字段是否istioctl authn tls-check设置CONFLICT为适合您的服务。例如:

$ istioctl authn tls-check httpbin.default.svc.cluster.local
HOST:PORT                                  STATUS       SERVER     CLIENT     AUTHN POLICY     DESTINATION RULE
httpbin.default.svc.cluster.local:8000     CONFLICT     mTLS       HTTP       default/         httpbin/default

每当您应用 时DestinationRule,请确保trafficPolicyTLS 模式与全局服务器配置匹配。

路由规则对入口网关请求没有影响

假设您正在使用入口Gateway并对应VirtualService访问内部服务。例如,你的VirtualService看起来像这样:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
  - "myapp.com" # or maybe "*" if you are testing without DNS using the ingress-gateway IP (e.g., http://1.2.3.4/hello)
  gateways:
  - myapp-gateway
  http:
  - match:
    - uri:
        prefix: /hello
    route:
    - destination:
        host: helloworld.default.svc.cluster.local
  - match:
    ...

您还可以将VirtualServicehelloworld 服务的流量路由到特定子集:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
  - helloworld.default.svc.cluster.local
  http:
  - route:
    - destination:
        host: helloworld.default.svc.cluster.local
        subset: v1

在这种情况下,您会注意到通过入口网关对 helloworld 服务的请求将不会定向到子集 v1,而是将继续使用默认的循环路由。

入口请求使用网关主机(例如),它将激活 myapp 中路由到 helloworld 服务的任何端点的myapp.com规则。VirtualService只有主机的内部请求helloworld.default.svc.cluster.local 才会使用 helloworld VirtualService,它将流量专门定向到子集 v1。

要控制来自网关的流量,您还需要在 myapp 中包含子集规则VirtualService

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
  - "myapp.com" # or maybe "*" if you are testing without DNS using the ingress-gateway IP (e.g., http://1.2.3.4/hello)
  gateways:
  - myapp-gateway
  http:
  - match:
    - uri:
        prefix: /hello
    route:
    - destination:
        host: helloworld.default.svc.cluster.local
        subset: v1
  - match:
    ...

或者,如果可能的话,您可以将两者合并VirtualServices为一个单元:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
  - myapp.com # cannot use "*" here since this is being combined with the mesh services
  - helloworld.default.svc.cluster.local
  gateways:
  - mesh # applies internally as well as externally
  - myapp-gateway
  http:
  - match:
    - uri:
        prefix: /hello
      gateways:
      - myapp-gateway #restricts this rule to apply only to ingress gateway
    route:
    - destination:
        host: helloworld.default.svc.cluster.local
        subset: v1
  - match:
    - gateways:
      - mesh # applies to all services inside the mesh
    route:
    - destination:
        host: helloworld.default.svc.cluster.local
        subset: v1

无头 TCP 服务失去连接

如果istio-citadel部署,Envoy 每 45 天重新启动一次以刷新证书。这会导致 TCP 流断开或服务之间长时间运行的连接。

您应该在应用程序中针对此类断开连接建立弹性,但如果您仍然想防止发生断开连接,则需要禁用相互 TLS 和部署istio-citadel

首先,编辑您的istio配置以禁用相互 TLS:

$ kubectl edit configmap -n istio-system istio
$ kubectl delete pods -n istio-system -l istio=pilot

接下来,缩小istio-citadel部署规模以禁用 Envoy 重新启动:

$ kubectl scale --replicas=0 deploy/istio-citadel -n istio-system

这应该会阻止 Istio 重新启动 Envoy 并断开 TCP 连接。

Envoy 在负载下崩溃

检查你的ulimit -a. 许多系统默认有 1024 个打开文件描述符限制,这将导致 Envoy 断言并崩溃:

[2017-05-17 03:00:52.735][14236][critical][assert] assert failure: fd_ != -1: external/envoy/source/common/network/connection_impl.cc:58

确保提高您的 ulimit。例子:ulimit -n 16384

Envoy 无法连接到我的 HTTP/1.0 服务

Envoy 需要上游服务的流量HTTP/1.1HTTP/2例如,当使用NGINX为 Envoy 后面的流量提供服务时,您需要将NGINX 配置中的proxy_http_version指令设置为“1.1”,因为 NGINX 默认值为 1.0。

配置示例:

upstream http_backend {
    server 127.0.0.1:8080;

    keepalive 16;
}

server {
    ...

    location /http/ {
        proxy_pass http://http_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        ...
    }
}