[Infrastructure as Code (IaC) Pulumi] Use Pulumi kubernetes (K8S) Helm Chart to deploy Sentry

Sentry

Sentry is a service that helps you monitor and fix crashes in realtime. The server is in Python, but it contains a full API for sending events from any language, in any application.

This article is about how to use Pulumi, kubernetes (K8S) provider, Helm Chart and TypeScript SDK to deploy Sentry within Kubernetes (K8S).

Prerequisites

Usage

Pulumi New

Create the workspace directory.

1
2
3
$ mkdir -p col-example-pulumi-typescript-sentry

$ cd col-example-pulumi-typescript-sentry

Pulumi login into local file system.

1
2
3
$ pulumi login file://.
Logged in to cloudolife as cloudolife (file://.)
or visit https://pulumi.com/docs/reference/install/ for manual instructions and release notes.

Pulumi new a project with kubernetes-typescript SDK.

1
$ pulumi new kubernetes-typescript

The above command will create some files within the current directory.

1
2
3
4
5
6
7
8
tree . -L 1
.
├── node_modules/
├── package.json
├── package.json.lock
├── Pulumi.dev.yaml
├── Pulumi.yaml
└── main.ts

Install js-yaml package to load and parse yaml file.

1
$ npm i js-yaml

Pulumi Configuration

Configure Kubernetes

By default, Pulumi will look for a kubeconfig file in the following locations, just like kubectl:

  • The environment variable: $KUBECONFIG,

  • Or in current user’s default kubeconfig directory: ~/.kube/config

If the kubeconfig file is not in either of these locations, Pulumi will not find it, and it will fail to authenticate against the cluster. Set one of these locations to a valid kubeconfig file, if you have not done so already.

Configure Values.yaml

Edit values.yaml and replace content within {{ }}.

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
# values.yaml

# charts/values.yaml at develop · sentry-kubernetes/charts
# https://github.com/sentry-kubernetes/charts/blob/develop/sentry/values.yaml

user:

email: {{ .Values.user.email }}
password: {{ .Values.user.password }}

# sentry:
# singleOrganization: true

ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"

hostname: {{ .Values.user.hostname }}

tls:
- secretName: {{ .Values.user.secretName }}

## Prometheus Exporter / Metrics
##
metrics:
enabled: true

main.ts

See and modify main.ts file.

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
// main.ts

import * as pulumi from "@pulumi/pulumi";

import * as k8s from "@pulumi/kubernetes";

const yaml = require('js-yaml');
const fs = require('fs');

const nameSentry = "sentry"

// kubernetes.core/v1.Namespace | Pulumi
// https://www.pulumi.com/docs/reference/pkg/kubernetes/core/v1/namespace/
const namespaceSentry = new k8s.core.v1.Namespace(nameSentry, {
metadata: {
name: nameSentry,
},
})

const values = yaml.safeLoad(fs.readFileSync("./values.yaml", 'utf8'))


const charNameSentry = "sentry"

// sentry 4.0.1 · kubernetes/sentry
// https://artifacthub.io/packages/helm/sentry/sentry
const charSentry = new k8s.helm.v3.Chart(charNameSentry, {
chart: charNameSentry,
version: "12.0.0",
fetchOpts:{
repo: "https://sentry-kubernetes.github.io/charts",
},
namespace: namespaceSentry.metadata.name,
values: values,
});

Pulumi Up

Run pulumi up to create the namespace and pods.

1
$ pulumi up

See pods about sentry.

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
$ kubectl get pods -n sentry
NAME READY STATUS RESTARTS AGE
sentry-clickhouse-0 1/1 Running 0 8h
sentry-clickhouse-1 1/1 Running 0 8h
sentry-clickhouse-2 1/1 Running 0 8h
sentry-cron-675595d4-mhdr9 1/1 Running 1 (8h ago) 8h
sentry-kafka-0 1/1 Running 0 8h
sentry-kafka-1 1/1 Running 0 8h
sentry-kafka-2 1/1 Running 2 (8h ago) 8h
sentry-metrics-bf85dc7f4-mgh27 1/1 Running 0 8h
sentry-nginx-6545fc549b-8fx9q 1/1 Running 0 8h
sentry-rabbitmq-0 1/1 Running 0 8h
sentry-rabbitmq-1 1/1 Running 0 8h
sentry-rabbitmq-2 1/1 Running 0 8h
sentry-sentry-postgresql-0 1/1 Running 0 8h
sentry-sentry-redis-master-0 1/1 Running 0 8h
sentry-sentry-redis-replicas-0 1/1 Running 5 (66m ago) 8h
sentry-sentry-redis-replicas-1 1/1 Running 1 (65m ago) 8h
sentry-sentry-redis-replicas-2 1/1 Running 5 (66m ago) 8h
sentry-snuba-api-7cd89745f7-92cpf 1/1 Running 0 8h
sentry-snuba-cleanup-errors-27285600--1-l9wfj 0/1 Completed 0 121m
sentry-snuba-cleanup-errors-27285660--1-7wkrv 0/1 Completed 0 61m
sentry-snuba-cleanup-errors-27285720--1-x5w55 0/1 Completed 0 118s
sentry-snuba-cleanup-transactions-27285600--1-d5j66 0/1 Completed 0 121m
sentry-snuba-cleanup-transactions-27285660--1-v6jht 0/1 Completed 0 61m
sentry-snuba-cleanup-transactions-27285720--1-g86n9 0/1 Completed 0 118s
sentry-web-5ff747d6c5-p7jp8 1/1 Running 1 (8h ago) 8h
sentry-worker-8d9f7bbbc-2l7fp 0/1 Running 35 (119s ago) 3h19m
sentry-worker-8d9f7bbbc-r5pzd 0/1 Running 34 (76s ago) 3h19m
sentry-worker-8d9f7bbbc-s2dgg 0/1 Running 35 (56s ago) 3h19m
sentry-zookeeper-0 1/1 Running 0 8h

Pulumi Destroy

Destroy all resources created by Pulumi.

1
$ pulumi destroy

FAQs

502 Bad Gateway

Sentry may fail to initialize or upgrade database since it will take too long. You can do it yoursef.

First, enter into Pod sentry-web bash.

1
$ kubectl exec -n sentry `kubectl get pods -n sentry | grep sentry-web | awk '{print $2}'` -it -- bash

Then, run sentry upgrade within container to run all migrations and create an admin account.

1
$ sentry upgrade

Finally, you can visit Web UI without any error.

AssertionError: cluster_name must be set when run snuba

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
root@sentry-snuba-api-7cd89745f7-9dd2f:/usr/src/snuba# snuba migrations migrate --force
2021-11-17 01:28:07,978 Running migration: 0001_migrations
Traceback (most recent call last):
File "/usr/local/bin/snuba", line 33, in <module>
sys.exit(load_entry_point('snuba', 'console_scripts', 'snuba')())
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/usr/src/snuba/snuba/cli/migrations.py", line 64, in migrate
runner.run_all(force=force)
File "/usr/src/snuba/snuba/migrations/runner.py", line 157, in run_all
self._run_migration_impl(migration_key, force=force)
File "/usr/src/snuba/snuba/migrations/runner.py", line 215, in _run_migration_impl
migration.forwards(context, dry_run)
File "/usr/src/snuba/snuba/migrations/migration.py", line 145, in forwards
op.execute(local=True)
File "/usr/src/snuba/snuba/migrations/operations.py", line 23, in execute
nodes = cluster.get_local_nodes() if local else cluster.get_distributed_nodes()
File "/usr/src/snuba/snuba/clusters/cluster.py", line 263, in get_local_nodes
assert self.__cluster_name is not None, "cluster_name must be set"
AssertionError: cluster_name must be set

Set CLICKHOUSE_SINGLE_NODE env to true.

1
2
3
4
5
$ export CLICKHOUSE_SINGLE_NODE=true

$ snuba migrations bootstrap --force

$ snuba migrations migrate --force

References

[1] charts/stable/sentry at master · helm/charts - https://github.com/helm/charts/tree/master/stable/sentry

[2] charts/sentry at develop · sentry-kubernetes/charts - https://github.com/sentry-kubernetes/charts/tree/develop/sentry

[3] charts/values.yaml at develop · sentry-kubernetes/charts - https://github.com/sentry-kubernetes/charts/blob/develop/sentry/values.yaml

[4] Sentry | Error Tracking Software — JavaScript, Python, PHP, Ruby, more - https://sentry.io/welcome/

[5] getsentry/sentry: Sentry is cross-platform application monitoring, with a focus on error reporting. - https://github.com/getsentry/sentry

[6] Kubernetes Getting Started | Pulumi - https://www.pulumi.com/docs/get-started/kubernetes/

[7] Pulumi - Modern Infrastructure as Code - https://www.pulumi.com/

[8] Kubernetes - https://kubernetes.io/

[9] TypeScript: Typed JavaScript at Any Scale. - https://www.typescriptlang.org/

[10] Helm - https://helm.sh/