feat: introduce signoz-standalone and fix systemdcasting (#80)
#### Features
- Add standalone Docker image (docs/standalone/): single container
running all SigNoz components via systemd
casting
- Add SQLite metastore support in systemd casting (enricher, signoz
molding, forge, cast)
- Add Restart=on-failure with RestartSec=5 to migrator, ingester, and
signoz service templates to remove job readiness checks with
`After`/`Wants`/`Requires`
#### Fixes
- Enable all services before starting any (fixes Unit not found during
start)
- Use --no-block for systemctl start (prevents cast from blocking on
oneshot services)
#### Refactors
- Remove inter-service dependency coupling (After=/Requires=/Wants=)
from all service templates; services manage their own readiness via
restart policies and readiness checks
- Move config material paths from configs/<component>/ to
<component>/<kind>/
- Move IsEnabled() checks to forgeCasting dispatcher instead of
individual forge methods
- Simplify discoverAndPrepareServices and startAllService, remove
service categorization map
- Render environment variables (Spec.Env) and ClickHouse DSN in
ingester, migrator, and telemetrystore templates
Related: https://github.com/SigNoz/platform-pod/issues/1522
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
#### Auto generated by make docker-version-debian. DO NOT EDIT! ####
|
||||
amd64=8af0e5095f9964007f5ebd11191dfe52dcb51bf3afa2c07f055fc5451b78ba0e
|
||||
unknown=aa26de2aeba103c4f2232de5efe83d2b4522c26fec20c5848c9f16f2aa244b3f
|
||||
arm=159390659db54d341957fe78ef829de76e5549d0f9fcbb777287bcfc6f6da2f8
|
||||
unknown=83be97aab0d6eb03517006eea2cd7ecece54c20d3acbfe312d0ff4505dd4c344
|
||||
arm=0a52c3389a9a13dbeb3f3183578c15dfd712e17dad4feacbe55d224d0f459afa
|
||||
unknown=728313602cf4214e7e5fd2ab88fa68f2f9a8e11118ec24b04f9f05e93fd443f0
|
||||
arm64=ee5473f786ff8a4e03409277c276b459b29afa55a84268bef55342c4f705b7ad
|
||||
unknown=35e1cb927bb44a86ca8799cfe3d482a9e54e31a3995c28887c28bed9c0338bdd
|
||||
386=02274f94f52336abd6ab4a8471ea09966613910ebaeed622429dc7b4b780e804
|
||||
unknown=3cc496e7c7df2b166481306e36070238a7644af6b230646688ca3c6f675995a2
|
||||
mips64le=b5bfd550af6266602aaef6c249baebf2c9835a2d0984013a23471cd8954503ff
|
||||
ppc64le=8e69db6097e3efc0901fc84af17ea906710ae90b5842d919723eda3518ea6811
|
||||
unknown=d1dc187105900becbeca525ab9ef08efa3c71cdb4b8c67a2151e3aadc1f57a48
|
||||
s390x=a54db69bf6707382949f777f5fb8d0651d34a1b8602111a41eee7533e4ce07d8
|
||||
unknown=57ae880cf756c23f9afd4ef46b418eaae9232ea48f7c994b5c81215b58f226a7
|
||||
@@ -77,6 +77,10 @@ docker compose -f pours/deployment/compose.yaml logs -f signoz
|
||||
cd pours/deployment && docker compose down
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> - `foundryctl cast` detects whether `docker compose` (v2 plugin) or `docker-compose` (legacy standalone) is available and uses whichever it finds, preferring the v2 plugin.
|
||||
> - The `metadata.name` is used as the Compose project name (`-p` flag).
|
||||
|
||||
## Customization
|
||||
|
||||
Override component images, replicas, or environment variables in the casting spec. For platform-level changes to the generated `compose.yaml` (memory limits, networks, volumes), use [patches](../../concepts/patches.md).
|
||||
|
||||
@@ -57,6 +57,9 @@ Run the full pipeline (generate Terraform files and apply):
|
||||
foundryctl cast -f casting.yaml
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> `foundryctl cast` runs `terraform init` followed by `terraform apply -auto-approve`. If you prefer to review the plan before applying, use the step-by-step approach below.
|
||||
|
||||
Step-by-step alternative:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -40,10 +40,16 @@ Or step by step:
|
||||
# Generate values.yaml
|
||||
foundryctl forge -f casting.yaml
|
||||
|
||||
# Add the SigNoz Helm repo
|
||||
helm repo add signoz https://charts.signoz.io
|
||||
|
||||
# Install with Helm
|
||||
helm install signoz signoz/signoz -f pours/deployment/values.yaml -n signoz --create-namespace
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> `foundryctl cast` is idempotent. It detects whether a Helm release already exists and runs `helm upgrade` instead of `helm install` accordingly.
|
||||
|
||||
## Generated output
|
||||
|
||||
```text
|
||||
|
||||
@@ -39,10 +39,19 @@ Or step by step:
|
||||
# Generate manifests
|
||||
foundryctl forge -f casting.yaml
|
||||
|
||||
# Apply CRDs first (cast does this automatically)
|
||||
kubectl apply -f https://raw.githubusercontent.com/Altinity/clickhouse-operator/0.25.3/deploy/operatorhub/0.25.3/clickhouseinstallations.clickhouse.altinity.com.crd.yaml
|
||||
kubectl apply -f https://raw.githubusercontent.com/Altinity/clickhouse-operator/0.25.3/deploy/operatorhub/0.25.3/clickhouseinstallationtemplates.clickhouse.altinity.com.crd.yaml
|
||||
kubectl apply -f https://raw.githubusercontent.com/Altinity/clickhouse-operator/0.25.3/deploy/operatorhub/0.25.3/clickhouseoperatorconfigurations.clickhouse.altinity.com.crd.yaml
|
||||
kubectl apply -f https://raw.githubusercontent.com/Altinity/clickhouse-operator/0.25.3/deploy/operatorhub/0.25.3/clickhousekeeperinstallations.clickhouse-keeper.altinity.com.crd.yaml
|
||||
|
||||
# Apply with kubectl
|
||||
kubectl apply -k pours/deployment/
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> `foundryctl cast` automatically fetches and applies the four Altinity ClickHouse Operator CRDs (v0.25.3) from GitHub before running `kubectl apply -k`. If you apply manually, you must install the CRDs first or the ClickHouseInstallation and ClickHouseKeeperInstallation resources will fail to create.
|
||||
|
||||
## Generated output
|
||||
|
||||
```text
|
||||
@@ -103,3 +112,67 @@ Open `http://localhost:8080` to access the SigNoz UI.
|
||||
## Customization
|
||||
|
||||
To set resource limits, storage classes, or scheduling constraints on the generated manifests, use [patches](../../concepts/patches.md). See the [kustomize-patches](../kustomize-patches/) example for a complete working configuration.
|
||||
|
||||
### Native Kustomize patches
|
||||
|
||||
Since Foundry generates standard Kustomize bases, you can also use native Kustomize patches on the generated `kustomization.yaml`. This lets you use strategic merge patches or overlays for environment-specific customization without re-forging.
|
||||
|
||||
Use a Foundry patch to inject a `patches` block into the root `kustomization.yaml`:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1alpha1
|
||||
metadata:
|
||||
name: signoz
|
||||
spec:
|
||||
deployment:
|
||||
flavor: kustomize
|
||||
mode: kubernetes
|
||||
patches:
|
||||
- target: "deployment/kustomization.yaml"
|
||||
operations:
|
||||
- op: add
|
||||
path: /patches
|
||||
value:
|
||||
- target:
|
||||
kind: StatefulSet
|
||||
name: signoz-signoz
|
||||
patch: |-
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: signoz-signoz
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
nodeSelector:
|
||||
node-role.kubernetes.io/observability: ""
|
||||
```
|
||||
|
||||
Or create an overlay directory that references the generated base:
|
||||
|
||||
```
|
||||
my-deployment/
|
||||
├── base/ # Copy of pours/deployment/
|
||||
│ └── ...
|
||||
└── overlays/
|
||||
└── prod/
|
||||
├── kustomization.yaml
|
||||
└── increase-resources.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# overlays/prod/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../base
|
||||
patches:
|
||||
- path: increase-resources.yaml
|
||||
target:
|
||||
kind: StatefulSet
|
||||
name: signoz-clickhouse
|
||||
```
|
||||
|
||||
```bash
|
||||
kubectl apply -k overlays/prod/
|
||||
```
|
||||
|
||||
@@ -45,6 +45,9 @@ Run the full pipeline (validate prerequisites, generate files, install and start
|
||||
sudo foundryctl cast -f casting.yaml
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> `foundryctl cast` requires `sudo` because it manages systemd services, creates system users, and writes to system directories.
|
||||
|
||||
Step-by-step alternative:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -142,6 +142,8 @@ spec:
|
||||
opamp.yaml: |
|
||||
server_endpoint: ws://localhost:4320/v1/opamp
|
||||
enabled: true
|
||||
env:
|
||||
SIGNOZ_OTEL_COLLECTOR_TIMEOUT: 10m
|
||||
image: signoz/signoz-otel-collector:latest
|
||||
version: latest
|
||||
status:
|
||||
@@ -276,6 +278,8 @@ spec:
|
||||
- signozclickhousemeter
|
||||
opamp.yaml: |
|
||||
server_endpoint: ws://localhost:4320/v1/opamp
|
||||
env:
|
||||
SIGNOZ_OTEL_COLLECTOR_TIMEOUT: 10m
|
||||
metastore:
|
||||
kind: postgres
|
||||
spec:
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/opt/ingester/bin/signoz-otel-collector --config=%Y/configs/ingester/ingester.yaml --manager-config=%Y/configs/ingester/opamp.yaml --copy-path=/var/lib/ingester/ingester.yaml
|
||||
Environment=SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN=tcp://localhost:9000
|
||||
Environment=SIGNOZ_OTEL_COLLECTOR_TIMEOUT=10m
|
||||
ExecStart=/opt/ingester/bin/signoz-otel-collector --config=%Y/ingester/ingester.yaml --manager-config=%Y/ingester/opamp.yaml --copy-path=/var/lib/ingester/ingester.yaml
|
||||
ExecStartPre=/opt/ingester/bin/signoz-otel-collector migrate sync check
|
||||
Group=signoz
|
||||
KillMode=mixed
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
Type=simple
|
||||
User=signoz
|
||||
|
||||
[Unit]
|
||||
After=signoz-telemetrystore-clickhouse-0-0 signoz-telemetrystore-migrator
|
||||
Description=SigNoz OTel Collector
|
||||
Documentation=https://signoz.io/docs
|
||||
Requires=signoz-telemetrystore-migrator
|
||||
|
||||
@@ -11,12 +11,11 @@ ExecStart=/opt/signoz/bin/signoz server
|
||||
Group=signoz
|
||||
KillMode=mixed
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
Type=simple
|
||||
User=signoz
|
||||
WorkingDirectory=/opt/signoz
|
||||
|
||||
[Unit]
|
||||
After=signoz-telemetrystore-clickhouse-0-0 signoz-metastore-postgres signoz-telemetrystore-migrator
|
||||
Description=SigNoz
|
||||
Documentation=https://signoz.io/docs
|
||||
Requires=signoz-telemetrystore-migrator
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ Type=simple
|
||||
User=clickhouse
|
||||
|
||||
[Unit]
|
||||
After=time-sync.target network-online.target signoz-telemetrykeeper-clickhousekeeper-0.service
|
||||
After=time-sync.target network-online.target
|
||||
Description=ClickHouse Server (v25.5.6)
|
||||
Requires=network-online.target
|
||||
Wants=time-sync.target signoz-telemetrykeeper-clickhousekeeper-0.service
|
||||
Wants=time-sync.target
|
||||
|
||||
+7
-4
@@ -2,14 +2,17 @@
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/bash -c '/opt/ingester/bin/signoz-otel-collector migrate bootstrap --clickhouse-dsn=tcp://localhost:9000 && /opt/ingester/bin/signoz-otel-collector migrate sync up --clickhouse-dsn=tcp://localhost:9000 && /opt/ingester/bin/signoz-otel-collector migrate async up --clickhouse-dsn=tcp://localhost:9000'
|
||||
Environment=SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN=tcp://localhost:9000
|
||||
Environment=SIGNOZ_OTEL_COLLECTOR_TIMEOUT=10m
|
||||
ExecStart=/bin/bash -c '/opt/ingester/bin/signoz-otel-collector migrate bootstrap && /opt/ingester/bin/signoz-otel-collector migrate sync up && /opt/ingester/bin/signoz-otel-collector migrate async up'
|
||||
ExecStartPre=/opt/ingester/bin/signoz-otel-collector migrate ready
|
||||
Group=signoz
|
||||
RemainAfterExit=yes
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
Type=oneshot
|
||||
User=signoz
|
||||
|
||||
[Unit]
|
||||
After=signoz-telemetrystore-clickhouse-0-0
|
||||
Description=SigNoz Schema Migrator
|
||||
Description=SigNoz TelemetryStore Migrator
|
||||
Documentation=https://signoz.io/docs
|
||||
Requires=signoz-telemetrystore-clickhouse-0-0
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
ARG DEBIAN_SHA="pass-a-valid-docker-sha-otherwise-this-will-fail"
|
||||
|
||||
FROM debian@sha256:${DEBIAN_SHA}
|
||||
LABEL maintainer="signoz"
|
||||
|
||||
ARG OS="linux"
|
||||
ARG ARCH
|
||||
|
||||
ARG SIGNOZ_VERSION=latest
|
||||
ARG INGESTER_VERSION=latest
|
||||
ARG FOUNDRY_VERSION=latest
|
||||
|
||||
# Install systemd
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
systemd \
|
||||
systemd-sysv \
|
||||
ca-certificates \
|
||||
curl \
|
||||
tar \
|
||||
gnupg && \
|
||||
rm -f /lib/systemd/system/multi-user.target.wants/* \
|
||||
/etc/systemd/system/*.wants/* \
|
||||
/lib/systemd/system/local-fs.target.wants/* \
|
||||
/lib/systemd/system/sockets.target.wants/*udev* \
|
||||
/lib/systemd/system/sockets.target.wants/*initctl* \
|
||||
/lib/systemd/system/sysinit.target.wants/systemd-tmpfiles-setup* \
|
||||
/lib/systemd/system/systemd-update-utmp*
|
||||
|
||||
# SigNoz
|
||||
RUN mkdir -p /opt/signoz && \
|
||||
curl -fsSL "https://github.com/SigNoz/signoz/releases/${SIGNOZ_VERSION}/download/signoz_${OS}_${ARCH}.tar.gz" | \
|
||||
tar -xz --strip-components=1 -C /opt/signoz && \
|
||||
chmod +x /opt/signoz/bin/signoz
|
||||
|
||||
# OTel Collector (ingester)
|
||||
RUN mkdir -p /opt/ingester && \
|
||||
curl -fsSL "https://github.com/SigNoz/signoz-otel-collector/releases/${INGESTER_VERSION}/download/signoz-otel-collector_${OS}_${ARCH}.tar.gz" | \
|
||||
tar -xz --strip-components=1 -C /opt/ingester && \
|
||||
chmod +x /opt/ingester/bin/signoz-otel-collector
|
||||
|
||||
# Foundry
|
||||
RUN mkdir -p /usr/local/bin && \
|
||||
curl -fsSL "https://github.com/SigNoz/foundry/releases/${FOUNDRY_VERSION}/download/foundry_${OS}_${ARCH}.tar.gz" | \
|
||||
tar -xz --strip-components=1 -C /tmp && \
|
||||
mv /tmp/bin/foundryctl /usr/local/bin/foundryctl && \
|
||||
chmod +x /usr/local/bin/foundryctl
|
||||
|
||||
|
||||
# Install ClickHouse from apt repo
|
||||
RUN curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | \
|
||||
gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg && \
|
||||
echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] https://packages.clickhouse.com/deb stable main" \
|
||||
> /etc/apt/sources.list.d/clickhouse.list && \
|
||||
apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
clickhouse-server \
|
||||
clickhouse-client && \
|
||||
systemctl disable clickhouse-server || true
|
||||
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN useradd -r -m -d /opt/signoz -s /bin/false signoz && \
|
||||
mkdir -p /var/lib/signoz /var/lib/ingester /etc/foundry /opt/signoz/web && \
|
||||
chown signoz:signoz /var/lib/signoz /var/lib/ingester /opt/signoz
|
||||
|
||||
COPY docs/standalone/casting.yaml /etc/foundry/casting.yaml
|
||||
COPY docs/standalone/foundry-setup.service /etc/systemd/system/foundry-setup.service
|
||||
RUN mkdir -p /var/lib/foundry && systemctl enable foundry-setup.service
|
||||
|
||||
EXPOSE 8080 4317 4318
|
||||
VOLUME ["/var/lib/clickhouse", "/var/lib/signoz"]
|
||||
|
||||
STOPSIGNAL SIGRTMIN+3
|
||||
CMD ["/sbin/init"]
|
||||
@@ -0,0 +1,86 @@
|
||||
# Standalone Docker Image
|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
| **Casting** | `systemd` / `binary` |
|
||||
| **Use Case** | Single Docker image for quick testing, development, and CI |
|
||||
|
||||
## Overview
|
||||
|
||||
An OpenTelemetry-native observability backend in a single Docker image. The standalone image bundles all SigNoz components into one container for development, demo, and testing environments.
|
||||
|
||||
**Included components:**
|
||||
|
||||
- **SigNoz** - query engine and UI
|
||||
- **OpenTelemetry Collector** - telemetry ingestion
|
||||
- **ClickHouse** - telemetry storage
|
||||
- **SQLite** - metadata storage
|
||||
- **[Foundry](https://github.com/SigNoz/foundry)** - deployment orchestration via `foundryctl`
|
||||
|
||||
Applications can send telemetry using OpenTelemetry's standard defaults (OTLP gRPC/HTTP) without additional configuration. On first boot, Foundry generates all service configs and starts components via systemd.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Engine 20.10+
|
||||
|
||||
## Deploy
|
||||
|
||||
```bash
|
||||
docker run -d --name signoz --privileged \
|
||||
-p 8080:8080 \
|
||||
-p 4317:4317 \
|
||||
-p 4318:4318 \
|
||||
signoz/signoz-standalone:latest
|
||||
```
|
||||
|
||||
Access SigNoz UI at `http://localhost:8080`.
|
||||
|
||||
Send telemetry to:
|
||||
|
||||
- OTLP gRPC: `localhost:4317`
|
||||
- OTLP HTTP: `localhost:4318`
|
||||
|
||||
## Customization
|
||||
|
||||
To customize the deployment, mount your own `casting.yaml` into the container:
|
||||
|
||||
```bash
|
||||
docker run -d --name signoz --privileged \
|
||||
-p 8080:8080 \
|
||||
-p 4317:4317 \
|
||||
-p 4318:4318 \
|
||||
-v ./casting.yaml:/etc/foundry/casting.yaml \
|
||||
signoz/signoz-standalone:latest
|
||||
```
|
||||
|
||||
See the default [casting.yaml](casting.yaml) for the full config structure.
|
||||
|
||||
## Persist Data
|
||||
|
||||
```bash
|
||||
docker run -d --name signoz --privileged \
|
||||
-p 8080:8080 \
|
||||
-p 4317:4317 \
|
||||
-p 4318:4318 \
|
||||
-v signoz-clickhouse:/var/lib/clickhouse \
|
||||
-v signoz-data:/var/lib/signoz \
|
||||
signoz/signoz-standalone:latest
|
||||
```
|
||||
|
||||
## After deployment
|
||||
|
||||
```bash
|
||||
# View logs for all services
|
||||
docker exec signoz journalctl -f
|
||||
|
||||
# View logs for a specific service
|
||||
docker exec signoz journalctl -u signoz-signoz.service -f
|
||||
docker exec signoz journalctl -u signoz-ingester.service -f
|
||||
docker exec signoz journalctl -u signoz-telemetrystore-clickhouse-0-0.service -f
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
- Requires `--privileged` flag (systemd needs cgroup access)
|
||||
- `docker logs` is empty - use `journalctl` inside the container
|
||||
- Single-node only (no clustering)
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1alpha1
|
||||
metadata:
|
||||
name: signoz
|
||||
annotations:
|
||||
foundry.signoz.io/signoz-binary-path: /opt/signoz/bin/signoz
|
||||
foundry.signoz.io/ingester-binary-path: /opt/ingester/bin/signoz-otel-collector
|
||||
spec:
|
||||
deployment:
|
||||
flavor: binary
|
||||
mode: systemd
|
||||
metastore:
|
||||
kind: sqlite
|
||||
@@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Foundry Setup - SigNoz Standalone
|
||||
After=multi-user.target
|
||||
ConditionPathExists=!/var/lib/foundry/.initialized
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/usr/local/bin/foundryctl cast -f /etc/foundry/casting.yaml -p /etc/foundry/pours --no-gauge
|
||||
ExecStartPost=/bin/touch /var/lib/foundry/.initialized
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -22,10 +22,6 @@ import (
|
||||
|
||||
const svcSuffix = ".service"
|
||||
|
||||
const (
|
||||
serviceStartTimeout = 2 * time.Minute
|
||||
)
|
||||
|
||||
var _ rootcasting.Casting = (*systemdCasting)(nil)
|
||||
|
||||
type systemdCasting struct {
|
||||
@@ -54,7 +50,7 @@ func (c *systemdCasting) Enricher(ctx context.Context, config *v1alpha1.Casting)
|
||||
func (c *systemdCasting) Forge(ctx context.Context, cfg v1alpha1.Casting, poursPath string) ([]types.Material, error) {
|
||||
var materials []types.Material
|
||||
for _, tmpl := range c.castings {
|
||||
m, err := c.forgeCasting(tmpl, &cfg, poursPath)
|
||||
m, err := c.forgeCasting(tmpl, &cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to forge: %w", err)
|
||||
}
|
||||
@@ -70,11 +66,11 @@ func (c *systemdCasting) Cast(ctx context.Context, config v1alpha1.Casting, pour
|
||||
defer cancel()
|
||||
|
||||
// Discover and prepare services
|
||||
serviceMap, err := c.discoverAndPrepareServices(runctx, poursPath)
|
||||
services, err := c.discoverAndPrepareServices(runctx, poursPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if serviceMap == nil {
|
||||
if len(services) == 0 {
|
||||
c.logger.WarnContext(runctx, "No service files found in pours directory")
|
||||
return nil
|
||||
}
|
||||
@@ -85,13 +81,21 @@ func (c *systemdCasting) Cast(ctx context.Context, config v1alpha1.Casting, pour
|
||||
}
|
||||
|
||||
if config.Spec.MetaStore.Spec.IsEnabled() {
|
||||
if err := c.initializePostgres(ctx, &config); err != nil {
|
||||
return err
|
||||
switch config.Spec.MetaStore.Kind {
|
||||
case v1alpha1.MetaStoreKindPostgres:
|
||||
if err := c.initializePostgres(ctx, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
case v1alpha1.MetaStoreKindSQLite:
|
||||
if err := os.MkdirAll("/var/lib/signoz", 0755); err != nil {
|
||||
return fmt.Errorf("failed to create sqlite data directory: %w", err)
|
||||
}
|
||||
_ = c.execCommand(ctx, "chown", "-R", "signoz:signoz", "/var/lib/signoz")
|
||||
}
|
||||
}
|
||||
|
||||
// Start all services - systemd dependencies handle ordering
|
||||
if err := c.startAllServices(runctx, serviceMap); err != nil {
|
||||
if err := c.startAllServices(runctx, services); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -99,115 +103,113 @@ func (c *systemdCasting) Cast(ctx context.Context, config v1alpha1.Casting, pour
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *systemdCasting) forgeCasting(tmpl *types.Template, cfg *v1alpha1.Casting, poursPath string) ([]types.Material, error) {
|
||||
func (c *systemdCasting) forgeCasting(tmpl *types.Template, cfg *v1alpha1.Casting) ([]types.Material, error) {
|
||||
switch tmpl {
|
||||
case signozServiceTemplate:
|
||||
if !cfg.Spec.Signoz.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
return c.forgeSignoz(tmpl, cfg)
|
||||
case metaStoreServiceTemplate:
|
||||
return c.forgeMetaStore(tmpl, cfg, poursPath)
|
||||
if !cfg.Spec.MetaStore.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
return c.forgeMetaStore(tmpl, cfg)
|
||||
case ingesterServiceTemplate:
|
||||
return c.forgeIngester(tmpl, cfg, poursPath)
|
||||
if !cfg.Spec.Ingester.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
return c.forgeIngester(tmpl, cfg)
|
||||
case telemetryStoreServiceTemplate:
|
||||
return c.forgeTelemetryStore(tmpl, cfg, poursPath)
|
||||
if !cfg.Spec.TelemetryStore.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
return c.forgeTelemetryStore(tmpl, cfg)
|
||||
case telemetryKeeperServiceTemplate:
|
||||
return c.forgeTelemetryKeeper(tmpl, cfg, poursPath)
|
||||
if !cfg.Spec.TelemetryKeeper.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
return c.forgeTelemetryKeeper(tmpl, cfg)
|
||||
case telemetryStoreMigratorServiceTemplate:
|
||||
if !cfg.Spec.TelemetryStore.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
return c.forgeMigrator(tmpl, cfg)
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// --- Forge Handlers ---
|
||||
|
||||
func (c *systemdCasting) forgeIngester(tmpl *types.Template, cfg *v1alpha1.Casting, poursPath string) ([]types.Material, error) {
|
||||
func (c *systemdCasting) forgeIngester(tmpl *types.Template, cfg *v1alpha1.Casting) ([]types.Material, error) {
|
||||
spec := &cfg.Spec.Ingester
|
||||
if !spec.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
if spec.Status.Config.Data == nil {
|
||||
return nil, fmt.Errorf("no config molded for %s", v1alpha1.MoldingKindIngester)
|
||||
}
|
||||
|
||||
// Initialize status extras
|
||||
if spec.Status.Extras == nil {
|
||||
spec.Status.Extras = make(map[string]string)
|
||||
}
|
||||
|
||||
// Create config materials
|
||||
mats, err := c.configMaterials(spec.Status.Config.Data, "ingester")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set extras for template
|
||||
spec.Status.Extras["cfgPath"] = "configs/ingester/ingester.yaml"
|
||||
spec.Status.Extras["cfgOpampPath"] = "configs/ingester/opamp.yaml"
|
||||
spec.Status.Extras["cfgPath"] = filepath.Join("ingester", "ingester.yaml")
|
||||
spec.Status.Extras["cfgOpampPath"] = filepath.Join("ingester", "opamp.yaml")
|
||||
spec.Status.Extras["workingDir"] = "/opt/ingester"
|
||||
|
||||
// Create service material
|
||||
var materials []types.Material
|
||||
|
||||
svcMat, err := c.renderTemplate(tmpl, cfg, cfg.Metadata.Name+"-ingester"+svcSuffix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(mats, svcMat), nil
|
||||
materials = append(materials, svcMat)
|
||||
|
||||
cfgMats, err := c.configMaterials(spec.Spec.Config.Data, "ingester", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
materials = append(materials, cfgMats...)
|
||||
|
||||
return materials, nil
|
||||
}
|
||||
|
||||
func (c *systemdCasting) forgeSignoz(tmpl *types.Template, cfg *v1alpha1.Casting) ([]types.Material, error) {
|
||||
spec := &cfg.Spec.Signoz
|
||||
if !spec.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Initialize status maps
|
||||
if spec.Status.Extras == nil {
|
||||
spec.Status.Extras = make(map[string]string)
|
||||
}
|
||||
|
||||
// Create env material
|
||||
prefix := cfg.Metadata.Name + "-signoz"
|
||||
|
||||
spec.Status.Extras["workingDir"] = "/opt/signoz"
|
||||
|
||||
// Create service material
|
||||
svcMat, err := c.renderTemplate(tmpl, cfg, prefix+svcSuffix)
|
||||
var materials []types.Material
|
||||
|
||||
svcMat, err := c.renderTemplate(tmpl, cfg, cfg.Metadata.Name+"-signoz"+svcSuffix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []types.Material{svcMat}, nil
|
||||
materials = append(materials, svcMat)
|
||||
|
||||
return materials, nil
|
||||
}
|
||||
|
||||
func (c *systemdCasting) forgeMetaStore(tmpl *types.Template, cfg *v1alpha1.Casting, poursPath string) ([]types.Material, error) {
|
||||
func (c *systemdCasting) forgeMetaStore(tmpl *types.Template, cfg *v1alpha1.Casting) ([]types.Material, error) {
|
||||
spec := &cfg.Spec.MetaStore
|
||||
if !spec.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Initialize status extras
|
||||
if spec.Status.Extras == nil {
|
||||
spec.Status.Extras = make(map[string]string)
|
||||
}
|
||||
|
||||
// Create env material
|
||||
prefix := fmt.Sprintf("%s-metastore-%s", cfg.Metadata.Name, spec.Kind.String())
|
||||
// Create service material
|
||||
svcMat, err := c.renderTemplate(tmpl, cfg, prefix+svcSuffix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var materials []types.Material
|
||||
|
||||
switch spec.Kind {
|
||||
case v1alpha1.MetaStoreKindPostgres:
|
||||
svcMat, err := c.renderTemplate(tmpl, cfg, fmt.Sprintf("%s-metastore-%s%s", cfg.Metadata.Name, spec.Kind.String(), svcSuffix))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
materials = append(materials, svcMat)
|
||||
}
|
||||
return []types.Material{svcMat}, nil
|
||||
|
||||
return materials, nil
|
||||
}
|
||||
|
||||
func (c *systemdCasting) forgeTelemetryStore(tmpl *types.Template, cfg *v1alpha1.Casting, poursPath string) ([]types.Material, error) {
|
||||
func (c *systemdCasting) forgeTelemetryStore(tmpl *types.Template, cfg *v1alpha1.Casting) ([]types.Material, error) {
|
||||
spec := &cfg.Spec.TelemetryStore
|
||||
if !spec.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
if spec.Status.Config.Data == nil {
|
||||
return nil, fmt.Errorf("no config molded for %s", v1alpha1.MoldingKindTelemetryStore)
|
||||
}
|
||||
|
||||
// Initialize status extras
|
||||
if spec.Status.Extras == nil {
|
||||
spec.Status.Extras = make(map[string]string)
|
||||
}
|
||||
@@ -216,36 +218,30 @@ func (c *systemdCasting) forgeTelemetryStore(tmpl *types.Template, cfg *v1alpha1
|
||||
reps := max(1, *spec.Spec.Cluster.Replicas+1)
|
||||
shards := max(1, *spec.Spec.Cluster.Shards)
|
||||
|
||||
// Create config materials
|
||||
mats, err := c.configMaterials(spec.Status.Config.Data, "telemetrystore")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var materials []types.Material
|
||||
|
||||
// Create service materials for each shard/replica
|
||||
for s := range shards {
|
||||
for r := range reps {
|
||||
svcName := fmt.Sprintf("%s-telemetrystore-%s-%d-%d%s", cfg.Metadata.Name, kind, s, r, svcSuffix)
|
||||
svcMat, err := c.renderTemplate(tmpl, cfg, svcName)
|
||||
svcMat, err := c.renderTemplate(tmpl, cfg, fmt.Sprintf("%s-telemetrystore-%s-%d-%d%s", cfg.Metadata.Name, kind, s, r, svcSuffix))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mats = append(mats, svcMat)
|
||||
materials = append(materials, svcMat)
|
||||
}
|
||||
}
|
||||
return mats, nil
|
||||
|
||||
cfgMats, err := c.configMaterials(spec.Spec.Config.Data, "telemetrystore", kind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
materials = append(materials, cfgMats...)
|
||||
|
||||
return materials, nil
|
||||
}
|
||||
|
||||
func (c *systemdCasting) forgeTelemetryKeeper(tmpl *types.Template, cfg *v1alpha1.Casting, poursPath string) ([]types.Material, error) {
|
||||
func (c *systemdCasting) forgeTelemetryKeeper(tmpl *types.Template, cfg *v1alpha1.Casting) ([]types.Material, error) {
|
||||
spec := &cfg.Spec.TelemetryKeeper
|
||||
if !spec.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
if spec.Status.Config.Data == nil {
|
||||
return nil, fmt.Errorf("no config molded for %s", v1alpha1.MoldingKindTelemetryKeeper)
|
||||
}
|
||||
|
||||
// Initialize status extras
|
||||
if spec.Status.Extras == nil {
|
||||
spec.Status.Extras = make(map[string]string)
|
||||
}
|
||||
@@ -253,42 +249,53 @@ func (c *systemdCasting) forgeTelemetryKeeper(tmpl *types.Template, cfg *v1alpha
|
||||
kind := spec.Kind.String()
|
||||
reps := max(1, *spec.Spec.Cluster.Replicas)
|
||||
|
||||
// Create config materials
|
||||
mats, err := c.configMaterials(spec.Status.Config.Data, "telemetrykeeper")
|
||||
// Config materials are created first because cfgPath extra is derived from them
|
||||
cfgMats, err := c.configMaterials(spec.Spec.Config.Data, "telemetrykeeper", kind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cfgMats) > 0 {
|
||||
spec.Status.Extras["cfgPath"] = filepath.Join("/etc/clickhouse-keeper/", filepath.Base(cfgMats[0].Path()))
|
||||
}
|
||||
|
||||
// Set config path for template
|
||||
spec.Status.Extras["cfgPath"] = filepath.Join("/etc/clickhouse-keeper/", filepath.Base(mats[0].Path()))
|
||||
var materials []types.Material
|
||||
|
||||
// Create service materials for each replica
|
||||
for r := range reps {
|
||||
svcName := fmt.Sprintf("%s-telemetrykeeper-%s-%d%s", cfg.Metadata.Name, kind, r, svcSuffix)
|
||||
svcMat, err := c.renderTemplate(tmpl, cfg, svcName)
|
||||
svcMat, err := c.renderTemplate(tmpl, cfg, fmt.Sprintf("%s-telemetrykeeper-%s-%d%s", cfg.Metadata.Name, kind, r, svcSuffix))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mats = append(mats, svcMat)
|
||||
materials = append(materials, svcMat)
|
||||
}
|
||||
return mats, nil
|
||||
|
||||
materials = append(materials, cfgMats...)
|
||||
|
||||
return materials, nil
|
||||
}
|
||||
|
||||
func (c *systemdCasting) forgeMigrator(tmpl *types.Template, cfg *v1alpha1.Casting) ([]types.Material, error) {
|
||||
spec := &cfg.Spec.TelemetryStore
|
||||
if !spec.Spec.IsEnabled() {
|
||||
return nil, nil
|
||||
}
|
||||
var materials []types.Material
|
||||
|
||||
// Create service material
|
||||
svcMat, err := c.renderTemplate(tmpl, cfg, cfg.Metadata.Name+"-telemetrystore-migrator"+svcSuffix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []types.Material{svcMat}, nil
|
||||
materials = append(materials, svcMat)
|
||||
|
||||
return materials, nil
|
||||
}
|
||||
|
||||
// --- Material Helpers ---
|
||||
func (c *systemdCasting) configMaterials(data map[string]string, component string, kind string) ([]types.Material, error) {
|
||||
mats := make([]types.Material, 0, len(data))
|
||||
for filename, content := range data {
|
||||
m, err := types.NewYAMLMaterial([]byte(content), filepath.Join(rootcasting.DeploymentDir, component, kind, filename))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create %s config material %s: %w", component, filename, err)
|
||||
}
|
||||
mats = append(mats, m)
|
||||
}
|
||||
return mats, nil
|
||||
}
|
||||
|
||||
func (c *systemdCasting) renderTemplate(tmpl *types.Template, cfg *v1alpha1.Casting, path string) (types.Material, error) {
|
||||
var buf bytes.Buffer
|
||||
@@ -298,18 +305,6 @@ func (c *systemdCasting) renderTemplate(tmpl *types.Template, cfg *v1alpha1.Cast
|
||||
return types.NewINIMaterial(buf.Bytes(), filepath.Join(rootcasting.DeploymentDir, path))
|
||||
}
|
||||
|
||||
func (c *systemdCasting) configMaterials(data map[string]string, path string) ([]types.Material, error) {
|
||||
mats := make([]types.Material, 0, len(data))
|
||||
for file, content := range data {
|
||||
m, err := types.NewYAMLMaterial([]byte(content), filepath.Join(rootcasting.DeploymentDir, "configs/", path, file))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create config material %s: %w", file, err)
|
||||
}
|
||||
mats = append(mats, m)
|
||||
}
|
||||
return mats, nil
|
||||
}
|
||||
|
||||
// execCommand executes a command and returns an error if it fails.
|
||||
func (c *systemdCasting) execCommand(ctx context.Context, name string, args ...string) error {
|
||||
cmd := exec.CommandContext(ctx, name, args...)
|
||||
@@ -318,61 +313,33 @@ func (c *systemdCasting) execCommand(ctx context.Context, name string, args ...s
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
// discoverAndPrepareServices discovers service files, categorizes them, and prepares systemd.
|
||||
// Returns nil serviceMap if no services found.
|
||||
func (c *systemdCasting) discoverAndPrepareServices(ctx context.Context, poursPath string) (map[string][]string, error) {
|
||||
// discoverAndPrepareServices discovers service files in the pours directory and reloads systemd.
|
||||
func (c *systemdCasting) discoverAndPrepareServices(ctx context.Context, poursPath string) ([]string, error) {
|
||||
deploymentPath := filepath.Join(poursPath, rootcasting.DeploymentDir)
|
||||
entries, err := os.ReadDir(deploymentPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read directory %s: %w", deploymentPath, err)
|
||||
}
|
||||
|
||||
serviceMap := map[string][]string{"keeper": {}, "store": {}, "postgres": {}, "signoz": {}, "ingester": {}, "migrator": {}}
|
||||
|
||||
var services []string
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".service") {
|
||||
if entry.IsDir() || !strings.HasSuffix(entry.Name(), svcSuffix) {
|
||||
continue
|
||||
}
|
||||
servicePath := filepath.Join(deploymentPath, entry.Name())
|
||||
baseName := strings.TrimSuffix(entry.Name(), ".service")
|
||||
|
||||
switch {
|
||||
case strings.HasSuffix(baseName, "-migrator"):
|
||||
serviceMap["migrator"] = append(serviceMap["migrator"], servicePath)
|
||||
case strings.Contains(baseName, "-telemetrykeeper-") && !strings.Contains(baseName, "-migrator"):
|
||||
serviceMap["keeper"] = append(serviceMap["keeper"], servicePath)
|
||||
case strings.Contains(baseName, "-telemetrystore-") && !strings.Contains(baseName, "-migrator"):
|
||||
serviceMap["store"] = append(serviceMap["store"], servicePath)
|
||||
case strings.Contains(baseName, "-metastore-postgres"):
|
||||
serviceMap["postgres"] = append(serviceMap["postgres"], servicePath)
|
||||
case strings.HasSuffix(baseName, "-signoz"):
|
||||
serviceMap["signoz"] = append(serviceMap["signoz"], servicePath)
|
||||
case strings.HasSuffix(baseName, "-ingester"):
|
||||
serviceMap["ingester"] = append(serviceMap["ingester"], servicePath)
|
||||
default:
|
||||
c.logger.WarnContext(ctx, "Unknown service type, skipping", slog.String("service", servicePath))
|
||||
}
|
||||
services = append(services, filepath.Join(deploymentPath, entry.Name()))
|
||||
}
|
||||
|
||||
// Check if any services were found
|
||||
total := 0
|
||||
for cat, svcs := range serviceMap {
|
||||
if len(svcs) > 0 {
|
||||
c.logger.DebugContext(ctx, "Found services", slog.String("category", cat), slog.Int("count", len(svcs)))
|
||||
total += len(svcs)
|
||||
}
|
||||
}
|
||||
if total == 0 {
|
||||
return map[string][]string{}, nil
|
||||
if len(services) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Reload systemd to pick up new service files
|
||||
c.logger.DebugContext(ctx, "Reloading systemd daemon")
|
||||
c.logger.DebugContext(ctx, "Found services", slog.Int("count", len(services)))
|
||||
|
||||
if err := c.execCommand(ctx, "systemctl", "daemon-reload"); err != nil {
|
||||
return nil, fmt.Errorf("systemd daemon-reload failed: %w", err)
|
||||
}
|
||||
|
||||
return serviceMap, nil
|
||||
return services, nil
|
||||
}
|
||||
|
||||
// setupSystemEnvironment creates signoz user, directories, copies configs, and validates binaries.
|
||||
@@ -394,12 +361,14 @@ func (c *systemdCasting) setupSystemEnvironment(ctx context.Context, config *v1a
|
||||
|
||||
// Copy clickhouse configs to standard locations
|
||||
if config.Spec.TelemetryStore.Spec.IsEnabled() {
|
||||
if err := c.copyDir(filepath.Join(poursPath, rootcasting.DeploymentDir, "configs", "telemetrystore"), "/etc/clickhouse-server/"); err != nil {
|
||||
src := filepath.Join(poursPath, rootcasting.DeploymentDir, "telemetrystore", config.Spec.TelemetryStore.Kind.String())
|
||||
if err := c.copyDir(src, "/etc/clickhouse-server/"); err != nil {
|
||||
return fmt.Errorf("failed to copy clickhouse-server configs: %w", err)
|
||||
}
|
||||
}
|
||||
if config.Spec.TelemetryKeeper.Spec.IsEnabled() {
|
||||
if err := c.copyDir(filepath.Join(poursPath, rootcasting.DeploymentDir, "configs", "telemetrykeeper"), "/etc/clickhouse-keeper/"); err != nil {
|
||||
src := filepath.Join(poursPath, rootcasting.DeploymentDir, "telemetrykeeper", config.Spec.TelemetryKeeper.Kind.String())
|
||||
if err := c.copyDir(src, "/etc/clickhouse-keeper/"); err != nil {
|
||||
return fmt.Errorf("failed to copy clickhouse-keeper configs: %w", err)
|
||||
}
|
||||
}
|
||||
@@ -463,32 +432,28 @@ func (c *systemdCasting) validateBinaries(config *v1alpha1.Casting) error {
|
||||
}
|
||||
|
||||
// startAllServices enables and starts all discovered services.
|
||||
// Systemd dependencies ensure proper ordering.
|
||||
func (c *systemdCasting) startAllServices(ctx context.Context, serviceMap map[string][]string) error {
|
||||
// Collect all services
|
||||
var allServices []string
|
||||
for _, services := range serviceMap {
|
||||
allServices = append(allServices, services...)
|
||||
}
|
||||
|
||||
if len(allServices) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enable and start all services - systemd will handle ordering via dependencies
|
||||
for _, svc := range allServices {
|
||||
// All services are enabled first so that dependency references resolve,
|
||||
// then started — systemd handles ordering via After=/Requires=.
|
||||
func (c *systemdCasting) startAllServices(ctx context.Context, services []string) error {
|
||||
// Enable all services first so dependencies can be resolved
|
||||
for _, svc := range services {
|
||||
unitName := filepath.Base(svc)
|
||||
c.logger.DebugContext(ctx, "Enabling service", slog.String("service", unitName), slog.String("path", svc))
|
||||
// Use full path for enable - systemctl can work with paths to service files
|
||||
c.logger.DebugContext(ctx, "Enabling service", slog.String("service", unitName))
|
||||
if err := c.execCommand(ctx, "systemctl", "enable", svc); err != nil {
|
||||
return fmt.Errorf("failed to enable service %s: %w", unitName, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Reload systemd to pick up all enabled services
|
||||
if err := c.execCommand(ctx, "systemctl", "daemon-reload"); err != nil {
|
||||
return fmt.Errorf("systemd daemon-reload failed: %w", err)
|
||||
}
|
||||
|
||||
// Start all services without blocking — systemd dependencies handle ordering
|
||||
for _, svc := range services {
|
||||
unitName := filepath.Base(svc)
|
||||
c.logger.InfoContext(ctx, "Starting service", slog.String("service", unitName))
|
||||
startCtx, cancel := context.WithTimeout(ctx, serviceStartTimeout)
|
||||
// Use full path for start as well
|
||||
err := c.execCommand(startCtx, "systemctl", "start", unitName)
|
||||
cancel()
|
||||
if err != nil {
|
||||
if err := c.execCommand(ctx, "systemctl", "start", "--no-block", unitName); err != nil {
|
||||
return fmt.Errorf("failed to start service %s: %w", unitName, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,20 +97,25 @@ func (e *linuxMoldingEnricher) enrichTelemetryKeeper(config *v1alpha1.Casting) e
|
||||
}
|
||||
|
||||
func (e *linuxMoldingEnricher) enrichMetaStore(config *v1alpha1.Casting) error {
|
||||
dsn := types.FormatAddress("postgres", "localhost", baseMetaStorePostgresPort)
|
||||
config.Spec.MetaStore.Status.Addresses.DSN = []string{dsn}
|
||||
switch config.Spec.MetaStore.Kind {
|
||||
case v1alpha1.MetaStoreKindSQLite:
|
||||
// SQLite — no addresses or binaries to enrich.
|
||||
case v1alpha1.MetaStoreKindPostgres:
|
||||
dsn := types.FormatAddress("postgres", "localhost", baseMetaStorePostgresPort)
|
||||
config.Spec.MetaStore.Status.Addresses.DSN = []string{dsn}
|
||||
|
||||
// Get the annotation value
|
||||
metastoreBin := config.Metadata.Annotations["foundry.signoz.io/metastore-postgres-binary-path"]
|
||||
// Get the annotation value
|
||||
metastoreBin := config.Metadata.Annotations["foundry.signoz.io/metastore-postgres-binary-path"]
|
||||
|
||||
// If it's missing, apply the default and write it back
|
||||
if metastoreBin == "" {
|
||||
metastoreBin = "/usr/bin/postgres"
|
||||
// If it's missing, apply the default and write it back
|
||||
if metastoreBin == "" {
|
||||
metastoreBin = "/usr/bin/postgres"
|
||||
|
||||
if config.Metadata.Annotations == nil {
|
||||
config.Metadata.Annotations = make(map[string]string)
|
||||
if config.Metadata.Annotations == nil {
|
||||
config.Metadata.Annotations = make(map[string]string)
|
||||
}
|
||||
config.Metadata.Annotations["foundry.signoz.io/metastore-postgres-binary-path"] = metastoreBin
|
||||
}
|
||||
config.Metadata.Annotations["foundry.signoz.io/metastore-postgres-binary-path"] = metastoreBin
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -157,5 +162,10 @@ func (e *linuxMoldingEnricher) enrichIngester(config *v1alpha1.Casting) error {
|
||||
config.Metadata.Annotations["foundry.signoz.io/ingester-binary-path"] = ingesterBin
|
||||
}
|
||||
|
||||
if config.Spec.Ingester.Status.Env == nil {
|
||||
config.Spec.Ingester.Status.Env = make(map[string]string)
|
||||
}
|
||||
config.Spec.Ingester.Status.Env["SIGNOZ_OTEL_COLLECTOR_TIMEOUT"] = "10m"
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+6
-4
@@ -1,9 +1,8 @@
|
||||
[Unit]
|
||||
Description=ClickHouse Server (v25.5.6)
|
||||
Requires=network-online.target
|
||||
After=time-sync.target network-online.target{{ if $.Spec.TelemetryKeeper.Spec.Enabled }} {{ $.Metadata.Name }}-telemetrykeeper-{{ $.Spec.TelemetryKeeper.Kind }}-0.service{{ end }}
|
||||
Wants=time-sync.target{{ if $.Spec.TelemetryKeeper.Spec.Enabled }} {{ $.Metadata.Name }}-telemetrykeeper-{{ $.Spec.TelemetryKeeper.Kind }}-0.service{{ end }}
|
||||
|
||||
After=time-sync.target network-online.target
|
||||
Wants=time-sync.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
@@ -13,9 +12,12 @@ Restart=always
|
||||
RestartSec=30
|
||||
RuntimeDirectory=clickhouse
|
||||
ExecStart=/usr/bin/clickhouse-server --config=/etc/clickhouse-server/config.yaml --pid-file=/run/clickhouse/clickhouse.pid
|
||||
{{- range $key, $value := $.Spec.TelemetryStore.Spec.Env }}
|
||||
Environment={{ $key }}={{ $value }}
|
||||
{{- end }}
|
||||
LimitCORE=infinity
|
||||
LimitNOFILE=500000
|
||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_IPC_LOCK CAP_SYS_NICE CAP_NET_BIND_SERVICE
|
||||
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
+5
-2
@@ -11,9 +11,12 @@ Group=clickhouse
|
||||
Restart=always
|
||||
RestartSec=30
|
||||
RuntimeDirectory=clickhouse-keeper
|
||||
{{ if and $.Spec.TelemetryKeeper.Status.Extras (index $.Spec.TelemetryKeeper.Status.Extras "cfgPath") }}
|
||||
{{- if and $.Spec.TelemetryKeeper.Status.Extras (index $.Spec.TelemetryKeeper.Status.Extras "cfgPath") }}
|
||||
ExecStart=/usr/bin/clickhouse-keeper --config={{ index $.Spec.TelemetryKeeper.Status.Extras "cfgPath" }} --pid-file=/run/clickhouse-keeper/clickhouse-keeper.pid
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := $.Spec.TelemetryKeeper.Spec.Env }}
|
||||
Environment={{ $key }}={{ $value }}
|
||||
{{- end }}
|
||||
LimitCORE=infinity
|
||||
LimitNOFILE=500000
|
||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_IPC_LOCK CAP_SYS_NICE CAP_NET_BIND_SERVICE
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
[Unit]
|
||||
Description=SigNoz OTel Collector
|
||||
Documentation=https://signoz.io/docs
|
||||
After={{ $.Metadata.Name }}-telemetrystore-{{ $.Spec.TelemetryStore.Kind }}-0-0{{ if $.Spec.TelemetryStore.Spec.Enabled }} {{ $.Metadata.Name }}-telemetrystore-migrator{{ end }}
|
||||
{{ if $.Spec.TelemetryStore.Spec.Enabled }}
|
||||
Requires={{ $.Metadata.Name }}-telemetrystore-migrator
|
||||
{{ end }}
|
||||
|
||||
[Service]
|
||||
User=signoz
|
||||
@@ -12,12 +8,20 @@ Group=signoz
|
||||
Type=simple
|
||||
KillMode=mixed
|
||||
Restart=on-failure
|
||||
{{/* Using Fragment specifier to get the config from pours directory */}}
|
||||
RestartSec=5
|
||||
{{- if and $.Metadata.Annotations (index $.Metadata.Annotations "foundry.signoz.io/ingester-binary-path") }}
|
||||
{{- $ingesterBinaryPath := index $.Metadata.Annotations "foundry.signoz.io/ingester-binary-path" }}
|
||||
{{ if and $.Spec.Ingester.Status.Extras (index $.Spec.Ingester.Status.Extras "cfgPath") (index $.Spec.Ingester.Status.Extras "cfgOpampPath") }}
|
||||
{{- if and $.Spec.Ingester.Status.Extras (index $.Spec.Ingester.Status.Extras "cfgPath") (index $.Spec.Ingester.Status.Extras "cfgOpampPath") }}
|
||||
ExecStartPre={{ $ingesterBinaryPath }} migrate sync check
|
||||
ExecStart={{ $ingesterBinaryPath }} --config=%Y/{{ index $.Spec.Ingester.Status.Extras "cfgPath" }} --manager-config=%Y/{{ index $.Spec.Ingester.Status.Extras "cfgOpampPath" }} --copy-path=/var/lib/ingester/ingester.yaml
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if and $.Spec.TelemetryStore.Spec.Enabled $.Spec.TelemetryStore.Status.Addresses.TCP (index $.Spec.TelemetryStore.Status.Addresses.TCP 0) }}
|
||||
Environment=SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN={{ index $.Spec.TelemetryStore.Status.Addresses.TCP 0 }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := $.Spec.Ingester.Spec.Env }}
|
||||
Environment={{ $key }}={{ $value }}
|
||||
{{- end }}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
[Unit]
|
||||
Description=SigNoz Schema Migrator
|
||||
Description=SigNoz TelemetryStore Migrator
|
||||
Documentation=https://signoz.io/docs
|
||||
{{ if $.Spec.TelemetryStore.Spec.Enabled }}
|
||||
{{ $firstStore := printf "%s-telemetrystore-%s-0-0" $.Metadata.Name $.Spec.TelemetryStore.Kind.String }}
|
||||
After={{ $firstStore }}
|
||||
Requires={{ $firstStore }}
|
||||
{{ end }}
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
User=signoz
|
||||
Group=signoz
|
||||
{{- if and $.Metadata.Annotations (index $.Metadata.Annotations "foundry.signoz.io/ingester-binary-path") }}
|
||||
{{- $migratorBinary := index $.Metadata.Annotations "foundry.signoz.io/ingester-binary-path" }}
|
||||
{{ if and $.Spec.TelemetryStore.Spec.Enabled $.Spec.TelemetryStore.Status.Addresses.TCP (index $.Spec.TelemetryStore.Status.Addresses.TCP 0) }}
|
||||
{{- $dsn := index $.Spec.TelemetryStore.Status.Addresses.TCP 0 }}
|
||||
ExecStart=/bin/bash -c '{{ $migratorBinary }} migrate bootstrap --clickhouse-dsn={{ $dsn }} && {{ $migratorBinary }} migrate sync up --clickhouse-dsn={{ $dsn }} && {{ $migratorBinary }} migrate async up --clickhouse-dsn={{ $dsn }}'
|
||||
{{ end }}
|
||||
ExecStartPre={{ $migratorBinary }} migrate ready
|
||||
ExecStart=/bin/bash -c '{{ $migratorBinary }} migrate bootstrap && {{ $migratorBinary }} migrate sync up && {{ $migratorBinary }} migrate async up'
|
||||
{{- end }}
|
||||
{{- if and $.Spec.TelemetryStore.Spec.Enabled $.Spec.TelemetryStore.Status.Addresses.TCP (index $.Spec.TelemetryStore.Status.Addresses.TCP 0) }}
|
||||
Environment=SIGNOZ_OTEL_COLLECTOR_CLICKHOUSE_DSN={{ index $.Spec.TelemetryStore.Status.Addresses.TCP 0 }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := $.Spec.Ingester.Spec.Env }}
|
||||
Environment={{ $key }}={{ $value }}
|
||||
{{- end }}
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -7,11 +7,9 @@ After=network-online.target
|
||||
[Service]
|
||||
Type=notify
|
||||
User=postgres
|
||||
{{ if $.Spec.MetaStore.Spec.Env }}
|
||||
{{ range $key, $value := $.Spec.MetaStore.Spec.Env }}
|
||||
{{- range $key, $value := $.Spec.MetaStore.Spec.Env }}
|
||||
Environment={{ $key }}={{ $value }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- if and $.Metadata.Annotations (index $.Metadata.Annotations "foundry.signoz.io/metastore-postgres-binary-path") }}
|
||||
{{- $metastoreBinaryPath := index $.Metadata.Annotations "foundry.signoz.io/metastore-postgres-binary-path" }}
|
||||
ExecStart={{ $metastoreBinaryPath }} -D /usr/local/pgsql/data
|
||||
@@ -22,4 +20,4 @@ KillSignal=SIGINT
|
||||
TimeoutSec=infinity
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
[Unit]
|
||||
Description=SigNoz
|
||||
Documentation=https://signoz.io/docs
|
||||
After={{ $.Metadata.Name }}-telemetrystore-{{ $.Spec.TelemetryStore.Kind }}-0-0 {{ $.Metadata.Name }}-metastore-{{ $.Spec.MetaStore.Kind }}{{ if $.Spec.TelemetryStore.Spec.Enabled }} {{ $.Metadata.Name }}-telemetrystore-migrator{{ end }}
|
||||
{{ if $.Spec.TelemetryStore.Spec.Enabled }}
|
||||
Requires={{ $.Metadata.Name }}-telemetrystore-migrator
|
||||
{{ end }}
|
||||
|
||||
[Service]
|
||||
User=signoz
|
||||
@@ -12,18 +8,16 @@ Group=signoz
|
||||
Type=simple
|
||||
KillMode=mixed
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
WorkingDirectory=/opt/signoz
|
||||
{{- if and $.Metadata.Annotations (index $.Metadata.Annotations "foundry.signoz.io/signoz-binary-path") }}
|
||||
{{- $signozBinaryPath := index $.Metadata.Annotations "foundry.signoz.io/signoz-binary-path" }}
|
||||
ExecStart={{ $signozBinaryPath }} server
|
||||
{{- end }}
|
||||
Environment=SIGNOZ_WEB_DIRECTORY=/opt/signoz/web
|
||||
{{ if $.Spec.Signoz.Spec.Env }}
|
||||
{{ range $key, $value := $.Spec.Signoz.Spec.Env }}
|
||||
{{- range $key, $value := $.Spec.Signoz.Spec.Env }}
|
||||
Environment={{ $key }}={{ $value }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if and $.Spec.Signoz.Status.Extras (index $.Spec.Signoz.Status.Extras "envPath") }}
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -48,24 +48,29 @@ func (molding *signoz) MoldV1Alpha1(ctx context.Context, config *v1alpha1.Castin
|
||||
// Add metastore addresses
|
||||
config.Spec.Signoz.Status.Env["SIGNOZ_SQLSTORE_PROVIDER"] = config.Spec.MetaStore.Kind.String()
|
||||
|
||||
if config.Spec.MetaStore.Status.Addresses.DSN != nil {
|
||||
if val, ok := config.Spec.Signoz.Spec.Env["SIGNOZ_SQLSTORE_POSTGRES_DSN"]; ok {
|
||||
molding.logger.WarnContext(ctx, "SIGNOZ_SQLSTORE_POSTGRES_DSN is going to be overridden", slog.String("value", val))
|
||||
switch config.Spec.MetaStore.Kind {
|
||||
case v1alpha1.MetaStoreKindSQLite:
|
||||
config.Spec.Signoz.Status.Env["SIGNOZ_SQLSTORE_SQLITE_PATH"] = "/var/lib/signoz/signoz.db"
|
||||
case v1alpha1.MetaStoreKindPostgres:
|
||||
if config.Spec.MetaStore.Status.Addresses.DSN != nil {
|
||||
if val, ok := config.Spec.Signoz.Spec.Env["SIGNOZ_SQLSTORE_POSTGRES_DSN"]; ok {
|
||||
molding.logger.WarnContext(ctx, "SIGNOZ_SQLSTORE_POSTGRES_DSN is going to be overridden", slog.String("value", val))
|
||||
}
|
||||
// construct postgres dsn with user, password, host, port, and db
|
||||
addrs, err := types.NewAddresses(config.Spec.MetaStore.Status.Addresses.DSN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse addresses: %w", err)
|
||||
}
|
||||
var dsns []string
|
||||
user := config.Spec.MetaStore.Status.Env["POSTGRES_USER"]
|
||||
password := config.Spec.MetaStore.Status.Env["POSTGRES_PASSWORD"]
|
||||
db := config.Spec.MetaStore.Status.Env["POSTGRES_DB"]
|
||||
for _, addr := range addrs {
|
||||
dsn := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=disable", user, password, addr.Host(), addr.Port(), db)
|
||||
dsns = append(dsns, dsn)
|
||||
}
|
||||
config.Spec.Signoz.Status.Env["SIGNOZ_SQLSTORE_POSTGRES_DSN"] = strings.Join(dsns, ",")
|
||||
}
|
||||
// construct postgres dsn with user, password, host, port, and db
|
||||
addrs, err := types.NewAddresses(config.Spec.MetaStore.Status.Addresses.DSN)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse addresses: %w", err)
|
||||
}
|
||||
var dsns []string
|
||||
user := config.Spec.MetaStore.Status.Env["POSTGRES_USER"]
|
||||
password := config.Spec.MetaStore.Status.Env["POSTGRES_PASSWORD"]
|
||||
db := config.Spec.MetaStore.Status.Env["POSTGRES_DB"]
|
||||
for _, addr := range addrs {
|
||||
dsn := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=disable", user, password, addr.Host(), addr.Port(), db)
|
||||
dsns = append(dsns, dsn)
|
||||
}
|
||||
config.Spec.Signoz.Status.Env["SIGNOZ_SQLSTORE_POSTGRES_DSN"] = strings.Join(dsns, ",")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user