From 35874bf520784e73944aa9bc4577817addd5c15e Mon Sep 17 00:00:00 2001 From: Vassiliy Yegorov Date: Mon, 6 Apr 2026 21:36:15 +0700 Subject: [PATCH] init --- .gitignore | 2 + README.md | 318 ++++++++++++++++++ docker-compose.yaml | 159 +++++++++ docs/architecture.excalidraw.png | Bin 0 -> 97958 bytes helm/loki-stack/Chart.yaml | 6 + helm/loki-stack/templates/_helpers.tpl | 40 +++ .../templates/grafana-configmap.yaml | 17 + .../templates/grafana-deployment.yaml | 56 +++ .../loki-stack/templates/grafana-ingress.yaml | 36 ++ helm/loki-stack/templates/grafana-pvc.yaml | 16 + .../loki-stack/templates/grafana-service.yaml | 16 + .../templates/loki-backend-statefulset.yaml | 69 ++++ helm/loki-stack/templates/loki-configmap.yaml | 74 ++++ .../templates/loki-read-statefulset.yaml | 69 ++++ helm/loki-stack/templates/loki-services.yaml | 133 ++++++++ .../templates/loki-write-statefulset.yaml | 69 ++++ .../templates/minio-deployment.yaml | 52 +++ helm/loki-stack/templates/minio-pvc.yaml | 16 + helm/loki-stack/templates/minio-service.yaml | 19 ++ helm/loki-stack/templates/namespace.yaml | 10 + helm/loki-stack/templates/networkpolicy.yaml | 33 ++ .../templates/vector-configmap.yaml | 43 +++ .../templates/vector-daemonset.yaml | 60 ++++ helm/loki-stack/templates/vector-rbac.yaml | 35 ++ helm/loki-stack/values.yaml | 112 ++++++ loki-config.yaml | 67 ++++ nginx.conf | 59 ++++ provisioning/datasources/loki.yaml | 9 + vector.yaml | 30 ++ 29 files changed, 1625 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 docker-compose.yaml create mode 100644 docs/architecture.excalidraw.png create mode 100644 helm/loki-stack/Chart.yaml create mode 100644 helm/loki-stack/templates/_helpers.tpl create mode 100644 helm/loki-stack/templates/grafana-configmap.yaml create mode 100644 helm/loki-stack/templates/grafana-deployment.yaml create mode 100644 helm/loki-stack/templates/grafana-ingress.yaml create mode 100644 helm/loki-stack/templates/grafana-pvc.yaml create mode 100644 helm/loki-stack/templates/grafana-service.yaml create mode 100644 helm/loki-stack/templates/loki-backend-statefulset.yaml create mode 100644 helm/loki-stack/templates/loki-configmap.yaml create mode 100644 helm/loki-stack/templates/loki-read-statefulset.yaml create mode 100644 helm/loki-stack/templates/loki-services.yaml create mode 100644 helm/loki-stack/templates/loki-write-statefulset.yaml create mode 100644 helm/loki-stack/templates/minio-deployment.yaml create mode 100644 helm/loki-stack/templates/minio-pvc.yaml create mode 100644 helm/loki-stack/templates/minio-service.yaml create mode 100644 helm/loki-stack/templates/namespace.yaml create mode 100644 helm/loki-stack/templates/networkpolicy.yaml create mode 100644 helm/loki-stack/templates/vector-configmap.yaml create mode 100644 helm/loki-stack/templates/vector-daemonset.yaml create mode 100644 helm/loki-stack/templates/vector-rbac.yaml create mode 100644 helm/loki-stack/values.yaml create mode 100644 loki-config.yaml create mode 100644 nginx.conf create mode 100644 provisioning/datasources/loki.yaml create mode 100644 vector.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e60f925 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.claude +.playwright-mcp \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a9a10e6 --- /dev/null +++ b/README.md @@ -0,0 +1,318 @@ +# Loki 3 + Vector + Grafana — Test Stand + +Test environment for centralized log collection using Grafana Loki in Simple Scalable mode with Vector as the log collector and MinIO as S3-compatible object storage. + +Two deployment options: **Docker Compose** (local testing with log-generator) and **Helm chart** (Kubernetes with DaemonSet log collection from all pods). + +## Architecture + +![Architecture Diagram](docs/architecture.excalidraw.png) + +## Components + +| Service | Image | Role | +|---|---|---| +| **minio** | `minio/minio:latest` | S3-compatible object storage for chunks and index | +| **loki-write** | `grafana/loki:3.4.2` | Ingester — accepts and stores log streams | +| **loki-read** | `grafana/loki:3.4.2` | Querier — executes LogQL queries | +| **loki-backend** | `grafana/loki:3.4.2` | Compactor, ruler, index gateway | +| **gateway** | `nginx:1.27-alpine` | Reverse proxy — Loki write/read/ruler + Grafana UI | +| **vector** | `timberio/vector:0.44.0-alpine` | Log collector — Loki sink | +| **grafana** | `grafana/grafana:12.4` | Visualization — Loki datasource pre-provisioned | + +## Data Flow + +1. **Vector** collects container logs (docker_logs / kubernetes_logs source) +2. Vector transforms logs (extracts metadata, removes raw labels) and pushes to **gateway** +3. **Gateway** (nginx) routes `/loki/api/v1/push` to **loki-write**, all other `/loki/api/*` to **loki-read** +4. **loki-write** ingests logs and stores chunks in **MinIO** (`loki-chunks` bucket) +5. **loki-backend** runs compactor on a 10-minute interval +6. **Grafana** queries logs via gateway → loki-read + +## Loki Configuration + +- **Deployment mode**: Simple Scalable (write / read / backend targets) +- **Schema**: v13 with TSDB store +- **Storage**: S3 (MinIO) — bucket `loki-chunks` +- **Service discovery**: memberlist (port 7946) +- **Replication factor**: 1 (test stand) +- **Chunk encoding**: snappy +- **Retention**: enabled via compactor, old samples rejected after 168h + +--- + +## Option 1: Docker Compose + +Local test stand with a built-in log-generator container (`flog`). Vector collects logs from containers with label `vector.collect=true` via Docker socket. + +### Quick Start + +```bash +docker compose up -d +``` + +Wait for all services to become healthy: + +```bash +docker compose ps +``` + +### Access Points + +| Service | URL | Credentials | +|---|---|---| +| Grafana (via gateway) | http://localhost:3000 | admin / admin (anonymous access enabled) | +| Loki API (via gateway) | http://localhost:3100 | — | +| MinIO Console | http://localhost:9001 | loki / supersecret | +| MinIO API | http://localhost:9000 | loki / supersecret | + +### Network + +All containers run on a static network `192.168.97.0/24`: + +| Container | IP | +|---|---| +| `loki-minio` | 192.168.97.10 | +| `loki-write` | 192.168.97.11 | +| `loki-read` | 192.168.97.12 | +| `loki-backend` | 192.168.97.13 | +| `loki-gateway` | 192.168.97.14 | +| `loki-vector` | 192.168.97.15 | +| `loki-grafana` | 192.168.97.16 | +| `loki-log-generator` | 192.168.97.17 | + +### Adding Your Own Containers + +To collect logs from any container, add the label: + +```yaml +services: + my-app: + image: my-app:latest + labels: + vector.collect: "true" +``` + +Logs will appear in Grafana with label `{container="my-app"}`. + +### Useful Commands + +```bash +# Start +docker compose up -d + +# Stop +docker compose down + +# Stop and remove volumes +docker compose down -v + +# View Vector logs +docker compose logs vector -f + +# View Loki write logs +docker compose logs loki-write -f + +# Check Loki readiness +curl -s http://localhost:3100/ready + +# Query logs via API +curl -s http://localhost:3100/loki/api/v1/query_range \ + --data-urlencode 'query={container="log-generator"}' \ + --data-urlencode 'limit=10' | jq . + +# Check MinIO bucket +docker compose exec minio mc ls local/loki-chunks/ +``` + +--- + +## Option 2: Helm Chart (Kubernetes) + +Production-oriented deployment. Vector runs as a **DaemonSet** collecting logs from all pods in the cluster via `kubernetes_logs` source. No log-generator — real workload logs are collected. + +### Prerequisites + +- Kubernetes cluster (1.24+) +- Helm 3 +- `kubectl` configured + +### Install + +```bash +helm install loki-stack ./helm/loki-stack -n loki --create-namespace +``` + +### Install with custom values + +```bash +helm install loki-stack ./helm/loki-stack -n loki --create-namespace \ + -f my-values.yaml +``` + +### Upgrade + +```bash +helm upgrade loki-stack ./helm/loki-stack -n loki +``` + +### Uninstall + +```bash +helm uninstall loki-stack -n loki +``` + +### Key Differences from Docker Compose + +| Feature | Docker Compose | Helm | +|---|---|---| +| Vector source | `docker_logs` (label filter) | `kubernetes_logs` (all pods) | +| Vector mode | container | DaemonSet (one per node) | +| Log labels | `container`, `project` | `namespace`, `pod`, `container`, `node` | +| Loki targets | Deployment | StatefulSet with PVC | +| Service discovery | static IPs + memberlist | headless Service + memberlist | +| Gateway (nginx) | yes — proxies Loki + Grafana | no — direct Service routing | +| Ingress | — | Grafana ingress (disabled by default) | + +### Configuration (values.yaml) + +Key parameters: + +```yaml +# Scale Loki components +loki: + write: + replicas: 1 # Increase for HA + read: + replicas: 1 # Increase for query throughput + backend: + replicas: 1 + +# MinIO storage +minio: + rootUser: loki + rootPassword: supersecret + storage: + size: 10Gi + +# Vector tolerations (to run on tainted nodes) +vector: + tolerations: [] + +# Grafana +grafana: + adminUser: admin + adminPassword: admin + anonymousAccess: true + service: + type: ClusterIP + ingress: + enabled: false + className: nginx + hosts: + - host: grafana.example.com + paths: + - path: / + pathType: Prefix + tls: [] +``` + +### Access in Kubernetes + +Port-forward to services: + +```bash +# Grafana +kubectl port-forward -n loki svc/loki-stack-grafana 3000:3000 + +# Loki API (read) +kubectl port-forward -n loki svc/loki-stack-loki-read 3100:3100 + +# Loki API (write / push) +kubectl port-forward -n loki svc/loki-stack-loki-write 3100:3100 + +# MinIO Console +kubectl port-forward -n loki svc/loki-stack-minio 9001:9001 +``` + +### Viewing Logs + +Open Grafana and query: + +```logql +# All logs from a namespace +{namespace="default"} + +# Specific pod +{pod="my-app-7d4b8c6f5-x2k9p"} + +# By container name across all namespaces +{container="nginx"} + +# By node +{node="worker-01"} +``` + +### Helm Chart Structure + +``` +helm/loki-stack/ +├── Chart.yaml +├── values.yaml +└── templates/ + ├── _helpers.tpl + ├── minio-deployment.yaml + ├── minio-pvc.yaml + ├── minio-service.yaml + ├── loki-configmap.yaml + ├── loki-write-statefulset.yaml + ├── loki-read-statefulset.yaml + ├── loki-backend-statefulset.yaml + ├── loki-services.yaml + ├── vector-rbac.yaml + ├── vector-configmap.yaml + ├── vector-daemonset.yaml + ├── grafana-configmap.yaml + ├── grafana-deployment.yaml + ├── grafana-ingress.yaml + ├── grafana-pvc.yaml + └── grafana-service.yaml +``` + +### Kubernetes Resources Created + +| Kind | Count | Description | +|---|---|---| +| StatefulSet | 3 | loki-write, loki-read, loki-backend | +| Deployment | 2 | minio, grafana | +| DaemonSet | 1 | vector (one per node) | +| Service | 9 | ClusterIP + headless for each Loki target + memberlist + minio + grafana | +| ConfigMap | 3 | loki config, vector config, grafana datasource | +| PVC | 2 + 3 | minio + grafana (static) + loki targets (via volumeClaimTemplates) | +| ServiceAccount | 1 | vector | +| ClusterRole | 1 | vector (pods, namespaces, nodes read access) | +| ClusterRoleBinding | 1 | vector | +| Ingress | 0/1 | grafana (disabled by default) | + +--- + +## File Structure + +``` +. +├── docker-compose.yaml # Docker Compose deployment +├── loki-config.yaml # Loki configuration (docker-compose) +├── nginx.conf # Gateway routing rules (docker-compose) +├── vector.yaml # Vector pipeline (docker-compose) +├── provisioning/ +│ └── datasources/ +│ └── loki.yaml # Grafana datasource provisioning (docker-compose) +├── docs/ +│ └── architecture.excalidraw.png # Architecture diagram +├── helm/ +│ └── loki-stack/ # Helm chart for Kubernetes +│ ├── Chart.yaml +│ ├── values.yaml +│ └── templates/ +└── README.md +``` diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..049364e --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,159 @@ +services: + # --- MinIO --- + minio: + container_name: loki-minio + image: minio/minio:latest + entrypoint: + - sh + - -euc + - | + mkdir -p /data/loki-chunks && \ + minio server /data --console-address ":9001" + environment: + MINIO_ROOT_USER: loki + MINIO_ROOT_PASSWORD: supersecret + ports: + - "9000:9000" + - "9001:9001" + volumes: + - minio-data:/data + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 5s + timeout: 5s + retries: 10 + networks: + loki-net: + ipv4_address: 192.168.97.10 + + # --- Loki Write --- + loki-write: + container_name: loki-write + image: grafana/loki:3.4.2 + hostname: loki-write + command: -config.file=/etc/loki/loki-config.yaml -config.expand-env=true -target=write + volumes: + - ./loki-config.yaml:/etc/loki/loki-config.yaml:ro + - loki-write-data:/loki + depends_on: + minio: + condition: service_healthy + networks: + loki-net: + ipv4_address: 192.168.97.11 + + # --- Loki Read --- + loki-read: + container_name: loki-read + image: grafana/loki:3.4.2 + hostname: loki-read + command: -config.file=/etc/loki/loki-config.yaml -config.expand-env=true -target=read + volumes: + - ./loki-config.yaml:/etc/loki/loki-config.yaml:ro + - loki-read-data:/loki + depends_on: + minio: + condition: service_healthy + networks: + loki-net: + ipv4_address: 192.168.97.12 + + # --- Loki Backend --- + loki-backend: + container_name: loki-backend + image: grafana/loki:3.4.2 + hostname: loki-backend + command: -config.file=/etc/loki/loki-config.yaml -config.expand-env=true -target=backend + volumes: + - ./loki-config.yaml:/etc/loki/loki-config.yaml:ro + - loki-backend-data:/loki + depends_on: + minio: + condition: service_healthy + networks: + loki-net: + ipv4_address: 192.168.97.13 + + # --- Gateway (nginx) --- + gateway: + container_name: loki-gateway + image: nginx:1.27-alpine + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + ports: + - "3100:3100" + - "3000:3000" + depends_on: + - loki-write + - loki-read + - loki-backend + - grafana + healthcheck: + test: ["CMD-SHELL", "wget --quiet --tries=1 --output-document=- http://192.168.97.14:3100/ready | grep -q 'ready'"] + interval: 10s + timeout: 5s + retries: 15 + networks: + loki-net: + ipv4_address: 192.168.97.14 + + # --- Vector --- + vector: + container_name: loki-vector + image: timberio/vector:0.44.0-alpine + volumes: + - ./vector.yaml:/etc/vector/vector.yaml:ro + - /var/run/docker.sock:/var/run/docker.sock:ro + depends_on: + gateway: + condition: service_healthy + networks: + loki-net: + ipv4_address: 192.168.97.15 + + # --- Grafana --- + grafana: + container_name: loki-grafana + image: grafana/grafana:12.4 + environment: + GF_SECURITY_ADMIN_USER: admin + GF_SECURITY_ADMIN_PASSWORD: admin + GF_AUTH_ANONYMOUS_ENABLED: "true" + GF_AUTH_ANONYMOUS_ORG_ROLE: Admin + volumes: + - ./provisioning:/etc/grafana/provisioning:ro + - grafana-data:/var/lib/grafana + depends_on: + loki-read: + condition: service_started + networks: + loki-net: + ipv4_address: 192.168.97.16 + + # --- Log Generator --- + log-generator: + container_name: loki-log-generator + image: mingrammer/flog:0.4.3 + command: -f json -d 2s -l + labels: + vector.collect: "true" + depends_on: + - vector + networks: + loki-net: + ipv4_address: 192.168.97.17 + +networks: + loki-net: + driver: bridge + ipam: + config: + - subnet: 192.168.97.0/24 + gateway: 192.168.97.1 + +volumes: + minio-data: + loki-write-data: + loki-read-data: + loki-backend-data: + grafana-data: diff --git a/docs/architecture.excalidraw.png b/docs/architecture.excalidraw.png new file mode 100644 index 0000000000000000000000000000000000000000..6d4018dba65d689c1811c12b05ce2dc52e8549dc GIT binary patch literal 97958 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

