Istio Bookinfo

理解Bookinfo

资源列表

$ kubectl get svc,pod,gateway,virtualservice -n book
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/details       ClusterIP   10.107.54.71    <none>        9080/TCP   5h14m
service/productpage   ClusterIP   10.102.44.220   <none>        9080/TCP   5h14m
service/ratings       ClusterIP   10.110.60.146   <none>        9080/TCP   5h14m
service/reviews       ClusterIP   10.102.61.22    <none>        9080/TCP   5h14m

NAME                                  READY   STATUS    RESTARTS   AGE
pod/details-v1-74f858558f-xnvwz       2/2     Running   0          5h14m
pod/productpage-v1-76589d9fdc-knv7t   2/2     Running   0          5h14m
pod/ratings-v1-7855f5bcb9-blrkh       2/2     Running   0          5h14m
pod/reviews-v1-64bc5454b9-6d96p       2/2     Running   0          5h14m
pod/reviews-v2-76c64d4bdf-6xmb6       2/2     Running   0          5h14m
pod/reviews-v3-5545c7c78f-j8bxg       2/2     Running   0          5h14m

NAME                                           AGE
gateway.networking.istio.io/bookinfo-gateway   5h13m

NAME                                          GATEWAYS             HOSTS   AGE
virtualservice.networking.istio.io/bookinfo   [bookinfo-gateway]   [*]     5h13m

alt

根据Istio网络原理,探究Bookinfo示例

外部入口Service

Bookinfo默认提供了bookinfo-gateway

alt

Istio Gateway指定了Ingress需要监听的端口

alt

外部流量需要通过Service进入集群内部

book.yaml:

kind: Service
apiVersion: v1
metadata:
  name: book-service
spec:
  selector:
    app: istio-ingressgateway
  type: LoadBalancer
  ports:
    - port: 5678
      targetPort: 80
      name: http  
      protocol: TCP

创建Service:

$ kubectl apply -f sample\book.yaml -n istio-system
service/book-service configured

需要基于istio-ingressgateway的Pod实例创建,在同一namespace中

