|
| 1 | +--- |
| 2 | +id: aggregate-cce-logs-with-fluentbit-and-grafana-loki |
| 3 | +title: Aggregate CCE Logs with Fluent Bit & Grafana Loki |
| 4 | +tags: [cce, observability, logging, grafana, loki, fluent-bit] |
| 5 | +sidebar_position: 3 |
| 6 | +--- |
| 7 | + |
| 8 | +# Aggregate CCE Logs with Fluent Bit & Grafana Loki |
| 9 | + |
| 10 | +This blueprint explains how to collect and centralize logs from Cloud Container Engine (CCE) workloads using [Fluent Bit](https://fluentbit.io/) and [Grafana Loki](https://grafana.com/oss/loki/). It covers the end-to-end setup for forwarding logs from CCE nodes and containers to a centralized Loki instance, enabling efficient querying, visualization, and troubleshooting through Grafana dashboards. The goal is to provide a consistent and scalable logging approach for Kubernetes environments running on Open Telekom Cloud. |
| 11 | + |
| 12 | +[Fluent Bit](https://fluentbit.io/) is a lightweight, high-performance log and metrics processor designed for cloud and containerized environments. It collects data from various sources, processes and filters it, and then forwards it to multiple destinations such as Loki, Elasticsearch, or cloud logging services. Built with minimal resource consumption in mind, Fluent Bit integrates seamlessly with Kubernetes through `DaemonSets`, making it an efficient choice for aggregating logs from all nodes and containers in a cluster. |
| 13 | + |
| 14 | +## Installing Grafana Loki |
| 15 | + |
| 16 | +If you don’t already have a Grafana Loki instance running, you can set it up first before proceeding with log aggregation. The installation process is covered in detail in the companion blueprint [Deploy Grafana Loki on CCE](/docs/blueprints/by-use-case/observability/deploy-grafana-loki-on-cce), which explains how to deploy Loki in microservices mode on Cloud Container Engine (CCE) with Open Telekom Cloud Object Storage (OBS) as the backend. Once Loki is up and running, you can continue here to install and configure Fluent-Bit and start collecting and centralizing logs from your CCE workloads. |
| 17 | + |
| 18 | +## Installing Fluent Bit as Log Forwarder |
| 19 | + |
| 20 | +Fluent Bit, as already mentioned, acts as the central log collector in the cluster, running as a `DaemonSet`, collecting logs from every node and container in the CCE cluster, parsing and enriching them with Kubernetes metadata, and finally forwarding them to Grafana Loki. |
| 21 | + |
| 22 | +Create a values file called **values-fluentbit.yaml**: |
| 23 | + |
| 24 | +```yaml title="values-fluentbit.yaml" |
| 25 | +elasticsearch: |
| 26 | + enabled: false |
| 27 | + |
| 28 | +opensearch: |
| 29 | + enabled: false |
| 30 | + |
| 31 | +kind: DaemonSet |
| 32 | + |
| 33 | +config: |
| 34 | + service: | |
| 35 | + [SERVICE] |
| 36 | + Daemon Off |
| 37 | + Flush 1 |
| 38 | + Log_Level info |
| 39 | + Parsers_File /fluent-bit/etc/parsers.conf |
| 40 | + Parsers_File /fluent-bit/etc/conf/custom_parsers.conf |
| 41 | + HTTP_Server On |
| 42 | + HTTP_Listen 0.0.0.0 |
| 43 | + HTTP_Port 2020 |
| 44 | + Health_Check On |
| 45 | +
|
| 46 | + inputs: | |
| 47 | + [INPUT] |
| 48 | + Name tail |
| 49 | + Path /var/log/containers/*.log |
| 50 | + Exclude_Path /var/log/containers/*fluent-bit*.log |
| 51 | + multiline.parser docker, cri |
| 52 | + Tag kube.* |
| 53 | + Mem_Buf_Limit 50MB |
| 54 | + Skip_Long_Lines On |
| 55 | + Refresh_Interval 10 |
| 56 | +
|
| 57 | + filters: | |
| 58 | + [FILTER] |
| 59 | + Name kubernetes |
| 60 | + Match kube.* |
| 61 | + Kube_URL https://kubernetes.default.svc:443 |
| 62 | + Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt |
| 63 | + Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token |
| 64 | + Kube_Tag_Prefix kube.var.log.containers. |
| 65 | + Merge_Log On |
| 66 | + Keep_Log On |
| 67 | + K8S-Logging.Parser On |
| 68 | + K8S-Logging.Exclude On |
| 69 | + Labels Off |
| 70 | + Annotations Off |
| 71 | +
|
| 72 | + [FILTER] |
| 73 | + Name modify |
| 74 | + Match kube.* |
| 75 | + Remove stream |
| 76 | + Remove time |
| 77 | + Remove kubernetes.container_hash |
| 78 | + Remove kubernetes.pod_id |
| 79 | +
|
| 80 | + outputs: | |
| 81 | + [OUTPUT] |
| 82 | + Name loki |
| 83 | + Match kube.* |
| 84 | + Host loki-gateway.monitoring.svc.cluster.local |
| 85 | + Port 80 |
| 86 | + uri /loki/api/v1/push |
| 87 | + labels job=fluent-bit, namespace=$kubernetes['namespace_name'], pod=$kubernetes['pod_name'], container=$kubernetes['container_name'] |
| 88 | + remove_keys kubernetes,host,container_id,_p |
| 89 | + line_format key_value |
| 90 | + drop_single_key raw |
| 91 | + auto_kubernetes_labels off |
| 92 | +
|
| 93 | + customParsers: | |
| 94 | + [PARSER] |
| 95 | + Name docker_no_time |
| 96 | + Format json |
| 97 | + Time_Keep Off |
| 98 | + Time_Key time |
| 99 | + Time_Format %Y-%m-%dT%H:%M:%S.%L |
| 100 | +
|
| 101 | +resources: |
| 102 | + requests: |
| 103 | + cpu: 100m |
| 104 | + memory: 128Mi |
| 105 | + limits: |
| 106 | + cpu: 500m |
| 107 | + memory: 256Mi |
| 108 | + |
| 109 | +tolerations: |
| 110 | + - operator: Exists |
| 111 | + effect: NoSchedule |
| 112 | + - operator: Exists |
| 113 | + effect: NoExecute |
| 114 | + |
| 115 | +securityContext: |
| 116 | + runAsNonRoot: true |
| 117 | + runAsUser: 1000 |
| 118 | + readOnlyRootFilesystem: true |
| 119 | + allowPrivilegeEscalation: false |
| 120 | + capabilities: |
| 121 | + drop: |
| 122 | + - ALL |
| 123 | + |
| 124 | +serviceMonitor: |
| 125 | + enabled: false |
| 126 | + |
| 127 | +hostNetwork: false |
| 128 | +dnsPolicy: ClusterFirst |
| 129 | +``` |
| 130 | +
|
| 131 | +and deploy via Helm: |
| 132 | +
|
| 133 | +```bash |
| 134 | +helm repo add fluent https://fluent.github.io/helm-charts |
| 135 | +helm repo update |
| 136 | + |
| 137 | +helm upgrade --install fluent-bit fluent/fluent-bit \ |
| 138 | +-f values-fluentbit.yaml \ |
| 139 | +--namespace monitoring --create-namespace \ |
| 140 | +--reset-values |
| 141 | +``` |
| 142 | + |
| 143 | +:::note |
| 144 | +For detailed guidance on configuring the Kubernetes filter, refer to the [Fluent Bit official documentation](https://docs.fluentbit.io/manual/data-pipeline/filters/kubernetes). |
| 145 | +::: |
| 146 | + |
| 147 | +## Installing Grafana (Optional) |
| 148 | + |
| 149 | +For verification, we’ll install Grafana with Helm and include a simple demo dashboard to confirm that logs are reaching Loki. This lightweight setup is only for validation and smoke testing. For most production clusters, the recommended approach is to deploy the [kube-prometheus-stack](https://github.com/prometheus-community/helm-charts/blob/main/charts/kube-prometheus-stack/README.md) bundle, which provides Grafana together with Prometheus, Alertmanager, and curated dashboards, offering tighter integration and easier ongoing operations. |
| 150 | + |
| 151 | +Create a values file called **values-grafana.yaml**: |
| 152 | + |
| 153 | +```yaml title="values-promtail.yaml" |
| 154 | +adminUser: admin |
| 155 | + |
| 156 | +persistence: |
| 157 | + enabled: true |
| 158 | + size: 5Gi |
| 159 | + accessModes: |
| 160 | + - ReadWriteOnce |
| 161 | + storageClassName: "csi-disk" |
| 162 | + |
| 163 | +service: |
| 164 | + enabled: true |
| 165 | + type: ClusterIP |
| 166 | + port: 80 |
| 167 | + |
| 168 | +resources: |
| 169 | + requests: |
| 170 | + cpu: 100m |
| 171 | + memory: 256Mi |
| 172 | + limits: |
| 173 | + cpu: 500m |
| 174 | + memory: 512Mi |
| 175 | + |
| 176 | +datasources: |
| 177 | + datasources.yaml: |
| 178 | + apiVersion: 1 |
| 179 | + datasources: |
| 180 | + - name: Loki |
| 181 | + type: loki |
| 182 | + access: proxy |
| 183 | + url: http://loki-gateway.monitoring.svc.cluster.local |
| 184 | + jsonData: |
| 185 | + maxLines: 1000 |
| 186 | + derivedFields: |
| 187 | + - datasourceUid: Loki |
| 188 | + matcherRegex: "traceID=(\\w+)" |
| 189 | + name: TraceID |
| 190 | + url: "$${__value.raw}" |
| 191 | + isDefault: true |
| 192 | + editable: true |
| 193 | + |
| 194 | +dashboardProviders: |
| 195 | + dashboardproviders.yaml: |
| 196 | + apiVersion: 1 |
| 197 | + providers: |
| 198 | + - name: 'default' |
| 199 | + orgId: 1 |
| 200 | + folder: '' |
| 201 | + type: file |
| 202 | + disableDeletion: false |
| 203 | + editable: true |
| 204 | + options: |
| 205 | + path: /var/lib/grafana/dashboards/default |
| 206 | + |
| 207 | +dashboards: |
| 208 | + default: |
| 209 | + loki-logs: |
| 210 | + gnetId: 18494 |
| 211 | + revision: 1 |
| 212 | + datasource: Loki |
| 213 | + |
| 214 | +grafana.ini: |
| 215 | + server: |
| 216 | + root_url: "%(protocol)s://%(domain)s:%(http_port)s/" |
| 217 | + analytics: |
| 218 | + check_for_updates: true |
| 219 | + check_for_plugin_updates: true |
| 220 | + log: |
| 221 | + mode: console |
| 222 | + paths: |
| 223 | + data: /var/lib/grafana/ |
| 224 | + logs: /var/log/grafana |
| 225 | + plugins: /var/lib/grafana/plugins |
| 226 | + provisioning: /etc/grafana/provisioning |
| 227 | + |
| 228 | +securityContext: |
| 229 | + runAsNonRoot: true |
| 230 | + runAsUser: 472 |
| 231 | + runAsGroup: 472 |
| 232 | + fsGroup: 472 |
| 233 | + allowPrivilegeEscalation: false |
| 234 | + capabilities: |
| 235 | + drop: |
| 236 | + - ALL |
| 237 | + |
| 238 | +serviceMonitor: |
| 239 | + enabled: false |
| 240 | + |
| 241 | +rbac: |
| 242 | + create: true |
| 243 | + pspEnabled: false |
| 244 | + |
| 245 | +serviceAccount: |
| 246 | + create: true |
| 247 | + autoMount: true |
| 248 | +``` |
| 249 | +
|
| 250 | +and deploy via Helm: |
| 251 | +
|
| 252 | +```bash |
| 253 | +helm repo add grafana https://grafana.github.io/helm-charts |
| 254 | +helm repo update |
| 255 | + |
| 256 | +helm upgrade --install grafana grafana/grafana \ |
| 257 | +-f values-grafana.yaml \ |
| 258 | +-n monitoring --create-namespace \ |
| 259 | +--set "adminPassword=$(openssl rand -base64 24)" \ |
| 260 | +--reset values |
| 261 | +``` |
| 262 | + |
| 263 | +Go to *Grafana* -> *Dashboards* and click the dashboard we provisioned as bundle with the Helm Chart *Loki Kubernetes Logs*: |
| 264 | + |
| 265 | + |
| 266 | + |
| 267 | +:::note |
| 268 | +:bulb: The Grafana admin password can be found in `grafana` secret in monitoring namespace. |
| 269 | +:warning: This Grafana installation and the provided [dashboard](https://grafana.com/grafana/dashboards/18494-kubernetes-logs-from-loki/) are intended for demonstration purposes only. |
| 270 | +::: |
0 commit comments