fZ89N$Tz< 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 literal 0 HcmV?d00001 diff --git a/helm/loki-stack/Chart.yaml b/helm/loki-stack/Chart.yaml new file mode 100644 index 0000000..f50aae9 --- /dev/null +++ b/helm/loki-stack/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: loki-stack +description: Loki 3 Simple Scalable + Vector DaemonSet + Grafana + MinIO +version: 0.1.0 +appVersion: "3.4.2" +type: application diff --git a/helm/loki-stack/templates/_helpers.tpl b/helm/loki-stack/templates/_helpers.tpl new file mode 100644 index 0000000..6573563 --- /dev/null +++ b/helm/loki-stack/templates/_helpers.tpl @@ -0,0 +1,40 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "loki-stack.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "loki-stack.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "loki-stack.labels" -}} +helm.sh/chart: {{ include "loki-stack.name" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +app.kubernetes.io/part-of: {{ include "loki-stack.name" . }} +{{- end }} + +{{/* +Selector labels for a component +*/}} +{{- define "loki-stack.selectorLabels" -}} +app.kubernetes.io/name: {{ include "loki-stack.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/helm/loki-stack/templates/grafana-configmap.yaml b/helm/loki-stack/templates/grafana-configmap.yaml new file mode 100644 index 0000000..9af6c9e --- /dev/null +++ b/helm/loki-stack/templates/grafana-configmap.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "loki-stack.fullname" . }}-grafana-datasources + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: grafana +data: + loki.yaml: | + apiVersion: 1 + datasources: + - name: Loki + type: loki + access: proxy + url: http://{{ include "loki-stack.fullname" . }}-loki-read:3100 + isDefault: true + editable: true diff --git a/helm/loki-stack/templates/grafana-deployment.yaml b/helm/loki-stack/templates/grafana-deployment.yaml new file mode 100644 index 0000000..fa22e36 --- /dev/null +++ b/helm/loki-stack/templates/grafana-deployment.yaml @@ -0,0 +1,56 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki-stack.fullname" . }}-grafana + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: grafana +spec: + replicas: {{ .Values.grafana.replicas }} + selector: + matchLabels: + {{- include "loki-stack.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: grafana + template: + metadata: + labels: + {{- include "loki-stack.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: grafana + spec: + securityContext: + fsGroup: 472 + containers: + - name: grafana + image: {{ .Values.grafana.image.repository }}:{{ .Values.grafana.image.tag }} + env: + - name: GF_SECURITY_ADMIN_USER + value: {{ .Values.grafana.adminUser }} + - name: GF_SECURITY_ADMIN_PASSWORD + value: {{ .Values.grafana.adminPassword }} + - name: GF_AUTH_ANONYMOUS_ENABLED + value: {{ .Values.grafana.anonymousAccess | quote }} + - name: GF_AUTH_ANONYMOUS_ORG_ROLE + value: Admin + ports: + - name: http + containerPort: 3000 + readinessProbe: + httpGet: + path: /api/health + port: http + initialDelaySeconds: 10 + periodSeconds: 10 + volumeMounts: + - name: datasources + mountPath: /etc/grafana/provisioning/datasources + - name: data + mountPath: /var/lib/grafana + resources: + {{- toYaml .Values.grafana.resources | nindent 12 }} + volumes: + - name: datasources + configMap: + name: {{ include "loki-stack.fullname" . }}-grafana-datasources + - name: data + persistentVolumeClaim: + claimName: {{ include "loki-stack.fullname" . }}-grafana diff --git a/helm/loki-stack/templates/grafana-ingress.yaml b/helm/loki-stack/templates/grafana-ingress.yaml new file mode 100644 index 0000000..bffc693 --- /dev/null +++ b/helm/loki-stack/templates/grafana-ingress.yaml @@ -0,0 +1,36 @@ +{{- if .Values.grafana.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "loki-stack.fullname" . }}-grafana + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: grafana + {{- with .Values.grafana.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.grafana.ingress.className }} + ingressClassName: {{ .Values.grafana.ingress.className }} + {{- end }} + {{- if .Values.grafana.ingress.tls }} + tls: + {{- toYaml .Values.grafana.ingress.tls | nindent 4 }} + {{- end }} + rules: + {{- range .Values.grafana.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "loki-stack.fullname" $ }}-grafana + port: + name: http + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/loki-stack/templates/grafana-pvc.yaml b/helm/loki-stack/templates/grafana-pvc.yaml new file mode 100644 index 0000000..b4cb839 --- /dev/null +++ b/helm/loki-stack/templates/grafana-pvc.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "loki-stack.fullname" . }}-grafana + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: grafana +spec: + accessModes: + - ReadWriteOnce + {{- if .Values.grafana.storage.storageClassName }} + storageClassName: {{ .Values.grafana.storage.storageClassName }} + {{- end }} + resources: + requests: + storage: {{ .Values.grafana.storage.size }} diff --git a/helm/loki-stack/templates/grafana-service.yaml b/helm/loki-stack/templates/grafana-service.yaml new file mode 100644 index 0000000..6173538 --- /dev/null +++ b/helm/loki-stack/templates/grafana-service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki-stack.fullname" . }}-grafana + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: grafana +spec: + type: ClusterIP + ports: + - name: http + port: 3000 + targetPort: http + selector: + {{- include "loki-stack.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: grafana diff --git a/helm/loki-stack/templates/loki-backend-statefulset.yaml b/helm/loki-stack/templates/loki-backend-statefulset.yaml new file mode 100644 index 0000000..d754f2e --- /dev/null +++ b/helm/loki-stack/templates/loki-backend-statefulset.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki-stack.fullname" . }}-loki-backend + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki-backend +spec: + replicas: {{ .Values.loki.backend.replicas }} + serviceName: {{ include "loki-stack.fullname" . }}-loki-backend-headless + selector: + matchLabels: + {{- include "loki-stack.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: loki-backend + template: + metadata: + labels: + {{- include "loki-stack.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: loki-backend + loki.grafana.com/memberlist: "true" + spec: + containers: + - name: loki + image: {{ .Values.loki.image.repository }}:{{ .Values.loki.image.tag }} + args: + - -config.file=/etc/loki/loki-config.yaml + - -config.expand-env=true + - -target=backend + env: + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + ports: + - name: http + containerPort: 3100 + - name: grpc + containerPort: 9095 + - name: memberlist + containerPort: 7946 + readinessProbe: + httpGet: + path: /ready + port: http + initialDelaySeconds: 15 + periodSeconds: 10 + volumeMounts: + - name: config + mountPath: /etc/loki + - name: data + mountPath: /loki + resources: + {{- toYaml .Values.loki.backend.resources | nindent 12 }} + volumes: + - name: config + configMap: + name: {{ include "loki-stack.fullname" . }}-loki + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: + - ReadWriteOnce + {{- if .Values.loki.backend.storage.storageClassName }} + storageClassName: {{ .Values.loki.backend.storage.storageClassName }} + {{- end }} + resources: + requests: + storage: {{ .Values.loki.backend.storage.size }} diff --git a/helm/loki-stack/templates/loki-configmap.yaml b/helm/loki-stack/templates/loki-configmap.yaml new file mode 100644 index 0000000..33f0108 --- /dev/null +++ b/helm/loki-stack/templates/loki-configmap.yaml @@ -0,0 +1,74 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "loki-stack.fullname" . }}-loki + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki +data: + loki-config.yaml: | + auth_enabled: false + + server: + http_listen_port: 3100 + grpc_listen_port: 9095 + log_level: info + + common: + compactor_address: http://{{ include "loki-stack.fullname" . }}-loki-backend:3100 + ring: + instance_addr: ${POD_IP} + kvstore: + store: memberlist + replication_factor: 1 + path_prefix: /loki + + memberlist: + join_members: + - {{ include "loki-stack.fullname" . }}-loki-memberlist:7946 + + schema_config: + configs: + - from: "2024-01-01" + store: tsdb + object_store: s3 + schema: v13 + index: + prefix: index_ + period: 24h + + storage_config: + aws: + endpoint: {{ include "loki-stack.fullname" . }}-minio:9000 + insecure: true + bucketnames: {{ .Values.minio.bucketName }} + access_key_id: {{ .Values.minio.rootUser }} + secret_access_key: {{ .Values.minio.rootPassword }} + s3forcepathstyle: true + tsdb_shipper: + active_index_directory: /loki/index + cache_location: /loki/index_cache + + ingester: + chunk_encoding: snappy + + querier: + max_concurrent: 4 + + frontend_worker: + frontend_address: 127.0.0.1:9095 + + limits_config: + reject_old_samples: true + reject_old_samples_max_age: 168h + allow_structured_metadata: true + volume_enabled: true + + compactor: + working_directory: /loki/compactor + compaction_interval: 10m + retention_enabled: true + delete_request_store: s3 + + pattern_ingester: + enabled: true diff --git a/helm/loki-stack/templates/loki-read-statefulset.yaml b/helm/loki-stack/templates/loki-read-statefulset.yaml new file mode 100644 index 0000000..1fdf396 --- /dev/null +++ b/helm/loki-stack/templates/loki-read-statefulset.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki-stack.fullname" . }}-loki-read + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki-read +spec: + replicas: {{ .Values.loki.read.replicas }} + serviceName: {{ include "loki-stack.fullname" . }}-loki-read-headless + selector: + matchLabels: + {{- include "loki-stack.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: loki-read + template: + metadata: + labels: + {{- include "loki-stack.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: loki-read + loki.grafana.com/memberlist: "true" + spec: + containers: + - name: loki + image: {{ .Values.loki.image.repository }}:{{ .Values.loki.image.tag }} + args: + - -config.file=/etc/loki/loki-config.yaml + - -config.expand-env=true + - -target=read + env: + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + ports: + - name: http + containerPort: 3100 + - name: grpc + containerPort: 9095 + - name: memberlist + containerPort: 7946 + readinessProbe: + httpGet: + path: /ready + port: http + initialDelaySeconds: 15 + periodSeconds: 10 + volumeMounts: + - name: config + mountPath: /etc/loki + - name: data + mountPath: /loki + resources: + {{- toYaml .Values.loki.read.resources | nindent 12 }} + volumes: + - name: config + configMap: + name: {{ include "loki-stack.fullname" . }}-loki + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: + - ReadWriteOnce + {{- if .Values.loki.read.storage.storageClassName }} + storageClassName: {{ .Values.loki.read.storage.storageClassName }} + {{- end }} + resources: + requests: + storage: {{ .Values.loki.read.storage.size }} diff --git a/helm/loki-stack/templates/loki-services.yaml b/helm/loki-stack/templates/loki-services.yaml new file mode 100644 index 0000000..7761fe2 --- /dev/null +++ b/helm/loki-stack/templates/loki-services.yaml @@ -0,0 +1,133 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki-stack.fullname" . }}-loki-write + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki-write +spec: + type: ClusterIP + ports: + - name: http + port: 3100 + targetPort: http + - name: grpc + port: 9095 + targetPort: grpc + selector: + {{- include "loki-stack.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: loki-write +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki-stack.fullname" . }}-loki-write-headless + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki-write +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http + port: 3100 + targetPort: http + selector: + {{- include "loki-stack.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: loki-write +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki-stack.fullname" . }}-loki-read + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki-read +spec: + type: ClusterIP + ports: + - name: http + port: 3100 + targetPort: http + - name: grpc + port: 9095 + targetPort: grpc + selector: + {{- include "loki-stack.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: loki-read +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki-stack.fullname" . }}-loki-read-headless + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki-read +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http + port: 3100 + targetPort: http + selector: + {{- include "loki-stack.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: loki-read +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki-stack.fullname" . }}-loki-backend + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki-backend +spec: + type: ClusterIP + ports: + - name: http + port: 3100 + targetPort: http + - name: grpc + port: 9095 + targetPort: grpc + selector: + {{- include "loki-stack.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: loki-backend +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki-stack.fullname" . }}-loki-backend-headless + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki-backend +spec: + type: ClusterIP + clusterIP: None + ports: + - name: http + port: 3100 + targetPort: http + selector: + {{- include "loki-stack.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: loki-backend +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki-stack.fullname" . }}-loki-memberlist + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki-memberlist +spec: + type: ClusterIP + clusterIP: None + publishNotReadyAddresses: true + ports: + - name: memberlist + port: 7946 + targetPort: memberlist + protocol: TCP + selector: + {{- include "loki-stack.selectorLabels" . | nindent 4 }} + loki.grafana.com/memberlist: "true" diff --git a/helm/loki-stack/templates/loki-write-statefulset.yaml b/helm/loki-stack/templates/loki-write-statefulset.yaml new file mode 100644 index 0000000..d284624 --- /dev/null +++ b/helm/loki-stack/templates/loki-write-statefulset.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "loki-stack.fullname" . }}-loki-write + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: loki-write +spec: + replicas: {{ .Values.loki.write.replicas }} + serviceName: {{ include "loki-stack.fullname" . }}-loki-write-headless + selector: + matchLabels: + {{- include "loki-stack.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: loki-write + template: + metadata: + labels: + {{- include "loki-stack.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: loki-write + loki.grafana.com/memberlist: "true" + spec: + containers: + - name: loki + image: {{ .Values.loki.image.repository }}:{{ .Values.loki.image.tag }} + args: + - -config.file=/etc/loki/loki-config.yaml + - -config.expand-env=true + - -target=write + env: + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + ports: + - name: http + containerPort: 3100 + - name: grpc + containerPort: 9095 + - name: memberlist + containerPort: 7946 + readinessProbe: + httpGet: + path: /ready + port: http + initialDelaySeconds: 15 + periodSeconds: 10 + volumeMounts: + - name: config + mountPath: /etc/loki + - name: data + mountPath: /loki + resources: + {{- toYaml .Values.loki.write.resources | nindent 12 }} + volumes: + - name: config + configMap: + name: {{ include "loki-stack.fullname" . }}-loki + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: + - ReadWriteOnce + {{- if .Values.loki.write.storage.storageClassName }} + storageClassName: {{ .Values.loki.write.storage.storageClassName }} + {{- end }} + resources: + requests: + storage: {{ .Values.loki.write.storage.size }} diff --git a/helm/loki-stack/templates/minio-deployment.yaml b/helm/loki-stack/templates/minio-deployment.yaml new file mode 100644 index 0000000..bb868b3 --- /dev/null +++ b/helm/loki-stack/templates/minio-deployment.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki-stack.fullname" . }}-minio + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: minio +spec: + replicas: 1 + selector: + matchLabels: + {{- include "loki-stack.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: minio + template: + metadata: + labels: + {{- include "loki-stack.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: minio + spec: + containers: + - name: minio + image: {{ .Values.minio.image.repository }}:{{ .Values.minio.image.tag }} + command: + - sh + - -euc + - | + mkdir -p /data/{{ .Values.minio.bucketName }} && \ + minio server /data --console-address ":9001" + env: + - name: MINIO_ROOT_USER + value: {{ .Values.minio.rootUser }} + - name: MINIO_ROOT_PASSWORD + value: {{ .Values.minio.rootPassword }} + ports: + - name: api + containerPort: 9000 + - name: console + containerPort: 9001 + readinessProbe: + exec: + command: ["mc", "ready", "local"] + initialDelaySeconds: 5 + periodSeconds: 5 + volumeMounts: + - name: data + mountPath: /data + resources: + {{- toYaml .Values.minio.resources | nindent 12 }} + volumes: + - name: data + persistentVolumeClaim: + claimName: {{ include "loki-stack.fullname" . }}-minio diff --git a/helm/loki-stack/templates/minio-pvc.yaml b/helm/loki-stack/templates/minio-pvc.yaml new file mode 100644 index 0000000..6ffd053 --- /dev/null +++ b/helm/loki-stack/templates/minio-pvc.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "loki-stack.fullname" . }}-minio + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: minio +spec: + accessModes: + - ReadWriteOnce + {{- if .Values.minio.storage.storageClassName }} + storageClassName: {{ .Values.minio.storage.storageClassName }} + {{- end }} + resources: + requests: + storage: {{ .Values.minio.storage.size }} diff --git a/helm/loki-stack/templates/minio-service.yaml b/helm/loki-stack/templates/minio-service.yaml new file mode 100644 index 0000000..c6a7b0d --- /dev/null +++ b/helm/loki-stack/templates/minio-service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "loki-stack.fullname" . }}-minio + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: minio +spec: + type: ClusterIP + ports: + - name: api + port: 9000 + targetPort: api + - name: console + port: 9001 + targetPort: console + selector: + {{- include "loki-stack.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: minio diff --git a/helm/loki-stack/templates/namespace.yaml b/helm/loki-stack/templates/namespace.yaml new file mode 100644 index 0000000..acd6cd4 --- /dev/null +++ b/helm/loki-stack/templates/namespace.yaml @@ -0,0 +1,10 @@ +{{- if .Values.createNamespace }} +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .Release.Namespace }} + labels: + pod-security.kubernetes.io/audit: privileged + pod-security.kubernetes.io/enforce: privileged + pod-security.kubernetes.io/warn: privileged +{{- end }} diff --git a/helm/loki-stack/templates/networkpolicy.yaml b/helm/loki-stack/templates/networkpolicy.yaml new file mode 100644 index 0000000..168b790 --- /dev/null +++ b/helm/loki-stack/templates/networkpolicy.yaml @@ -0,0 +1,33 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "loki-stack.fullname" . }}-allow-internal + labels: + {{- include "loki-stack.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "loki-stack.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + - Egress + ingress: + # Allow all traffic within the namespace + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: {{ .Release.Namespace }} + egress: + # Allow all traffic within the namespace + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: {{ .Release.Namespace }} + # Allow DNS + - to: + - namespaceSelector: {} + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 diff --git a/helm/loki-stack/templates/vector-configmap.yaml b/helm/loki-stack/templates/vector-configmap.yaml new file mode 100644 index 0000000..5f1187c --- /dev/null +++ b/helm/loki-stack/templates/vector-configmap.yaml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "loki-stack.fullname" . }}-vector + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: vector +data: + vector.yaml: | + sources: + kubernetes_logs: + type: kubernetes_logs + self_node_name: ${VECTOR_SELF_NODE_NAME} + + transforms: + parse_logs: + type: remap + inputs: + - kubernetes_logs + source: | + .namespace = .kubernetes.pod_namespace + .pod = .kubernetes.pod_name + .container = .kubernetes.container_name + .node = .kubernetes.pod_node_name + del(.kubernetes) + del(.file) + del(.source_type) + + sinks: + loki: + type: loki + inputs: + - parse_logs + endpoint: http://{{ include "loki-stack.fullname" . }}-loki-write:3100 + encoding: + codec: text + labels: + source: vector + namespace: "{{`{{ namespace }}`}}" + pod: "{{`{{ pod }}`}}" + container: "{{`{{ container }}`}}" + node: "{{`{{ node }}`}}" + remove_label_fields: true diff --git a/helm/loki-stack/templates/vector-daemonset.yaml b/helm/loki-stack/templates/vector-daemonset.yaml new file mode 100644 index 0000000..848735f --- /dev/null +++ b/helm/loki-stack/templates/vector-daemonset.yaml @@ -0,0 +1,60 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "loki-stack.fullname" . }}-vector + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: vector +spec: + selector: + matchLabels: + {{- include "loki-stack.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: vector + template: + metadata: + labels: + {{- include "loki-stack.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: vector + spec: + serviceAccountName: {{ include "loki-stack.fullname" . }}-vector + containers: + - name: vector + image: {{ .Values.vector.image.repository }}:{{ .Values.vector.image.tag }} + securityContext: + privileged: true + env: + - name: VECTOR_SELF_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - name: config + mountPath: /etc/vector/vector.yaml + subPath: vector.yaml + - name: var-log + mountPath: /var/log + readOnly: true + - name: var-lib-containers + mountPath: /var/log/pods + readOnly: true + - name: data + mountPath: /vector-data-dir + resources: + {{- toYaml .Values.vector.resources | nindent 12 }} + {{- with .Values.vector.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + configMap: + name: {{ include "loki-stack.fullname" . }}-vector + - name: var-log + hostPath: + path: /var/log + - name: var-lib-containers + hostPath: + path: /var/log/pods + - name: data + hostPath: + path: /var/lib/vector diff --git a/helm/loki-stack/templates/vector-rbac.yaml b/helm/loki-stack/templates/vector-rbac.yaml new file mode 100644 index 0000000..e9e4186 --- /dev/null +++ b/helm/loki-stack/templates/vector-rbac.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "loki-stack.fullname" . }}-vector + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: vector +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "loki-stack.fullname" . }}-vector + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: vector +rules: + - apiGroups: [""] + resources: ["namespaces", "nodes", "pods"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "loki-stack.fullname" . }}-vector + labels: + {{- include "loki-stack.labels" . | nindent 4 }} + app.kubernetes.io/component: vector +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "loki-stack.fullname" . }}-vector +subjects: + - kind: ServiceAccount + name: {{ include "loki-stack.fullname" . }}-vector + namespace: {{ .Release.Namespace }} diff --git a/helm/loki-stack/values.yaml b/helm/loki-stack/values.yaml new file mode 100644 index 0000000..1f49402 --- /dev/null +++ b/helm/loki-stack/values.yaml @@ -0,0 +1,112 @@ +nameOverride: "" +fullnameOverride: "" + +# Create namespace with PSA labels (privileged) for Talos +createNamespace: false + +# --- MinIO --- +minio: + image: + repository: minio/minio + tag: latest + rootUser: loki + rootPassword: supersecret + bucketName: loki-chunks + storage: + size: 10Gi + storageClassName: "" + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + +# --- Loki --- +loki: + image: + repository: grafana/loki + tag: "3.4.2" + write: + replicas: 1 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + storage: + size: 10Gi + storageClassName: "" + read: + replicas: 1 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + storage: + size: 10Gi + storageClassName: "" + backend: + replicas: 1 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + storage: + size: 10Gi + storageClassName: "" + +# --- Vector --- +vector: + image: + repository: timberio/vector + tag: 0.44.0-alpine + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 200m + memory: 256Mi + tolerations: [] + +# --- Grafana --- +grafana: + image: + repository: grafana/grafana + tag: "12.4" + adminUser: admin + adminPassword: admin + anonymousAccess: true + replicas: 1 + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi + service: + type: ClusterIP + storage: + size: 5Gi + storageClassName: "" + ingress: + enabled: false + className: "" + annotations: {} + hosts: + - host: grafana.local + paths: + - path: / + pathType: Prefix + tls: [] diff --git a/loki-config.yaml b/loki-config.yaml new file mode 100644 index 0000000..f0f1609 --- /dev/null +++ b/loki-config.yaml @@ -0,0 +1,67 @@ +auth_enabled: false + +server: + http_listen_port: 3100 + grpc_listen_port: 9095 + log_level: info + +common: + compactor_address: http://loki-backend:3100 + ring: + instance_addr: ${HOSTNAME} + kvstore: + store: memberlist + replication_factor: 1 + path_prefix: /loki + +memberlist: + join_members: + - loki-write:7946 + - loki-read:7946 + - loki-backend:7946 + +schema_config: + configs: + - from: "2024-01-01" + store: tsdb + object_store: s3 + schema: v13 + index: + prefix: index_ + period: 24h + +storage_config: + aws: + endpoint: minio:9000 + insecure: true + bucketnames: loki-chunks + access_key_id: loki + secret_access_key: supersecret + s3forcepathstyle: true + tsdb_shipper: + active_index_directory: /loki/index + cache_location: /loki/index_cache + +ingester: + chunk_encoding: snappy + +querier: + max_concurrent: 4 + +frontend_worker: + frontend_address: loki-read:9095 + +limits_config: + reject_old_samples: true + reject_old_samples_max_age: 168h + allow_structured_metadata: true + volume_enabled: true + +compactor: + working_directory: /loki/compactor + compaction_interval: 10m + retention_enabled: true + delete_request_store: s3 + +pattern_ingester: + enabled: true diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..3a4a949 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,59 @@ +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + resolver 127.0.0.11 valid=10s; + + # Loki gateway + server { + listen 3100; + + location = /ready { + proxy_pass http://loki-read:3100$request_uri; + } + + # Write path + location = /loki/api/v1/push { + proxy_pass http://loki-write:3100$request_uri; + } + + # Read path + location ~ /loki/api/.* { + proxy_pass http://loki-read:3100$request_uri; + } + + # Ruler + location ~ /api/prom/rules.* { + proxy_pass http://loki-backend:3100$request_uri; + } + + location ~ /prometheus/api/v1/rules.* { + proxy_pass http://loki-backend:3100$request_uri; + } + } + + # Grafana proxy + server { + listen 3000; + + location / { + proxy_pass http://grafana:3000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # Grafana WebSocket (live features) + location /api/live/ { + proxy_pass http://grafana:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + } + } +} diff --git a/provisioning/datasources/loki.yaml b/provisioning/datasources/loki.yaml new file mode 100644 index 0000000..ff422b9 --- /dev/null +++ b/provisioning/datasources/loki.yaml @@ -0,0 +1,9 @@ +apiVersion: 1 + +datasources: + - name: Loki + type: loki + access: proxy + url: http://gateway:3100 + isDefault: true + editable: true diff --git a/vector.yaml b/vector.yaml new file mode 100644 index 0000000..6298f71 --- /dev/null +++ b/vector.yaml @@ -0,0 +1,30 @@ +sources: + docker_logs: + type: docker_logs + include_labels: + - vector.collect=true + +transforms: + parse_logs: + type: remap + inputs: + - docker_logs + source: | + .container_name = del(.label."com.docker.compose.service") + .compose_project = del(.label."com.docker.compose.project") + # Remove unnecessary labels + del(.label) + +sinks: + loki: + type: loki + inputs: + - parse_logs + endpoint: http://gateway:3100 + encoding: + codec: text + labels: + source: vector + container: "{{ container_name }}" + project: "{{ compose_project }}" + remove_label_fields: true