通过Helm Chart在Kubernetes集群Self-Hosted私有化部署Sentry(离线)

我们知道,Sentry是非常优秀的应用错误跟踪系统,还可以支持大多数的语言。不论是用在灰度的时候做验证也好,还是生产上用来快速追踪、定位以及提高对错误的治理能力也好,都非常适合,让运维人员不再依赖和等待用户的报错。

在上一篇文章《docker-compose安装sentry 9.1.2不踩坑指南》中我们聊了docker-compose部署Sentry,这次我们尝试下通过Helm Chart的方式在Kubernetes集群私有化部署。

话不多说,我们进入正题。

版本和环境

根据helm官方给出的要求

  • Kubernetes 1.4+,我手上的用的是1.14
  • helm >= v2.3.0,我的环境是2.14.3
  • PV provisoner support,我的集群提供ceph-rbd的StorageClass

Sentry版本在Helm Chart当前是9.1.2

环境的话,是公司内部局域网,而且是无法连接外网的局域网,即我们需要通过离线的方式部署,增加了部署的难度,最最关键是我们还没有chartmusium。而且即使有,比如说通过harbor,也是需要修改对应的Chart镜像改为公司内网镜像的。所以这增加了我们的安装难度,不过没有关系,通过配置可以让我们更加了解Sentry。

如果你的集群环境可以联网在线部署,那么强烈推荐这篇博客,前几天刚发布的:
《Sentry实时应用错误跟踪系统在Kubernetes中私有化部署》
,会更加适合你。

安装步骤

一、下载Chart包和镜像

既然离线,那么只有自己下载了,金融行业局域网限制得太严了。

1、Sentry chart

2、postgres chart

3、redis chart

4、docker镜像

在上述chart文件里面用到的images需要全部下载并导入到局域网镜像仓库。主要包括:

二、部署依赖postgres和redis

1、postgres

(1)修改values.yaml文件

  • 修改image地址和标签为内网harbor仓库镜像地址,包括postgres和minideb的镜像
  • 设置postgresqlPassword
  • 数据持久化,我们设置存到ceph rbd上
    persistence.storageClass: "ceph-rbd"

(2)helm install

helm install . --debug --name postgres --namespace sentry

稍等一下看到如下的消息就表示安装成功了,你可以按照提示去验证:

NOTES:
** Please be patient while the chart is being deployed **

PostgreSQL can be accessed via port 5432 on the following DNS name from within your cluster:

    postgresql.sentry.svc.cluster.local - Read/Write connection

To get the password for "postgres" run:

    export POSTGRES_PASSWORD=$(kubectl get secret --namespace sentry postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode)

To connect to your database run the following command:

    kubectl run postgresql-client --rm --tty -i --restart='Never' --namespace sentry --image harbor.****.com.cn/baseimg/awx/postgres:11.7.0-bitnami --env="PGPASSWORD=$POSTGRES_PASSWORD" --command -- psql --host postgresql -U postgres -d postgres -p 5432

To connect to your database from outside the cluster execute the following commands:

    kubectl port-forward --namespace sentry svc/postgresql 5432:5432 &
    PGPASSWORD="$POSTGRES_PASSWORD" psql --host 127.0.0.1 -U postgres -d postgres -p 5432

2、redis

redis有几种模式,看你自己具体的需求,下载chart包的时候有两个选择,一个是redis chart,一个是redis cluster chart。我们用的是redis chart,在redis里面可以配置单节点模式、主从模式、哨兵模式,我们这里选择默认的主从模式,一个master,2个slave。你可以在values.yaml里面配置你想要的模式。

(1)修改values.yaml文件

  • 修改image地址和标签为内网harbor仓库镜像地址,包括redis和minideb的镜像
  • 设置password,也可以不设置,那么就是默认10个随机字符,但如果自己设置,记得不要包含 # 号
  • 数据持久化,包括master和slave
    master.persistence.storageClass: "ceph-rbd"
    slave.persistence.storageClass: "ceph-rbd"

(2)helm install

helm install . --debug --name redis --namespace sentry

稍等一下看到如下消息就表示安装成功了,你可以按照提示去验证:

To get your password run:

    export REDIS_PASSWORD=$(kubectl get secret --namespace sentry redis -o jsonpath="{.data.redis-password}" | base64 --decode)

To connect to your Redis server:

1. Run a Redis pod that you can use as a client:

   kubectl run --namespace sentry redis-client --rm --tty -i --restart='Never' \
    --env REDIS_PASSWORD=$REDIS_PASSWORD \
   --image harbor.****.com.cn/google_containers/redis:5.0.8-bitnami -- bash

2. Connect using the Redis CLI:
   redis-cli -h redis-master -a $REDIS_PASSWORD
   redis-cli -h redis-slave -a $REDIS_PASSWORD

To connect to your database from outside the cluster execute the following commands:

    kubectl port-forward --namespace sentry svc/redis-master 6379:6379 & redis-cli -h 127.0.0.1 -p 6379 -a $REDIS_PASSWORD

