FLG (Fluentd, Loki Grafana) Stack para la observabilidad de aplicaciones
Published on May 14, 2023 by Lucho
post kubernetes devops fluentd loki grafana FLG
6 min READ
En esta publicación, discutiemos una alternativa para el monitoreo de registros de aplicaciones como seria FLG.
Fluentd es un controlador de registros de código abierto cuya arquitectura conectable lo diferencia de otras alternativas como Logstash, Datadog. Su capa de registro unificada le permite conectarse fácilmente a varias fuentes de datos y destinos de salida. Esto es evidente en la gran cantidad de complementos, filtros, analizadores disponibles para administrar datos/registros de una gran cantidad de fuentes de entrada (por ejemplo, registros de aplicaciones, Syslog, MQTT, Docker, Amazon Cloudwatch, Twitter) y enviarlos a una lista igualmente extensa de salida objetivos (por ejemplo, Elasticsearch, Amazon S3, Google BigQuery, Graphite, Zabbix, Splunk, Sumologic, slack).
Con el siguiente manifiesto se puede desplegar una version sencilla del stack FLG:
---
# source: grafana.yaml
apiVersion: v1
kind: Service
metadata:
name: grafana
labels:
app: grafana
spec:
type: NodePort
ports:
- name: web
protocol: TCP
port: 80
targetPort: 3000
nodePort: 31000
selector:
app: grafana
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
labels:
app: grafana
spec:
selector:
matchLabels:
app: grafana
replicas: 1
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana-container
image: grafana/grafana:latest
imagePullPolicy: Always
---
# source: loki.yaml
apiVersion: v1
kind: Service
metadata:
name: loki
labels:
app: loki
spec:
type: ClusterIP
ports:
- name: loki
protocol: TCP
port: 3100
targetPort: 3100
selector:
app: loki
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: loki
labels:
app: loki
spec:
selector:
matchLabels:
app: loki
replicas: 1
template:
metadata:
labels:
app: loki
spec:
restartPolicy: Always
containers:
- name: loki
image: grafana/loki:latest
imagePullPolicy: Always
args: ["-config.file=/etc/loki/local-config.yaml"]
stdin: true
tty: true
ports:
- containerPort: 3100
---
# component: fluentd.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluentd
labels:
app: fluentd
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fluentd
labels:
app: fluentd
rules:
- apiGroups:
- ""
resources:
- pods
- namespaces
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: fluentd
roleRef:
kind: ClusterRole
name: fluentd
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: fluentd
namespace: default # <- change to your preferred workspace
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
labels:
app: fluentd
kubernetes.io/cluster-service: "true"
spec:
selector:
matchLabels:
app: fluentd
kubernetes.io/cluster-service: "true"
template:
metadata:
labels:
app: fluentd
kubernetes.io/cluster-service: "true"
spec:
serviceAccount: fluentd
serviceAccountName: fluentd
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd
imagePullPolicy: Always
image: fluent/fluentd-kubernetes-daemonset:v1.4-debian-forward-1
command:
- /bin/sh
- '-c'
- >
fluent-gem i fluent-plugin-grafana-loki-licence-fix ;
tini /fluentd/entrypoint.sh;
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: config
mountPath: /fluentd/etc
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: config
configMap:
name: fluentd-logging
---
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentd-logging
labels:
app: fluentd-logging
data:
fluent.conf: |
<source>
@type tail
@id in_tail_container_logs
path /var/log/containers/*.log
pos_file /var/log/fluentd-containers.log.pos
tag kubernetes.*
read_from_head true
#<parse>
# @type cri
# merge_cri_fields false
# <parse>
# @type json
# time_key time
# time_format %Y-%m-%dT%H:%M:%S.%L%z
# </parse>
#</parse>
<parse>
@type json
time_format %Y-%m-%dT%H:%M:%S.%NZ
</parse>
</source>
<match fluentd.**>
@type null
</match>
<match kubernetes.var.log.containers.**fluentd**.log>
@type null
</match>
<filter kubernetes.**>
@type kubernetes_metadata
@id filter_kube_metadata
</filter>
<filter kubernetes.var.log.containers.**>
@type record_transformer
enable_ruby
#remove_keys kubernetes, docker
<record>
app ${ record.dig("kubernetes", "labels", "app") }
job ${ record.dig("kubernetes", "labels", "app") }
namespace ${ record.dig("kubernetes", "namespace_name") }
pod ${ record.dig("kubernetes", "pod_name") }
container ${ record.dig("kubernetes", "container_name") }
host ${ record.dig("kubernetes", "host") }
</record>
</filter>
<match kubernetes.var.log.containers.**>
@type copy
<store>
@type loki
url "http://10.99.148.193:3100"
label_keys "app,job,namespace,pod,host"
extra_labels {"env":"dev"}
flush_interval 10s
flush_at_shutdown true
buffer_chunk_limit 1m
</store>
<store>
@type stdout
</store>
</match>
---
Para entornos los cuales no dispongan de internet, podrian compilar una imagen ya con la gema instalada
# source: 0lucho0/fluentd-loki:1.0.0
FROM fluent/fluentd-kubernetes-daemonset:v1.4-debian-forward-1
RUN fluent-gem i fluent-plugin-grafana-loki-licence-fix