apiVersion: v1 kind: ConfigMap metadata: name: loki-config namespace: observability labels: app.kubernetes.io/name: loki app.kubernetes.io/part-of: observability project.pi.io/type: platform data: config.yaml: | auth_enabled: false server: http_listen_port: 3100 common: path_prefix: /var/loki replication_factor: 1 ring: kvstore: store: inmemory storage: filesystem: chunks_directory: /var/loki/chunks rules_directory: /var/loki/rules schema_config: configs: - from: 2024-01-01 store: tsdb object_store: filesystem schema: v13 index: prefix: index_ period: 24h storage_config: filesystem: directory: /var/loki/chunks limits_config: allow_structured_metadata: false reject_old_samples: true reject_old_samples_max_age: 168h retention_period: 168h compactor: working_directory: /var/loki/compactor retention_enabled: true delete_request_store: filesystem analytics: reporting_enabled: false --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: loki-data namespace: observability labels: app.kubernetes.io/name: loki app.kubernetes.io/part-of: observability project.pi.io/type: platform spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 20Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: loki namespace: observability labels: app.kubernetes.io/name: loki app.kubernetes.io/part-of: observability project.pi.io/type: platform spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: loki template: metadata: labels: app.kubernetes.io/name: loki app.kubernetes.io/part-of: observability spec: securityContext: fsGroup: 10001 containers: - name: loki image: grafana/loki:3.0.0 args: - -config.file=/etc/loki/config.yaml ports: - name: http containerPort: 3100 readinessProbe: httpGet: path: /ready port: http initialDelaySeconds: 10 periodSeconds: 10 livenessProbe: httpGet: path: /ready port: http initialDelaySeconds: 30 periodSeconds: 15 volumeMounts: - name: config mountPath: /etc/loki readOnly: true - name: data mountPath: /var/loki volumes: - name: config configMap: name: loki-config - name: data persistentVolumeClaim: claimName: loki-data --- apiVersion: v1 kind: Service metadata: name: loki namespace: observability labels: app.kubernetes.io/name: loki app.kubernetes.io/part-of: observability project.pi.io/type: platform spec: selector: app.kubernetes.io/name: loki ports: - name: http port: 3100 targetPort: http --- apiVersion: v1 kind: ServiceAccount metadata: name: promtail namespace: observability labels: app.kubernetes.io/name: promtail app.kubernetes.io/part-of: observability project.pi.io/type: platform --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: promtail labels: app.kubernetes.io/name: promtail app.kubernetes.io/part-of: observability project.pi.io/type: platform rules: - apiGroups: [""] resources: - nodes - nodes/proxy - services - endpoints - pods - namespaces verbs: - get - list - watch - apiGroups: ["discovery.k8s.io"] resources: - endpointslices verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: promtail labels: app.kubernetes.io/name: promtail app.kubernetes.io/part-of: observability project.pi.io/type: platform roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: promtail subjects: - kind: ServiceAccount name: promtail namespace: observability --- apiVersion: v1 kind: ConfigMap metadata: name: promtail-config namespace: observability labels: app.kubernetes.io/name: promtail app.kubernetes.io/part-of: observability project.pi.io/type: platform data: config.yaml: | server: http_listen_port: 3101 grpc_listen_port: 0 positions: filename: /run/promtail/positions.yaml clients: - url: http://loki.observability.svc.cluster.local:3100/loki/api/v1/push scrape_configs: - job_name: kubernetes-pods kubernetes_sd_configs: - role: pod pipeline_stages: - cri: {} relabel_configs: - source_labels: - __meta_kubernetes_pod_node_name target_label: __host__ - action: labelmap regex: __meta_kubernetes_pod_label_(.+) - action: replace source_labels: - __meta_kubernetes_namespace target_label: namespace - action: replace source_labels: - __meta_kubernetes_pod_name target_label: pod - action: replace source_labels: - __meta_kubernetes_pod_container_name target_label: container - action: replace source_labels: - __meta_kubernetes_namespace - __meta_kubernetes_pod_name separator: / replacement: $1 target_label: job - action: replace source_labels: - __meta_kubernetes_pod_uid - __meta_kubernetes_pod_container_name separator: / replacement: /var/log/pods/*$1/*.log target_label: __path__ - action: replace source_labels: - __meta_kubernetes_pod_annotationpresent_kubernetes_io_config_hash - __meta_kubernetes_pod_annotation_kubernetes_io_config_hash - __meta_kubernetes_pod_container_name regex: true/(.*) separator: / replacement: /var/log/pods/*$1/*.log target_label: __path__ --- apiVersion: apps/v1 kind: DaemonSet metadata: name: promtail namespace: observability labels: app.kubernetes.io/name: promtail app.kubernetes.io/part-of: observability project.pi.io/type: platform spec: selector: matchLabels: app.kubernetes.io/name: promtail template: metadata: labels: app.kubernetes.io/name: promtail app.kubernetes.io/part-of: observability spec: serviceAccountName: promtail containers: - name: promtail image: grafana/promtail:3.0.0 args: - -config.file=/etc/promtail/config.yaml env: - name: HOSTNAME valueFrom: fieldRef: fieldPath: spec.nodeName ports: - name: http containerPort: 3101 securityContext: runAsUser: 0 runAsGroup: 0 volumeMounts: - name: config mountPath: /etc/promtail readOnly: true - name: run mountPath: /run/promtail - name: varlog mountPath: /var/log readOnly: true volumes: - name: config configMap: name: promtail-config - name: run emptyDir: {} - name: varlog hostPath: path: /var/log type: Directory --- apiVersion: v1 kind: ConfigMap metadata: name: grafana-datasources namespace: observability labels: app.kubernetes.io/name: grafana app.kubernetes.io/part-of: observability project.pi.io/type: platform data: loki.yaml: | apiVersion: 1 datasources: - name: Loki type: loki access: proxy url: http://loki.observability.svc.cluster.local:3100 isDefault: true editable: false --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: grafana-data namespace: observability labels: app.kubernetes.io/name: grafana app.kubernetes.io/part-of: observability project.pi.io/type: platform spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: grafana namespace: observability labels: app.kubernetes.io/name: grafana app.kubernetes.io/part-of: observability project.pi.io/type: platform spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: grafana template: metadata: labels: app.kubernetes.io/name: grafana app.kubernetes.io/part-of: observability spec: securityContext: fsGroup: 472 containers: - name: grafana image: grafana/grafana:11.0.0 env: - name: GF_SECURITY_ADMIN_USER valueFrom: secretKeyRef: name: observability-secrets key: grafana_admin_user - name: GF_SECURITY_ADMIN_PASSWORD valueFrom: secretKeyRef: name: observability-secrets key: grafana_admin_password - name: GF_AUTH_ANONYMOUS_ENABLED value: "false" - name: GF_USERS_ALLOW_SIGN_UP value: "false" - name: GF_EXPLORE_ENABLED value: "true" - name: GF_SERVER_ROOT_URL valueFrom: secretKeyRef: name: observability-secrets key: grafana_root_url ports: - name: http containerPort: 3000 readinessProbe: httpGet: path: /api/health port: http initialDelaySeconds: 10 periodSeconds: 10 livenessProbe: httpGet: path: /api/health port: http initialDelaySeconds: 30 periodSeconds: 15 volumeMounts: - name: data mountPath: /var/lib/grafana - name: datasources mountPath: /etc/grafana/provisioning/datasources readOnly: true volumes: - name: data persistentVolumeClaim: claimName: grafana-data - name: datasources configMap: name: grafana-datasources --- apiVersion: v1 kind: Service metadata: name: grafana namespace: observability labels: app.kubernetes.io/name: grafana app.kubernetes.io/part-of: observability project.pi.io/type: platform spec: selector: app.kubernetes.io/name: grafana ports: - name: http port: 3000 targetPort: 3000