Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Istio服务网格细节剖析

Istio服务网格细节剖析

作者头像
王先森sec
发布于 2023-04-24 09:36:14
发布于 2023-04-24 09:36:14
82800
代码可运行
举报
文章被收录于专栏:王先森王先森
运行总次数:0
代码可运行

Envoy简介

什么是Envoy

  • envoy 是作为微服务服务架构中以独立进程方式实现高级网络功能的,轻量级的7层服务代理程序,通常以sidecar的方式运行在应用程序的周边,也可以作为网络的边缘代理来运行。
  • envoy 的特性 进程外体系结构 ,L3/L4过滤器体系结构,HTTP L7过滤器体系结构, 一流的HTTP/2支持, HTTP/3支持(目前为alpha),HTTP L7路由,gRPC支持,服务发现和动态配置,健康检查,高级负载平衡,前端/边缘代理支持, 一流的可观察性

服务网格细节剖析

宏观分析

执行的操作:

  • 使用istioctl为pod注入了sidecar
  • 创建了virtualservice和destinationrule

如何最终影响到了pod的访问行为?

宏观角度

nginx的配置中,可以提供类似如下的配置片段实现按照权重的转发:

因为nginx是代理层,可以转发请求,istio也实现了流量转发的效果,肯定也有代理层,并且识别了前面创建的虚拟服务中定义的规则。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ istioctl kube-inject -f front-tomcat-dpl-v1.yaml

可以看到注入后yaml中增加了很多内容:

pod被istio注入后,被纳入到服务网格中,每个pod都会添加一个名为istio-proxy的容器(常说的sidecar容器),istio-proxy容器中有两个进程,一个是piolot-agent,一个是envoy

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ kubectl exec -ti front-tomcat-v1-8687f9f845-rmlxt -c istio-proxy bash
# ps aux

目前已知:

  • 在istio网格内,每个Pod都会被注入一个envoy代理
  • envoy充当nginx的角色,做为proxy代理,负责接管pod的入口和出口流量

目前,还需要搞清楚几个问题:

  • istio-init初始化容器作用是什么?
  • istio-proxy如何接管业务服务的出入口流量?

认识envoy

Envoy 是为云原生应用设计的代理。

可以和nginx做类比: https://fuckcloudnative.io/posts/migrating-from-nginx-to-envoy/

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ docker run -d --name envoy -v `pwd`/envoy.yaml:/etc/envoy/envoy.yaml -p 10000:10000 envoyproxy/envoy-alpine:v1.15.2

$ curl localhost:10000
envoy.yaml
admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 127.0.0.1, port_value: 9901 }

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 10000 }
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          stat_prefix: ingress_http
          codec_type: AUTO
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route: { cluster: some_service }
          http_filters:
          - name: envoy.router
  clusters:
  - name: some_service
    connect_timeout: 2s
    type: STATIC
    lb_policy: ROUND_ROBIN
    hosts: [{ socket_address: { address: 10.103.211.217, port_value: 9999 }}]

脑补一下网络代理程序的流程,比如作为一个代理,首先要能获取请求流量,通常是采用监听端口的方式实现;其次拿到请求数据后需要对其做微处理,例如附加 Header 或校验某个 Header 字段的内容等,这里针对来源数据的层次不同,可以分为 L3/L4/L7,然后将请求转发出去;转发这里又可以衍生出如果后端是一个集群,需要从中挑选一台机器,如何挑选又涉及到负载均衡等。

  • listener : Envoy 的监听地址。Envoy 会暴露一个或多个 Listener 来监听客户端的请求。
  • filter : 过滤器。在 Envoy 中指的是一些“可插拔”和可组合的逻辑处理层,是 Envoy 核心逻辑处理单元。
  • route_config : 路由规则配置。即将请求路由到后端的哪个集群。
  • cluster : 服务提供方集群。Envoy 通过服务发现定位集群成员并获取服务,具体路由到哪个集群成员由负载均衡策略决定。

envoy动态配置(xDS)

Envoy的启动配置文件分为两种方式:静态配置和动态配置。

  • 静态配置是将所有信息都放在配置文件中,启动的时候直接加载。
  • 动态配置需要提供一个Envoy的服务端,用于动态生成Envoy需要的服务发现接口,这里叫XDS,通过发现服务来动态的调整配置信息,Istio就是实现了v2的API。

Envoy 接收到请求后,会先走 FilterChain,通过各种 L3/L4/L7 Filter 对请求进行微处理,然后再路由到指定的集群,并通过负载均衡获取一个目标地址,最后再转发出去。

其中每一个环节可以静态配置,也可以动态服务发现,也就是所谓的 xDS。这里的 x 是一个代词,类似云计算里的 XaaS 可以指代 IaaSPaaSSaaS 等。

所以,envoy的架构大致的样子如下:

