乔克
乔克
Published on 2024-11-15 / 60 Visits
0
0

错误跟踪系统Sentry到底是何方神圣?

作者:乔克
公众号:《运维开发故事》
知乎:巧克叔叔

大家好,我是乔克,一名一线运维实践者。

今天和大家分享一下什么是错误跟踪系统,以及如何使用。

在应用的整个生命周期里,避无可避的就是“错误”,很多时候都是借助日志平台来捕获、查看日志,以此来找到错误的原因,但是很多时候应用的日志有很多误导性,也不能够很直观的指出问题的源点,并且也缺乏及时分析和告警能力(当然现在很多商用的日志系统都有这个功能了,但是需要 Money)。

有没有比较好用的开源软件呢?

Sentry 就是这样一款优秀的应用错误跟踪系统,并且支持大多数的语言,如下。

图片.png

错误跟踪系统是什么?

从字面上就可以很好理解,错误跟踪系统就是跟踪系统错误、异常的一个软件,旨在帮助开发、运维等技术人员跟踪应用的一些错误信息。

通过对应用的错误进行实时追踪并统一跟进,提高对错误的治理能力。让业务场景下自己发现 Bug 的速度快于用户报告 Bug 的速度。

Sentry 是什么

Sentry 是一个跨平台的应用错误跟踪系统,专注于错误报告。

当线上应用程序触发了一个 bug,Sentry 会立即发现错误,并通过邮件或其他基于通知规则的集成通知到相关责任人员,这个通知可以把我们引入到这个报错的 Dashboard,为我们提供了快速分类问题所需的上下文,如:频率、用户影响、代码那一部分受到影响以及哪个团队可能是问题的所有者。进入报错详情会显示帮助我们调试的详细信息,比如堆栈跟踪、堆栈本地信息、前面的事件、可能导致问题的提交以及在错误发生时捕获的定制数据。我们还可以在 JIRA 或 GitLab Issue 等项目管理工具中自动开始跟踪问题。

Sentry 的原理是什么呢?

首先,应用要集成 Sentry 的 SDK,然后在应用发生错误是将错误信息发送给 Sentry 服务端。Sentry 的服务端分为 web、cron、worker 这几个部分,应用(客户端)发生错误后将错误信息上报给 web,web 处理后放入消息队列或 Redis 内存队列,worker 从队列中消费数据进行处理

其主要优点如下:

  • 提供精美的 WEB UI 界面
  • 支持几乎所有的主流开发语言的 SDK,接入简单
  • 提供完整的错误详情
  • 支持统一的错误聚合分析
  • 支持仪表盘、监控、告警等功能
  • 支持团队管理、成员管理
  • 支持日志审计等

当然也有一些缺点,针对维护部署其需要的中间件非常多,有 kafka、rabbitMQ、redis、pgsql 等,这一套部署下来的成本还是比较高。不过瑕不掩瑜,相比于它给我们带来的好处,这些问题都可以克服。

图片.png

部署 Sentry

Sentry 提供服务的方式有两种:

  • SAAS 平台,有不同的付费方式
  • 私有化部署

这里主要阐述如何在 Kubernetes 中进行部署。

环境介绍

  • Kubernetes: 1.17.17
  • Docker:18.09.0
  • Helm:3.6.3
  • 存储:使用 Local PV

OpenEBS 简介

OpenEBS 是一款使用 Go 语言编写的基于容器的块存储开源软件。OpenEBS 使得在容器中运行关键性任务和需要数据持久化的负载变得更可靠。

使用 OpenEBS,你可以将有持久化数据的容器,像对待其他普通容器一样来对待。OpenEBS 本身也是通过容器来部署的,支持 Kubernetes、Swarm、Mesos、Rancher 编排调度,存储服务可以分派给每个 pod、应用程序、集群或者容器级别,包括:

  • 跨节点的数据持久化
  • 跨可用区和云厂商的数据同步
  • 使用商业硬件和容器引擎来提供高可扩展的块存储
  • 与容器编排引擎集成,开发者的应用程序可以自动的配置 OpenEBS
  • 基于 CloudByte 在 BSD 的容器化经验,为用户提供 OpenEBS 的 QoS 保证

OpenEBS 的架构可以分为数据平面(Data Plane)和控制平面(Control Plane)两部分:

  • 数据平面:为应用程序提供数据存储
  • 控制平面:管理 OpenEBS 卷容器,这通常会用到容器编排软件的功能

环境部署

1、部署 OpenEBS

OpenEBS 支持 Helm Chart 和 Operator 部署.
(1)使用 Helm Chart 部署

