istio内置资源和sidecar注入初探

目录

Gateway(gw)

VirtualService(vs)

DestinationRule(dr)

ServiceEntry(se)

sidecar注入以及流量劫持

sidecar注入过程

sidecar注入原理

sidecar注入结果


Gateway(gw)

istio中gateway资源可以将网格内部的服务暴露给网格外部的服务,供网格外部的服务调用,该资源描述了需要公开的端口、端口的协议类型、以及域名等。

下面是服务的gw资源配置文件示例。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

apiVersion: networking.istio.io/v1alpha3

kind: Gateway

metadata:

  name: mis-gateway-gateway

  namespace: lyl

spec:

  selector:

    istio: ingressgateway # use istio default controller

  servers:

  - port:

      number: 80

      name: http

      protocol: HTTP

    hosts:

    - "*"

 

selector标明了该gateway选择用的pod,ingressgateway实际上是一个istio-proxy,这里gateway用label关联了istio的ingressgateway。

我们可以用命令查找出该pod:

kubectl get po -l istio=ingressgateway -n istio-system

我们查看该pod的配置,发现该pod有一个container,名称为istio-proxy,该服务负责从网格外转发请求到网格内。

istio-proxy实际上是envoy + 管理envoy的父进程pilot-agent。

kubectl get po -l istio=ingressgateway -n istio-system -o json

istio内置资源和sidecar注入初探_第1张图片

VirtualService(vs)

virtualService用来与Gateway绑定,实现服务访问路由控制、服务版本与流量的控制。

下面是服务的vs配置示例:

apiVersion: networking.istio.io/v1alpha3

kind: VirtualService

metadata:

  name: go-center-mis-gateway-vs

  namespace: lyl

spec:

  hosts:

  - "*"

  gateways:

  - mis-gateway-gateway

  http:

  - match:

    - uri:

        exact: /

    route:

    - destination:

        host: go-center-mis-gateway

        subset: v1

      weight: 80

    - destination:

        host: go-center-mis-gateway

        subset: v2

      weight: 20

  1. gateways表示与哪些gateway绑定,可以绑定多个gateway资源,这里我们绑定了上面创建的gateway资源。
  2. match与route搭配可实现路由控制,上面是将path / 下的请求全部路由到两个destination上。
  3. destination中描述了目标服务的具体信息,包含host服务域名、服务版本、版本权重等。
  4. virtual service与destination rule结合,可以实现服务版本的流量控制,新版本的灰度发布可以根据这个来实现。

协议支持:

istio内置资源和sidecar注入初探_第2张图片

http协议流量规则:

istio内置资源和sidecar注入初探_第3张图片

DestinationRule(dr)

外部请求经过VirtualService的路由规则后,如果目标服务设置了dr,那么dr配置的目标服务策略会生效。

下面是服务的dr配置示例:

apiVersion: networking.istio.io/v1alpha3

kind: DestinationRule

metadata:

  name: go-center-mis-gateway-dr

  namespace: lyl

spec:

  host: go-center-mis-gateway

  trafficPolicy:

    loadBalancer:

      simple: ROUND_ROBIN

  subsets:

  - name: v1

    labels:

      version: v1

  - name: v2

    labels:

      version: v2

  1. host是服务的域名
  2. trafficPolicy是对于服务pod的流量规则,比较重要的如loadBalancer、connectionPool、outlierDetection

    istio内置资源和sidecar注入初探_第4张图片

    loadBalancer simple规则:
    istio内置资源和sidecar注入初探_第5张图片

    http connectionPool规则:

    istio内置资源和sidecar注入初探_第6张图片

    outlierDetection可实现异常点检测与熔断:

    istio内置资源和sidecar注入初探_第7张图片

  3. subset描述了服务的子集,该子集由带有标签(version: v2)的pod组成,不同的子集也可以设置不同的trafficPolicy,如下面的例子,默认lb策略是least_conn,而v3版本则是轮询策略。

    apiVersion: networking.istio.io/v1alpha3

    kind: DestinationRule

    metadata:

      name: bookinfo-ratings

    spec:

      host: ratings.prod.svc.cluster.local

      trafficPolicy:

        loadBalancer:

          simple: LEAST_CONN

      subsets:

      - name: testversion

        labels:

          version: v3

        trafficPolicy:

          loadBalancer:

            simple: ROUND_ROBIN

ServiceEntry(se)

功能:

  1. 将网格外的服务加到服务发现中,就像是网格内的服务一样被治理(成为k8s中的一个service),如网格外的mysql、redis等服务,或是部署在物理机上未加入网格内部的服务。