$ kubectl describe svc book -n istio-system
Name:                     book-service
Namespace:                istio-system
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"book-service","namespace":"istio-system"},"spec":{"ports":[{"name...
Selector:                 app=istio-ingressgateway
Type:                     LoadBalancer
IP:                       10.109.196.213
LoadBalancer Ingress:     localhost
Port:                     http  5678/TCP
TargetPort:               80/TCP
NodePort:                 http  30735/TCP
Endpoints:                10.1.0.142:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

外部流量通过LoadBalancer入口localhost:5678,经过节点NodePort的30735/TCP,到达目标TargetPort的80/TCP,即网关istio-ingressgateway的80端口

http://localhost:5678/productpage

alt

入口网关Gateway

$ kubectl describe gateway bookinfo-gateway -n book
Name:         bookinfo-gateway
Namespace:    book
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"networking.istio.io/v1alpha3","kind":"Gateway","metadata":{"annotations":{},"name":"bookinfo-gateway","namespace":"book"},"...
API Version:  networking.istio.io/v1beta1
Kind:         Gateway
Metadata:
  Creation Timestamp:  2020-04-03T03:04:27Z
  Generation:          3
  Resource Version:    12043
  Self Link:           /apis/networking.istio.io/v1beta1/namespaces/book/gateways/bookinfo-gateway
  UID:                 f3f566fc-f6b5-4c8a-842c-54556c2562f0
Spec:
  Selector:
    Istio:  ingressgateway
  Servers:
    Hosts:
      *
    Port:
      Name:      http
      Number:    80
      Protocol:  HTTP
Events:          <none>

Bookinfo在ingressgateway上配置80监听端口

alt

Istio通过更新Envoy配置信息实现流量控制

Envoy 概念:

  • Listener,监听器,命名网地址可以被下游客户端连接,由LDS提供动态配置接口
  • Router,路由,一组将虚拟主机(virtual hosts)与群集(cluster)匹配的规则(rule),允许创建流量转移规则,由RDS提供动态配置接口
  • Cluster,集群,指Envoy连接到的逻辑上相同的一组上游主机,由CDS提供动态配置接口
  • Endpoint,端点,群集(Cluster)中可用的IP和端口,由EDS提供动态配置接口

流量经过Envoy的路径:请求来自Downstream,经过Listener、Router、Cluster、Endpoint,到达目的地Upstream

Istio envoy sidecar proxy 配置中包含以下四个部分:

  • bootstrap:Envoy proxy 启动时候加载的静态配置。
  • listeners:监听器配置,使用 LDS 下发。
  • clusters:集群配置,静态配置中包括 xds-grpc 和 zipkin 地址,动态配置使用 CDS 下发。
  • routes:路由配置,静态配置中包括了本地监听的服务的集群信息,其中引用了 cluster,动态配置使用 RDS 下发。
  • endpoints:后端节点列表配置。

Envoy Listener的特点:

  • 每个 Envoy 进程中可以有多个 Listener,Envoy 与 Listener 之间是一对多的关系。
  • 每个 Listener 中可以配置一条 filter 链表(filter_chains),Envoy 会根据 filter 顺序执行过滤。
  • Listener 可以监听下游的端口,也可以接收来自其他 listener 的数据,形成链式处理。
  • filter 是可扩展的。
  • 可以静态配置,也可以使用 LDS 动态配置。
  • 目前只能监听 TCP,UDP 还未支持。

检查Envoy Listener:

$ istioctl proxy-config listeners istio-ingressgateway-75877dc5bf-zfqlw -n istio-system
ADDRESS     PORT      TYPE
0.0.0.0     80        HTTP
0.0.0.0     15090     HTTP
$ istioctl proxy-config listeners istio-ingressgateway-75877dc5bf-zfqlw -n istio-system -o json                                         
[                                                                                                                                       
    {                                                                                                                                   
        "name": "0.0.0.0_80",                                                                                                           
        "address": {                                                                                                                    
            "socketAddress": {                                                                                                          
                "address": "0.0.0.0",                                                                                                   
                "portValue": 80                                                                                                         
            }                                                                                                                           
        },                                                                                                                              
        "filterChains": [                                                                                                               
            {                                                                                                                           
                "filters": [                                                                                                            
                    {                                                                                                                   
                        "name": "envoy.http_connection_manager",                                                                        
                        "typedConfig": {                                                                                                
                            "@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager",
                            "statPrefix": "outbound_0.0.0.0_80",                                                                        
                            "rds": {                                                                                                    
                                "configSource": {                                                                                       
                                    "ads": {}                                                                                           
                                },                                                                                                      
                                "routeConfigName": "http.80"                                                                            
                            },                                                                                                          
......

istioctl proxy-config可以查看Envoy详细配置信息

  • name:该 listener 的 UUID,唯一限定名
  • address:监听的逻辑/物理地址和端口号
  • filter_chains:这是一个列表,顺序执行 filter

监听端口80,http请求关联至http.80的routeConfig

路由VirtualService

$ kubectl describe virtualservice bookinfo -n book                                               
Name:         bookinfo                                                                           
Namespace:    book                                                                               
Labels:       <none>                                                                             
Annotations:  kubectl.kubernetes.io/last-applied-configuration:                                  
                {"apiVersion":"networking.istio.io/v1alpha3","kind":"VirtualService","metadata":{
API Version:  networking.istio.io/v1beta1                                                        
Kind:         VirtualService                                                                     
Metadata:                                                                                        
  Creation Timestamp:  2020-04-03T03:04:27Z                                                      
  Generation:          1                                                                         
  Resource Version:    7693                                                                      
  Self Link:           /apis/networking.istio.io/v1beta1/namespaces/book/virtualservices/bookinfo
  UID:                 893d9328-5c1d-44c4-8871-0daa361e5559                                      
Spec:                                                                                            
  Gateways:                                                                                      
    bookinfo-gateway                                                                             
  Hosts:                                                                                         
    *                                                                                            
  Http:                                                                                          
    Match:                                                                                       
      Uri:                                                                                       
        Exact:  /productpage                                                                     
      Uri:                                                                                       
        Prefix:  /static                                                                         
      Uri:                                                                                       
        Exact:  /login                                                                           
      Uri:                                                                                       
        Exact:  /logout                                                                          
      Uri:                                                                                       
        Prefix:  /api/v1/products                                                                
    Route:                                                                                       
      Destination:                                                                               
        Host:  productpage                                                                       
        Port:                                                                                    
          Number:  9080                                                                          
Events:            <none>                                                                                                                                                                                                     

路由规则:所有从Hosts:*过来的流量,匹配Uri条件,路由到Destination,即集群productpage:9080

Envoy HTTP 路由的特点:

  • 前缀和精确路径匹配规则。
  • 可跨越多个上游集群进行基于权重/百分比的路由。
  • 基于优先级的路由。
  • 基于哈希策略的路由。

检查Envoy路由信息:

$ istioctl proxy-config routes istio-ingressgateway-75877dc5bf-zfqlw -n istio-system -o json
[
    {
        "name": "http.80",
        "virtualHosts": [
            {
                "name": "*:80",
                "domains": [
                    "*",
                    "*:80"
                ],
                "routes": [
                    {
                        "match": {
                            "path": "/productpage",
                            "caseSensitive": true
                        },
                        "route": {
                            "cluster": "outbound|9080||productpage.book.svc.cluster.local",
                            "timeout": "0s",
                            "retryPolicy": {
                                "retryOn": "connect-failure,refused-stream,unavailable,cancelled,resource-exhausted,retriable-status-codes",
                                "numRetries": 2,
                                "retryHostPredicate": [
                                    {
                                        "name": "envoy.retry_host_predicates.previous_hosts"
                                    }
                                ],
                                "hostSelectionRetryMaxAttempts": "5",
                                "retriableStatusCodes": [
                                    503
                                ]
                            },
                            "maxGrpcTimeout": "0s"
                        },
......
  • name:该名字跟 envoy.http_connection_manager filter 中的 http_filters.rds.route_config_name 一致
  • virtual_hosts:路由配置中的顶级元素,
    • name:该 VirtualHost 的名字,一般是 FQDN 加端口
    • domains:这是个用来匹配 VirtualHost 的域名列表,
    • routes:针对入口流量的有序路由列表,第一个匹配上的路由将被执行
      • match:路由匹配参数。例如 URL prefix(前缀)、path(URL 的完整路径)、regex(规则表达式)等
      • route:这里面配置路由的行为

匹配/productpage的请求,路由至cluster:outbound|9080||productpage.book.svc.cluster.local,外加上其他执行策略

Envoy Cluster 的特点:

  • 一组逻辑上相同的主机构成一个 cluster。
  • 可以在 cluster 中定义各种负载均衡策略。
  • 新加入的 cluster 需要一个热身的过程才可以给路由引用,该过程是原子的,即在 cluster 热身之前对于 Envoy 及 Service Mesh 的其余部分来说是不可见的。
  • 可以通过多种方式来配置 cluster,例如静态类型、严格限定 DNS、逻辑 DNS、EDS 等。

检查Envoy集群信息:

$ istioctl proxy-config clusters istio-ingressgateway-75877dc5bf-zfqlw -n istio-system -o json --fqdn productpage.book.svc.cluster.local
......
        "name": "outbound|9080||productpage.book.svc.cluster.local",
        "type": "EDS",
        "edsClusterConfig": {
            "edsConfig": {
                "ads": {}
            },
            "serviceName": "outbound|9080||productpage.book.svc.cluster.local"
        },
        "connectTimeout": "1s",
        "circuitBreakers": {
            "thresholds": [
                {
                    "maxConnections": 4294967295,
                    "maxPendingRequests": 4294967295,
                    "maxRequests": 4294967295,
                    "maxRetries": 4294967295
                }
            ]
        },
......
  • name:集群名字
  • type:即服务发现类型,支持的参数有 STATIC(缺省值)、STRICT_DNS、LOGICAL_DNS、EDS、ORIGINAL_DST
  • eds_cluster_config:如果使用 EDS 做服务发现,则需要配置该项目,其中包括的配置有 service_name 和 ads

路由至服务outbound|9080||productpage.book.svc.cluster.local

检查Envoy端点信息:

$ istioctl proxy-config endpoints istio-ingressgateway-75877dc5bf-zfqlw --cluster "outbound|9080||productpage.book.svc.cluster.local" -n istio-system -o json
[
    {
        "name": "outbound|9080||productpage.book.svc.cluster.local",
        "addedViaApi": true,
        "hostStatuses": [
            {
                "address": {
                    "socketAddress": {
                        "address": "10.1.0.152",
                        "portValue": 9080
                    }
                },

后端节点列表信息

$ kubectl get endpoints -n book
NAME          ENDPOINTS                                         AGE
details       10.1.0.147:9080                                   6h50m
productpage   10.1.0.152:9080                                   6h50m
ratings       10.1.0.148:9080                                   6h50m
reviews       10.1.0.149:9080,10.1.0.150:9080,10.1.0.151:9080   6h50m

最终路由至productpage服务

服务

流量进入productpage后,路径和前面过程类似,经过Listener、Router、Cluster、Endpoint,到达目的地Upstream

Bookinfo服务内部视图如下:

alt

参考: