istio问题定位分析

服务调用异常

一、定位到异常服务

多服务调用链的问题定位。单服务的调用出现问题可直接查看网关或服务的日志确定具体问题。

  1. 获取链路ID或traceId
  2. 通过ID查询到发生异常调用的服务
二、分析响应状态或日志

1、查看服务状态(运行状态、可读探针、存活探针)
2. 查看该请求的response_code(状态码)和response_flags(响应标识)
1. response_flags为"-":常表现为TCP请求或程序异常
2. response_flags为特定标识:可对照响应标识表获取具体原因
2. 服务本身异常:如果为服务异常,查看服务详细日志
3. 其他因素:

响应标识表
  • 常用

响应标识

协议

解释

备注

DC

HTTP

下游主动中断连接

UC

HTTP

上游连接终止

DI

HTTP

通过故障注入延迟处理请求

FI

HTTP

通过故障注入指定了响应代码

NR

HTTP和TCP

没有配置路由或过滤器链

如VirtualService和DestinationRule中的subset.name不匹配

UH

HTTP和TCP

上游没有健康主机

在服务配置了可读探针的情况下,常发生在熔断驱逐时

UO

HTTP和TCP

上游溢出(电路断开)

配置的最大连接数等限制导致部分请求失败

URX

HTTP和TCP

达到上游最大重试限制

  • 不常用

响应标识

解释

UF

上游连接失败,常发生在TLS认证

LH

503响应代码,本地服务运行状况检查请求失败。

UT

上游请求超时以及504响应代码。

LR

连接本地重置,除了503响应代码。

UR

503响应代码,还可以进行上游远程复位。

RL

429个响应代码,该请求还受HTTP速率限制过滤器本地限制。

UAEX

外部授权服务拒绝了该请求。

RLSE

请求被拒绝,因为速率限制服务中存在错误。

IH

请求被拒绝,因为除了400个响应代码外,它还为严格检查的标头设置了无效的值 。

SI

408响应码,流空闲超时。

DPE

下游请求具有HTTP协议错误。

UMSDR

上游请求达到最大流持续时间。

路由规则异常

比如路由规则不生效等问题。未特别说明是网格外服务的,均表示网格内服务

  1. 定位到具体哪2个服务之间的路由规则异常
  1. 网关与服务
  2. 服务与服务
  3. 网格外服务与服务
    2、在1、2、情况下,查看创建的vs规则是否正常应用到服务上

模拟问题

1.6.2版本

1. deploy副本数为1,启动数为0

连接istio控制平面失败,需查看istiod服务的健康状态

Warning  FailedCreate      15s (x14 over 64s)  replicaset-controller  Error creating: Internal error occurred: failed calling webhook "sidecar-injector.istio.io": Post https://istiod.istio-system.svc:443/inject?timeout=30s: dial tcp 10.96.129.113:443: connect: connection refused
[root@pass1 city]# kubectl get pods -n istio-system 
NAME                                    READY   STATUS             RESTARTS   AGE
grafana-74dc798895-zjqrc                1/1     Running            3          5d
istio-egressgateway-667578dd9b-5bmgw    1/1     Running            3          5d
istio-ingressgateway-579b8f7dd4-mh96s   1/1     Running            0          36m
istio-tracing-8584b4d7f9-m7qdp          1/1     Running            3          5d
istiod-d9875bd5d-j6tnf                  0/1     CrashLoopBackOff   4          2m
kiali-6f457f5964-hp2jv                  1/1     Running            3          5d
prometheus-7c9ddc484d-rzv8t             2/2     Running            6          5d
2. 配置的vs未生效
  1. 判断是集群内部调用还是通过网关调用
  1. 网关调用:查看绑定了网关的virtualservices配置是否正常
  2. 集群内部调用:
  1. 服务网格外服务————>服务网格内服务:路由规则不会生效
  2. 服务网格内服务————>服务网格内服务:正常情况下路由规则将会生效
  1. 查看服务的路由规则是否配置成功
istioctl x describe svc -n namespace service_name
  1. 查看容器的服务路由规则是否配置成功
istioctl x describe pod -n namespace pod_name
3. 链路跟踪数据没有形成串联

istio的其他功能对于代码无侵入性,但是链路需要对代码进行一定程度的侵入,需要将一些请求标头在发送请求时进行传递

  • 基于OpenTracing
x-request-id
x-b3-traceid
x-b3-spanid
x-b3-parentspanid
x-b3-sampled
x-b3-flags
x-ot-span-context
  • 基于OpenCensus
x-cloud-trace-context
traceparent
grpc-trace-bin
4. match的匹配规则未生效

创建的VirtualService路由规则将会按照配置顺序加载到evnoy上,当请求路由到evnoy后,系那个会按照加载的顺序进行匹配,所以match的匹配规则需要优先进行匹配,同时一个VirtualService的匹配规则中,前面的匹配规则不能是后面规则的子集。相当于if判断句,逐步判断条件是否满足

例如,将请求头end-user=demo的流量路由到v1,将请求头end-user=demo和message=agree的流量路由到v2。