三、部署Sentry

(1)删除requirement.yaml和requirement.lock文件

这是Sentry chart的依赖chart,因为我们没有chartmesium,所以没有用,而是改手工部署的redis和postgres,所以删除掉它

(2)修改values.yaml文件

  • 修改image地址和标签为内网harbor仓库镜像地址,包括sentry和
  • 设置邮件配置,在email里面,按照自己的smtp服务器及帐号设置
email:
  from_address: '[email protected]'
  host: *******
  port: 25
  use_tls: false
  user: ****
  password: ****
  enable_replies: false
  • 修改service类型,我们是内网环境,采用Ingress做域名暴露,所以修改默认的LoadBalancer为serve.type: ClusterIP

  • 数据持久化filestore,可以使用默认的filesystem,不过我的db和redis都是单独部署的用的ceph rbd,所以这里禁掉了,这里也可以配置将数据放到s3上面了,所以这点需要留意,并根据实际需求 配置

  • 配置ingres和域名

ingress:
  enabled: true
  hostname: sentry.****.com.cn
  • 配置redis和postgres
    这里特别的就是我们相当于用的外置的redis和postgres,所以需要配置host和password,这里因为是同一个集群,直接通过serve就可以访问到:
postgresql:
  enabled: false
  nameOverride: sentry-postgresql
  postgresqlDatabase: sentry
  postgresqlUsername: postgres
  # The following variables are only used when internal PG is disabled
  postgresqlHost: postgresql.sentry.svc.cluster.local
  postgresqlPassword: '**********'
  postgresqlPort: 5432
  # When defined the `postgresqlPassword` field is ignored
  # existingSecret: secret-name
  # existingSecretKey: postgresql-password

redis:
  enabled: false
  nameOverride: sentry-redis
  # The following variables are only used when internal PG is disabled
  host: redis-master.sentry.svc.cluster.local
  # Just omit the password field if your redis cluster doesn't use password
  password: '*********'
  port: 6379
  # When defined the `password` field is ignored
  # existingSecret: secret-name
  # existingSecretKey: redis-password
  master:
    persistence:
      enabled: true
      # If change pvc size redis.master.persistence.size: 20Gi
  • serviceaccount配置为false,因为我们单独建了个namespace并且直接用namespace默认的sa,所以这里就不单独建了
serviceAccount:
  # Specifies whether a service account should be created
  create: false

(3)helm install
这里我们需要先在postgres里面创建sentry db,否则会报错,具体看第五点的分析

# 先dry-run一下,并将部署日志打印到yaml文件中确认都没有问题再部署,这一步很有用,方便做检查
helm install . --debug --dry-run --name sentry --namespace sentry | sed 'w ../sentryt-dry-run.yml'

# 没有问题了再去掉--dry-run直接安装,并打印部署日志
helm install . --debug  --name sentry --namespace sentry --wait | sed 'w ../sentryt-deploy.yml'

这里注意添加–wait参数,因为创建db时间会比较久,所以可能会超出默认等待时长。等待的时候可以不断检查pod状态以及日志看是否有问题。直到看到如下提示就标识安装成功了

NOTES:

1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace sentry -l "app=sentry,role=web" -o jsonpath="{.items[0].metadata.name}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward --namespace sentry $POD_NAME 8080:9000

2. Log in with

  USER: [email protected]
  Get login password with
    kubectl get secret --namespace sentry sentry -o jsonpath="{.data.user-password}" | base64 --decode

四、登录验证

用在values.yaml中配置的用户名和密码登录验证即可,具体参见上一篇docker-compose部署中第四部的登录验证,这里不再赘述。

五、安装中遇到的问题及解决

(1)数据库sentry不存在的问题:database "sentry" does not exist