Downstream

下游(downstream)主机连接到 Envoy,发送请求并或获得响应。

Upstream

上游(upstream)主机获取来自 Envoy 的链接请求和响应。

监听器

  • 除了过滤器链之外,还有一种过滤器叫监听器过滤器(Listener filters),它会在过滤器链之前执行,用于操纵连接的元数据。这样做的目的是,无需更改 Envoy 的核心代码就可以方便地集成更多功能。
  • 每个监听器都可以配置多个过滤器链(Filter Chains),监听器会根据 filter_chain_match 中的匹配条件将流量转交到对应的过滤器链,其中每一个过滤器链都由一个或多个网络过滤器Network filters)组成。这些过滤器用于执行不同的代理任务,如速率限制,TLS 客户端认证,HTTP 连接管理,MongoDB 嗅探,原始 TCP 代理等。

envoy在微服务治理中的工作环境

可以在服务旁运行,以平台无关的方式提供必要的特性,所有到服务的流量都通过 Envoy 代理,这里 Envoy 扮演的就是 Sidecar 的角色。

针对于k8s的pod来讲:

在istio中,envoy的位置:

很明显,istio中,envoy进行流量治理,更多的使用的是XDS进行配置更新,而我们知道,XDS需要有服务端来提供接口,istiod中的pilot组件则提供了xDS服务端接口的实现 。

工作原理

目前为止,我们可以知道大致的工作流程:

  • 用户端,通过创建服务治理的规则(VirtualService、DestinationRule等资源类型),存储到ETCD中
  • istio控制平面中的Pilot服务监听上述规则,转换成envoy可读的规则配置,通过xDS接口同步给各envoy
  • envoy通过xDS获取最新的配置后,动态reload,进而改变流量转发的策略

思考两个问题:

  • istio中envoy的动态配置到底长什么样子?
  • 在istio的网格内,front-tomcat访问到bill-service,流量的流向是怎么样的?

针对问题1:

每个envoy进程启动的时候,会在127.0.0.1启动监听15000端口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ kubectl exec -ti front-tomcat-v1-8687f9f845-rmlxt -c istio-proxy -- bash
# netstat -nltp
# curl localhost:15000/help
# curl localhost:15000/config_dump

针对问题2:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ kubectl exec -ti front-tomcat-v1-8687f9f845-rmlxt -c front-tomcat -- bash
# curl bill-service:9999

按照之前的认知,

现在为什么流量分配由5:5 变成了9:1?流量经过envoy了的处理