spec:
  hosts:
  - nginx-svc
  http:
  - match:
    - headers:
        end-user:
          exact: demo
        message:
          exact: agree
    route:
    - destination:
        host: nginx-svc
        subset: v2
  - match:
    - headers:
        end-user:
          exact: demo
    route:
    - destination:
        host: nginx-svc
        subset: v1
{
                "name": "nginx-svc.default.svc.cluster.local:80",
                "domains": [
                    "nginx-svc.default.svc.cluster.local",
                    "nginx-svc.default.svc.cluster.local:80",
                    "nginx-svc",
                    "nginx-svc:80",
                    "nginx-svc.default.svc.cluster",
                    "nginx-svc.default.svc.cluster:80",
                    "nginx-svc.default.svc",
                    "nginx-svc.default.svc:80",
                    "nginx-svc.default",
                    "nginx-svc.default:80",
                    "10.96.130.229",
                    "10.96.130.229:80"
                ],
                "routes": [
                    {
                        "match": {
                            "prefix": "/",
                            "caseSensitive": true,
                            "headers": [
                                {
                                    "name": "end-user",
                                    "prefixMatch": "jason"
                                },
                                {
                                    "name": "message",
                                    "exactMatch": "agree"
                                }
                            ]
                        },
                        "route": {
                            "cluster": "outbound|80|v2|nginx-svc.default.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                ... ...
                            },
                            "maxGrpcTimeout": "0s"
                        }
                    },
                    {
                        "match": {
                            "prefix": "/",
                            "caseSensitive": true,
                            "headers": [
                                {
                                    "name": "end-user",
                                    "exactMatch": "jason"
                                }
                            ]
                        },
                        "route": {
                            "cluster": "outbound|80|v1|nginx-svc.default.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                ... ...
                            }
                            "maxGrpcTimeout": "0s"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            }
5. sidecar与业务容器启动顺序

sidecar先于业务容器启动的情况下,在业务容器启动之前拦截的流量将会请求失败。后于业务容器启动的情况下,sidecar将不会拦截流量。可通过istio或k8s两方面进行控制

  • istio方面

istio-1.8版本新增holdApplicationUntilProxyStarts配置,将阻止其他容器的启动,知道sidecar启动为止。

values.global.proxy.holdApplicationUntilProxyStarts: true
  • k8s方面

k8s 1.18版本可以通过将container指定为sidecar类型,sidecar类型的container将会优先启动

- name: istio-proxy
  image: docker.io/istio/proxyv2:1.6.2
  lifecycle:
    type: Sidecar
6. 业务容器进程启动慢

部分业务容器进程启动慢,在启动成功之前对于该服务的访问均处于请求失败状态

7. envoy在高负载下崩溃(官网问题统计)

检查ulimit -a,查看文件描述符限制。使用ulimit -n NUM修改

[critical][assert] assert failure: fd_ != -1: external/envoy/source/common/network/connection_impl.cc:58
8. 不自动注入sidecar的容器
  1. namespace未开启自动注入
  2. kube-system、kube-public忽略自动注入
  3. hostNetwork:true。忽略自动注入
9. vs绑定的资源不存在:gw、dr

该错误状态的检查是通过galley组件进行的,1.5版本之后该组件并入了istiod,默认istiod未开启检查功能,需要手动开启。设置istiod的环境变量PILOT_ENABLE_ANALYSIS为true,或者在安装时指定enableAnalysis=true

status:
  validationMessages:
  - code: IST0101
    documentation_url: https://istio.io/docs/reference/config/analysis/IST0101?ref=status-controller
    level: Error
    message: 'Referenced host+subset in destinationrule not found: "city+v1"'
10. 网关偶发探针失败(待解决)
Events:
  Type     Reason     Age                 From             Message
  ----     ------     ----                ----             -------
  Warning  Unhealthy  14m (x868 over 8d)  kubelet, slave3  Readiness probe failed: Get http://10.244.3.7:15021/healthz/ready: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
warn    Envoy proxy is NOT ready: failed to get readiness stats: Get "http://127.0.0.1:15000/stats?usedonly&filter=^(server.state|listener_manager.workers_started)": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
info    Envoy proxy is ready

1.8.0版本

11.创建80网关绑定失败

在1.7版本之后(包含1.7版本),istio-ingressgateway的启动方式默认变为了非root用户,无法绑定1024以下的端口,需要对网关进行调整。

方式一:使用targetPort将1024以下的端口绑定到有效端口

方式二:istio-ingressgateway改为root用户

gRPC config for type.googleapis.com/envoy.config.listener.v3.Listener rejected: Error adding/updating listener(s) 0.0.0.0_80: cannot bind '0.0.0.0:80': Permission denied
12.执行istioctl命令报错

一般是istioctl客户端与控制平面和数据平面版本不一致导致

Error: mismatched message type: got "envoy.config.route.v3.RouteConfiguration" want "envoy.api.v2.RouteConfiguration"
[root@pass1 ~]# istioctl version
client version: 1.6.2
control plane version: 1.8.0
data plane version: 1.8.0 (3 proxies)