王先森2024-01-222024-01-22
Skywalking 是一个国产的开源框架,2015年有吴晟个人开源,2017年加入Apache孵化器,国人开源的产品,主要开发人员来自于华为,2019年4月17日Apache董事会批准SkyWalking成为顶级项目,支持Java、.Net、NodeJs等探针,数据存储支持Mysql、Elasticsearch等,跟Pinpoint一样采用字节码注入的方式实现代码的无侵入,探针采集数据粒度粗,但性能表现优秀,且对云原生支持,目前增长势头强劲,社区活跃。 Skywalking是分布式系统的应用程序性能监视工具,专为微服务,云原生架构和基于容器(Docker,K8S,Mesos)架构而设计,它是一款优秀的APM(Application Performance Management)工具,包括了分布式追踪,性能指标分析和服务依赖分析等。
微服务架构已经是一个很通用的系统架构,常见的技术栈如下图所示,这张架构图基本涵括了当前微服务体系下的各种技术栈,可能不同的技术栈有不同的开源实现。
目前市面上开源的APM系统主要有CAT、Zipkin、Pinpoint、SkyWalking,大都是参考Google的Dapper实现的
Pinpoint | Zipkin | Cat | Skywalking | |
---|---|---|---|---|
OpenTracing兼容 | 否 | 是 | 是 | 是 |
客户端支持语言 | java、php | java,c#,go,php等 | java,.net | Java, .NET Core, NodeJS and PHP |
存储 | hbase | ES,MySQL,Cassandra,内存 | MySQL、本地文件/HDFS | ES,H2,MySQL,TIDB,sharding sphere |
传输协议支持 | thrift | http、MQ | udp/http | gRPC |
ui丰富程度 | 高 | 低 | 中 | 中 |
实现方式-代码侵入性 | 字节码注入,无侵入 | 拦截请求,侵入 | 侵入 | 字节码注入,无侵入 |
扩展性 | 低 | 高 | 高 | 中 |
trace查询 | 不支持 | 支持 | 支持 | 支持 |
告警支持 | 支持 | 不支持 | 支持 | 支持 |
jvm监控 | 支持 | 不支持 | 支持 | 支持 |
性能损失 | 高 | 中 | 中 | 低 |
模拟了三种并发用户,500,750,1000,使用JMeter测试,每个线程发送30个请求,设置间隔时间为10ms,使用采用频率为1,即100%。下面是性能测试报告:
从上表可以看出,在三种链路监控组件中,
SkyWalking 逻辑上分为四部分: 探针, 平台后端, 存储和用户界面。
Skywalking OAP Server
会将数据存储到 Elasticsearch 中,并通过 Elasticsearch 进行数据查询和分析。Elasticsearch 安装请参考 使用ELK实现日志监控和分析。
# vim job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: "skywalking-es-init"
namespace: skywalking
labels:
app: skywalking-job
spec:
template:
metadata:
name: "skywalking-es-init"
labels:
app: skywalking-job
spec:
nodeName: k8s-node2
serviceAccountName: skywalking-oap
restartPolicy: Never
initContainers:
- name: wait-for-elasticsearch
image: busybox:1.30
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'for i in $(seq 1 60); do nc -z -w3 elasticsearch-es-logging.logging.svc 9200 && exit 0 || sleep 5; done; exit 1']
containers:
- name: oap
image: skywalking.docker.scarf.sh/apache/skywalking-oap-server:9.7.0
imagePullPolicy: IfNotPresent
env:
- name: JAVA_OPTS
value: "-Dmode=init -Xmx2g -Xms2g"
- name: SW_ENABLE_UPDATE_UI_TEMPLATE
value: "true"
- name: SW_CLUSTER
value: kubernetes
- name: SW_CLUSTER_K8S_NAMESPACE
value: "skywalking"
- name: SW_CLUSTER_K8S_LABEL
value: "app=oap"
- name: SKYWALKING_COLLECTOR_UID
valueFrom:
fieldRef:
fieldPath: metadata.uid
- name: SW_STORAGE
value: elasticsearch
- name: SW_STORAGE_ES_CLUSTER_NODES
value: "elastic.od.com" # 指定es地址,由于在k8s内部访问需要通过https协议,这里就指定外部地址,需要pods可以解析此地址。
- name: SW_ES_USER # 指定es用户
value: "elastic"
- name: SW_ES_PASSWORD # 指定es密码
value: "admin123"
- name: SW_OTEL_RECEIVER
value: "default"
- name: SW_TELEMETRY
value: "prometheus"
RBACDeploymentService
# vim rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app: skywalking
name: skywalking-oap
namespace: skywalking
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: skywalking
namespace: skywalking
labels:
app: skywalking
rules:
- apiGroups: [""]
resources: ["pods", "endpoints", "services", "nodes"]
verbs: ["get", "watch", "list"]
- apiGroups: ["extensions"]
resources: ["deployments", "replicasets"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: skywalking
namespace: skywalking
labels:
app: skywalking
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: skywalking
subjects:
- kind: ServiceAccount
name: skywalking-oap
namespace: skywalking
# vim dp.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: oap
name: oap
namespace: skywalking
spec:
replicas: 1
selector:
matchLabels:
app: oap
template:
metadata:
labels:
app: oap
spec:
serviceAccountName: skywalking-oap
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: app1
operator: In
values:
- skywalking
initContainers:
- name: wait-for-elasticsearch
image: busybox:1.30
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'for i in $(seq 1 60); do nc -z -w3 elasticsearch-es-http.logging.svc 9200 && exit 0 || sleep 5; done; exit 1']
containers:
- name: oap
image: skywalking.docker.scarf.sh/apache/skywalking-oap-server:9.7.0
imagePullPolicy: IfNotPresent
livenessProbe:
tcpSocket:
port: 12800
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
tcpSocket:
port: 12800
initialDelaySeconds: 15
periodSeconds: 20
ports:
- containerPort: 11800
name: grpc
- containerPort: 1234
name: prometheus-port
- containerPort: 12800
name: rest
env:
- name: JAVA_OPTS
value: "-Dmode=no-init -Xmx2g -Xms2g"
- name: TZ # 设置时区
value: Asia/Shanghai
- name: SW_OTEL_RECEIVER
value: "default"
- name: SW_ENABLE_UPDATE_UI_TEMPLATE # 开启试图可编辑,默认为:false
value: "true"
- name: SW_CLUSTER
value: kubernetes
- name: SW_CLUSTER_K8S_NAMESPACE
value: "skywalking"
- name: SW_CLUSTER_K8S_LABEL
value: "app=oap"
- name: SKYWALKING_COLLECTOR_UID
valueFrom:
fieldRef:
fieldPath: metadata.uid
- name: SW_STORAGE # 使用es作为存储
value: elasticsearch
- name: SW_STORAGE_ES_CLUSTER_NODES # es地址
value: "elastic.od.com"
- name: SW_ES_USER # es用户
value: "elastic"
- name: SW_ES_PASSWORD # es密码
value: "admin123"
- name: SW_TELEMETRY
value: "prometheus"
vim svc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: oap-svc
namespace: skywalking
labels:
app: oap
spec:
type: ClusterIP
ports:
- port: 11800
name: grpc
- port: 1234
name: prometheus-port
- port: 12800
name: rest
selector:
app: oap
kubectl apply -f rbac.yaml
kubectl apply -f dp.yaml
kubectl apply -f svc.yaml
DeploymentServiceIngress
# vim ui-dp.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ui
namespace: skywalking
labels:
app: ui
spec:
replicas: 1
selector:
matchLabels:
app: ui
template:
metadata:
labels:
app: ui
spec:
affinity:
containers:
- name: ui
image: skywalking.docker.scarf.sh/apache/skywalking-ui:9.7.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: page
env:
- name: SW_OAP_ADDRESS
value: http://oap-svc:12800 # 根据oap的svc一致
# vim ui-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
labels:
app: ui
name: ui-svc
namespace: skywalking
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 8080
protocol: TCP
selector:
app: ui
# vim ing.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: skywalking-web
namespace: skywalking
spec:
entryPoints:
- web
routes:
- match: Host(`skywalking.od.com`)
kind: Rule
services:
- name: ui-svc
port: 80
kubectl apply -f ui-dp.yaml
kubectl apply -f ui-svc.yaml
kubectl apply -f ing.yaml
通过浏览器访问 http://skywalking.od.com,Skywalking 默认没有任何监控指标的。
skywalking
的ui
界面默认没有访问控制,可以通过下面基于Traefik
的basicAuth
方案,实现自定义服务的外部验证。
安装 htpasswd 工具生成密码文件
yum -y install httpd-tools.x86_64
# 密码文件名称为htpasswd
htpasswd -bc htpasswd wangxiansen 123456
kubectl create secret generic basic-auth --from-file=htpasswd -n skywalking
创建 ingressroute,使用 basicAuth 中间件
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: basic-auth-middleware
namespace: skywalking
spec:
basicAuth:
secret: basic-auth
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: skywalking-web
namespace: skywalking
spec:
entryPoints:
- web
routes:
- match: Host(`skywalking.od.com`)
kind: Rule
services:
- name: ui-svc
port: 80
middlewares:
- name: basic-auth-middleware
设置环境变量
# 配置安装helm软件的名称
export SKYWALKING_RELEASE_NAME=skywalking
# 配置skywalking安装到k8s的命名空间
export SKYWALKING_RELEASE_NAMESPACE=devops
# 配置helm仓库名称
export REPO=skywalking
helm添加仓库
$ helm repo add ${REPO} https://apache.jfrog.io/artifactory/skywalking-helm
把skywalking安装包拉取下来
$ helm pull ${REPO}/skywalking --untar
修改values.yaml
elasticsearch:
...
config:
host: elasticsearch.devops.svc
password:
port:
http: 9200
user:
enabled: false
...
oap:
antiAffinity: soft
dynamicConfigEnabled: false
env: null
envoy:
als:
enabled: false
image:
pullPolicy: IfNotPresent
repository: skywalking.docker.scarf.sh/apache/skywalking-oap-server
tag: 9.7.0
....
ui:
image:
pullPolicy: IfNotPresent
repository: skywalking.docker.scarf.sh/apache/skywalking-ui
tag: 9.7.0
部署&&升级
## 安装部署
$ helm install skywalking skywalking -n devops --values ./skywalking/values.yaml
## 更新
$ helm upgrade skywalking skywalking -n devops --values ./skywalking/values.yaml
## 卸载
$ helm uninstall skywalking -ndevops
基于 Kubernetes 的 SkyWalking 部署方式总结:
总的来说,基于 Kubernetes 的 SkyWalking 部署方式充分利用了 Kubernetes 的弹性伸缩、故障恢复、资源管理和简化部署等优势。
这种部署方式使 SkyWalking 能够更好地适应动态的监控需求,并与微服务架构紧密集成,提供高效、可靠的分布式追踪和监控能力。