envoy如何接管由front-tomcat容器发出的请求流量?(istio-init

回顾iptables:

istio-init容器作用

Istio 给应用 Pod 注入的配置主要包括:

Init 容器 istio-init

Istio 在 pod 中注入的 Init 容器名为 istio-init,作用是为 pod 设置 iptables 端口转发。

我们在上面 Istio 注入完成后的 YAML 文件中看到了该容器的启动命令是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
istio-iptables -p 15001 -z 15006 -u 1337 -m REDIRECT -i '*' -x "" -b '*' -d 15090,15021,15020

Init 容器的启动入口是 istio-iptables 命令行,该命令行工具的用法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ istio-iptables [flags]
  -p: 指定重定向所有 TCP 出站流量的 sidecar 端口(默认为 $ENVOY_PORT = 15001-m: 指定入站连接重定向到 sidecar 的模式,“REDIRECT” 或 “TPROXY”(默认为 $ISTIO_INBOUND_INTERCEPTION_MODE)
  -b: 逗号分隔的入站端口列表,其流量将重定向到 Envoy(可选)。使用通配符 “*” 表示重定向所有端口。为空时表示禁用所有入站重定向(默认为 $ISTIO_INBOUND_PORTS-d: 指定要从重定向到 sidecar 中排除的入站端口列表(可选),以逗号格式分隔。使用通配符“*” 表示重定向所有入站流量(默认为 $ISTIO_LOCAL_EXCLUDE_PORTS-o:逗号分隔的出站端口列表,不包括重定向到 Envoy 的端口。
  -i: 指定重定向到 sidecar 的 IP 地址范围(可选),以逗号分隔的 CIDR 格式列表。使用通配符 “*” 表示重定向所有出站流量。空列表将禁用所有出站重定向(默认为 $ISTIO_SERVICE_CIDR-x: 指定将从重定向中排除的 IP 地址范围,以逗号分隔的 CIDR 格式列表。使用通配符 “*” 表示重定向所有出站流量(默认为 $ISTIO_SERVICE_EXCLUDE_CIDR)。
  -k:逗号分隔的虚拟接口列表,其入站流量(来自虚拟机的)将被视为出站流量。
  -g:指定不应用重定向的用户的 GID(默认值与 -u param 相同)
  -u:指定不应用重定向的用户的 UID。通常情况下,这是代理容器的 UID(默认值是 1337,即 istio-proxy 的 UID)。
  -z: 所有进入 pod/VMTCP 流量应被重定向到的端口(默认 $INBOUND_CAPTURE_PORT = 15006)。

以上传入的参数都会重新组装成 iptables 规则,关于 Istio 中端口用途请参考 Istio 官方文档

这条启动命令的作用是:

  • 将应用容器的所有入站流量都转发到 sidecar的 15006 端口(15090 端口(Envoy Prometheus telemetry)和 15020 端口(Ingress Gateway)除外,15021(sidecar健康检查)端口)
  • 将所有出站流量都重定向到 sidecar 代理(通过 15001 端口)
  • 上述规则对id为1337用户除外,因为1337是istio-proxy自身的流量

该容器存在的意义就是让 sidecar 代理可以拦截pod所有的入站(inbound)流量以及出站(outbound)流量,这样就可以实现由sidecar容器来接管流量,进而实现流量管控。

init容器进行入站出站流量监控

因为 Init 容器初始化完毕后就会自动终止,因为我们无法登陆到容器中查看 iptables 信息,但是 Init 容器初始化结果会保留到应用容器和 sidecar 容器中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 查看front-tomcat服务的istio-proxy容器的id
$ docker ps |grep front-tomcat
6c0c6478ce2a   43e421a14aec                         "/bin/sh -c 'mkdir /…"   2 hours ago    Up 2 hours              k8s_front-tomcat_front-tomcat-v1-8687f9f845-rmlxt_default_0204ab7e-a083-4e71-9af6-dcc675ec7000_0

# 根据容器id获取front-tomcat容器在宿主机中的进程
$ docker inspect 6c0c6478ce2a|grep -i pid
            "Pid": 97369,
            "PidMode": "",
            "PidsLimit": null,
# 进入该进程的网络命名空间
$ nsenter -n --target 97369
# 查看命名空间的iptables规则
$ iptables -t nat -vnL
# PREROUTING 链:用于目标地址转换(DNAT),将所有入站 TCP 流量跳转到 ISTIO_INBOUND 链上。
Chain PREROUTING (policy ACCEPT 3879 packets, 233K bytes)
 pkts bytes target     prot opt in     out     source               destination         
 3884  233K ISTIO_INBOUND  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0  

# INPUT 链:处理输入数据包,非 TCP 流量将继续 OUTPUT 链。
Chain INPUT (policy ACCEPT 3884 packets, 233K bytes)
 pkts bytes target     prot opt in     out     source               destination  

# OUTPUT 链:将所有出站数据包跳转到 ISTIO_OUTPUT 链上。
Chain OUTPUT (policy ACCEPT 46 packets, 3926 bytes)
 pkts bytes target     prot opt in     out     source               destination
    8   480 ISTIO_OUTPUT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0
# POSTROUTING 链:所有数据包流出网卡时都要先进入POSTROUTING 链,内核根据数据包目的地判断是否需要转发出去,我们看到此处未做任何处理。
Chain POSTROUTING (policy ACCEPT 46 packets, 3926 bytes)
 pkts bytes target     prot opt in     out     source               destination

# ISTIO_INBOUND 链:将所有入站流量重定向到 ISTIO_IN_REDIRECT 链上,目的地为 150901502015021端口的流量除外,发送到以上两个端口的流量将返回 iptables 规则链的调用点,即 PREROUTING 链的后继 POSTROUTING。
Chain ISTIO_INBOUND (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15008
    0     0 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15090
 3879  233K RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15021
    0     0 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15020
    5   300 ISTIO_IN_REDIRECT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0 

# ISTIO_IN_REDIRECT 链:将所有入站流量跳转到本地的 15006 端口,至此成功的拦截了流量到sidecar中。
Chain ISTIO_IN_REDIRECT (3 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15006

# ISTIO_OUTPUT 链:选择需要重定向到 Envoy(即本地) 的出站流量,所有非 localhost 的流量全部转发到 ISTIO_REDIRECT。为了避免流量在该 Pod 中无限循环,所有到 istio-proxy 用户空间的流量都返回到它的调用点中的下一条规则,本例中即 OUTPUT 链,因为跳出 ISTIO_OUTPUT 规则之后就进入下一条链 POSTROUTING。如果目的地非 localhost 就跳转到 ISTIO_REDIRECT;如果流量是来自 istio-proxy 用户空间的,那么就跳出该链,返回它的调用链继续执行下一条规则(OUTPUT 的下一条规则,无需对流量进行处理);所有的非 istio-proxy 用户空间的目的地是 localhost 的流量就跳转到 ISTIO_REDIRECT。
Chain ISTIO_OUTPUT (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 RETURN     all  --  *      lo      127.0.0.6            0.0.0.0/0
    0     0 ISTIO_IN_REDIRECT  all  --  *      lo      0.0.0.0/0           !127.0.0.1            owner UID match 1337
    0     0 RETURN     all  --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner UID match 1337
    8   480 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1337
    0     0 ISTIO_IN_REDIRECT  all  --  *      lo      0.0.0.0/0           !127.0.0.1            owner GID match 1337
    0     0 RETURN     all  --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner GID match 1337
    0     0 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner GID match 1337
    0     0 RETURN     all  --  *      *       0.0.0.0/0            127.0.0.1
    0     0 ISTIO_REDIRECT  all  --  *      *       0.0.0.0/0            0.0.0.0/0

# ISTIO_REDIRECT 链:将所有流量重定向到 Sidecar(即本地) 的 15001 端口。
Chain ISTIO_REDIRECT (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15001
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ kubectl exec -ti front-tomcat-v1-8687f9f845-rmlxt -c istio-proxy -- bash
istio-proxy@front-tomcat-v1-8687f9f845-rmlxt:/$ netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:8005          0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:15021           0.0.0.0:*               LISTEN      16/envoy            
tcp        0      0 0.0.0.0:15021           0.0.0.0:*               LISTEN      16/envoy            
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:15090           0.0.0.0:*               LISTEN      16/envoy            
tcp        0      0 0.0.0.0:15090           0.0.0.0:*               LISTEN      16/envoy            
tcp        0      0 127.0.0.1:15000         0.0.0.0:*               LISTEN      16/envoy            
tcp        0      0 0.0.0.0:15001           0.0.0.0:*               LISTEN      16/envoy            
tcp        0      0 0.0.0.0:15001           0.0.0.0:*               LISTEN      16/envoy            
tcp        0      0 127.0.0.1:15004         0.0.0.0:*               LISTEN      1/pilot-agent       
tcp        0      0 0.0.0.0:15006           0.0.0.0:*               LISTEN      16/envoy            
tcp        0      0 0.0.0.0:15006           0.0.0.0:*               LISTEN      16/envoy            
tcp6       0      0 :::15020                :::*                    LISTEN      1/pilot-agent

说明pod内的出站流量请求被监听在15001端口的envoy的进程接收到,进而就走到了envoy的Listener -> route -> cluster -> endpoint 转发流程。

问题就转变为:如何查看envoy的配置,跟踪转发的过程?

envoy流量转发跟踪分析

我们知道,envoy的配置非常复杂,直接在config_dump里去跟踪xDS的过程非常繁琐。因此istio提供了调试命令,方便查看envoy的流量处理流程。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ istioctl proxy-config -h

比如,通过如下命令可以查看envoy的监听器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 查看15001的监听
$ istioctl proxy-config listener front-tomcat-v1-8687f9f845-rmlxt --port 15001 -ojson
# virtualOutbound的监听不做请求处理,useOriginalDst: true, 直接转到原始的请求对应的监听器中

# 查看访问端口是9999的监听器
$ istioctl proxy-config listener front-tomcat-v1-8687f9f845-rmlxt --port 9999 -ojson
...
    {
        "name": "0.0.0.0_9999",
        "address": {
            "socketAddress": {
                "address": "0.0.0.0",
                "portValue": 9999
            }
        },
        "filterChains": [
            {
                "filterChainMatch": {
                    "applicationProtocols": [
                        "http/1.0",
                        "http/1.1",
                        "h2c"
                    ]
                },
                "filters": [
                    {
                        "name": "envoy.filters.network.http_connection_manager",
                        "typedConfig": {
                            "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
                            "statPrefix": "outbound_0.0.0.0_9999",
                            "rds": {
                                "configSource": {
                                    "ads": {},
                                    "resourceApiVersion": "V3"
                                },
                                "routeConfigName": "9999"
                            },
...

envoy收到请求后,会转给监听器进行处理请求,监听器先匹配address和port和socket都一致的Listener,如果没找到再找port一致,address==0.0.0.0的Listener

发现istio会为网格内的Service Port创建名为0.0.0.0_<Port>的虚拟监听器,本例中为0.0.0.0_9999

envoy的15001端口收到请求后,直接转到了0.0.0.0_9999,进而转到了"routeConfigName": "9999",即9999这个route中。

下面,看下route的内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ istioctl pc route front-tomcat-v1-8687f9f845-rmlxt --name 9999
NOTE: This output only contains routes loaded via RDS.
NAME     DOMAINS          MATCH     VIRTUAL SERVICE
9999     bill-service     /*        vs-bill-service.default

# 发现了前面创建的virtual service
$ istioctl pc route front-tomcat-v1-8687f9f845-rmlxt --name 9999 -ojson
[
    {
        "name": "9999",
        "virtualHosts": [
            {
                "name": "allow_any",
                "domains": [
                    "*"
                ],
                "routes": [
                    {
                        "name": "allow_any",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "PassthroughCluster",
                            "timeout": "0s",
                            "maxGrpcTimeout": "0s"
                        }
                    }
                ],
                "includeRequestAttemptCount": true
            },
            {
                "name": "bill-service.default.svc.cluster.local:9999",
                "domains": [
                    "bill-service.default.svc.cluster.local",
                    "bill-service.default.svc.cluster.local:9999",
                    "bill-service",
                    "bill-service:9999",
                    "bill-service.default.svc.cluster",
                    "bill-service.default.svc.cluster:9999",
                    "bill-service.default.svc",
                    "bill-service.default.svc:9999",
                    "bill-service.default",
                    "bill-service.default:9999",
                    "192.168.18.251",
                    "192.168.18.251:9999"
                ],
                "routes": [
                    {
                        "name": "bill-service-route",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "weightedClusters": {
                                "clusters": [
                                    {
                                        "name": "outbound|9999|v1|bill-service.default.svc.cluster.local",
                                        "weight": 90
                                    },
                                    {
                                        "name": "outbound|9999|v2|bill-service.default.svc.cluster.local",
                                        "weight": 10
                                    }
                                ]
                            },
...

满足访问domains列表的会优先匹配到,我们访问的是192.168.18.251:9999,因此匹配bill-service.default.svc.cluster.local:9999这组虚拟hosts,进而使用到基于weight的集群配置。

我们看到,流量按照预期的配置进行了转发:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
90% -> outbound|9999|v1|bill-service.default.svc.cluster.local
10% -> outbound|9999|v2|bill-service.default.svc.cluster.local

下面,看一下cluster的具体内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ istioctl pc cluster front-tomcat-v1-8687f9f845-rmlxt --fqdn bill-service.default.svc.cluster.local -ojson
...
        "name": "outbound|9999|v1|bill-service.default.svc.cluster.local",
        "type": "EDS",
        "edsClusterConfig": {
            "edsConfig": {
                "ads": {},
                "resourceApiVersion": "V3"
            },
            "serviceName": "outbound|9999|v1|bill-service.default.svc.cluster.local"
        },
...

我们发现,endpoint列表是通过eds获取的,因此,查看endpoint信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ istioctl pc endpoint front-tomcat-v1-8687f9f845-rmlxt  --cluster 'outbound|9999|v1|bill-service.default.svc.cluster.local' -ojson
[
    {
        "name": "outbound|9999|v1|bill-service.default.svc.cluster.local",
        "addedViaApi": true,
        "hostStatuses": [
            {
                "address": {
                    "socketAddress": {
                        "address": "172.7.100.3",
                        "portValue": 80
                    }
                },
...

目前为止,经过envoy的规则,流量从front-tomcat的pod中知道要发往10.244.0.7:80 这个pod地址。前面提到过,envoy不止接管出站流量,入站流量同样会接管。

下面看下流量到达bill-service-v1的pod后的处理:

先回顾前面的iptables规则,除特殊情况以外,所有的出站流量被监听在15001端口的envoy进程拦截处理,同样的,分析bill-service-v1的iptables规则可以发现,监听在15006端口的envoy进程通过在PREROUTING链上添加规则,同样将进入pod的入站流量做了拦截。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# PREROUTING 链:用于目标地址转换(DNAT),将所有入站 TCP 流量跳转到 ISTIO_INBOUND 链上。
Chain PREROUTING (policy ACCEPT 148 packets, 8880 bytes)
 pkts bytes target     prot opt in     out     source               destination
  148  8880 ISTIO_INBOUND  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0

# INPUT 链:处理输入数据包,非 TCP 流量将继续 OUTPUT 链。
Chain INPUT (policy ACCEPT 148 packets, 8880 bytes)
 pkts bytes target     prot opt in     out     source               destination

# ISTIO_INBOUND 链:将所有入站流量重定向到 ISTIO_IN_REDIRECT 链上,目的地为 150901502015021端口的流量除外,发送到以上两个端口的流量将返回 iptables 规则链的调用点,即 PREROUTING 链的后继 POSTROUTING。
Chain ISTIO_INBOUND (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15008
    0     0 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15090
  143  8580 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15021
    5   300 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15020
    0     0 ISTIO_IN_REDIRECT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0

# ISTIO_IN_REDIRECT 链:将所有入站流量跳转到本地的 15006 端口,至此成功的拦截了流量到sidecar中。
Chain ISTIO_IN_REDIRECT (3 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15006

15006端口是一个名为 virtualInbound虚拟入站监听器,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ istioctl pc l bill-service-v1-59b4f4ccc7-qvhw6.default --port 15006 -ojson
"name": "envoy.filters.network.http_connection_manager",
"typedConfig": {
    "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
    "statPrefix": "inbound_0.0.0.0_80",
    "routeConfig": {
        "name": "inbound|80||",
        "virtualHosts": [
            {
                "name": "inbound|http|9999",
                "domains": [
                    "*"
                ],
                "routes": [
                    {
                        "name": "default",
                        "match": {
                            "prefix": "/"
                        },
                        "route": {
                            "cluster": "inbound|80||",
                            "timeout": "0s",
                            "maxStreamDuration": {
                                "maxStreamDuration": "0s",
                                "grpcTimeoutHeaderMax": "0s"
                            }
                        },
                        "decorator": {
                            "operation": "bill-service.default.svc.cluster.local:9999/*"
                        }
                    }
                ]
            }
        ],
        "validateClusters": false

相比于VirtualOutboundvirtualInbound 不会再次转给别的虚拟监听器,而是直接由本监听器的filterChains处理,本例中我们可以发现本机目标地址为80的http请求,转发到了inbound|9999|http|bill-service.default.svc.cluster.local这个集群中。

查看该集群的信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ istioctl pc cluster bill-service-v1-59b4f4ccc7-qvhw6.default -h
$ istioctl pc cluster bill-service-v1-59b4f4ccc7-qvhw6.default  --fqdn "inbound|80||" -ojson
[
    {
        "name": "inbound|80||",
        "type": "ORIGINAL_DST",
        "connectTimeout": "10s",
        "lbPolicy": "CLUSTER_PROVIDED",
        "circuitBreakers": {
            "thresholds": [
                {
                    "maxConnections": 4294967295,
                    "maxPendingRequests": 4294967295,
                    "maxRequests": 4294967295,
                    "maxRetries": 4294967295,
                    "trackRemaining": true
                }
            ]
        },
        "cleanupInterval": "60s",
        "upstreamBindConfig": {
            "sourceAddress": {
                "address": "127.0.0.6",
                "portValue": 0
            }
        },
        "metadata": {
            "filterMetadata": {
                "istio": {
                    "services": [
                        {
                            "host": "bill-service.default.svc.cluster.local",
                            "name": "bill-service",
                            "namespace": "default"
                        }
                    ]
                }
            }
        }
    }
]

istio小知识

同一个Pod,不同的表现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ kubectl exec -ti front-tomcat-v1-8687f9f845-rmlxt -c front-tomcat bash
# curl bill-service:9999

$ kubectl exec -ti front-tomcat-v1-8687f9f845-rmlxt -c istio-proxy bash
# curl bill-service:9999

可以发现,在front-tomcat容器中的访问请求,是受到我们设置的 9:1的流量分配规则限制的,但是istio-proxy容器中的访问是不受限制的。

istio-proxy自身,发起的往192.168.18.251的请求,使用的用户是 uid=1337(istio-proxy),因此不会被istio-init初始化的防火墙规则拦截,可以直接走pod的网络进行通信。

集群内的Service都相应的创建了虚拟出站监听器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ kubectl exec -ti front-tomcat-v1-8687f9f845-rmlxt -c front-tomcat bash
# curl sonarqube.jenkins:9000

$ istioctl pc l front-tomcat-v1-8687f9f845-rmlxt --port 9000 
ADDRESS      PORT MATCH     DESTINATION
192.168.18.33 9000 App: HTTP Route: sonarqube.jenkins.svc.cluster.local:9000
192.168.18.33 9000 ALL       Cluster: outbound|9000||sonarqube.jenkins.svc.cluster.local

$ istioctl pc r front-tomcat-v1-8687f9f845-rmlxt --name 'sonarqube.jenkins.svc.cluster.local:9000'

$ istioctl pc ep front-tomcat-v1-8687f9f845-rmlxt --cluster 'outbound|9000||sonarqube.jenkins.svc.cluster.local'

virtualOutBound 15001 —> virtial listener 192.168.18.33_9000 —> route sonarqube.jenkins.svc.cluster.local:9000 —> cluster outbound|9000||sonarqube.jenkins.svc.cluster.local —> 192.168.18.33:9000

istio服务网格内,流量请求完全绕过了kube-proxy组件

通过上述流程调试,我们可以得知,front-tomcat中访问bill-service:9999,流量是没有用到kube-proxy维护的宿主机中的iptables规则的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-02-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Traefik2.3.x 使用大全(更新版)
Traefik 是一个开源的可以使服务发布变得轻松有趣的边缘路由器。它负责接收你系统的请求,然后使用合适的组件来对这些请求进行处理。
我是阳明
2021/01/04
5.3K0
Traefik2.3.x 使用大全(更新版)
还不会Traefik?看这篇文章就够了!(文末送书)
暂且我们把Traefik当成和Nginx差不多的一类软件,待读完整篇文章,你就会对Traefik有不一样的认识。
没有故事的陈师傅
2021/11/12
3.9K0
还不会Traefik?看这篇文章就够了!(文末送书)
Traefik 2.0 Now GA! Traefik V2真正来了!
没错,Traefik V2已经GA了,代表着Traefik v2已经在生产环境使用。进入官网https://traefik.io/ ,可以看到醒目的Traefik 2.0 Now GA。
用户3013098
2022/05/31
5500
Traefik 2.0 Now GA! Traefik V2真正来了!
# 一篇文章让你搞懂如何在K8s 里使用 Traefik 2.0作为Ingress Controller(上)
了解K8s的同学应该都知道,如果想要把应用暴露到公网上供外部访问,那么不可避免的会接触到Ingress资源。本文以Traefik为例,让大家对Ingress和Traefik的使用有一定的了解。
100000798482
2020/02/13
1.1K0
# 一篇文章让你搞懂如何在K8s 里使用 Traefik 2.0作为Ingress Controller(上)
一篇文章让你搞懂K8s Ingress,Traefik 2.0为例(上)
了解K8s的同学应该都知道,如果想要把应用暴露到公网上供外部访问,那么不可避免的会接触到Ingress资源。本文以Traefik为例,让大家对Ingress和Traefik的使用有一定的了解。
100000798482
2020/01/16
5.6K2
一篇文章让你搞懂K8s Ingress,Traefik 2.0为例(上)
Traefik2.2从坑出发
Traefik 2.2新增的功能如下: 1. 支持了udp 2. traefik2.2 支持使用K/V存储做为动态配置的源,分别是 consul, etcd, Redis, zookeeper 3. 能够使用kubernetes CRD自定义资源定义UDP负载平衡 IngressRouteUDP。 4. 能够使用 rancher, consul catalog, docker和 marathon中的标签定义UDP的负载平衡 5. 增加了对ingress注解的主持 6. 将TLS存储功能 TLSStores添加到Kubernetes CRD中,使kubernetes用户无需使用配置文件和安装证书即可提供默认证书。 7. 在日志中增加了http的请求方式,是http还是https 8. 因为TLS的配置可能会影响CPU的使用率,因此增加了 TLS version和 TLS cipher使用的指标信息 9. 当前的WRR算法对于权重不平衡端点存在严重的偏差问题,将EDF调度算法用于WeightedRoundRobin, Envoy也是使用了 EOF调度算法 10. 支持请求主体用于流量镜像 11. 增加了 ElasticAPM作为traefik的tracing系统。 12. Traefik的Dashboard增加了UDP的页面 13. Traefik也增加了黑暗主题
极客运维圈
2020/06/01
2.8K0
Traefik2.2从坑出发
TKE上部署treafik2
腾讯云上有默认的提供的ingress服务,如果你不想用提供的,想用最新的treafik来暴露服务通过域名访问也是可以的。下面我们来部署操作下。
聂伟星
2020/06/10
8700
Kubernetes (K8S)中Traefik的服务发布
traefik 的路由规则就可以实现 4 层和 7 层的基本负载均衡操作,使用 IngressRoute IngressRouteTCP IngressRouteUDP 资源即可。但是如果想要实现 加权轮询、流量复制 等高级操作,traefik抽象出了一个 TraefikService 资源。此时整体流量走向为:外部流量先通过 entryPoints 端口进入 traefik,然后由 IngressRoute/IngressRouteTCP/IngressRouteUDP 匹配后进入 TraefikService,在 TraefikService 这一层实现加权轮循和流量复制,最后将请求转发至kubernetes的service。
王先森sec
2023/10/17
3210
Kubernetes (K8S)中Traefik的服务发布
附021.Traefik-ingress部署及使用
[root@master01 ingress]# helm repo add traefik https://containous.github.io/traefik-helm-chart
木二
2020/06/04
1.3K0
Kubernetes (K8S) 中Traefik自动申请证书
Traefik实现自动申请HTTPS证书要使用Let’s Encrypt自动生成证书,需要使用ACME。需要在静态配置中定义 “证书解析器”,Traefik负责从ACME服务器中检索证书。
王先森sec
2023/10/17
1.8K0
Kubernetes (K8S) 中Traefik自动申请证书
Kubernetes (K8S)中Traefik路由(ingressRoute)
kubernetes 中使用 Traefik ingress 的 ingressRoute 代理 http、https、tcp、udp。
王先森sec
2023/10/17
2.7K0
Kubernetes (K8S)中Traefik路由(ingressRoute)
Step by Step!教你如何在k3s集群上使用Traefik 2.x
Traefik是一个十分可靠的云原生动态反向代理。轻量级Kubernetes发行版K3s早在去年就已经内置Traefik,将其作为集群的默认反向代理和Ingress Controller。然而,在本文成文时K3s中的默认内置Traefik版本为v1.7.14。这一版本固然也能很好地运行,但还是少了一些有用的功能。我最想用的功能是为正在使用的Ingress Route自动生成Let’s Encrypt证书。而使用Traefik 2.x版本可以获得这一功能,甚至还有更多其他功能。那么,我们来看看如何使用K3s设置并使用新版本的Traefik。
k3s中文社区
2020/04/10
3.7K0
Step by Step!教你如何在k3s集群上使用Traefik 2.x
Kubernetes (K8S)中Traefik中间件(Middleware)
Traefik Middlewares 是一个处于路由和后端服务之前的中间件,在外部流量进入 Traefik,且路由规则匹配成功后,将流量发送到对应的后端服务前,先将其发给中间件进行一系列处理(类似于过滤器链 Filter,进行一系列处理),例如,添加 Header 头信息、鉴权、流量转发、处理访问路径前缀、IP 白名单等等,经过一个或者多个中间件处理完成后,再发送给后端服务,这个就是中间件的作用。 Traefik内置了很多不同功能的Middleware,主要是针对HTTP和TCP,这里挑选几个比较常用的进行演示。
王先森sec
2023/10/17
9760
Kubernetes (K8S)中Traefik中间件(Middleware)
Kubernetes生态Ingress组件Traefik v2.0浅析
上一篇文章简单介绍了下Kubernetes生态的几个组件,这篇文章重点讲解下其中的Traefik组件,Traefik组件类似与Nginx,可以为整个集群做服务暴露、域名控制等等的作用,目前Traefik主要分为两个版本,v1.x与v2.x,这两个版本之间差距较大,让人感觉在使用不同的软件。本篇文章是以v2.x版本为基础来演示的,相关脚本代码都在Github仓库https://github.com/lateautumn4lin/KubernetesResearch里面,大家使用的时候可以切换目录到ClusterEcology/initTraefik下面。
云爬虫技术研究笔记
2020/02/19
8210
Kubernetes的Ingress控制器比较(Traefik)
Traefik支持动态配置和静态配置,因此在实践的过程中,我们将Traefik运行的端口配置在静态配置文件中,Traefik因为功能的丰富性得到很多的人的青睐,尤其是它的弹性功能,从大量的技术博客上观察来看,现在很多人在使用并且很稳定,对于ingress-nginx来说,能动态配置的Traefik显然略胜一筹,这是一个非常大且好的升级。更多的功能点可以在官方文档(https://docs.traefik.io/)详细查阅:
公众号: 云原生生态圈
2021/11/15
1.9K0
Kubernetes的Ingress控制器比较(Traefik)
traefik系列之四 | 服务(TraefikService)
kubernetes 中使用 Traefik ingress 的 TraefikService 实现加权轮询、灰度发布、流量复制、会话保持(粘性会话)等功能
Amadeus
2023/04/27
8610
掀起 Traefik 2 的盖头来
我的测试集群中经常会使用 Traefik 做 Ingress,又有 Maesh 加入 Service Mesh 的暖场战之中,所以 Traefik 2.0 还是值得看看的。它的文档做的还不太完善,着实花了一段时间来摸索,这里做个记录,方便后续的使用和学习。
崔秀龙
2019/09/24
2.2K0
掀起 Traefik 2 的盖头来
TraefikIngressRoute配置
端口说明: 8080是dashboard 80是http入口 443是https入口
mikelLam
2022/10/31
5830
TraefikIngressRoute配置
在 Kubernetes 集群上部署 VSCode
近来由于武汉冠状病毒疫情的扩散,很多公司不得不开始了远程办公的模式,远程办公最大的成本自然是沟通成本了,对于我们开发人员来说最重要的自然也是有一个顺手的 IDE 工具,现在在云端作业的工具也在逐渐增长,比如最近比较流行的设计应用 Figma,就完全是云端操作的方式,大有要取代 Sketch 的趋势,对于开发工具来说云端 IDE 也逐渐受到大家重视,特别是对于远程办公的团队,Cloud IDE 允许开发团队在一个统一的开发环境中实时协作的工具,这可以大大提高生产效率。而且只需要通过 web 浏览器就可以访问,还有一个优点就是可以利用集群的能力,这可以大大超过我们之前的个人 PC 的处理能力,我们也不用为本地 IDE 占用了电脑大量资源而苦恼了。
我是阳明
2020/06/15
1.8K0
在 Kubernetes 集群上部署 VSCode
Traefik - Kubernetes 配置TCP/HTTP服务
本文主要介绍 Kubernetes采用Traefik做ingress代理服务时,TCP服务和HTTP服务的最基础代理方式。
用户3013098
2022/06/01
2.1K0
相关推荐
Traefik2.3.x 使用大全(更新版)
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文