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.
|
||||
- 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.
|
||||
- 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).
|
||||
- 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.
|
||||
|
|
|
|||
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
|
||||
metadata:
|
||||
name: lomavuokraus-test
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: logging
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue