一、Istio 使用 Apache SkyWalking 链路追踪和告警
SkyWalking
是一个开源的观测平台,用于从服务和云原生等基础设施中收集、分析、聚合以及可视化数据,SkyWalking
提供了一种简便的方式来清晰地观测分布式系统,甚至可以观测横跨不同云的系统,SkyWalking
更像是一种现代的应用程序性能监控(Application Performance Monitoring
,即APM
)工具,专为云原生,基于容器以及分布式系统而设计。
此外,SkyWalking
还提供了链路监控告警功能,允许用户在服务性能指标异常时及时得到通知。用户可以定义多种告警规则,如服务响应时间、成功率等指标的阈值,当指标超过阈值时触发告警。系统还会记录所有告警的历史信息,便于用户回顾和分析系统的稳定性问题。
Istio
针对链路追踪本身就支持多种方式,包括 Zipkin、Jaeger
和 SkyWalking
,默认支持 Zipkin
格式的追踪数据,本篇文章实验 Istio
使用 SkyWalking
进行服务链路追踪和监控告警,其中告警本次采用钉钉机器人,所以在开启前请准备好一个钉钉机器人,机器人的安全验证模式,这里我采用的加签模式:
二、K8s 部署 Apache SkyWalking
这里将 SkyWalking
的数据存储至 ES
中,需要有一个可用的 ES
服务,如果没有可以参考下面文章在 K8s
中部署一个:
K8s 部署 elasticsearch-7.14.0 集群 及 kibana 客户端
编写 skywalking.yml
清单,注意其中 ES
和钉钉机器人的信息换成你的环境下的:
vi skywalking.yml
kind: ConfigMap
apiVersion: v1
metadata:
name: alarm-settings
namespace: istio-system
data:
alarm-settings.yml: |-
rules:
# Rule unique name, must be ended with `_rule`.
service_resp_time_rule: ## 服务的平均响应时间超过1000毫秒时,如果在过去10分钟内发生3次,就会触发告警。
metrics-name: service_resp_time
op: ">"
threshold: 1000
period: 10
count: 3
silence-period: 5
message: Response time of service {name} is more than 1000ms in 3 minutes of last 10 minutes.
service_sla_rule: ## 服务的成功响应率低于80%(即8000/10000)时,如果在过去10分钟内发生2次,就会触发告警。
# Metrics value need to be long, double or int
metrics-name: service_sla
op: "<"
threshold: 8000
# The length of time to evaluate the metrics
period: 10
# How many times after the metrics match the condition, will trigger alarm
count: 2
# How many times of checks, the alarm keeps silence after alarm triggered, default as same as period.
silence-period: 3
message: Successful rate of service {name} is lower than 80% in 2 minutes of last 10 minutes
service_resp_time_percentile_rule: ## 服务的响应时间百分位数(p50, p75, p90, p95, p99)中的任何一个超过1000毫秒时,如果在过去10分钟内发生3次,就会触发告警。
# Metrics value need to be long, double or int
metrics-name: service_percentile
op: ">"
threshold: 1000,1000,1000,1000,1000
period: 10
count: 3
silence-period: 5
message: Percentile response time of service {name} alarm in 3 minutes of last 10 minutes, due to more than one condition of p50 > 1000, p75 > 1000, p90 > 1000, p95 > 1000, p99 > 1000
service_instance_resp_time_rule: ## 服务实例的平均响应时间
metrics-name: service_instance_resp_time
op: ">"
threshold: 1000
period: 10
count: 2
silence-period: 5
message: Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes
database_access_resp_time_rule: ## 数据库访问的平均响应时间
metrics-name: database_access_resp_time
threshold: 1000
op: ">"
period: 10
count: 2
message: Response time of database access {name} is more than 1000ms in 2 minutes of last 10 minutes
endpoint_relation_resp_time_rule: ## 端点关系的平均响应时间
metrics-name: endpoint_relation_resp_time
threshold: 1000
op: ">"
period: 10
count: 2
message: Response time of endpoint relation {name} is more than 1000ms in 2 minutes of last 10 minutes
# Active endpoint related metrics alarm will cost more memory than service and service instance metrics alarm.
# Because the number of endpoint is much more than service and instance.
#
# endpoint_resp_time_rule:
# metrics-name: endpoint_resp_time
# op: ">"
# threshold: 1000
# period: 10
# count: 2
# silence-period: 5
# message: Response time of endpoint {name} is more than 1000ms in 2 minutes of last 10 minutes
dingtalkHooks:
textTemplate: |-
{
"msgtype": "text",
"text": {
"content": "Apache SkyWalking Alarm: \n %s."
}
}
webhooks:
- url: https://oapi.dingtalk.com/robot/send?access_token=你的机器人token
secret: 你的Secret
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: skywalking-oap
namespace: istio-system
labels:
app: skywalking-oap
spec:
selector:
matchLabels:
app: skywalking-oap
template:
metadata:
labels:
app: skywalking-oap
sidecar.istio.io/inject: "false"
spec:
containers:
- name: skywalking-oap
image: apache/skywalking-oap-server:9.1.0
env:
- name: SW_HEALTH_CHECKER
value: default
- name: SW_STORAGE
value: elasticsearch
- name: SW_STORAGE_ES_CLUSTER_NODES
value: es.default.svc.cluster.local:9200
- name: SW_ES_USER
value: esuser
- name: SW_ES_PASSWORD
value: espassword
volumeMounts:
- name: alarm-settings
mountPath: /skywalking/config/alarm-settings.yml
subPath: alarm-settings.yml
readinessProbe:
exec:
command:
- /skywalking/bin/swctl
- health
initialDelaySeconds: 30
periodSeconds: 5
volumes:
- name: alarm-settings
configMap:
name: alarm-settings
---
apiVersion: v1
kind: Service
metadata:
name: tracing
namespace: istio-system
labels:
app: skywalking-oap
spec:
type: ClusterIP
ports:
- name: grpc
port: 11800
protocol: TCP
targetPort: 11800
- name: http-query
port: 12800
protocol: TCP
targetPort: 12800
selector:
app: skywalking-oap
---
apiVersion: v1
kind: Service
metadata:
labels:
name: skywalking-oap
name: skywalking-oap
namespace: istio-system
spec:
ports:
- port: 11800
targetPort: 11800
name: grpc
- port: 12800
targetPort: 12800
name: http-query
selector:
app: skywalking-oap
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: skywalking-ui
namespace: istio-system
labels:
app: skywalking-ui
spec:
selector:
matchLabels:
app: skywalking-ui
template:
metadata:
labels:
app: skywalking-ui
annotations:
sidecar.istio.io/inject: "false"
spec:
containers:
- name: skywalking-ui
image: apache/skywalking-ui:9.1.0
env:
- name: SW_OAP_ADDRESS
value: http://skywalking-oap:12800
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 30
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: tracing-ui
namespace: istio-system
labels:
app: skywalking-ui
spec:
type: ClusterIP
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: skywalking-ui
---
apiVersion: v1
kind: Service
metadata:
labels:
name: skywalking-ui
name: skywalking-ui
namespace: istio-system
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
name: http
selector:
app: skywalking-ui
其中告警规则字段的解释如下:
metrics-name:监控的指标名称。
op:比较操作符(例如 > 表示大于)。
threshold:触发告警的阈值。
period:评估指标的周期(分钟)。
count:在周期内满足条件的最小次数,以触发告警。
silence-period:告警触发后的静默期(分钟)。
message:告警消息,其中 {name} 将被替换为实际的服务名、实例名或端点名。
提交:
kubectl apply -f skywalking.yml
查看 pod
:
kubectl get pods -n istio-system
查看 skywalking-ui
的 NodePort
端口:
kubectl get svc -n istio-system
浏览器访问:http://{node ip}:32327
:
三、Istio 配置向 SkyWalking 发送链路追踪
Istio
代理默认不向 SkyWalking
发送链路追踪,需要修改 Istio
配置文件,在 k8s
中是以 ConfigMap
的方式存储的:
kubectl get cm -n istio-system
修改 istio
:
kubectl edit cm istio -n istio-system
在 defaultProviders
下增加 :
defaultProviders:
metrics:
- prometheus
tracing:
- "skywalking"
extensionProviders
下 skywalking
的地址指向上面部署的服务:
extensionProviders:
- name: skywalking
skywalking:
port: 11800
service: tracing.istio-system.svc.cluster.local
整体配置如下:
保存后自动生效。
四、链路追踪测试
这里部署 istio
官方使用的 Bookinfo
示例应用,测试链路追踪,该应用的结构如下:
创建一个命名空间,将Bookinfo
服务放在该空间下:
kubectl create ns test
给该命名空间添加标签,指示在部署应用的时候,自动注入 Envoy
边车代理:
kubectl label namespace test istio-injection=enabled
部署 Bookinfo
示例应用:
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.21/samples/bookinfo/platform/kube/bookinfo.yaml -n test
查看 pod
:
kubectl get pods -n test
部署 Bookinfo
应用的 Gateway
和 VirtualService
,允许外部访问:
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.21/samples/bookinfo/networking/bookinfo-gateway.yaml -n test
查看 istio-ingressgateway
入口的 NodePort
端口:
kubectl get svc istio-ingressgateway -n istio-system
80
端口对应的是 30868
,然后使用浏览器访问 http://{node port}:30868/productpage
,可以打开 Bookinfo
的示例页面:
然后多刷新访问几次后,去 SkyWalking
中查看,可以看到服务信息已经记录上来了:
点击 Topology
可以看到服务链路模型
点击 Trace
可以看到详细追踪信息:
五、链路监控告警测试
修改 Bookinfo
应用 review
的访问规则,使用 VirtualService
注入随机故障:
vi reviews-vs.yml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews-dr
namespace: test
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-vs
namespace: test
spec:
hosts:
- "reviews"
http:
- route:
- destination:
host: reviews
port:
number: 9080
subset: v1
weight: 30
- destination:
host: reviews
port:
number: 9080
subset: v2
weight: 30
- destination:
host: reviews
port:
number: 9080
subset: v3
weight: 40
fault:
delay:
percentage:
value: 20
fixedDelay: 5s
abort:
percentage:
value: 80
httpStatus: 500
这里随机注入了 20%
的请求产生 5
秒的延时,80%
的请求直接中止返回 500
状态码。
下面在浏览器多次访问 http://{node port}:30868/productpage
,等待片刻后观察 SkyWalking
中的告警信息:
已经出现告警了,此时钉钉机器人应该也收到了告警信息: