一、背景
随着单片应用程序向分布式微服务架构过渡 ,特别是服务之间呈现拓扑状的复杂关系,service mesh的提出就是为了简化管理微服务之间的通信问题。为了实现微服务 Service Mesh 模式和诸多理念,Google , IBM 和 Lyft 这三家公司协同研发,并于 2017 年 6 月 8 日( 根据 Github 最后一次提交的时间 )发布了 Istio 的第一个发行版——Istio 0.1 版本。
二、istio架构
istio分为控制面和数据面,架构如下图所示。
 -c sleep -n ${from} -- curl "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
sleep.foo to httpbin.foo: 503
sleep.foo to httpbin.bar: 503
sleep.bar to httpbin.foo: 503
sleep.bar to httpbin.bar: 503
创建 destination rules使能TLS,目标是所有的集群内部的服务,然后服务之间就可以正常的访问了,使能TLS的操作如下:
kubectl apply -f - <<EOF
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "default"
namespace: "istio-system"
spec:
host: "*.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
EOF
根据destination rules,访问所有集群内部服务都会带上TLS证书进行访问,使能TLS的访问结果:
for from in "foo" "bar"; do for to in "foo" "bar"; do kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl "http://httpbin.${to}:8000/ip" -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done
sleep.foo to httpbin.foo: 200
sleep.foo to httpbin.bar: 200
sleep.bar to httpbin.foo: 200
sleep.bar to httpbin.bar: 200
除了全局指定tls,也可以单独指定namespace使能TLS,操作如下:
kubectl apply -f - <<EOF
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "default"
namespace: "foo"
spec:
peers:
- mtls: {}
EOF
kubectl apply -f - <<EOF
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "default"
namespace: "foo"
spec:
host: "*.foo.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
EOF
指定特定service tls,操作如下:
cat <<EOF | kubectl apply -n bar -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "httpbin"
spec:
targets:
- name: httpbin
peers:
- mtls: {}
EOF
cat <<EOF | kubectl apply -n bar -f -
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "httpbin"
spec:
host: "httpbin.bar.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
EOF
3、策略
这里还是以官方的bookinfo为例,指定应用拒绝访问。
首先修改istio configmap修改disablePolicyChecks为false,使能policy;然后制定策略拒绝v3版本的访问版本,匹配源为reviews v3和目的ratings制定rule对应handler为拒绝访问,yaml如下:
apiVersion: "config.istio.io/v1alpha2"
kind: handler
metadata:
name: denyreviewsv3handler
spec:
compiledAdapter: denier
params:
status:
code: 7
message: Not allowed
---
apiVersion: "config.istio.io/v1alpha2"
kind: instance
metadata:
name: denyreviewsv3request
spec:
compiledTemplate: checknothing
---
apiVersion: "config.istio.io/v1alpha2"
kind: rule
metadata:
name: denyreviewsv3
spec:
match: destination.labels["app"] == "ratings" && source.labels["app"]=="reviews" && source.labels["version"] == "v3"
actions:
- handler: denyreviewsv3handler
instances: [ denyreviewsv3request ]
4、可观察性
Istio为网格内的所有服务通信生成详细的telemetry信息。此telemetry提供服务行为的可观察性,使运维人员能够对应用程序进行故障排除、维护和优化, 具体通过三个方面表现,第一个是metrics即指标,Istio根据监控的四个维度(延迟、流量、错误和饱和度)生成一组服务指标,暴露给proetheus。第二个是访问日志,当流量流入网格内的服务时,Istio可以生成每个请求的完整记录,包括源和目标元数据。此信息使操作员能够审核服务行为,直至各个工作负载实例级别。 第三个是分布式跟踪, Istio提供了一种通过监视流经网格的各个请求来监视和了解行为的方法,了解服务网状网内的服务依赖关系和延迟来源。
以bookinfo为例,配置istio自动收集服务指标,每次调用网格内的服务,都会有相应的指标生成。
配置收集metrics的yaml文件如下:
# Configuration for metric instances
apiVersion: config.istio.io/v1alpha2
kind: instance
metadata:
name: doublerequestcount
namespace: istio-system
spec:
compiledTemplate: metric
params:
value: "2" # count each request twice
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"'
---
# Configuration for a Prometheus handler
apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
name: doublehandler
namespace: istio-system
spec:
compiledAdapter: prometheus
params:
metrics:
- name: double_request_count # Prometheus metric name
instance_name: doublerequestcount.instance.istio-system # Mixer instance name (fully-qualified)
kind: COUNTER
label_names:
- reporter
- source
- destination
- message
---
# Rule to send metric instances to a Prometheus handler
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
name: doubleprom
namespace: istio-system
spec:
actions:
- handler: doublehandler
instances: [ doublerequestcount ]
在prometheus graph界面搜索istio_double_request_count,结果如下:
日志功能,使用资源instance,handler,rule创建,具体内容如下:
# Configuration for logentry instances
apiVersion: config.istio.io/v1alpha2
kind: instance
metadata:
name: newlog
namespace: istio-system
spec:
compiledTemplate: logentry
params:
severity: '"warning"'
timestamp: request.time
variables:
source: source.labels["app"] | source.workload.name | "unknown"
user: source.user | "unknown"
destination: destination.labels["app"] | destination.workload.name | "unknown"
responseCode: response.code | 0
responseSize: response.size | 0
latency: response.duration | "0ms"
monitored_resource_type: '"UNSPECIFIED"'
---
# Configuration for a stdio handler
apiVersion: config.istio.io/v1alpha2
kind: handler
metadata:
name: newloghandler
namespace: istio-system
spec:
compiledAdapter: stdio
params:
severity_levels:
warning: 1 # Params.Level.WARNING
outputAsJson: true
---
# Rule to send logentry instances to a stdio handler
apiVersion: config.istio.io/v1alpha2
kind: rule
metadata:
name: newlogstdio
namespace: istio-system
spec:
match: "true" # match for all requests
actions:
- handler: newloghandler
instances:
- newlog
访问productpage,可以看到有对应的日志生成,操作如下:
kubectl logs -n istio-system -l istio-mixer-type=telemetry -c mixer | grep "newlog" | grep -v '"destination":"telemetry"' | grep -v '"destination":"pilot"' | grep -v '"destination":"policy"' | grep -v '"destination":"unknown"'
{"level":"warn","time":"2019-12-16T16:45:53.950607Z","instance":"newlog.instance.istio-system","destination":"ratings","latency":"1.494269ms","responseCode":200,"responseSize":48,"source":"reviews","user":"unknown"}
分布式跟踪,使用jaeger进行trace, 默认采样率为1%。至少需要发送100个请求,才能看到一个跟踪,访问productpage操作:
for i in `seq 1 100`; do curl -s -o /dev/null http://$GATEWAY_URL/productpage; done
可以在jaeger dashboard看到对应跟踪信息,如下图:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。