istio系列:第一章-核心概念与原理
Istio是一个用于服务治理的开放平台
Istio是一个Service Mesh形态的用于服务治理的开放平台
Istio是一个与Kubernetes紧密结合的适用于云原生场景的Service Mesh形态的用于服务治理的开放平台。
概念
提供的功能
istio是一个产品,那么这个产品肯定提供了一些功能让用户使用。
- 自动通过服务发现获取recommendation服务实例列表,并根据负载均衡策略选择一个服务实例;
- 对服务双方启用双向认证和通道加密;
- 如果某个服务实例连续访问出错,则可以将该实例隔离一段时间,以提高访问质量;
- 设置最大连接数、最大请求数、访问超时等对服务进行保护;
- 限流;
- 对请求进行重试;
- 修改请求中的内容;
- 将一定特征的服务重定向;
- 灰度发布;
- 自动记录服务访问信息;
- 记录调用链,进行分布式追踪;
- 根据访问数据形成完整的应用访问拓扑;
- …
运行原理
因为Istio与k8s的高度结合,所以对于这些功能的使用,采用了CRD的方式。用户只需要创建相应的规则资源,istio监听到资源后会进行一些系列的操作比如创建一个路由规则VirtualService,istio监听到该资源后,会将规则解析成Sidecar识别的配置,然后推送给POD中的Sidecar。
- istio可以分为两个模块,服务发现与规则处理发布模块、具体路由转发模块
- 对于服务发现与规则处理模块,主要由Pilot组件完成,它相当于微服务架构中注册中心,管理着所有已注册的应用、规则、配置等。
- 路由转发模块Sidecar是在每个POD中拦截POD的出入流量,并根据规则进行管理。
接下来让我们对Sidecar进行讲解。
Sidecar
Istio的流量管理、遥测、治理等功能均需要通过下发配置规则到应用所在的运行环境执行才能生效,而负责执行这些配置规则的组件在服务网格中被称为服务代理。我们通常将承载服务的实体称为应用,将承载服务代理的实体称为应用Sidecar(简称Sidecar)
Sidecar注入
Sidecar存在于每个POD当中,它有两种安装方式,一种是通过istioctl命令行工具手动注入,另一种是通IstioSidecar Injector自动注入这两种方法的最终目的是,在POD资源initcontainer字段添加上实现Sidecar的容器。
自动注入方法 在命名空间 加上istio-injection=enabled这个标签
手动注入没什么好讲的,让我们直接分析自动注入原理。
自动注入原理其实很好理解,就是采用了准入的概念。准入,我们在请求kube-apiserver时,它会有以下流程
- 创建http连接
- 身份校验
- 权限校验
- 准入控制器调度
K8s提供了一个准入控制器供我们自定义设置,Webhook。
webhook提供了两个函数MutatingAdmissionWebhook、validatingAdmissionWebhook(参数校验)。而自动注入的原理就是使用了MutatingAdmissionWebhook。用户可以在MutatingAdmissionWebhook这一步对请求资源进行修改,比如创建POD,可以在这里修改该POD的标签信息等。而自动化注入就是在这里添加了initcontainer
Sidecar流量拦截
既然注入完成了,接下来就开始正式工作了。
对于POD中的流量拦截,原理是修改节点上的iptables。
我认为这样有个好处是与kubeproxy的机制保持一致,让我们访问时一二三层还是使用kubeproxy进行路由选择,四层应用层使用Sidecar管理。
istio中还有很多组件比如Mixer提供了istio访问策略、Citadel提供了证书的管理等,但是最重要的就是上面两个组件。
测试iptables。这里我们使用到了nsenter命令,它的作用是将当前进程放到指定的进程命名空间里,那么这样就能实现在节点上查看容器里的信息。
首先我们应该知道容器运行的PID,这里我使用的是containerd所以运行ctr -n k8s.io containers info <容器ID>查找到PID为7235
nsenter -t 7235 -n
[root@slave01 ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
这里为空值,是正常现象如果没有指定-t 参数的话,默认是查询filter表。在istio中,有两种流量拦截方式REDIRECT模式和TPROXY模式,TPROXY模式用来做透明代理,操作的是mangle表,同时需要原始客户端socket设置IP_TRANSPARENT选项,REDIRECT 模式虽然会进行源地址转换,但依然是默认的设置,因为:配合 Istio提供的遥测数据依然可以进行调用链分析;在Kubernetes平台上Pod及其IP地址并不是持久不变的,会随着集群的资源状况动态销毁及迁移,所以源地址这种传统的软件系统记录客户端的方式并不适合云原生应用平台Kubernetes。
这里我们使用REDIRECT 所以只需要访问nat表即可,因为nat表只存在于PREROUTING POSTROUTING OUTPUT 链中所以我们只看这三个链
# 访问nat表
[root@slave01 ~]# iptables -t nat -L
# 这里我们可以看到将所有的请求都调用ISTIO_INBOUND链
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
ISTIO_INBOUND tcp -- anywhere anywhere
# 这里是流量的出口,我们可以看到ISTIO也进行了拦截操作
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ISTIO_OUTPUT tcp -- anywhere anywhere
# 这里并没有拦截,可能是因为总出口已拦截的原因吧
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
Chain ISTIO_INBOUND (1 references)
target prot opt source destination
RETURN tcp -- anywhere anywhere tcp dpt:15008
RETURN tcp -- anywhere anywhere tcp dpt:15090
RETURN tcp -- anywhere anywhere tcp dpt:15021
RETURN tcp -- anywhere anywhere tcp dpt:15020
ISTIO_IN_REDIRECT tcp -- anywhere anywhere
Chain ISTIO_IN_REDIRECT (3 references)
target prot opt source destination
REDIRECT tcp -- anywhere anywhere redir ports 15006
Chain ISTIO_OUTPUT (1 references)
target prot opt source destination
RETURN all -- 127.0.0.6 anywhere
ISTIO_IN_REDIRECT all -- anywhere !localhost owner UID match 1337
RETURN all -- anywhere anywhere ! owner UID match 1337
RETURN all -- anywhere anywhere owner UID match 1337
ISTIO_IN_REDIRECT all -- anywhere !localhost owner GID match 1337
RETURN all -- anywhere anywhere ! owner GID match 1337
RETURN all -- anywhere anywhere owner GID match 1337
RETURN all -- anywhere localhost
ISTIO_REDIRECT all -- anywhere anywhere
Chain ISTIO_REDIRECT (1 references)
target prot opt source destination
REDIRECT tcp -- anywhere anywhere redir ports 15001
该图为istio中流量走向图