Service Mesh Istio 从入门到放弃 (二) istio 流量管理

VirtualService && DestinationRule

VirtualService

官方解释如下

A VirtualService defines a set of traffic routing rules to apply when a host is addressed. Each routing rule defines matching criteria for traffic of a specific protocol. If the traffic is matched, then it is sent to a named destination service (or subset/version of it) defined in the registry.

大概意思是说,VirtualService 是一组用来对host 解析寻址的流量路由规则集合,每一个路由规则都为特定协议的流量请求定义了匹配条件,如果请求被某个规则匹配,这个请求就会被发送到指定的目的service,这个目的service也可能是一个标有version标签的服务子集

通常VirtualService 都会与DestinationRule 联合使用,DestinationRule用来规定一个service下的多个子集。
例如下面这个例子中,对于review服务,默认情况下所有http流量都会被路由到v1子集对应的pod服务上,那么v1
子集的定义就在DestinationRule这个资源对象中,它定义了v1子集是所有被打上version: v1 标签的pod,如果忘记了可以打开bookinfo.yaml看一下reviews-v1这个deployment的定义。
所有路由前缀匹配是/wpcatalog/ 或者 /consumercatalog/的请求都会被重写为/newcatalog 发送到子集是v2的pod服务上

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews-route
spec:
  hosts:
  - reviews.prod.svc.cluster.local
  http:
  - name: "reviews-v2-routes"
    match:
    - uri:
        prefix: "/wpcatalog"
    - uri:
        prefix: "/consumercatalog"
    rewrite:
      uri: "/newcatalog"
    route:
    - destination:
        host: reviews.prod.svc.cluster.local
        subset: v2
  - name: "reviews-v1-route"
    route:
    - destination:
        host: reviews.prod.svc.cluster.local
        subset: v1
---------
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews-destination
spec:
  host: reviews.prod.svc.cluster.local
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

VirtualService 动态路由实践

执行如下命令后,将访问reviews的请求全部路由到了v1子集,这样在界面刷新只能看到没有星的reviews服务的数据了

kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml

virtual-service-all-v1.yaml 中指定所有对reviews服务的访问都路由到v1子集

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1

destination-rule-all.yaml中定义了reviews服务中v1子集是那些打了version: v1 标签的pod

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3

VirtualService 权重路由实践

执行下面的配置,可以将reviews服务的v1和v3版本分别配置50%的权重,配置成功后,刷新页面可以看到reviews服务会在没有星和红星之间改变

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml

看一下配置,其中每个路由都有一个weight的选项用来控制权重比例

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 50
    - destination:
        host: reviews
        subset: v3
      weight: 50

Gateway

Gateway describes a load balancer operating at the edge of the mesh receiving incoming or outgoing HTTP/TCP connections. The specification describes a set of ports that should be exposed, the type of protocol to use, SNI configuration for the load balancer, etc.

引用官方定义,Gateway是个负载均衡器 作用于网格边缘,用来接收入口或者出口流量,它定义了一组对外暴露的端口的集合

官方的例子中,如下的网关配置了一个代理来充当负载均衡器,对外暴露了80 ,9080 (http), 443 (https), 9443(https) , port 2379 (TCP) 端口作为入口,它会作用于所有配置了app: my-gateway-controller标签的pod,这个代理会监控所有的请求上面这几个对外暴露端口的流量到内部的服务

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: my-gateway
  namespace: some-config-namespace
spec:
  selector:
    app: my-gateway-controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - uk.bookinfo.com
    - eu.bookinfo.com
    tls:
      httpsRedirect: true # sends 301 redirect for http requests
  - port:
      number: 443
      name: https-443
      protocol: HTTPS
    hosts:
    - uk.bookinfo.com
    - eu.bookinfo.com
    tls:
      mode: SIMPLE # enables HTTPS on this port
      serverCertificate: /etc/certs/servercert.pem
      privateKey: /etc/certs/privatekey.pem
  - port:
      number: 9443
      name: https-9443
      protocol: HTTPS
    hosts:
    - "bookinfo-namespace/*.bookinfo.com"
    tls:
      mode: SIMPLE # enables HTTPS on this port
      credentialName: bookinfo-secret # fetches certs from Kubernetes secret
  - port:
      number: 9080
      name: http-wildcard
      protocol: HTTP
    hosts:
    - "*"
  - port:
      number: 2379 # to expose internal service via external port 2379
      name: mongo
      protocol: MONGO
    hosts:
    - "*"

