• docker swarm 部署 sentry9.1.2


    使用 Electron 时需要收集前端的日志信息,就有了部署sentry的需求。

    环境

    考虑到业务上对日志收集的需求和费用的问题,就直接将sentry部署到已有的演示环境中。演示环境是腾讯云两台服务器组成的docker swarm,并使用 Portainer 对docker swarm 进行管理,所以我们的部署都是通过 portainer 进行。
    两台服务器的 /mnt目录时挂载的同一个NFS目录,这样方便容器进行统一挂载宿主机目录。

    Sentry 说明

    Sentry的服务端分为web、cron、worker这几个部分,应用(客户端)发生错误后将错误信息上报给web,web处理后放入消息队列(Redis存队列),worker从队列中消费数据进行处理,最终数据将存储在PostgreSQL。
    其中web、cron、worker这几个部分使用的是同一个docker 镜像,只是启动时的参数不一样;分别对应 sentry run web、sentry run cron、sentry run worker。

    部署

    dockerhub上最新的sentry版本为9.1.2,还是3年前更新的,已经不建议自己直接使用 docker 镜像进行部署了,官方推荐基于 bash 脚本安装和升级;但是我还是选择了自己使用doker 镜像部署的方式(这样我就可以直接使用Portainer进行操作);
    在这里插入图片描述

    虚拟网络

    创建一个覆盖网络,后续的所以容器都将加入该网络,我们直接使用portainer来创建:
    在这里插入图片描述

    Redis

    Redis 用来实现 Sentry中的消息队列, Redis Stack:

    version: '3.7'
    networks:
      yanshi-network: 
        external: true
    services:
      redis:
        user: root
        image: redis:6.0
        networks:
          - yanshi-network
        deploy:
          replicas: 1
          update_config:
            parallelism: 1
            delay: 5s
            order: stop-first
          resources:
            limits:
              cpus: '0.5'
              memory: 1g
        ports: 
          - "6379:6379"
        environment:
          TZ : 'Asia/Shanghai'
        volumes:
          - /mnt/redis/data:/data
          - /mnt/redis/conf/redis.conf:/etc/redis/redis.conf
        entrypoint: docker-entrypoint.sh redis-server /etc/redis/redis.conf
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    注意:sentry9.1.2 和 redis 高版本存在兼容性问题,redis:6.0是OK的。

    PostgreSQL

    Sentry 需要PostgreSQL 来存储数据,PostgreSQL Stack:

    version: '3.7'
    networks:
      yanshi-network: 
        external: true
    services:
      postgres:
        image: postgres:14.0
        networks:
          - yanshi-network
        privileged: true
        restart: unless-stopped
        volumes:
          - /mnt/postgres/data:/var/lib/postgresql/data
        environment:
          POSTGRES_USER: root
          POSTGRES_PASSWORD: ******
        ports:
          - "5432:5432"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Sentry

    sentry init

    首先我们需要启动一个sentry cli 容器,通过 sentry init 命令生成配置文件 /etc/sentry/config.yml、/etc/sentry/sentry.conf.py, 所以我们需要启动一个sentry 的容器:

    version: '3.7'
    networks:
      yanshi-network: 
        external: true
    services:
      cli:
        image: sentry:9.1.2
        networks:
          - yanshi-network
        volumes:
          - /mnt/sentry/conf:/etc/sentry/
        stdin_open: true # -i interactive
        tty: true # -t tty
        privileged: true
        entrypoint: ["sh"] # 执行 sh
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    然后进入容器执行 sentry init 命令,然后就会在宿主机 /mnt/sentry/conf 目录下会生成两个配置文件:
    在这里插入图片描述

    sentry upgrade

    上面我们生成配置文件后,我们就需要对配置文件进行修改;

    /etc/sentry/config.yml

    # 邮箱配置
    mail.host: 'smtp.qq.com'
    mail.port: 587
    mail.username: xxxx@foxmail.com'
    mail.password: 'xxxxxx'
    mail.use-tls: true
    mail.from: 'xxxx@foxmail.com'
    # redis 配置
    redis.clusters:
      default:
        hosts:
          0:
            host: redis
            port: 6379
            db: 0
            password: xxxxxx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    /etc/sentry/sentry.conf.py

    # 数据库配置
    DATABASES = {
        'default': {
            'ENGINE': 'sentry.db.postgres',
            'NAME': 'sentry',
            'USER': 'xx',
            'PASSWORD': 'xxxxxx',
            'HOST': 'postgres',
            'PORT': '',
            'AUTOCOMMIT': True,
            'ATOMIC_REQUESTS': False,
        }
    }
    # Redis 配置
    BROKER_URL = 'redis://:xxxx@redis:6379/0'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在 PostgreSql 中创建对应的数据库,我这里配置的数据库名为 sentry;
    然后有到上一步(sentry init)的容器中执行 sentry upgrade, 这一步操作 sentry库中就会自动创建好系统需要的所有数据表, redis 中也会自动创建好相关的数据。
    sentry upgrade 执行中会询问是否创建用户:

    Would you like to create a user account now? [Y/n]:
    
    • 1

    我们选择创建,然后根据提示输入用户邮箱和密码就行啦。

    sentry web \ worker \ cron

    接下来我们就可以完整的部署 sentry了,完整的 stack yaml:

    version: '3.7'
    networks:
      yanshi-network: 
        external: true
    services:
      cli:
        image: sentry:9.1.2
        networks:
          - yanshi-network
        volumes:
          - /mnt/sentry/conf:/etc/sentry/
        stdin_open: true # -i interactive
        tty: true # -t tty
        privileged: true
        entrypoint: ["sh"] # 执行 sh
      server:
        image: sentry:9.1.2
        privileged: true
        restart: unless-stopped
        networks:
          - yanshi-network
        volumes:
          - /mnt/sentry/data:/var/lib/sentry/files
          - /mnt/sentry/conf:/etc/sentry/
        command: /bin/bash -c "sentry run web"
        environment:
          C_FORCE_ROOT: "true"
        ports: 
          - "9000:9000"
      cron:
        image: sentry:9.1.2
        privileged: true
        restart: unless-stopped
        networks:
          - yanshi-network
        volumes:
          - /mnt/sentry/data:/var/lib/sentry/files
          - /mnt/sentry/conf:/etc/sentry/
        command: /bin/bash -c "sentry run cron"
        environment:
          C_FORCE_ROOT: "true"
      worker:
        image: sentry:9.1.2
        privileged: true
        restart: unless-stopped
        networks:
          - yanshi-network
        volumes:
          - /mnt/sentry/data:/var/lib/sentry/files
          - /mnt/sentry/conf:/etc/sentry/
        command: /bin/bash -c "sentry run worker"
        environment:
          C_FORCE_ROOT: "true"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    部署完成后就可以通过 http://ip:9000 访问sentry了,输入用户密码登录。
    在这里插入图片描述

    坎坷

    1. sentry upgrade 时报错:django.db.utils.OperationalError: FATAL: database “sentry” does not exist
      没有在postgreSql中创建好对应的数据库,手动创建后就没问题了。
    2. sentry upgrade 创建用户时选择了N,没有用户登录
      这个可以通过 sentry createuser 来创建用户。
    3. 在管理页面测试邮件发送失败(连接超时)。
      这个是我配置的 mail.port 写错了。
    4. 在管理页面测试邮件发送正常,但邀请成员邮件发送失败。
      查看日志发现如下报错:
    16:10:49 [WARNING] sentry.utils.geo: settings.GEOIP_PATH_MMDB not configured.
    16:10:52 [INFO] sentry.plugins.github: apps-not-configured
    16:10:52 [INFO] sentry.bgtasks: bgtask.spawn (task_name=u'sentry.bgtasks.clean_dsymcache:clean_dsymcache')
     
     -------------- celery@a6d25dd3513d v3.1.18 (Cipater)
    ---- **** ----- 
    --- * ***  * -- Linux-3.10.0-1160.66.1.el7.x86_64-x86_64-with-debian-9.11
    -- * - **** --- 
    - ** ---------- [config]
    - ** ---------- .> app:         sentry:0x7f055f43f150
    - ** ---------- .> transport:   redis://:**@redis:6379/2
    - ** ---------- .> results:     disabled
    - *** --- * --- .> concurrency: 4 (prefork)
    -- ******* ---- 
    --- ***** ----- [queues]
     -------------- .> activity.notify  exchange=default(direct) key=activity.notify
                    .> alerts           exchange=default(direct) key=alerts
                    .> app_platform     exchange=default(direct) key=app_platform
                    .> assemble         exchange=default(direct) key=assemble
                    .> auth             exchange=default(direct) key=auth
                    .> buffers.process_pending exchange=default(direct) key=buffers.process_pending
                    .> cleanup          exchange=default(direct) key=cleanup
                    .> commits          exchange=default(direct) key=commits
                    .> counters-0       exchange=counters(direct) key=
                    .> default          exchange=default(direct) key=default
                    .> digests.delivery exchange=default(direct) key=digests.delivery
                    .> digests.scheduling exchange=default(direct) key=digests.scheduling
                    .> email            exchange=default(direct) key=email
                    .> events.index_event_tags exchange=default(direct) key=events.index_event_tags
                    .> events.preprocess_event exchange=default(direct) key=events.preprocess_event
                    .> events.process_event exchange=default(direct) key=events.process_event
                    .> events.reprocess_events exchange=default(direct) key=events.reprocess_events
                    .> events.reprocessing.preprocess_event exchange=default(direct) key=events.reprocessing.preprocess_event
                    .> events.reprocessing.process_event exchange=default(direct) key=events.reprocessing.process_event
                    .> events.save_event exchange=default(direct) key=events.save_event
                    .> files.delete     exchange=default(direct) key=files.delete
                    .> integrations     exchange=default(direct) key=integrations
                    .> merge            exchange=default(direct) key=merge
                    .> options          exchange=default(direct) key=options
                    .> reports.deliver  exchange=default(direct) key=reports.deliver
                    .> reports.prepare  exchange=default(direct) key=reports.prepare
                    .> search           exchange=default(direct) key=search
                    .> sleep            exchange=default(direct) key=sleep
                    .> stats            exchange=default(direct) key=stats
                    .> triggers-0       exchange=triggers(direct) key=
                    .> unmerge          exchange=default(direct) key=unmerge
                    .> update           exchange=default(direct) key=update
    
    Traceback (most recent call last):
      File "/usr/local/lib/python2.7/site-packages/sentry/digests/backends/redis.py", line 191, in maintenance
        self.__maintenance_partition(host, deadline, timestamp)
      File "/usr/local/lib/python2.7/site-packages/sentry/digests/backends/redis.py", line 181, in __maintenance_partition
        deadline,
      File "/usr/local/lib/python2.7/site-packages/sentry/utils/redis.py", line 239, in call_script
        return script(keys, args, client)
      File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 2699, in __call__
        return client.evalsha(self.sha, len(keys), *args)
      File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 1944, in evalsha
        return self.execute_command('EVALSHA', sha, numkeys, *keys_and_args)
      File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 573, in execute_command
        return self.parse_response(connection, command_name, **options)
      File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 585, in parse_response
        response = connection.read_response()
      File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 582, in read_response
        raise response
    ResponseError: user_script:11: Attempt to modify a readonly table script: 094f8735408af273da283389ad983f63977831e8, on @user_script:11.
    16:10:57 [ERROR] sentry.digests: Failed to perform maintenance on digest partition 0 due to error: ResponseError('user_script:11: Attempt to modify a readonly table script: 094f8735408af273da283389ad983f63977831e8, on @user_script:11.',)
    Traceback (most recent call last):
      File "/usr/local/lib/python2.7/site-packages/sentry/digests/backends/redis.py", line 162, in schedule
        for key, timestamp in self.__schedule_partition(host, deadline, timestamp):
      File "/usr/local/lib/python2.7/site-packages/sentry/digests/backends/redis.py", line 152, in __schedule_partition
        deadline,
      File "/usr/local/lib/python2.7/site-packages/sentry/utils/redis.py", line 239, in call_script
        return script(keys, args, client)
      File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 2694, in __call__
        return client.evalsha(self.sha, len(keys), *args)
      File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 1944, in evalsha
        return self.execute_command('EVALSHA', sha, numkeys, *keys_and_args)
      File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 573, in execute_command
        return self.parse_response(connection, command_name, **options)
      File "/usr/local/lib/python2.7/site-packages/redis/client.py", line 585, in parse_response
        response = connection.read_response()
      File "/usr/local/lib/python2.7/site-packages/redis/connection.py", line 582, in read_response
        raise response
    ResponseError: user_script:11: Attempt to modify a readonly table script: 094f8735408af273da283389ad983f63977831e8, on @user_script:11.
    16:10:57 [ERROR] sentry.digests: Failed to perform scheduling for partition 0 due to error: ResponseError('user_script:11: Attempt to modify a readonly table script: 094f8735408af273da283389ad983f63977831e8, on @user_script:11.',)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    后来google发现是redis版本太新,兼容性问题,换redis6.0后正常。

    参考

    docker-compose运行sentry
    Sentry-docker版本
    centos7 docker方式部署sentry
    Self-Hosted Releases & Upgrading

  • 相关阅读:
    Java21上手体验-分代ZGC和虚拟线程
    初识JavaScript
    linux下的采用epoll网络模型的文件传输
    【前端】JavaScript
    08-分布式
    JavaScript实现冒泡排序
    视觉与机器人的九点标定(三)
    OBS Studio 30.0 承诺在 Linux 上支持英特尔 QSV,为 DeckLink 提供 HDR 回放功能
    selenium的基本操作
    docker安装wiki
  • 原文地址:https://blog.csdn.net/i_love_t/article/details/126672355