前言

Istio已经18年中推出1.0 正式版本,并表示已可用于生产环境。

目前我们对网络计费计量有需求,而服务网格能实现网络指标收集、限流、访问控制和端到端认证、故障恢复和监控以及通常更加复杂的运维需求。

对于开发来说,只需要进行http服务(支持tcp/udp)调用(与使用原来的服务发现模式一样),中间的连接、控制、限流、认证全部交由Istio完成。

服务的实现

基于Istio微服务开发服务间的调用_服务器

简单来说,Istio会在我们部署的每一个服务(Service),以sidecar的方式都被注入1个Proxy, 所有流量经过这个高性能的proxy继续转发,以Control Plane (控制面)进行规则的定义、控制、遥测。

基本功能展示

流量控制(灰度发布)

基于Istio微服务开发服务间的调用_运维_02

路由转发

基于Istio微服务开发服务间的调用_负载均衡_03

指标监控、负载均衡、故障注入、处理等等

基于Istio微服务开发服务间的调用_服务器_04

Kubernetes Istio的部署

对于官方文档提供的多种部署方式,由于我们的集群已经部署了helm和titler服务端,所以部署相当的简单

下载

istio 1.2.2 已经验证对kubernetes1.12, 1.13, 1.14支持

wget https://github.com/istio/istio/releases/download/1.2.2/istio-1.2.2-linux.tar.gz

部署

解压使用helm安装

tar -xvf istio-1.2.2-linux.tar.gz
cd istio-1.2.2/
kubectl create namespace istio-system
helm install install/kubernetes/helm/istio-init --name istio-init --namespace istio-system

等待crd(自定义控制器)的配置完成

helm status istio-init

基于Istio微服务开发服务间的调用_服务器_05

当所有pod 和job都complete之后,部署istio

helm install install/kubernetes/helm/istio --name istio --namespace istio-system

基于Istio微服务开发服务间的调用_运维_06

部署服务时引入Istio

以后部署服务的时候,我们只要在命名空间设置label , istio-injection=enabled:

kubectl label namespaces <namespace> istio-injection=enabled

或者手动注入

kubectl apply -f <(istioctl kube-inject -f xxx.yaml)

即可完成Istio 的引入,推荐第一种方式,第二种方式需要下载istio的ctl工具支持;

Demo应用

先得说Istio的4个控制概念

  • 1. VirtualService,用于配置实现请求路由的功能 (路由)
  • 2. DestinationRule ,实现服务发现和负载均衡、故障处理和故障注入的功能 (策略)
  • 3. ServiceEntry ,让服务网格内的服务,可以看到外面的世界 (出口控制)
  • 4. Gateway ,让服务网格的服务,可以被全世界看到 (入口控制)
     

因为官方demo提供了3个明显标识的应用(页面),可以让我们快速看到流量的变化,先使用官方的应用进行测试;
后续使用我们自己的应用进行部署;
bookinfo DEMO应用

kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml  -n istioinj

根据上述概念,我们部署一个gateway 对这个bookinfo集群进行访问

kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

基于Istio微服务开发服务间的调用_负载均衡_07

查询istio的gateway代理的地址是80 -> 31380, 443 -> 31390

# kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)                                                                                                                                      AGE
istio-ingressgateway   LoadBalancer   10.43.4.72   <pending>     15020:31818/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:31912/TCP,15030:30074/TCP,15031:30408/TCP,15032:30763/TCP,15443:31776/TCP

浏览器进行访问 http://192.168.108.3:31380/productpage 

基于Istio微服务开发服务间的调用_负载均衡_08

该集群有3个后端页面,多次访问url会因为轮询的规则,页面发生变化。通过

基于Istio微服务开发服务间的调用_linux_09

星的颜色和数量进行区分 ↓

基于Istio微服务开发服务间的调用_负载均衡_10

访问策略

设置默认的DestinationRule 策略

kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml -n istioinj
destination-ruel.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: productpage
spec:
  host: productpage
  subsets:
  - name: v1
    labels:
      version: v1
---
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 对流量进行转发

kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v1.yaml -n istioinj
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml -n istioinj

策略v1

实现了所有流量只访问1页面v1:

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

v1实现了所有流量只访问1页面:

基于Istio微服务开发服务间的调用_linux_11

策略v2

使用jason用户登录,流量全部走2页面v2

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v1

使用jason用户登录,全部走2页面

