在前面一篇文章,我们介绍了分布式日志系统的相关背景。云原生以容器为基础的日志收集方式与传统的日志收集有什么异同。随后介绍了 ELKB 分布式日志系统。本文将会接着上一篇文章继续介绍如何基于 EFK 搭建云原生日志平台。
日志的存储涉及到持久化相关的问题。因此,部署前需要创建数据 k8s 持久化存储,pv 和 pvc。我们的实践涉及到 3 台主机,信息分别如下所示:
角色 | IP |
---|---|
master | 192.168.11.195 |
node1 | 192.168.11.196 |
node2 | 192.168.11.197 |
选择 Node1:192.168.11.196 作为 NFS 服务器 。
# 三台都安装 NFS 和 RPCBIND
yum -y install nfs-utils rpcbind
mkdir -pv /ifs/kubernetes
systemctl enable rpcbind
systemctl enable nfs
systemctl start nfs
$ vim /etc/exports
/ifs/kubernetes *(rw,no_root_squash)
exportfs -r
执行完如上命令之后,在其他机器上面测试:
mount -t nfs 192.168.11.196:/ifs/kubernetes /mnt/
在 NFS 服务器上面(即 k8snode1)新建三个文件夹:
mkdir -pv /ifs/kubernetes/{pv00001,pv00002,pv00003}
采用动态分配 pv 的方式。
#生产动态存储卷
kubectl apply -f class.yaml
#生成pods
kubectl apply -f deployment.yaml
#赋权
kubectl apply -f rbac.yaml
# 最后自动创建存储卷
kubectl apply -f deployment-pvc.yaml
#验证效果
kubectl get pv,pvc
执行完上面的命令之后,既可以查看 pv,pvc 的信息:
相关的配置文件 class.yaml、deployment.yaml、rbac.yaml、deployment-pvc.yaml 较为简单,此处就不一一列出来了,如有需要,公众号后台领取。
依据上面创建的 pv 存储,我们启动如下的服务:
# 启动 es
kubectl apply -f elasticsearch.yaml
# filebeat.yaml
kubectl apply -f filebeat.yaml
# kibana.yaml
kubectl apply -f kibana.yaml
通过上面的命令,即可部署这三个组件。下面我们分别看看这三个组件的配置文件。
elasticsearch 的资源文件如下:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: elasticsearch
namespace: kube-system
labels:
k8s-app: elasticsearch
spec:
serviceName: elasticsearch
selector:
matchLabels:
k8s-app: elasticsearch
template:
metadata:
labels:
k8s-app: elasticsearch
spec:
containers:
- image: elasticsearch:7.3.2
name: elasticsearch
resources:
limits:
cpu: 1
memory: 2Gi
requests:
cpu: 0.5
memory: 500Mi
env:
- name: "discovery.type"
value: "single-node"
- name: ES_JAVA_OPTS
value: "-Xms512m -Xmx2g"
ports:
- containerPort: 9200
name: db
protocol: TCP
volumeMounts:
- name: elasticsearch-data
mountPath: /usr/share/elasticsearch/data
volumeClaimTemplates:
- metadata:
name: elasticsearch-data
spec:
storageClassName: "managed-nfs-storage"
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 20Gi
---
apiVersion: v1
kind: Service
metadata:
name: elasticsearch
namespace: kube-system
spec:
clusterIP: None
ports:
- port: 9200
protocol: TCP
targetPort: db
selector:
k8s-app: elasticsearch
指定了 elasticsearch 镜像的版本为 7.3.2,设定 1 核 2G 的配置,挂载了 managed-nfs-storage 存储,Service 将 elasticsearch 的 db 端口暴露出来。
接着安装 filebeat,filebeat 轻量级数据收集引擎。我们这里同样也是基于 k8s 平台。配置文件如下:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeat-config
namespace: kube-system
labels:
k8s-app: filebeat
data:
filebeat.yml: |-
filebeat.config:
inputs:
reload.enabled: false
modules:
path: ${path.config}/modules.d/*.yml
output.elasticsearch:
hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
---
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeat-inputs
namespace: kube-system
labels:
k8s-app: filebeat
data:
kubernetes.yml: |-
- type: docker
containers.ids:
- "*"
processors:
- add_kubernetes_metadata:
in_cluster: true
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat
namespace: kube-system
labels:
k8s-app: filebeat
spec:
selector:
matchLabels:
k8s-app: filebeat
template:
metadata:
labels:
k8s-app: filebeat
spec:
serviceAccountName: filebeat
terminationGracePeriodSeconds: 30
containers:
- name: filebeat
image: elastic/filebeat:7.3.2
args: [
"-c", "/etc/filebeat.yml",
"-e",
]
env:
- name: ELASTICSEARCH_HOST
value: elasticsearch
- name: ELASTICSEARCH_PORT
value: "9200"
securityContext:
runAsUser: 0
# If using Red Hat OpenShift uncomment this:
#privileged: true
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
volumeMounts:
- name: config
mountPath: /etc/filebeat.yml
readOnly: true
subPath: filebeat.yml
- name: inputs
mountPath: /usr/share/filebeat/inputs.d
readOnly: true
- name: data
mountPath: /usr/share/filebeat/data
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: config
configMap:
defaultMode: 0600
name: filebeat-config
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: inputs
configMap:
defaultMode: 0600
name: filebeat-inputs
- name: data
hostPath:
path: /var/lib/filebeat-data
type: DirectoryOrCreate
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: filebeat
subjects:
- kind: ServiceAccount
name: filebeat
namespace: kube-system
roleRef:
kind: ClusterRole
name: filebeat
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: filebeat
labels:
k8s-app: filebeat
rules:
- apiGroups: [""] # "" indicates the core API group
resources:
- namespaces
- pods
verbs:
- get
- watch
- list
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: filebeat
namespace: kube-system
labels:
k8s-app: filebeat
---
filebeat 镜像的版本为 7.3.2,通过 configMap 配置采集的数据源。filebeat 基于 Logstash-fowarder 的源码改造出来。换句话说:Filebeat就是新版的 Logstash-fowarder,也会是 ELK Stack 在 shipper 端的第一选择。
kibana 用于日志的可视化展示。它能够搜索、展示存储在 Elasticsearch 中索引数据。使用它可以很方便的用图表、表格、地图展示和分析数据。
apiVersion: apps/v1
kind: Deployment
metadata:
name: kibana
namespace: kube-system
labels:
k8s-app: kibana
spec:
replicas: 1
selector:
matchLabels:
k8s-app: kibana
template:
metadata:
labels:
k8s-app: kibana
spec:
containers:
- name: kibana
image: kibana:7.3.2
resources:
limits:
cpu: 1
memory: 500Mi
requests:
cpu: 0.5
memory: 200Mi
env:
- name: ELASTICSEARCH_HOSTS
value: http://elasticsearch-0.elasticsearch.kube-system:9200
- name: I18N_LOCALE
value: zh-CN
ports:
- containerPort: 5601
name: ui
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: kibana
namespace: kube-system
spec:
type: NodePort
ports:
- port: 5601
protocol: TCP
targetPort: ui
nodePort: 30601
selector:
k8s-app: kibana
kibana 对外暴露了 nodePort 为 30601。我们就是通过这个主机端口进行访问。
此时,我们查看 pod,svc,发现都已经是 running 的状态了。三个组件成功安装。
通过上面的组件安装,我们就可以构建索引,来搜索日志信息了。
访问 k8s mater 对应的宿主机 IP + 30601 端口,结果如下所示:
接下来,我们需要建立索引:filebeat-7.3.2-*
索引创建完成之后,就可以在搜索页面进行检索对应的关键词了。
查看 K8S 一些 pod,命名空间,service 的日志,如上图所示全都收集到了。
上面是对 k8s 组件相关的日志进行了采集和搜索,那么我们的微服务日志该如何采集呢。首先,我们部署一个 webdemo 这样的微服务。
kubectl create deployment webdemo --image=nginx
kubectl expose deployment webdemo --port=80 --target-port=80 --name=webdemo --type=NodePort
执行的过程如上图所示。我们来查看下是否创建成功:
为了从浏览器模拟请求,来制造日志,我们需要查看 webdemo 的端口号:
通过 service 的配置可以知道 webdemo 的 nodeport 为 32008。通过命令行进行请求:
curl http://192.168.11.195:32008/
同时,打开 webdemo 的容器服务日志,看看是否对应产生日志:
可以看到上面在对应的产生日志,接着就可以到 kibana 上面进行检索日志了。
成功获取日志。上述的配置表明这种方式能够正常的获取微服务的日志。
通过两篇文章,我们介绍了云原生日志采集相关的概念和基于 EFK 组件的实践,从安装到日志检索的过程。
K8s 的特性是容器日志输出控制台,Docker 本身提供了一种日志采集能力。通过 k8s 搭建 elasticsearch + filebeat + kibana 的日志平台,成功地将容器、k8s 组件和微服务日志都采集到,并通过 kibana 进行图形化展示。