机制:

  1. 将ServiceEntry描述的service加到服务发现中,对这些服务的outbound流量进行拦截,从而进行治理。
  2. 当ServiceEntry描述的service有endpoint变化时,我们可以监听其变化,利用k8s基建,创建或者删除k8s该service的endpoint,由于istio的服务发现依赖于k8s,该变化会被istio pilot-discovery感知到,并通过xDs通知envoy。
  3. istio服务发现概览:
  4. istio内置资源和sidecar注入初探_第8张图片
  5. TODO:serviceEntry其他配置文件等待补充……

sidecar注入以及流量劫持

sidecar模式:

istio内置资源和sidecar注入初探_第9张图片

Sidecar 连接到父应用并且为其添加扩展或者增强功能。

使用sidecar的优势:

  • 将与应用业务逻辑无关的功能抽象到共同基础设施,降低了微服务代码的复杂度。
  • 因为不再需要编写相同的第三方组件配置文件和代码,所以能够降低微服务架构中的代码重复度。
  • Sidecar 可独立升级,降低应用程序代码和底层平台的耦合度。

sidecar注入过程

在创建namespace lyl时,我们使用了istio的自动注入:

kubectl label namespace lyl istio-injection=enabled --overwrite

注入以后,我们看下namespace的配置,多了一个label,istio-injection=enable

istio内置资源和sidecar注入初探_第10张图片

sidecar注入原理

sidecar注入依赖于Kubernetes 的准入控制器。

来自 Kubernetes 文档:

准入控制器是一段代码,会拦截 Kubernetes API Server 收到的请求,拦截发生在认证和鉴权完成之后,对象进行持久化之前。可以定义两种类型的 Admission webhook:Validating 和 Mutating。Validating 类型的 Webhook 可以根据自定义的准入策略决定是否拒绝请求;Mutating 类型的 Webhook 可以根据自定义配置来对请求进行编辑。

简单来说,sidecar的注入是在api-server接收到deployment pod的请求之后,写入etcd之前做的事情。

对于 sidecar 自动注入,Istio 依赖于 Mutating Admission Webhook。让我们来看看 istio-sidecar-injector 中的配置详情。

kubectl get mutatingwebhookconfiguration istio-sidecar-injector -o yaml

apiVersion: admissionregistration.k8s.io/v1beta1

kind: MutatingWebhookConfiguration

metadata:

  annotations:

    kubectl.kubernetes.io/last-applied-configuration: |

      {"apiVersion":"admissionregistration.k8s.io/v1beta1","kind":"MutatingWebhookConfiguration","metadata":{"annotations":{},"labels":{"app":"istio-sidecar-injector","chart":"sidecarInjectorWebhook-1.0.1","heritage":"Tiller","release":"istio-remote"},"name":"istio-sidecar-injector","namespace":""},"webhooks":[{"clientConfig":{"caBundle":"","service":{"name":"istio-sidecar-injector","namespace":"istio-system","path":"/inject"}},"failurePolicy":"Fail","name":"sidecar-injector.istio.io","namespaceSelector":{"matchLabels":{"istio-injection":"enabled"}},"rules":[{"apiGroups":[""],"apiVersions":["v1"],"operations":["CREATE"],"resources":["pods"]}]}]}

  creationTimestamp: 2018-12-10T08:40:15Z

  generation: 2

  labels:

    app: istio-sidecar-injector

    chart: sidecarInjectorWebhook-1.0.1

    heritage: Tiller

    release: istio-remote

  name: istio-sidecar-injector

  .....

webhooks:

- clientConfig:

    service:

      name: istio-sidecar-injector

      namespace: istio-system

      path: /inject

  name: sidecar-injector.istio.io

  namespaceSelector:

    matchLabels:

      istio-injection: enabled

  rules:

  - apiGroups:

    - ""

    apiVersions:

    - v1

    operations:

    - CREATE

    resources:

    - pods

在配置文件中,我们看到有namespaceSelector配置,matchLabels表明如果namespace满足有label:istio-injection=enable(上面截图可以看到我们的namespace lyl已经满足这个条件),并且满足下面列的rules:v1 version,且动作是pod的创建,那么mutatingWebhook会执行istio-sidecar-injector这个service,给创建的pod注入配置。

sidecar注入结果

sidecar注入以后,查看服务启动的pod信息

istio内置资源和sidecar注入初探_第11张图片

可以看到,每个pod都有两个ready的容器,一个是我们的服务容器,另一个就是sidecar容器。

查看下第一个pod具体的配置信息:

kubectl get po $(kubectl get po -n lyl | grep v1 | awk '{print $1}') -n lyl -o json

 

istio内置资源和sidecar注入初探_第12张图片

 

发现有两个containers,具体展开可以看到一个是我们自己服务的容器,第二个是istio-proxy容器,也就是sidecar容器,之前说到istio-proxy实际上是pilot-agent + envoy两个父子进程,pilot负责管理envoy,所以实际上服务的sidecar就是envoy。