基于Istio微服务开发服务间的调用_负载均衡_12

流量控制

可以看到流量的路由配置比较简单,Istio会对符合规则的流量进行转发。
同时,在此基础上添加百分百,即可对流量进行控制:

策略v3

分流50%流量到 v3页面

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

virtual-service-reviews-50-v3.yaml 

# cat samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml
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

 

可视化与遥测

需要启用KIALI工具,创建secret

KIALI_USERNAME=$(echo -n 'admin' | base64)
KIALI_PASSPHRASE=$(echo -n 'mysecret' | base64)
NAMESPACE=istio-system
$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: kiali
  namespace: $NAMESPACE
  labels:
    app: kiali
type: Opaque
data:
  username: $KIALI_USERNAME
  passphrase: $KIALI_PASSPHRASE
EOF

启用,使用helm upgrade

helm upgrade \
--set grafana.enabled=true \
--set kiali.enabled=true \
--set tracing.enabled=true \
--set "kiali.dashboard.jaegerURL=http://$(kubectl get svc tracing --namespace istio-system -o jsonpath='{.spec.clusterIP}'):80" \
--set "kiali.dashboard.grafanaURL=http://$(kubectl get svc grafana --namespace istio-system -o jsonpath='{.spec.clusterIP}'):3000" \
istio  install/kubernetes/helm/istio  --namespace istio-system

在设置了kiali的nodeport访问后,

基于Istio微服务开发服务间的调用_linux_13

上述配置的帐号和密码(admin/mysecret)

实现我们的网络可视化:

Kiali

http://192.168.108.3:31379

无virtualservices策略:

基于Istio微服务开发服务间的调用_基于Istio微服务开发服务间的调用_14

virtual-service-reviews-50-v3策略:

基于Istio微服务开发服务间的调用_运维_15

同时我们启动了grafana、jaeger trace插件

Jaeger 

http://192.168.108.3:30340

对于上面的请求流程,jaeger细化到每个请求全程跟踪,包括请求、param、延时等等,极其方便研发对性能及请求status的分析

基于Istio微服务开发服务间的调用_linux_16

Grafana

在grafana http://192.168.108.3:30578/ 中,

我们可以很熟悉的查看我们每一个页面:

workload:

基于Istio微服务开发服务间的调用_运维_17

或者是整个集群的一个监控状态,Istio Performance:

基于Istio微服务开发服务间的调用_运维_18

指标度量

指标采集逻辑:

  • 1. 从 Istio 属性中生成 这里是指标值以及日志
  • 2.创建 handler(配置 Mixer 适配器),用来处理生成的日志

3. 根据一系列的 rule,把 日志(instance)传递给 handler

# 指标 instance 的配置
apiVersion: "config.istio.io/v1alpha2"
kind: metric
metadata:
  name: doublerequestcount
  namespace: istio-system
spec:
  value: "2" # 每个请求计数两次
  dimensions:
    reporter: conditional((context.reporter.kind | "inbound") == "outbound", "client", "server")
    source: source.workload.name | "unknown"
    destination: destination.workload.name | "unknown"
    message: '"twice the fun!"'
  monitored_resource_type: '"UNSPECIFIED"'
---
# prometheus handler 的配置
apiVersion: "config.istio.io/v1alpha2"
kind: prometheus
metadata:
  name: doublehandler
  namespace: istio-system
spec:
  metrics:
  - name: double_request_count # Prometheus 指标名称
    instance_name: doublerequestcount.metric.istio-system # Mixer Instance 名称(全限定名称)
    kind: COUNTER
    label_names:
    - reporter
    - source
    - destination
    - message
---
# 将指标 Instance 发送给 prometheus handler 的 rule 对象
apiVersion: "config.istio.io/v1alpha2"
kind: rule
metadata:
  name: doubleprom
  namespace: istio-system
spec:
  actions:
  - handler: doublehandler.prometheus
    instances:
    - doublerequestcount.metric

注意:若暂无法进行指标收集,由于目前 Istio 1.2.2版本官方文档与英文文档是冲突的,

基于Istio微服务开发服务间的调用_负载均衡_19

基于Istio微服务开发服务间的调用_linux_20

该配置也是缺失CRDS的:

基于Istio微服务开发服务间的调用_基于Istio微服务开发服务间的调用_21

查找各类文档目前无法解决该crd缺失问题,建议Istio使用旧版 1.1.15。1.2.2指标度量收集目前无法进行;