在demo应用中,也配置了网关来允许外部的请求
samples/bookinfo/networking/bookinfo-gateway.yaml

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway
  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

上面这个例子中,bookinfo-gateway这个网关绑定了配置了istio: ingressgateway标签的网关,这个网关是istio自带默认的网关,他其实也是个pod,在istio-system空间下,通过查看这个pod,可以看到这个pod配置了istio: ingressgateway的标签

root@kube1:~/istio/istio-1.5.1/samples/bookinfo/networking# kubectl describe po istio-ingressgateway-75877dc5bf-gdmsl -n istio-system
Name:           istio-ingressgateway-75877dc5bf-gdmsl
Namespace:      istio-system
Priority:       0
Node:           kube2/192.168.188.130
Start Time:     Thu, 03 Sep 2020 16:33:20 +0800
Labels:         app=istio-ingressgateway
                chart=gateways
                heritage=Tiller
                istio=ingressgateway
                pod-template-hash=75877dc5bf
                release=istio
                service.istio.io/canonical-name=istio-ingressgateway
                service.istio.io/canonical-revision=1.5
Annotations:    sidecar.istio.io/inject: false
Status:         Running
IP:             10.244.1.28
Controlled By:  ReplicaSet/istio-ingressgateway-75877dc5bf
Containers:
  istio-proxy:
    Container ID:  docker://4a0894b8de09d9f874ed90a988f23f4311d4f45f6f7877fce70c8f282582f950
    Image:         docker.io/istio/proxyv2:1.5.1
    Image ID:      docker-pullable://istio/proxyv2@sha256:3ad9ee2b43b299e5e6d97aaea5ed47dbf3da9293733607d9b52f358313e852ae
    Ports:         15020/TCP, 80/TCP, 443/TCP, 15029/TCP, 15030/TCP, 15031/TCP, 15032/TCP, 31400/TCP, 15443/TCP, 15011/TCP, 15012/TCP, 8060/TCP, 853/TCP, 15090/TCP
    Host Ports:    0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP, 0/TCP
    Args:
      proxy
      router
      --domain
      $(POD_NAMESPACE).svc.cluster.local
      --proxyLogLevel=warning
      --proxyComponentLogLevel=misc:error
      --log_output_level=default:info
      --drainDuration
      45s
      --parentShutdownDuration
      1m0s
      --connectTimeout
      10s
      --serviceCluster
      istio-ingressgateway
      --zipkinAddress
      zipkin.istio-system:9411
      --proxyAdminPort
      15000
      --statusPort
      15020
      --controlPlaneAuthPolicy
      NONE
      --discoveryAddress
      istio-pilot.istio-system.svc:15012
      --trust-domain=cluster.local
    State:          Running
      Started:      Thu, 03 Sep 2020 16:33:57 +0800
    Ready:          True
    Restart Count:  0
    Limits:
      cpu:     2
      memory:  1Gi
    Requests:
      cpu:      10m
      memory:   40Mi
    Readiness:  http-get http://:15020/healthz/ready delay=1s timeout=1s period=2s #success=1 #failure=30
    Environment:
      JWT_POLICY:                   first-party-jwt
      PILOT_CERT_PROVIDER:          istiod
      ISTIO_META_USER_SDS:          true
      CA_ADDR:                      istio-pilot.istio-system.svc:15012
      NODE_NAME:                     (v1:spec.nodeName)
      POD_NAME:                     istio-ingressgateway-75877dc5bf-gdmsl (v1:metadata.name)
      POD_NAMESPACE:                istio-system (v1:metadata.namespace)
      INSTANCE_IP:                   (v1:status.podIP)
      HOST_IP:                       (v1:status.hostIP)
      SERVICE_ACCOUNT:               (v1:spec.serviceAccountName)
      ISTIO_META_WORKLOAD_NAME:     istio-ingressgateway
      ISTIO_META_OWNER:             kubernetes://apis/apps/v1/namespaces/istio-system/deployments/istio-ingressgateway
      ISTIO_META_MESH_ID:           cluster.local
      ISTIO_AUTO_MTLS_ENABLED:      true
      ISTIO_META_POD_NAME:          istio-ingressgateway-75877dc5bf-gdmsl (v1:metadata.name)
      ISTIO_META_CONFIG_NAMESPACE:  istio-system (v1:metadata.namespace)
      ISTIO_META_ROUTER_MODE:       sni-dnat
      ISTIO_META_CLUSTER_ID:        Kubernetes
    Mounts:
      /etc/istio/ingressgateway-ca-certs from ingressgateway-ca-certs (ro)
      /etc/istio/ingressgateway-certs from ingressgateway-certs (ro)
      /etc/istio/pod from podinfo (rw)
      /var/run/ingress_gateway from ingressgatewaysdsudspath (rw)
      /var/run/secrets/istio from istiod-ca-cert (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from istio-ingressgateway-service-account-token-l6pbp (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  istiod-ca-cert:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      istio-ca-root-cert
    Optional:  false
  podinfo:
    Type:  DownwardAPI (a volume populated by information about the pod)
    Items:
      metadata.labels -> labels
      metadata.annotations -> annotations
  ingressgatewaysdsudspath:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:
    SizeLimit:  <unset>
  ingressgateway-certs:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  istio-ingressgateway-certs
    Optional:    true
  ingressgateway-ca-certs:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  istio-ingressgateway-ca-certs
    Optional:    true
  istio-ingressgateway-service-account-token-l6pbp:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  istio-ingressgateway-service-account-token-l6pbp
    Optional:    false
QoS Class:       Burstable
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:          <none>

我们也可以自己定义一个网关暴露另一个服务来验证它的功能,这个测试网关直接暴露了details服务的/details和/health接口,yaml如下

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway-test
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo-gateway-test
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway-test
  http:
  - match:
    - uri:
        exact: /details
    - uri:
        prefix: /health
    route:
    - destination:
        host: details
        port:
          number: 9080

执行之后就可以在浏览器访问这个接口了

Service Entry

服务入口可以把网格外部的服务纳入到网格内部统一管理,相当于把外部的服务进行抽象注册到网格内部,供内部的其他服务像调用内部服务一样调用这个外部服务,这样也就可以扩展我们的网格,对于一些访问外部的流量做一些控制,同样如果要对这个外部服务进行控制,也需要配置对应的virtual service

在demo应用用没有一个内部服务可以访问外部服务,为了模拟这个情况,需要启动demo中提供的sleep服务,它内部提供了一个curl服务,可以模拟对外部服务的访问,首先来创建这个服务

kubectl apply -f samples/sleep/sleep.yaml


root@kube1:~/istio/istio-1.5.1/samples/sleep# kubectl get po | grep sleep
sleep-6bdb595bcb-xktfl            2/2     Running   0          13m

由于istio默认是可以从内部访问外部的,所以直接执行下面这个命令是可以访问百度首页的

kubectl exec -it sleep-6bdb595bcb-xktfl -c sleep curl http://baidu.com
<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>

所以还需要关闭istio对外界的访问,需要修改istio的configmap配置文件把outboundTrafficPolicy的mode从ALLOW_ANY改为REGISTRY_ONLY

kubectl edit cm istio -n istio-system

修改以后需要等一会配置才能生效,这时再执行curl命令就不会有结果了

接着为外部服务创建service entry

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: sleep
spec:
  hosts:
  - baidu.com
  location: MESH_EXTERNAL
  ports:
  - number: 80
    name: http
    protocol: HTTP
  resolution: DNS

之后再执行curl就可以看到相应内容了

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值