[root@SYSOPS00613596 ~]# kubectl -n sentry logs sentry-db-init-bqkh7
11:38:41 [WARNING] sentry.utils.geo: settings.GEOIP_PATH_MMDB not configured.
11:38:44 [INFO] sentry.plugins.github: apps-not-configured
Syncing...
Traceback (most recent call last):
  File "/usr/local/bin/sentry", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python2.7/site-packages/sentry/runner/__init__.py", line 162, in main
    cli(prog_name=get_prog(), obj={}, max_content_width=100)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sentry/runner/decorators.py", line 36, in inner
    return ctx.invoke(f, *args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sentry/runner/commands/upgrade.py", line 75, in upgrade
    _upgrade(not noinput, traceback, verbosity, not no_repair)
  File "/usr/local/lib/python2.7/site-packages/sentry/runner/commands/upgrade.py", line 30, in _upgrade
    ignore_ghost_migrations=True,
  File "/usr/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 159, in call_command
    return klass.execute(*args, **defaults)
  File "/usr/local/lib/python2.7/site-packages/django/core/management/base.py", line 285, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python2.7/site-packages/django/core/management/base.py", line 415, in handle
    return self.handle_noargs(**options)
  File "/usr/local/lib/python2.7/site-packages/south/management/commands/syncdb.py", line 119, in handle_noargs
    self.sync_apps(apps_needing_sync, app_name_to_app_map, options)
  File "/usr/local/lib/python2.7/site-packages/south/management/commands/syncdb.py", line 174, in sync_apps
    syncdb.Command().execute(**options)
  File "/usr/local/lib/python2.7/site-packages/django/core/management/base.py", line 285, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python2.7/site-packages/django/core/management/base.py", line 415, in handle
    return self.handle_noargs(**options)
  File "/usr/local/lib/python2.7/site-packages/django/core/management/commands/syncdb.py", line 57, in handle_noargs
    cursor = connection.cursor()
  File "/usr/local/lib/python2.7/site-packages/django/db/backends/__init__.py", line 162, in cursor
    cursor = util.CursorWrapper(self._cursor(), self)
  File "/usr/local/lib/python2.7/site-packages/sentry/db/postgres/decorators.py", line 44, in inner
    return func(self, *args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sentry/db/postgres/base.py", line 95, in _cursor
    cursor = super(DatabaseWrapper, self)._cursor()
  File "/usr/local/lib/python2.7/site-packages/django/db/backends/__init__.py", line 132, in _cursor
    self.ensure_connection()
  File "/usr/local/lib/python2.7/site-packages/django/db/backends/__init__.py", line 127, in ensure_connection
    self.connect()
  File "/usr/local/lib/python2.7/site-packages/django/db/utils.py", line 99, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/usr/local/lib/python2.7/site-packages/django/db/backends/__init__.py", line 127, in ensure_connection
    self.connect()
  File "/usr/local/lib/python2.7/site-packages/django/db/backends/__init__.py", line 115, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/usr/local/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 115, in get_new_connection
    return Database.connect(**conn_params)
  File "/usr/local/lib/python2.7/site-packages/psycopg2/__init__.py", line 130, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
django.db.utils.OperationalError: FATAL:  database "sentry" does not exist

这里一直等待都不行,可能是因为外置数据库的原因,所以我们手动去postgres里面创建了sentry就可以了。

[root@ ~]# kubectl -n sentry exec -it postgresql-postgresql-0  bash
I have no name!@postgresql-postgresql-0:/$ psql --host 127.0.0.1 -U postgres -d postgres -p 5432
Password for user postgres: 
psql (11.7)
Type "help" for help.

postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(4 rows)

postgres=# create database sentry
postgres=# \q
I have no name!@postgresql-postgresql-0:/$ exit
exit

(2)cron容器报redis无法转换为整形的问题:invalid literal for int() with base 10: ‘redis123!’

[root@SYSOPS00613596 ~]# kubectl -n sentry logs sentry-cron-dd59f9b74-kcrwg
11:38:22 [WARNING] sentry.utils.geo: settings.GEOIP_PATH_MMDB not configured.
11:38:25 [INFO] sentry.plugins.github: apps-not-configured
celery beat v3.1.18 (Cipater) is starting.
Traceback (most recent call last):
  File "/usr/local/bin/sentry", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python2.7/site-packages/sentry/runner/__init__.py", line 162, in main
    cli(prog_name=get_prog(), obj={}, max_content_width=100)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sentry/runner/decorators.py", line 73, in inner
    return ctx.invoke(f, *args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sentry/runner/decorators.py", line 36, in inner
    return ctx.invoke(f, *args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sentry/runner/commands/run.py", line 252, in cron
    **options
  File "/usr/local/lib/python2.7/site-packages/celery/apps/beat.py", line 83, in run
    self.start_scheduler()
  File "/usr/local/lib/python2.7/site-packages/celery/apps/beat.py", line 104, in start_scheduler
    c.reset(self.startup_info(beat)))))
  File "/usr/local/lib/python2.7/site-packages/celery/apps/beat.py", line 127, in startup_info
    conninfo=self.app.connection().as_uri(),
  File "/usr/local/lib/python2.7/site-packages/celery/app/base.py", line 385, in connection
    'BROKER_CONNECTION_TIMEOUT', connect_timeout
  File "/usr/local/lib/python2.7/site-packages/kombu/connection.py", line 167, in __init__
    params.update(parse_url(hostname))
  File "/usr/local/lib/python2.7/site-packages/kombu/utils/url.py", line 32, in parse_url
    scheme, host, port, user, password, path, query = _parse_url(url)
  File "/usr/local/lib/python2.7/site-packages/kombu/utils/url.py", line 24, in _parse_url
    return (scheme, unquote(parts.hostname or '') or None, parts.port,
  File "/usr/local/lib/python2.7/urlparse.py", line 113, in port
    port = int(port, 10)
ValueError: invalid literal for int() with base 10: 'redis123!'

参考文章:

发布了25 篇原创文章 · 获赞 24 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/arnolan/article/details/105715163