同时,在配置下方,我们还发现了另一个container,叫作istio-init container,这个init容器在pod初始化时创建,pod初始化完成就自动销毁了,从配置的command中可以看出,init容器主要用来创建iptables规则。istio-iptables的代码位于istio代码仓库的tools/istio-iptables目录。

istio内置资源和sidecar注入初探_第13张图片

 

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

  • Init 容器 istio-init:用于 pod 中设置 iptables 端口转发。
  • Sidecar 容器 istio-proxy:运行 sidecar 代理,即envoy。

iptables注入解析(以下iptables规则引用自这里,本文不在详述):

# 查看 NAT 表中规则配置的详细信息。

$ iptables -t nat -L -v

# PREROUTING 链:用于目标地址转换(DNAT),将所有入站 TCP 流量跳转到 ISTIO_INBOUND 链上。

Chain PREROUTING (policy ACCEPT 2701 packets, 162K bytes)

 pkts bytes target     prot opt in     out     source               destination

 2701  162K ISTIO_INBOUND  tcp  --  any    any     anywhere             anywhere

 

# INPUT 链:处理输入数据包,非 TCP 流量将继续 OUTPUT 链。

Chain INPUT (policy ACCEPT 2701 packets, 162K bytes)

 pkts bytes target     prot opt in     out     source               destination

 

# OUTPUT 链:将所有出站数据包跳转到 ISTIO_OUTPUT 链上。

Chain OUTPUT (policy ACCEPT 79 packets, 6761 bytes)

 pkts bytes target     prot opt in     out     source               destination

   15   900 ISTIO_OUTPUT  tcp  --  any    any     anywhere             anywhere

 

# POSTROUTING 链:所有数据包流出网卡时都要先进入POSTROUTING 链,内核根据数据包目的地判断是否需要转发出去,我们看到此处未做任何处理。

Chain POSTROUTING (policy ACCEPT 79 packets, 6761 bytes)

 pkts bytes target     prot opt in     out     source               destination

 

# ISTIO_INBOUND 链:将所有入站流量重定向到 ISTIO_IN_REDIRECT 链上,目的地为 15090(mixer 使用)和 15020(Ingress gateway 使用,用于 Pilot 健康检查)端口的流量除外,发送到以上两个端口的流量将返回 iptables 规则链的调用点,即 PREROUTING 链的后继 POSTROUTING。

Chain ISTIO_INBOUND (1 references)

 pkts bytes target     prot opt in     out     source               destination

    0     0 RETURN     tcp  --  any    any     anywhere             anywhere             tcp dpt:ssh

    2   120 RETURN     tcp  --  any    any     anywhere             anywhere             tcp dpt:15090

 2699  162K RETURN     tcp  --  any    any     anywhere             anywhere             tcp dpt:15020

    0     0 ISTIO_IN_REDIRECT  tcp  --  any    any     anywhere             anywhere

 

# ISTIO_IN_REDIRECT 链:将所有的入站流量跳转到本地的 15006 端口,至此成功的拦截了流量到 sidecar 中。

Chain ISTIO_IN_REDIRECT (3 references)

 pkts bytes target     prot opt in     out     source               destination

    0     0 REDIRECT   tcp  --  any    any     anywhere             anywhere             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  --  any    lo      127.0.0.6            anywhere

    0     0 ISTIO_IN_REDIRECT  all  --  any    lo      anywhere            !localhost            owner UID match 1337

    0     0 RETURN     all  --  any    lo      anywhere             anywhere             ! owner UID match 1337

   15   900 RETURN     all  --  any    any     anywhere             anywhere             owner UID match 1337

    0     0 ISTIO_IN_REDIRECT  all  --  any    lo      anywhere            !localhost            owner GID match 1337

    0     0 RETURN     all  --  any    lo      anywhere             anywhere             ! owner GID match 1337

    0     0 RETURN     all  --  any    any     anywhere             anywhere             owner GID match 1337

    0     0 RETURN     all  --  any    any     anywhere             localhost

    0     0 ISTIO_REDIRECT  all  --  any    any     anywhere             anywhere

 

# ISTIO_REDIRECT 链:将所有流量重定向到 Sidecar(即本地) 的 15001 端口。

Chain ISTIO_REDIRECT (1 references)

 pkts bytes target     prot opt in     out     source               destination

    0     0 REDIRECT   tcp  --  any    any     anywhere             anywhere             redir ports 15001

istio内置资源和sidecar注入初探_第14张图片

 

 

 

参考资料:

https://jimmysong.io/blog/sidecar-injection-iptables-and-traffic-routing/

https://istio.io/zh/docs/reference/config/networking/destination-rule/#OutlierDetection

 

你可能感兴趣的:(istio,k8s,微服务)