在Kubernetes上使用Elasticsearch+Fluentd+Kibana集中管理日志
2017-01-21
Kubernetes和EFK #
我们使用Kubernetes作为微服务架构的基础,在我们的系统中每个微服务都有多个副本,每个副本的数量以及所在的Node都是可变的。因此对于日志需要集中化管理,在使用Kubernetes之前,我们的系统使用ELK(Elasticsearch+Logstash+Kibana)实现日志的聚集、查询和展现。由于Kubernetes推荐使用Fluentd,所以我们尝试使用EFK(Elasticsearch+Fluentd+Kibana)作为我们的日志集中管理组件。
Kubernetes官方文档Logging and Monitoring Cluster Activity中给出了在Node上通过Logging Agent将日志收集到Logging Backend中的架构方案,如下图:
其中Logging Agent推荐使用Fluentd,Logging Backend推荐使用Elasticsearch和Kibana。
准备镜像 #
Kubernetes已经给了Logging Agent For Elasticsearch的部署参考,我们从其中的 fluentd-es-ds.yaml, es-controller.yaml, kibana-controller.yaml中可以看出我们需要如下三个Docker镜像:
1gcr.io/google_containers/fluentd-elasticsearch:1.22
2gcr.io/google_containers/elasticsearch:v2.4.1-2
3gcr.io/google_containers/kibana:v4.6.1-1
由于某些的原因,我们从gcr.io/google_containers上pull镜像会遇到一些麻烦,这里我们做一些准备工作,到这里查看gcr.io的host,并配置到各个Node的hosts中。
测试Node到grc连接:
1curl https://gcr.io/v1
并可在某个Node上测试pull这些镜像:
1docker pull gcr.io/google_containers/fluentd-elasticsearch:1.22
2docker pull gcr.io/google_containers/elasticsearch:v2.4.1-2
3docker pull gcr.io/google_containers/kibana:v4.6.1-1
以DaemonSet形式启动Fluentd #
Fluentd需要作为Logging Agent的形式在每个Node启动,因此DaemonSet是最好的选择。
1wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml
接下来创建DaemonSet时出错了:
1kubectl create -f fluentd-es-ds.yaml
2error: error validating "fluentd-es-ds.yaml": error validating data: found invalid field tolerations for v1.PodSpec; if you choose to ignore these errors, turn validation off with --validate=false
修改fluentd-es-ds.yaml,注释掉下面的几行:
1 nodeSelector:
2 beta.kubernetes.io/fluentd-ds-ready: "true"
3 tolerations:
4 - key : "node.alpha.kubernetes.io/ismaster"
5 effect: "NoSchedule"
这下创建成功了:
1kubectl create -f fluentd-es-ds.yaml
2daemonset "fluentd-es-v1.22" created
查看创建结果:
1 kubectl get ds --namespace=kube-system -l k8s-app=fluentd-es
2NAME DESIRED CURRENT READY NODE-SELECTOR AGE
3fluentd-es-v1.22 3 3 3 <none> 1m
1kubectl get pod --namespace=kube-system -l k8s-app=fluentd-es -o wide
2NAME READY STATUS RESTARTS AGE IP NODE
3fluentd-es-v1.22-38x88 1/1 Running 0 3m 10.244.3.102 cent1
4fluentd-es-v1.22-5579j 1/1 Running 0 3m 10.244.2.17 cent2
5fluentd-es-v1.22-5sd4b 1/1 Running 0 3m 10.244.0.158 cent0
可以看出fluentd的DaemonSet正常创建,同时在集群的每个Node上启动了一个Pod。
启动Elasticsearch #
1wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/es-service.yaml
2wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/es-controller.yaml
创建ES的RC和Service:
1kubectl create -f es-controller.yaml
2replicationcontroller "elasticsearch-logging-v1" created
3
4kubectl create -f es-service.yaml
5service "elasticsearch-logging" created
查看创建的Service和Pod:
1kubectl get svc --namespace=kube-system -l k8s-app=elasticsearch-logging -o wide
2NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
3elasticsearch-logging 10.97.140.122 <none> 9200/TCP 1m k8s-app=elasticsearch-logging
4
5
6kubectl get rc --namespace=kube-system -l k8s-app=elasticsearch-logging
7NAME DESIRED CURRENT READY AGE
8elasticsearch-logging-v1 2 2 2 2m
9
10
11kubectl get pod --namespace=kube-system -l k8s-app=elasticsearch-logging -o wide
12NAME READY STATUS RESTARTS AGE IP NODE
13elasticsearch-logging-v1-67v53 1/1 Running 0 3m 10.244.3.103 cent1
14elasticsearch-logging-v1-sn8h9 1/1 Running 0 3m 10.244.2.18 cent2
启动Kibana #
1wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/kibana-controller.yaml
2wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/kibana-service.yaml
1kubectl create -f kibana-controller.yaml
2kubectl create -f kibana-service.yaml
查看创建的Service和Pod:
1kubectl get svc --namespace=kube-system -l k8s-app=kibana-logging -o wide
2NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
3kibana-logging 10.110.251.77 <none> 5601/TCP 1m k8s-app=kibana-logging
4
5
6kubectl get deploy --namespace=kube-system -l k8s-app=kibana-logging
7NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
8kibana-logging 1 1 1 1 1m
9
10
11kubectl get pod --namespace=kube-system -l k8s-app=kibana-logging -o wide
12NAME READY STATUS RESTARTS AGE IP NODE
13kibana-logging-1918083406-6cq9n 1/1 Running 0 1m 10.244.2.19 cent2
查看Kibana服务的地址:
1kubectl cluster-info
2Kibana is running at http://localhost:8080/api/v1/proxy/namespaces/kube-system/services/kibana-logging
看到Kibana服务只在Master Node的localhost好用,下面我们kubectl proxy代理api server:
1kubectl proxy --port=8011 --address=192.168.61.100 --accept-hosts='^192\.168\.61\.*'
2Starting to serve on 192.168.61.100:8011
使用下面的地址访问Kibana:
1http://192.168.61.100:8011/api/v1/proxy/namespaces/kube-system/services/kibana-logging
创建index后,就可以在Kibana中查看到Kubernetes集群中的日志了:
最后 #
Kubernetes官方EFK的部署参考中,Elasticsearch挂载的Volume是emptyDir。
1 template:
2 metadata:
3 labels:
4 k8s-app: elasticsearch-logging
5 version: v1
6 kubernetes.io/cluster-service: "true"
7 spec:
8 containers:
9 - image: gcr.io/google_containers/elasticsearch:v2.4.1-2
10 name: elasticsearch-logging
11 resources:
12 # need more cpu upon initialization, therefore burstable class
13 limits:
14 cpu: 1000m
15 requests:
16 cpu: 100m
17 ports:
18 - containerPort: 9200
19 name: db
20 protocol: TCP
21 - containerPort: 9300
22 name: transport
23 protocol: TCP
24 volumeMounts:
25 - name: es-persistent-storage
26 mountPath: /data
27 env:
28 - name: "NAMESPACE"
29 valueFrom:
30 fieldRef:
31 fieldPath: metadata.namespace
32 volumes:
33 - name: es-persistent-storage
34 emptyDir: {}
因此官方的部署参考仅可用于试验,实际部署到生产环境时需要使用Persistent Volume。