helm repo add openebs https://openebs.github.io/charts
helm repo update
helm install openebs --namespace openebs openebs/openebs --create-namespace

(2)使用 Operator 部署

kubectl apply -f https://openebs.github.io/charts/openebs-operator.yaml

部署完成后会生成如下 Pod。

# kubectl get pod -n openebs 
NAME                                          READY   STATUS    RESTARTS   AGE
maya-apiserver-67b5b5c858-4mstb               1/1     Running   0          5d19h
openebs-admission-server-6bdf9b76d6-r4r6b     1/1     Running   0          5d19h
openebs-localpv-provisioner-966d864cd-sf8fp   1/1     Running   0          5d19h
openebs-ndm-59lkx                             1/1     Running   0          5d19h
openebs-ndm-bphgw                             1/1     Running   0          5d19h
openebs-ndm-grxlb                             1/1     Running   0          5d19h
openebs-ndm-operator-55b8ccc64b-r7tkr         1/1     Running   0          5d19h
openebs-ndm-zwhmm                             1/1     Running   0          5d19h
openebs-provisioner-55794b6cd4-ptd85          1/1     Running   0          5d19h
openebs-snapshot-operator-5d78fcbd96-7xqzv    2/2     Running   0          5d19h

以及如下的 StorageClass。

# kubectl get sc | grep openebs
local (default)             openebs.io/local                                           Delete          WaitForFirstConsumer   false                  5d19h
openebs-device              openebs.io/local                                           Delete          WaitForFirstConsumer   false                  5d19h
openebs-hostpath            openebs.io/local                                           Delete          WaitForFirstConsumer   false                  5d19h
openebs-jiva-default        openebs.io/provisioner-iscsi                               Delete          Immediate              false                  5d19h
openebs-snapshot-promoter   volumesnapshot.external-storage.k8s.io/snapshot-promoter   Delete          Immediate              false                  5d19h

2、部署 Postgresql

其实在 Sentry 的 Helm Chart 中有 Postgresql 的 Chart 包,这里之所以单独来部署,是因为通过 Sentry 中的 Chart 包部署,在 Postgresql 环节出现了各种问题,比如:

FATAL: password authentication failed for user "postgres"

这里通过 Helm Chart 来部署 Postgresql,具体步骤如下:

# 添加Helm仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# 把Chart包下载下来
helm pull bitnami/postgresql

编写配置文件(my-value.yaml),如下:

global:
  postgresql:
    postgresqlDatabase: "sentry"
    postgresqlUsername: "postgres"
    existingSecret: ""
    postgresqlPassword: "postgres"
    servicePort: ""
    replicationPassword: ""

安装 PGSQL,命令如下:

helm install postgresql -n sentry -f my-value.yaml bitnami/postgresql

部署完成后,可以看到如下 Pod:

# kubectl get po -n sentry 
NAME                                                  READY   STATUS      RESTARTS   AGE
postgresql-postgresql-0                               1/1     Running     0          3h39m
3、部署 Sentry

Sentry 也是采用 Helm Chart 来进行部署,如下:

# 添加Helm仓库
helm repo add sentry https://sentry-kubernetes.github.io/charts
helm repo update
helm search repo sentry
# 下载Chart包,便于查看修改Chart
helm pull sentry/sentry

编写配置文件(my-value.yaml),如下:

externalPostgresql:
  database: sentry
  port: 5432
  username: postgres
  host: postgresql
  password: postgres
postgresql:
  enabled: false
mail:
  backend: dummy
  from: "joker2021@163.com"
  host: "smtp"
  password: "UZKSGLFEANWGLZNT"
  port: 465
  useTls: true
  username: ""
user:
  create: true
  email: admin@sentry.local
  password: P@ssword

部署 Sentry,如下:

helm install sentry -n sentry -f my-value.yaml sentry/sentry

部署完成后,会生成如下 Pod:

