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镜像:
gcr.io/google_containers/fluentd-elasticsearch:1.22
gcr.io/google_containers/elasticsearch:v2.4.1-2
gcr.io/google_containers/kibana:v4.6.1-1由于某些的原因,我们从gcr.io/google_containers上pull镜像会遇到一些麻烦,这里我们做一些准备工作,到这里查看gcr.io的host,并配置到各个Node的hosts中。
测试Node到grc连接:
curl https://gcr.io/v1并可在某个Node上测试pull这些镜像:
docker pull gcr.io/google_containers/fluentd-elasticsearch:1.22
docker pull gcr.io/google_containers/elasticsearch:v2.4.1-2
docker pull gcr.io/google_containers/kibana:v4.6.1-1以DaemonSet形式启动Fluentd
Fluentd需要作为Logging Agent的形式在每个Node启动,因此DaemonSet是最好的选择。
wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/fluentd-es-ds.yaml接下来创建DaemonSet时出错了:
kubectl create -f fluentd-es-ds.yaml
error: 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,注释掉下面的几行:
nodeSelector:
beta.kubernetes.io/fluentd-ds-ready: "true"
tolerations:
- key : "node.alpha.kubernetes.io/ismaster"
effect: "NoSchedule"这下创建成功了:
kubectl create -f fluentd-es-ds.yaml
daemonset "fluentd-es-v1.22" created查看创建结果:
kubectl get ds --namespace=kube-system -l k8s-app=fluentd-es
NAME DESIRED CURRENT READY NODE-SELECTOR AGE
fluentd-es-v1.22 3 3 3 <none> 1mkubectl get pod --namespace=kube-system -l k8s-app=fluentd-es -o wide
NAME READY STATUS RESTARTS AGE IP NODE
fluentd-es-v1.22-38x88 1/1 Running 0 3m 10.244.3.102 cent1
fluentd-es-v1.22-5579j 1/1 Running 0 3m 10.244.2.17 cent2
fluentd-es-v1.22-5sd4b 1/1 Running 0 3m 10.244.0.158 cent0可以看出fluentd的DaemonSet正常创建,同时在集群的每个Node上启动了一个Pod。
启动Elasticsearch
wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/es-service.yaml
wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/es-controller.yaml创建ES的RC和Service:
kubectl create -f es-controller.yaml
replicationcontroller "elasticsearch-logging-v1" created
kubectl create -f es-service.yaml
service "elasticsearch-logging" created查看创建的Service和Pod:
kubectl get svc --namespace=kube-system -l k8s-app=elasticsearch-logging -o wide
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
elasticsearch-logging 10.97.140.122 <none> 9200/TCP 1m k8s-app=elasticsearch-logging
kubectl get rc --namespace=kube-system -l k8s-app=elasticsearch-logging
NAME DESIRED CURRENT READY AGE
elasticsearch-logging-v1 2 2 2 2m
kubectl get pod --namespace=kube-system -l k8s-app=elasticsearch-logging -o wide
NAME READY STATUS RESTARTS AGE IP NODE
elasticsearch-logging-v1-67v53 1/1 Running 0 3m 10.244.3.103 cent1
elasticsearch-logging-v1-sn8h9 1/1 Running 0 3m 10.244.2.18 cent2启动Kibana
wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/kibana-controller.yaml
wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/kibana-service.yamlkubectl create -f kibana-controller.yaml
kubectl create -f kibana-service.yaml查看创建的Service和Pod:
kubectl get svc --namespace=kube-system -l k8s-app=kibana-logging -o wide
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kibana-logging 10.110.251.77 <none> 5601/TCP 1m k8s-app=kibana-logging
kubectl get deploy --namespace=kube-system -l k8s-app=kibana-logging
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kibana-logging 1 1 1 1 1m
kubectl get pod --namespace=kube-system -l k8s-app=kibana-logging -o wide
NAME READY STATUS RESTARTS AGE IP NODE
kibana-logging-1918083406-6cq9n 1/1 Running 0 1m 10.244.2.19 cent2查看Kibana服务的地址:
kubectl cluster-info
Kibana is running at http://localhost:8080/api/v1/proxy/namespaces/kube-system/services/kibana-logging看到Kibana服务只在Master Node的localhost好用,下面我们kubectl proxy代理api server:
kubectl proxy --port=8011 --address=192.168.61.100 --accept-hosts='^192\.168\.61\.*'
Starting to serve on 192.168.61.100:8011使用下面的地址访问Kibana:
http://192.168.61.100:8011/api/v1/proxy/namespaces/kube-system/services/kibana-logging创建index后,就可以在Kibana中查看到Kubernetes集群中的日志了:
最后
Kubernetes官方EFK的部署参考中,Elasticsearch挂载的Volume是emptyDir。
template:
metadata:
labels:
k8s-app: elasticsearch-logging
version: v1
kubernetes.io/cluster-service: "true"
spec:
containers:
- image: gcr.io/google_containers/elasticsearch:v2.4.1-2
name: elasticsearch-logging
resources:
# need more cpu upon initialization, therefore burstable class
limits:
cpu: 1000m
requests:
cpu: 100m
ports:
- containerPort: 9200
name: db
protocol: TCP
- containerPort: 9300
name: transport
protocol: TCP
volumeMounts:
- name: es-persistent-storage
mountPath: /data
env:
- name: "NAMESPACE"
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumes:
- name: es-persistent-storage
emptyDir: {}因此官方的部署参考仅可用于试验,实际部署到生产环境时需要使用Persistent Volume。