
Continuando con la serie de artículos centrada en la instalación de las principales herramientas de monitorización en Kubernetes haciendo uso de los operadores, hoy es el turno de EFK, la solución más popular del momento para la centralización de los logs.
En el presente artículo se pretende describir los componentes que conforman el stack EFK así como detallar los pasos a seguir para instalar dicha solución.
Caso de uso
Se dispone de una cluster “vanilla” de Kubernetes, compuesto por un único nodo y con varios microservicios desplegados, en el que se quiere instalar un stack de EFK haciendo uso de los correspondientes operadores.
¿Que es EFK?
Las siglas EFK hace referencia a “Elasticsearch“, “Fluentd” y “Kibana“, tres soluciones open-source que combinadas permiten confeccionar un completo sistema de centralización de logs.
Elasticsearch
Elasticsearch es una base de datos distribuida orientada a documentos que cuenta con un potente motor de búsquedas de cadenas de texto en tiempo real, gracias a la inclusión de Apache Lucene.
Fluentd
Fluentd es un colector de datos open-source para unificar la infraestructura de logging. Básicamente se encarga de recopilar eventos de distintas fuentes de datos y escribirlos después en archivos, RDBMS, NoSQL, IaaS, SaaS o Hadoop, entre otros.
Kibana
Kibana es una herramienta open-source para visualizar y explotar datos almacenados en Elasticsearch. Su potente Web-UI permite crear un sinfín de histogramas, gráficos, o mapas de calor con los que sacar el mayor partido a la información recolectada.
Funcionamiento
El funcionamiento es bien sencillo, Fluentd se encarga de recolectar y procesar los logs de los distintos aplicativos y persistirlos en Elasticsearch. Posteriormente los usuarios pueden explotar esta información haciendo uso de la interfaz proporcionada por Kibana.
Instalación
Elasticsearch
Elasticsearch, al contrario de otros productos descritos anteriormente, dispone de un operador oficial desarrollado por el equipo de Elastic, si bien por el momento no es posible instalarlo haciendo uso de Helm.
Dicho esto, el primer paso será desplegar el operador haciendo uso del ya tradicional kubectl.
kubectl apply -f https://download.elastic.co/downloads/eck/0.9.0/all-in-one.yaml
Con el operador ya desplegado, es el momento de definir la configuración del cluster mediante un CRD de tipo “Elasticsearch”. En el presente ejemplo se definen 3 nodos, dado que es el mínimo establecido por la documentación oficial para la confección de un cluster productivo.
cat <<EOF | kubectl apply -f -
apiVersion: elasticsearch.k8s.elastic.co/v1alpha1
kind: Elasticsearch
metadata:
name: elasticsearch
namespace: elastic-system
spec:
version: 7.2.0
nodes:
- nodeCount: 3
config:
node.master: true
node.data: true
node.ingest: true
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
podTemplate:
spec:
containers:
- name: elasticsearch
resources:
limits:
memory: 3Gi
cpu: 0.3
requests:
memory: 2Gi
cpu: 0.2
EOF
Es importante aclarar una serie de conceptos antes de continuar.
En primera instancia, toda la configuración del producto que tradicionalmente se ubicaba en el fichero “elasticssearch.yaml”, ahora deberá ser definida en el objeto “Elasticsearch” de Kubernetes, concretamente bajo la rama “config”, es decir, al nivel de “node.master”.
En segundo lugar y dado que XPack, la extensión que provee funciones de seguridad, alertas, monitoring, reporting o machine learning a Elasticsearch es gratuita desde las versiones 6.8.0 y 7.1.0, tanto la comunicación interna entre los nodos como los accesos externos están securizados vía TLS y se requiere de un usuario/password para acceder a ellos.
El usuario por defecto es “elasticsearch”, mientras que la password se encuentra almacenada en un Secret de Kubernetes denominado “elasticsearch-es-elastic-user” en el namespace “elastic-system”.
El siguiente comando permite obtener su valor de forma sencilla:
PASSWORD=$(kubectl -n elastic-system get secret elasticsearch-es-elastic-user -o=jsonpath='{.data.elastic}' | base64 --decode)
Kibana
Una vez instalado Elasticsearch, es hora de proceder con la instalación de Kibana.
Dado que ambos productos comparten el mismo operador, simplemente habrá que crear un CRD de tipo Kibana con la configuración deseada.
cat <<EOF | kubectl apply -f -
apiVersion: kibana.k8s.elastic.co/v1alpha1
kind: Kibana
metadata:
name: kibana
namespace: elastic-system
spec:
version: 7.2.0
nodeCount: 1
elasticsearchRef:
name: elasticsearch
podTemplate:
spec:
containers:
- name: kibana
resources:
limits:
memory: 0.7Gi
cpu: 0.3
requests:
memory: 0.5Gi
cpu: 0.2
EOF
Fluentd
Una vez instalado el sistema de persistencia, es hora de proceder con el despliegue de Fluentd haciendo uso del operador logging-operator desarrollado Banzaicloud.
Este operador se encargará de instalar todas las herramientas necesarias para la ingesta de logs.
Por un lado está Fluentbit, el daemonset encargado de recolectar y enriquecer los logs de los contenedores para enviarlos finalmente a Fluentd, el cual realizara los filtrados y transformaciones requeridas para almacenarlos depuse en el sistema de persistencia definido.
La instalación del operador se realizará a través del chart de Helm desarrollado para ello y como siempre es recomendable revisar el fichero values, por si se quisiera modificar alguno de sus valores, pero en principio no es necesario para el caso de uso actual. Es importante saber que en esto punto se instalará únicamente el operador.
helm repo add banzaicloud-stable https://kubernetes-charts.banzaicloud.com
helm repo update
helm install --namespace fluent-system --name logging banzaicloud-stable/logging-operator
Con el operador ya desplegado, es el momento de definir la configuración de instalación de Fluentd y Fluentbit mediante los CRDs correspondientes.
Este proceso se realizará mediante el chart de Helm desarrollado para ello y como siempre es recomendable revisar el fichero values, por si se quisiera modificar alguno de sus valores, pero de nuevo, no es necesario para el caso de uso actual.
helm install -n fluent-system banzaicloud-stable/logging-operator-logging
El siguiente paso es configurar el sistema de persistencia de Fluentd, en este caso, el Elasticsearch instalado anteriormente, mediante un CRD de tipo ClusterOutput.
Dado que no existe un chart de Helm para ello, será necesario hacer uso del ya conocido kubectl. Recordar sustituir la password de Elasticsearch de la configuración adjuntada por la obtenida previamente.
cat <<EOF | kubectl -n logging apply -f -
apiVersion: logging.banzaicloud.io/v1beta1
kind: ClusterOutput
metadata:
name: elasticsearch-output
namespace: fluent-system
spec:
elasticsearch:
host: elasticsearch-es.elastic-system.svc
port: 9200
scheme: https
user: elastic
password: my-password
EOF
Finalmente solo queda definir los contenedores de los que se quiere recolectar logs mediante un CRD de tipo ClusterFlow.
Dado que no existe un chart de Helm para ello, será necesario hacer uso de nuevo del cliente kubectl.
cat <<EOF | kubectl -n logging apply -f -
apiVersion: logging.banzaicloud.io/v1beta1
kind: ClusterFlow
metadata:
name: elasticsearch-clusterflow
namespace: fluent-operator
spec:
filters:
- tag_normaliser: {}
selectors: {}
outputRefs:
- elasticsearch-output
EOF
Conclusiones
En conclusión combinando de forma sencilla los operadores de Elasticsearch y Fluend es posible construir un robusto sistema de centralización de logs.
Eso sí, para los entornos productivos se recomienda encarecidamente revisar todas las configuraciones con el objetivo de encontrar aquella que mejor se ajuste al caso de uso.