# kubectl get po -n sentry 
NAME                                                  READY   STATUS      RESTARTS   AGE
postgresql-postgresql-0                               1/1     Running     0          3h50m
sentry-clickhouse-0                                   1/1     Running     0          3h50m
sentry-clickhouse-1                                   1/1     Running     0          3h50m
sentry-clickhouse-2                                   1/1     Running     0          3h50m
sentry-cron-578647dd7-gk7gf                           1/1     Running     0          3h50m
sentry-ingest-consumer-7564f644bf-srkj2               1/1     Running     0          3h47m
sentry-kafka-0                                        1/1     Running     2          3h50m
sentry-kafka-1                                        1/1     Running     2          3h50m
sentry-kafka-2                                        1/1     Running     2          3h50m
sentry-nginx-675d779699-tfdr5                         1/1     Running     0          3h50m
sentry-post-process-forward-5f586f6cdf-lxmc4          1/1     Running     0          3h47m
sentry-rabbitmq-0                                     1/1     Running     0          3h50m
sentry-rabbitmq-1                                     1/1     Running     0          3h49m
sentry-rabbitmq-2                                     1/1     Running     0          3h48m
sentry-relay-75597cb98b-jm282                         1/1     Running     0          3h47m
sentry-sentry-redis-master-0                          1/1     Running     0          3h50m
sentry-sentry-redis-slave-0                           1/1     Running     0          3h50m
sentry-sentry-redis-slave-1                           1/1     Running     0          3h49m
sentry-sessions-consumer-6b499bf64d-lm7gq             1/1     Running     0          3h47m
sentry-snuba-api-5586d5f9f8-tcn5s                     1/1     Running     0          3h50m
sentry-snuba-cleanup-errors-1630472400-xv5wh          0/1     Completed   0          134m
sentry-snuba-cleanup-errors-1630476000-xd7d2          0/1     Completed   0          74m
sentry-snuba-cleanup-errors-1630479600-sd59b          0/1     Completed   0          14m
sentry-snuba-cleanup-transactions-1630472400-l9bcx    0/1     Completed   0          134m
sentry-snuba-cleanup-transactions-1630476000-cjsbd    0/1     Completed   0          74m
sentry-snuba-cleanup-transactions-1630479600-zn5dz    0/1     Completed   0          14m
sentry-snuba-consumer-58b7bfd545-rnjmx                1/1     Running     0          3h47m
sentry-snuba-outcomes-consumer-57c589bf6d-lxg5m       1/1     Running     0          3h47m
sentry-snuba-replacer-5bf4d6b5d7-gcc7g                1/1     Running     0          3h47m
sentry-snuba-transactions-consumer-57bb7f8ccb-q6gkt   1/1     Running     0          3h47m
sentry-web-7c9766768b-njxjl                           1/1     Running     0          3h50m
sentry-worker-844fd65687-6b26p                        1/1     Running     2          3h50m
sentry-worker-844fd65687-k2h6z                        1/1     Running     2          3h50m
sentry-worker-844fd65687-rfjcl                        1/1     Running     2          3h50m
sentry-zookeeper-0                                    1/1     Running     0          3h50m

然后可以通过 ingress 或者 nodeport 的方式进行访问,用户名和密码是上面配置的 admin@sentry.localP@ssword

创建项目

进入 WEB UI 界面,在项目专栏创建项目,如下:

图片.png

我这里创建一个 Go 项目,如下:

图片.png

点击创建后,就会生成一个 Dsn 地址,并且给出一个配置示例,如下:

package main

import (
	"fmt"
	"github.com/getsentry/sentry-go"
	sentrygin "github.com/getsentry/sentry-go/gin"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"net/http"
)

func main() {
	// To initialize Sentry's handler, you need to initialize Sentry itself beforehand
	if err := sentry.Init(sentry.ClientOptions{
		Dsn: "https://b06bcc1c67b44084a3f65fc8b219a5fc@o985819.ingest.sentry.io/5942245",
	}); err != nil {
		fmt.Printf("Sentry initialization failed: %v\n", err)
	}
	sentry.CaptureMessage("It works!")
	sentry.CaptureException(errors.New("error msg"))
	// Then create your app
	app := gin.Default()

	// Once it's done, you can attach the handler as one of your middleware
	app.Use(sentrygin.New(sentrygin.Options{}))

	// Set up routes
	app.GET("/", func(ctx *gin.Context) {
		ctx.String(http.StatusOK, "Hello world!")
	})

	// And run it
	app.Run(":3000")

}

其他类型的项目与此类似,具体步骤也就三步:

  • 在 Sentry WEB UI 界面创建项目
  • 生成对应的 Dsn
  • 将其引入到具体的应用代码中

然后应用部署过后,就会通过 Post 的方式上报应用错误,届时就可以在 WEB 界面进行查看。

图片.png

创建告警

可以创建的告警类型还是比较丰富,如下:

图片.png

然后创建规则,如下:

图片.png

除此之外还可以进行团队、成员管理,日志审计等,更多功能需要自己去实践了。

参考

[1] https://sentry.io/
[2] https://openebs.io/
[3] https://github.com/getsentry/sentry
[4] https://github.com/sentry-kubernetes/charts


Comment