Sidecar及流量拦截机制-上
更多相关文章
个人博客 :pyenv.cc
ServiceMesh基本概念
手把手教你部署istio控制平面
四个案例让你掌握istio网格功能
VirtualService实现Istio高级流量治理
DestinationRule实现Istio集群高级配置
一、Istio环境中运行Pod的要求
- Service association (服务关联)
- Pod 必须从属于某个Service,哪怕Pod不需要暴露任何端口,否则此Pod就是一个无Service的Pod,会导致网格内部无法于相关的Sidecar进行关联;
- 同时从属于多个Service时,这些Service不能为该类Pod的同一个端口标识使用不同的协议;
- Application UIDs
- UID 1337 预留给了Sidecar Proxy 使用,业务应用不能以这一 UID 运行;
- NET_ADMIN and NET_RAW capabilities
- 强制启用了PSP(Pod Security Policy)的Kubernetes环境中,必须允许在网格内的Pod上使用NET_ADMIN和 NET_RAW这两个Capability,以确保Sidecar Envoy依赖的初始化Pod能够正常运行;
- 未启用PSP,或者启用了PSP但使用了专用的Istio CNI Plugin的场景,可以不用;
- Pods with app and version labels (部署在网格内的每一个应用程序都需要明确使用以下两个标签)
- 显式地为 Pod使用app和version标签;
- app标签用于为分布式追踪生成context,而label则用于指示应用的版本化;
- Named Service Ports (为网格内的每一个Service的端口定义一个名称及明确其协议)
- Service Port 应该明确指定使用的协议;
- 命名格式 :
- [-] 如 http-8080
- Kubernetes v1.18 及之后的版本中,可以直接使用 appProtocol 字段进行标识;
# 网格会依赖对应方式指定的协议标识作为协议,即应用程序对外提供服务协议的特定标识;这也是Envoy在代理应用程序基于的协议类型;1、<protocol>[-<suffix>] 格式
apiVersion: v1
kind: Service
metadata:name: demoappv10
spec:ports:- name: http-8080port: 8080protocol: TCPtargetPort: 8080selector:app: demoappversion: v1.0type: ClusterIP2、Kubernetes v1.18 及之后的版本中,可以直接使用 appProtocol 字段进行标识
apiVersion: v1
kind: Service
metadata:name: demoappv10
spec:appProtocol: httpports:- name: httpport: 8080protocol: TCPtargetPort: 8080selector:app: demoappversion: v1.0type: ClusterIP
二、协议选择 (Protocol Selection)
- Istio 支持代理的协议
- 支持代理任何类型的TCP流量,包括HTTP、HTTPS、gRPC及原始TCP(raw tcp) 协议;
- 但为了提供额外的能力,比如路由和更加丰富的指标,Istio需要确定更加具体的协议( 应用层协议) ;
- Istio不会代理任何UDP协议;
- 协议选择
- istio 能够自动检测并识别 HTTP和HTTP/2 的流量,未检测出的协议类型将一律视为普通的TCP流量;
- 也支持由用户手动指定;
- 手动指定协议
- Service Port 应该明确指定使用的协议;
- 命名格式 :
- [-]
- Kubernetes v1.18 及之后的版本中,可以直接使用 appProtocol 字段进行标识;
- Istio支持的协议类型如下 :
https://istio.io/latest/docs/ops/configuration/traffic-management/protocol-selection/
三、Sidecar代理方式简介
- Kubernetes平台上,Envoy Sidecar容器与application容器于同一个Pod中共存,它们共享 NETWORK、UTS和IPC等名称空间,因此也共用同一个网络协议栈;
- Envoy Sidecar 基于 init 容器 (需要使用 NET_ADMIN 和 NET_RAW Capability 于 Pod启动时设置的 iptables规则以实现流量拦截)
- 入站流量由iptables拦截后转发给Envoy;
- Envoy根据配置完成入栈流量代理;
- 后端应用程序生成的出站流量依然由iptables拦截并转发给Envoy;
- Envoy 根据配置完成出站流量代理;
- Envoy Sidecar 基于 init 容器 (需要使用 NET_ADMIN 和 NET_RAW Capability 于 Pod启动时设置的 iptables规则以实现流量拦截)
- 流量拦截模式
- REDIRECT : 重定向模式
- TPROXY : 透明代理模式
- 具体操作参考 : https://github.com/istio/istio/blob/master/tools/packaging/common/istio-start.sh
四、Sidecar Envoy 流量劫持
- 流量的透明劫持
- 流量的透明劫持,用于确保让应用无需事先改造即可获得服务治理和观测能力;
- 开启透明劫持功能后,出入应用的业务流量将会被Sidecar Envoy自动拦截;
五、Istio注入的Envoy Sidecar
- Istio 基于 Kubernetes Admission Controller Webhook 完成sidecar自动注入,它会为每个微服务分别添加两个相关的容器;
- istio-init : 隶属于 Init Containers ,即初始化容器,负责在微服务相关的Pod中 生成iptables规则 以进行流量拦截并向Envoy Proxy进行转发,运行完成后退出;
- istio-proxy : 隶属于Contianers, 即Pod中的正常容器,程序为 Envoy Proxy;
# 查看每个Pod上是如何指定注入的 istio init container
# Init Containers 生成流量劫持规则
Init Containers:istio-init:Container ID: docker://943e9512f4e3ec0f64b25b26ac334c70800169416389abc58b723413481c787fImage: docker.io/istio/proxyv2:1.12.1Image ID: docker-pullable://istio/proxyv2@sha256:4704f04f399ae24d99e65170d1846dc83d7973f186656a03ba70d47bd1aba88fPort: <none>Host Port: <none>Args:istio-iptables# 入向流量生成规则的重定向端口-p15001# 出向流量端口-z15006# 使用用户UID-u1337-mREDIRECT-i*-x-b*-d15090,15021,15020
...
Containers:demoapp:Container ID: docker://563a48b833baf3ab46ef35f147012e124ba3c114323377c261f2cb5c8729a34fImage: ikubernetes/demoapp:v1.0Image ID: docker-pullable://ikubernetes/demoapp@sha256:6698b205eb18fb0171398927f3a35fe27676c6bf5757ef57a35a4b055badf2c3Port: <none>Host Port: <none>
...
# istio-proxy: 真正意义上流量治理 sidecar envoyistio-proxy:Container ID: docker://bab78cd8993123c8a24a236a02a0b572a3acbc0e013559a24dd57959d9c7430cImage: docker.io/istio/proxyv2:1.12.1Image ID: docker-pullable://istio/proxyv2@sha256:4704f04f399ae24d99e65170d1846dc83d7973f186656a03ba70d47bd1aba88fPort: 15090/TCPHost Port: 0/TCPArgs:proxysidecar # sidecar 模式运行--domain$(POD_NAMESPACE).svc.cluster.local--proxyLogLevel=warning--proxyComponentLogLevel=misc:error--log_output_level=default:info--concurrency2
5.1、istio-init初始化容器
- istio-init初始化容器基于 istio/proxyv2 镜像启动,它运行 istio-iptables 程序以生成流量拦截规则
- 拦截的流量将转发至两个相关的端口
- 15006 :由 -z 选项定义,指定用于接收拦截所有发往当前Pod/VM的入栈流量的目标端口,该配置仅用于 REDIRECT 转发模式;
- 15001 :由 -p 选项定义,指定用于接收拦截的所有TCP流量的目标端口;
- 流量拦截模式由 -m 选项指定,目前支持 REDIRECT 和 TPROXY 两种模式;
- 流量拦截时要包含的目标端口列表使用 -b 选项指定,而要排除的目标端口列表则使用 -d 选项指定;
- 流量拦截时要包含的目标 CIDR 地址列表可使用 -i 选项指定,而要排除的目标 CIDR 格式的地址列表则使用 -x 选项指定;
- 拦截的流量将转发至两个相关的端口
5.1.1、istio中用于流量拦截的iptables规则
- nsenter 命令于宿主机上可直接于目标容器的网络名称空间中运行 iptables 命令,例如,假设 productpage 相关的 Pod被调度运行于 k8s-node02 节点之上,且其内部的 envoy 进程的 pid在宿主机为 5607 ;
# 对应运行envoy sidecar 节点上运行命令
root@native:~# ps aux | grep envoy | grep 1337
root@native:~# nsenter -t 8134 -n iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N ISTIO_INBOUND
-N ISTIO_IN_REDIRECT
-N ISTIO_OUTPUT
-N ISTIO_REDIRECT
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_INBOUND -p tcp -m tcp --dport 15008 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 22 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15090 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15021 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
-A ISTIO_OUTPUT -s 127.0.0.6/32 -o lo -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
5.1.2、流量拦截的处理机制
- 入向流量拦截 : PREROUTING -> ISTIO_INBOUND
- RETURN
- 目标端口为 TCP 协议的 22、15020、15021、15008、15090 时将报文返回至上级 PREROUTING 链,即不予拦截;
- ISTIO_IN_REDIRECT : 其它目标端口的请求报文则由该自定链中的规则 (-A ISTIO_IN_REDIRECT -p tcp -j RESIRECT --to-ports 15006) 将请求重定向至 15006 端口;
- 15006 端口时为 envoy 的 VirtualInboundListener 绑定的端口,于是请求则转交由Envoy处理;
- Envoy 根据报文目标地址匹配入向 (Inbound) 方向的Listener,若存在,则根据该 Listener的配置决定如何将请求转发至 Envoy后端的应用程序;
- RETURN
- 出向流量拦截 : OUTPUT -> ISTIO_OUTPUT
- RETURN
- 从 LO 接口流出,且源地址为 127.0.0.6/32 的出向流量
- UID Owner 为 1337 的出向流量
- GID Owner 为 1337 的出向流量
- 从 LO 接口流出,且UID Owner 非为 1337 的出向流量
- 从 LO 接口流出,且GID Owner 非为 1337 的出向流量
- 目标地址是 127.0.0.1/32 的出向流量
- ISTIO_IN_REDIRECT : Sidecar Envoy 同其反向代理的本地后端应用程序间的通信
- 从 LO 接口流出,目标地址非为 127.0.0.1/32,且UID Owner 为 1337 的出向流量
- 从 LO 接口流出,目标地址非为 127.0.0.1/32,且GID Owner 为 1337 的出向流量
- RETURN
- ISTIO_REDIRECT:其它报文则由该自定义链中的规则(-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001)重定向至15001端口;
- Envoy根据报文目标地址匹配出向(Outbound)方向的Listener,若存在,则 根据该Listener的配置决定如何将报文向外转发;
5.2、istio-proxy 容器
- istio-proxy即所谓的sidecar容器,它运行两个进程:
- pilot-agent
- 基于k8s api server 为 envoy 初始化出可用的 bootstrap 配置文件并启动envoy;
- 监控并管理envoy的运行状态,包括envoy出错时重启envoy,以及envoy配置变更后将其重载等;
- envoy
- envoy 由pilot-agent 进程基于生成bootstrap 配置进行启动,而后根据配置中指定的 pilot 地址,通过xDS API获取动态配置信息;
- Sidecar形式的Envoy通过流量拦截机制为应用程序实现入站和出站代理功能;
# kubectl exec demoappv10-6ff964cbff-84kqr -it -c istio-proxy -- ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
istio-p+ 1 0.1 0.4 747732 47700 ? Ssl Feb19 0:50 /usr/local/bin/pilot-agent proxy sidecar --domain default.svc.cluster.local --proxyLogLevel=
istio-p+ 28 0.4 0.5 185544 58488 ? Sl Feb19 3:16 /usr/local/bin/envoy -c etc/istio/proxy/envoy-rev0.json --restart-epoch 0 --drain-time-s 45
istio-p+ 42 0.0 0.0 5900 2804 pts/0 Rs+ 03:45 0:00 ps aux
5.2.1、istio-proxy 容器及其Listener
- Envoy 的bootstrap 配合文件由pilot-agent 负责生成,而生效的大多配置则定义了dynamic resources ,并通过xDS静态集群指向的Plot 获取;
- 而这些配置则来自于 VirtaulService、DestinationRule、Gateway和ServiceEntry资源对象等提供的配置;
- 由Pilot基于Kubernetes发现的网格内的各Service均会被自动转换为下发给各Sidecar实例的Listener、Route、Cluster和Endpoint的相关配置;
- 为了能够让Sidecar Envoy代理网格内进出各Service的流量,所以需要进行流量劫持,而后由Envoy根据请求特征,将流量派发至合适的Listener,进而完成后续的流量路由、负载均衡等;
5.2.2、istio-proxy Listener (几个重要侦听器的作用)
- Envoy Listener 支持绑定于 IP Socket 或 Unix Domain Socket 之上,也可以不予绑定,而是接收由其他的Listener转发来的数据;
- VirtualOutboundListener
- 通过一个端口接收所有的出口流量,而后再按照请求的端口分别转发给相应的 Listener进行处理;
- VirtualInboundListner
- 功能相似,但主要用于处理入向流量;
VirtualOutboundListener(不过多展开)
- iptables 将其所在的Pod中的外发流量拦截后转发至监听于15001的Listener,而该Listener通过在配置中将 use_origin_dest 参数设置为true,从而实现将接收到的请求转发给同请求原目标地址关联的Listener之上;
- 若不存在可接收转发报文的Listener,则Envoy将根据Istio的全局配置选项 outboundTrafficPolicy 参数的值决定如何进行处理 :
- ALLOW_ANY :
- 允许外发至任何服务的请求,无论目标服务是否存在于Pilot的注册表中;此时,没有匹配的目标Listener的流量将由该侦听器上 tcp_proxy 过滤器指向的 Passthrouh Cluster 进行透传;
- REGISTRY_ONLY :
- 仅允许外发请求至注册与Polit 中的服务;此时,没有匹配的目标Listener的流量将由该侦听器上 tcp_proxy 过滤器指向的 BlackHoleCluster 将流量直接丢弃;
- 出向流量劫持方式总结 :
- 所有应用的出向流量会被重定向给 Envoy Sidecar 的 15001 侦听器,而后 15001 侦听器将流量根据其请求的原有的目标IP和目标端口来在Envoy中找出真正于该流量相关的出站侦听器,再把其请求转交至其真正相关的出站侦听器;若其没有找到对应条件的出站侦听器则根据出站流量策略 outboundTrafficPolicy 确定是交给 Passthrouh Cluster 进行透传还是 BlackHoleCluster 进行丢弃;
VirtualInbound Listener(不过多展开)
- 入向流量劫持
- 较早版本的 Istio 基于同一个 VirtualListener 在 15001 端口上同时处理入站和出站流量;
- 自 1.4 版本起,Istio引入了 REDIRECT 代理模式,它通过监听于 15006 端口 的专用 VirtualInboundListener 处理入向流量代理以避免潜在的死循环问题;
- 入向流量处理
- 对于进入到 侦听器 “0.0.0.0:15006” 的流量,VirtaulInboundListener 会在 filterChains 中,通过一系列的 filter_chain_match 对流量进行匹配检测,以确定应该由哪个或哪些过滤器进行流量处理;
- 入向流量劫持方式总结
- istio proxy 对所有相关入向流量的处理方式是所有请求的无论目标 APP服务监听的端口,Envoy 都不会为其在前端创建入站侦听器而是所有流量交给 15006 ,在15006入站侦听器内部 都会通过 filter_chain_match 进行处理,然后通过其内部 filterChainMatch 进行匹配,而后又经过filter进行流量转发;
5.3、istio-proxy Clusters
- Istio 网格中的Cluster分别由 static_resources 提供的静态配置集群以及 dynamic_resources 提供的动态配置集群组成;
- 静态集群由 envoy_rev0.json 的初始化配置中的 prometheus_stats 、xDS server 和zipkin server等组成;
- 动态集群则是由通过xDS API 从Pilot获取的配置信息生成;
- 对于网格内的一个特定Pod来说,其集群可主要分为两类 :
- inbound : 该Pod内的Sidecar Envoy直接代理的服务;
- outbound : 网格内的所有服务;
- 动态集群类型
- Inbound Cluster :Sidecar Envoy直接代理的应用,同一Pod中,由Sidecar Envoy反向代理的应用容器;
- Outbound Cluster :网格中的所有服务,包括当前Sidecar Envoy直接代理的服务,该类Cluster占了Envoy可用集 群中的绝大多数;
- PassthroughCluster和InboundPassthroughClusterIpv4 :发往此类集群的请求报文会被直接透传至其请求中的原 始目标地址,Envoy不会进行重新路由;
- BlackHoleCluster :Envoy的一个特殊集群,它没有任何可用的endpoint,接收到的请求会被直接丢弃;未能正 确匹配到目标服务的请求通常会被发往此Cluster;
Sidecar及流量拦截机制-上相关推荐
- Sidecar及流量拦截机制-下
更多相关文章 个人博客 :pyenv.cc ServiceMesh基本概念 手把手教你部署istio控制平面 四个案例让你掌握istio网格功能 VirtualService实现Istio高级流量治理 ...
- Attribute在拦截机制上的应用
http://blog.csdn.net/niuyongjie/article/details/1295842 从这一节开始我们讨论Attribute的高级应用,为此我准备了一个实际的例子:我们有一个 ...
- Nginx流量拦截算法
0x00.About 电商平台营销时候,经常会碰到的大流量问题,除了做流量分流处理,可能还要做用户黑白名单.信誉分析,进而根据用户ip信誉权重做相应的流量拦截.限制流量. Nginx自身有的请求限制模 ...
- 千亿流量拦截控制处理技术-Nginx(安装 命令 路由匹配 负载均衡 常用配置)
千亿流量拦截控制处理技术-Nginx Nginx使用与配置 1 什么是nginx 1.1 可大量并行处理 1.2 与 Apache 相比 1.2.1 Apache VS Nginx 1.2.2 常用w ...
- Nginx流量拦截算法 1
0x00.About 电商平台营销时候,经常会碰到的大流量问题,除了做流量分流处理,可能还要做用户黑白名单.信誉分析,进而根据用户ip信誉权重做相应的流量拦截.限制流量. Nginx自身有的请求限制模 ...
- Nginx + LUA下流量拦截算法
前言 电商平台营销时候,经常会碰到的大流量问题,除了做流量分流处理,可能还要做用户黑白名单.信誉分析,进而根据用户ip信誉权重做相应的流量拦截.限制流量. Nginx自身有的请求限制模块ngx_htt ...
- 如何绕过chrome的弹窗拦截机制
如何绕过chrome的弹窗拦截机制 在chrome的安全机制里面,非用户触发的window.open方法,是会被拦截的.举个例子: var btn = $('#btn'); btn.click(fun ...
- 反思|Android 事件拦截机制的设计与实现,android组件化开发
最顶层View直接持有最下层某个View的引用合理吗?答案是否定的.首先,这导致View层级依赖之间的混乱:其次,顶层View本身持有了最下层某个View的引用,则这之间若干个层级的View的targ ...
- Android短信拦截机制适配的坑(下)--4.4以上系统,主要是6.0
前一篇文章,Android短信拦截机制适配的坑(上)--4.4以下系统 介绍了广播接收的顺序,但是我明确说明在4.4以下系统,那么4.4及以上系统会遇到说明问题呢? 首先我们要来了解4.4系统短信的机 ...
最新文章
- 树莓派视觉小车 -- 物体跟踪(OpenCV)
- vue 取数组第一个值_vue遍历对象中的数组取值示例
- BugKuCTF WEB web基础$_GET
- 在利用计算机生成,计算机生成人像,从而使人脸的模糊变为现实
- php cli 判断,php cli 命令行详解【转】
- python 抓包基于pypcap
- python 统计单词个数---从文件读取版本---不去重
- Android 仿美团网,大众点评购买框悬浮效果之修改版
- 对R语言发展与历史的一个初步认识
- [python] 字典 pop(key)函数:删除字典中key及其值,并返回该值
- Linux多线程服务端编程学习(四)finger服务的实现
- 【POJ】2676-Sudoku 【51Nod】1211-数独(DFS)
- Android malware样本SLocker Mobile Ransomware
- javascript-ECMAScript
- 中国中试工厂市场现状研究分析与发展前景预测报告
- 【315】备份全盘和备份C盘的区别
- python计算协方差_在Python中计算协方差
- 什么是promise,promise的使用及实现
- 年前找Java实习面试经历
- Hive案例之股票分析