理解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
根据Istio网络原理,探究Bookinfo示例
外部入口Service
Bookinfo默认提供了bookinfo-gateway
Istio Gateway指定了Ingress需要监听的端口
外部流量需要通过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
入口网关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监听端口
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服务内部视图如下:
参考: