Add Loki logging stack
This commit is contained in:
parent
c93cabb8ad
commit
070c3e1575
8 changed files with 267 additions and 0 deletions
|
|
@ -66,6 +66,7 @@
|
||||||
- Price hint now stored in euros (schema field `priceHintPerNightEuros`); Prisma migration added to convert from cents, seeds and API/UI updated, and build now runs `prisma generate` automatically.
|
- Price hint now stored in euros (schema field `priceHintPerNightEuros`); Prisma migration added to convert from cents, seeds and API/UI updated, and build now runs `prisma generate` automatically.
|
||||||
- Listing creation amenities UI improved with toggle cards and EV button group.
|
- Listing creation amenities UI improved with toggle cards and EV button group.
|
||||||
- Edit listing form now matches the create form styling, including amenity icon grid and price helpers.
|
- Edit listing form now matches the create form styling, including amenity icon grid and price helpers.
|
||||||
|
- Centralized logging stack scaffolded (Loki + Promtail + Grafana) with Helm values and install script; Grafana ingress defaults to `logs.lomavuokraus.fi`.
|
||||||
- Mermaid docs fixed: all sequence diagrams declare their participants and avoid “->” inside message text; the listing creation diagram message was rewritten to prevent parse errors. Use mermaid.live or browser console to debug future syntax issues (errors flag the offending line/column).
|
- Mermaid docs fixed: all sequence diagrams declare their participants and avoid “->” inside message text; the listing creation diagram message was rewritten to prevent parse errors. Use mermaid.live or browser console to debug future syntax issues (errors flag the offending line/column).
|
||||||
- New amenities added: kitchen, dishwasher, washing machine, barbecue; API/UI/i18n updated and seeds randomized to populate missing prices/amenities. Prisma migration `20250210_more_amenities` applied to shared DB; registry pull secret added to k8s Deployment to avoid image pull errors in prod.
|
- New amenities added: kitchen, dishwasher, washing machine, barbecue; API/UI/i18n updated and seeds randomized to populate missing prices/amenities. Prisma migration `20250210_more_amenities` applied to shared DB; registry pull secret added to k8s Deployment to avoid image pull errors in prod.
|
||||||
- Added About and Pricing pages (FI/EN), moved highlights/runtime config to About, and linked footer navigation.
|
- Added About and Pricing pages (FI/EN), moved highlights/runtime config to About, and linked footer navigation.
|
||||||
|
|
|
||||||
56
deploy/install-logging.sh
Normal file
56
deploy/install-logging.sh
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
if [[ -f scripts/load-secrets.sh ]]; then
|
||||||
|
source scripts/load-secrets.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
LOGGING_NAMESPACE="${LOGGING_NAMESPACE:-logging}"
|
||||||
|
LOGS_HOST="${LOGS_HOST:-logs.lomavuokraus.fi}"
|
||||||
|
GRAFANA_CLUSTER_ISSUER="${GRAFANA_CLUSTER_ISSUER:-letsencrypt-prod}"
|
||||||
|
: "${GRAFANA_ADMIN_PASSWORD:?Set GRAFANA_ADMIN_PASSWORD to provision Grafana.}"
|
||||||
|
|
||||||
|
HELM_BIN="${HELM_BIN:-$(command -v helm || true)}"
|
||||||
|
|
||||||
|
ensure_helm() {
|
||||||
|
if [[ -n "$HELM_BIN" && -x "$HELM_BIN" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
echo "Helm not found, downloading to a temp dir..."
|
||||||
|
TMP_DIR="$(mktemp -d)"
|
||||||
|
curl -fsSL https://get.helm.sh/helm-v3.16.1-linux-amd64.tar.gz | tar -xz -C "$TMP_DIR"
|
||||||
|
HELM_BIN="$TMP_DIR/linux-amd64/helm"
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_helm
|
||||||
|
|
||||||
|
echo "Using helm at: $HELM_BIN"
|
||||||
|
|
||||||
|
$HELM_BIN repo add grafana https://grafana.github.io/helm-charts
|
||||||
|
$HELM_BIN repo update
|
||||||
|
|
||||||
|
export LOGS_HOST GRAFANA_CLUSTER_ISSUER GRAFANA_ADMIN_PASSWORD
|
||||||
|
|
||||||
|
LOKI_TMP=$(mktemp)
|
||||||
|
PROMTAIL_TMP=$(mktemp)
|
||||||
|
GRAFANA_TMP=$(mktemp)
|
||||||
|
|
||||||
|
cat k8s/logging/loki-values.yaml >"$LOKI_TMP"
|
||||||
|
cat k8s/logging/promtail-values.yaml >"$PROMTAIL_TMP"
|
||||||
|
envsubst < k8s/logging/grafana-values.yaml >"$GRAFANA_TMP"
|
||||||
|
|
||||||
|
echo "Installing/Upgrading Loki..."
|
||||||
|
$HELM_BIN upgrade --install loki grafana/loki -n "$LOGGING_NAMESPACE" -f "$LOKI_TMP" --create-namespace
|
||||||
|
|
||||||
|
echo "Installing/Upgrading Promtail..."
|
||||||
|
$HELM_BIN upgrade --install promtail grafana/promtail -n "$LOGGING_NAMESPACE" -f "$PROMTAIL_TMP"
|
||||||
|
|
||||||
|
echo "Installing/Upgrading Grafana..."
|
||||||
|
$HELM_BIN upgrade --install grafana grafana/grafana -n "$LOGGING_NAMESPACE" -f "$GRAFANA_TMP"
|
||||||
|
|
||||||
|
echo "Resources in $LOGGING_NAMESPACE:"
|
||||||
|
kubectl get pods,svc,ingress -n "$LOGGING_NAMESPACE"
|
||||||
|
|
||||||
|
echo "Done. Grafana ingress host: https://${LOGS_HOST}"
|
||||||
22
deploy/update-logs-dns.sh
Normal file
22
deploy/update-logs-dns.sh
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
AUTH_FILE="creds/joker_com_dyndns_creds.txt"
|
||||||
|
if [[ ! -f "$AUTH_FILE" ]]; then
|
||||||
|
echo "Joker DYNDNS credentials missing at $AUTH_FILE" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
JOKER_AUTH="$(cat "$AUTH_FILE")"
|
||||||
|
TARGET_IP="${TARGET_IP:-157.180.66.64}"
|
||||||
|
LOGS_HOST="${LOGS_HOST:-logs.lomavuokraus.fi}"
|
||||||
|
|
||||||
|
echo "Updating $LOGS_HOST -> $TARGET_IP"
|
||||||
|
resp="$(curl -sS -u "$JOKER_AUTH" "https://svc.joker.com/nic/update?hostname=${LOGS_HOST}&myip=${TARGET_IP}")"
|
||||||
|
echo "$resp"
|
||||||
|
if [[ "$resp" != good* && "$resp" != nochg* ]]; then
|
||||||
|
echo "DNS update failed for $LOGS_HOST (response: $resp)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
52
docs/logging.md
Normal file
52
docs/logging.md
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Centralized logging (Loki + Promtail + Grafana)
|
||||||
|
|
||||||
|
We ship a lightweight logging stack into the cluster so API/UI logs are searchable.
|
||||||
|
|
||||||
|
- **Loki** (single-binary) stores logs with 14d retention by default, on a PVC.
|
||||||
|
- **Promtail** DaemonSet tails container logs and ships them to Loki with `namespace`, `pod`, and `app` labels.
|
||||||
|
- **Grafana** provides the UI with a pre-wired Loki data source and TLS ingress.
|
||||||
|
|
||||||
|
## Install / upgrade
|
||||||
|
|
||||||
|
Prereqs:
|
||||||
|
- `kubectl`/`helm` access to the cluster (the script downloads Helm if missing).
|
||||||
|
- Environment: `GRAFANA_ADMIN_PASSWORD` (required), optional `LOGS_HOST` (default `logs.lomavuokraus.fi`), `GRAFANA_CLUSTER_ISSUER` (default `letsencrypt-prod`), `LOGGING_NAMESPACE` (default `logging`).
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LOGS_HOST=logs.lomavuokraus.fi \
|
||||||
|
GRAFANA_ADMIN_PASSWORD='change-me' \
|
||||||
|
GRAFANA_CLUSTER_ISSUER=letsencrypt-prod \
|
||||||
|
bash deploy/install-logging.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The script:
|
||||||
|
1. Ensures Helm is available.
|
||||||
|
2. Installs/updates Loki, Promtail, and Grafana in the logging namespace.
|
||||||
|
3. Creates a Grafana ingress with TLS via the chosen ClusterIssuer.
|
||||||
|
|
||||||
|
## Access
|
||||||
|
|
||||||
|
- Grafana: `https://<LOGS_HOST>` (admin user `admin`, password from `GRAFANA_ADMIN_PASSWORD`).
|
||||||
|
- Loki endpoint (internal): `http://loki.logging.svc.cluster.local:3100`.
|
||||||
|
|
||||||
|
## Querying
|
||||||
|
|
||||||
|
Example LogQL in Grafana Explore:
|
||||||
|
|
||||||
|
```
|
||||||
|
{namespace="lomavuokraus-test", app="lomavuokraus-web"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Filter by pod:
|
||||||
|
|
||||||
|
```
|
||||||
|
{namespace="lomavuokraus-test", app="lomavuokraus-web", pod=~".*"} |= "ERROR"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tuning
|
||||||
|
|
||||||
|
- Retention: `k8s/logging/loki-values.yaml` (`limits_config.retention_period`).
|
||||||
|
- PVC sizes: adjust `persistence.size` in `k8s/logging/loki-values.yaml` and `k8s/logging/grafana-values.yaml`.
|
||||||
|
- Ingress issuer/host: override via environment when running `deploy/install-logging.sh`.
|
||||||
45
k8s/logging/grafana-values.yaml
Normal file
45
k8s/logging/grafana-values.yaml
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
adminUser: admin
|
||||||
|
adminPassword: "${GRAFANA_ADMIN_PASSWORD}"
|
||||||
|
|
||||||
|
initChownData:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
size: 10Gi
|
||||||
|
storageClassName: ""
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
ingressClassName: traefik
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "${GRAFANA_CLUSTER_ISSUER}"
|
||||||
|
hosts:
|
||||||
|
- "${LOGS_HOST}"
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- "${LOGS_HOST}"
|
||||||
|
secretName: grafana-logs-tls
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
datasources.yaml:
|
||||||
|
apiVersion: 1
|
||||||
|
datasources:
|
||||||
|
- name: Loki
|
||||||
|
type: loki
|
||||||
|
access: proxy
|
||||||
|
url: http://loki.logging.svc.cluster.local:3100
|
||||||
|
isDefault: true
|
||||||
|
jsonData:
|
||||||
|
timeout: 60
|
||||||
|
maxLines: 5000
|
||||||
|
|
||||||
|
grafana.ini:
|
||||||
|
server:
|
||||||
|
root_url: https://${LOGS_HOST}
|
||||||
|
analytics:
|
||||||
|
reporting_enabled: false
|
||||||
|
check_for_updates: false
|
||||||
61
k8s/logging/loki-values.yaml
Normal file
61
k8s/logging/loki-values.yaml
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
deploymentMode: SingleBinary
|
||||||
|
|
||||||
|
singleBinary:
|
||||||
|
replicas: 1
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
size: 20Gi
|
||||||
|
storageClass: ""
|
||||||
|
|
||||||
|
# Disable simple scalable targets to satisfy chart validation
|
||||||
|
write:
|
||||||
|
replicas: 0
|
||||||
|
read:
|
||||||
|
replicas: 0
|
||||||
|
backend:
|
||||||
|
replicas: 0
|
||||||
|
|
||||||
|
loki:
|
||||||
|
auth_enabled: false
|
||||||
|
commonConfig:
|
||||||
|
replication_factor: 1
|
||||||
|
storage:
|
||||||
|
type: filesystem
|
||||||
|
filesystem:
|
||||||
|
chunks_directory: /var/loki/chunks
|
||||||
|
rules_directory: /var/loki/rules
|
||||||
|
limits_config:
|
||||||
|
retention_period: 0s
|
||||||
|
compactor:
|
||||||
|
retention_enabled: false
|
||||||
|
retention_delete_delay: 2h
|
||||||
|
retention_delete_worker_count: 1
|
||||||
|
ruler:
|
||||||
|
storage:
|
||||||
|
type: local
|
||||||
|
local:
|
||||||
|
directory: /rules
|
||||||
|
schemaConfig:
|
||||||
|
configs:
|
||||||
|
- from: "2024-01-01"
|
||||||
|
store: tsdb
|
||||||
|
object_store: filesystem
|
||||||
|
schema: v13
|
||||||
|
index:
|
||||||
|
prefix: loki_index_
|
||||||
|
period: 24h
|
||||||
|
storage_config:
|
||||||
|
filesystem:
|
||||||
|
directory: /var/loki/chunks
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
|
||||||
|
chunksCache:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
resultsCache:
|
||||||
|
enabled: false
|
||||||
25
k8s/logging/promtail-values.yaml
Normal file
25
k8s/logging/promtail-values.yaml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
config:
|
||||||
|
lokiAddress: http://loki.logging.svc.cluster.local:3100/loki/api/v1/push
|
||||||
|
snippets:
|
||||||
|
extraRelabelConfigs:
|
||||||
|
# Skip Promtail's own logs to reduce noise
|
||||||
|
- source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_name]
|
||||||
|
action: drop
|
||||||
|
regex: promtail
|
||||||
|
# Drop logs from the logging stack itself
|
||||||
|
- source_labels: [__meta_kubernetes_namespace]
|
||||||
|
action: drop
|
||||||
|
regex: logging
|
||||||
|
# Promote common labels for easier querying
|
||||||
|
- action: replace
|
||||||
|
replacement: $1
|
||||||
|
source_labels: [__meta_kubernetes_namespace]
|
||||||
|
target_label: namespace
|
||||||
|
- action: replace
|
||||||
|
replacement: $1
|
||||||
|
source_labels: [__meta_kubernetes_pod_name]
|
||||||
|
target_label: pod
|
||||||
|
- action: replace
|
||||||
|
replacement: $1
|
||||||
|
source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_name]
|
||||||
|
target_label: app
|
||||||
|
|
@ -12,3 +12,8 @@ apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: lomavuokraus-test
|
name: lomavuokraus-test
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: logging
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue