一、EFK
EFK是ELK的另一种形式。
E:elasticsearch,他是一个标准搜索引擎
L:logstash:主要是用于帮助我们生成日志的节点负责收集节点上的日志并转换格式后注入到elasticsearch中去,注入进去的格式应该是json格式的。
他能扮演两重功用,在收集日志的节点上能扮演成agent收集日志的代理程序,所以在k8s上如果每一个节点都要部署一个并且部署一个就够了我们可以使用控制器daemonset,生成日志以后应该发送给logstash server,统一整理之后再发送给elasticsearch中去,一般情况下es应该是一个集群,并且logstash agent和server端中间可以加一个消息队列。logstash server扮演了一个非常重要的作用可以把所有的节点所发来的日志做统一的格式转换等额外操作以后把日志信息注入到我们的es集群中。所以logstash server有很重要的作用,我们也讲过logstash如果去做收集日志的agent这个功能来讲就太重量级了,所以我们说过他还可以使用filebeat来替换。所以可以做成ELFK或ELLK。
我们接下来说的EFK可不是上面所说的F,用于在节点上工作能够收集日志信息的组件不光有logstash或filebeat,还有Fluentd,他是一个组织研发的,在k8s集群上运行了很多节点每一个也需要收集日志,并且还有pod,每一个pod中有可能不止一个容器,每一个容器都会生成应用程序日志的,我想去了解这些日志信息,如果我们没有统一的日志收集平台我们管理日志将会变成什么情形?我们突然之间发现我们某一个pod中的容器崩了,我想知道容器中的日志是什么我们此时的做法是什么呢?可以使用kubectl logs 连入容器内部。所以我们需要实时获取每一个pod中的每一个容器中的单独的获取方式不是一个理想的解决方案。我们使用kubectl logs 尽管能获取日志但是对于死掉的容器这种做法都是不可行的因此我们非常有必要应该把pod中的容器包括我们的节点运行中所生成的日志提前收集到一个专门的日志存储中,以免在节点丢失pod down掉或容器down掉时我们想分析日志你还得想办法去把其硬盘扯下来找日志,这个很多时候几乎是不可能的。所以我们说在k8s上复杂的云环境中几乎必须要用到一个日志收集平台以便于能够提供一个统一的接口让我们去查看和分析日志,因此从这个角度来讲日志统一收集存储平台是k8s之上除标准的四大附件之外的另外一个算不上附件的非常重要的基础组件。所以我们说一个完整意义上的k8s集群我们应该部署像 kube-dns(coredns),ingress-controller,heapster(metrics-server),dashboard这四大附件,EFK是一个日志统一收集工具不是基础附件但是基本算是一个完整意义上的k8s必须提供的组件
因此接下来我们来部署这个组件。在k8s上收集日志的风格有两种,第一种我们可以外置收集日志,第二种就是在每一个Pod上都能生成日志,每一个pod单独发送日志给日志存储,但是这个时候我们需要在每一个pod内额外部署一个seidcar容器,因为一个容器中只运行一个应用程序,你的主容器中运行redis后他就不可能再运行一个日志收集工具和发送工具了,所以这个时候我们只能在Pod中同时运行两个容器,主容器提供服务,附容器用来收集主容器日志并发送给日志统一收集平台
但这样一来,万一我们部署一万个Pod那么就要运行一万个日志收集容器,虽然我们一个pod包含两个容器,pod是我们最小粒度单位,但真正意义上来讲两个容器在节点上是需要同时运行的,这样一来就悲剧了。我们也可以在一个容器上运行两个进程但是我们一般不建议这样干,所以最常用的方式我们一般都是基于节点直接部署一个统一的插件,这个节点上的所有容器包括节点自身的日志都由这个插件统一收集以后统一发往日志收集平台,那么这个日志收集平台是应该部署在k8s之上还是之外呢?假如我们使用es存储日志信息,那么es应该运行在集群之上还是集群之外呢?其实都可以。单独部署一套和k8s没关系的集群也可以。因此只有确保k8s自身不会统一所有都出问题时这种情况下才应该把他部署在k8s之上,我们可以把很多应用和k8s这样的应用组合起来统一工作的,这没有任何问题。
在每一个节点上部署一个fluentd,在fluentd基于节点的ip工作向节点之外的没有运行在k8s上的es集群发日志也可以,但是以后我们通过fluentd来作为日志收集器,一般来讲在k8s上用的时候可以用filebeat,只不过用fluentd的居多。假如我们要使用flu的话我们对于flu来说他是部署为守护进程呢还是部署为k8s之上的pod?
首先flu本身是通过我们节点的本地文件系统/var/log来获取日志的,其实我们节点上的每一个容器的日志都被输出到 /var/log/containers/下的,也就意味着我们通过/var/log目录可以获取到所有日志的。都是节点级别的目录,说白了就是要节点的文件系统,因此我们把flu运行为节点的守护进程也是理所当然的,但是我们说过如果flu在节点上挂了怎么办呢?因此如果把flu本身也运行在k8s上运行为daemonset并使用hostpath方式直接把节点的/var/log关联到相关节点的pod上去就能让pod直接访问节点的某特定路径下的文件中的内容了。因此flu可以部署为daemonset托管在k8s上。flu负责收集日志发送给es,es中的内容让kibana来展示,kibana我们也可以运行为容器。并且它是无状态的因此用deployment都可以控制。
在 elk中我们通常使用logstash或filebeat去收集节点日志并同一发给logstash server,由logstash server将格式转换以后再发给es,现在我们提到flu时logstash就没了么?其实为了让我们的es能运行在k8s之上,es官方就直接制作好了相关镜像打包好了相关文件让其直接能运行在我们k8s上,这个镜像文件一般而言他可以运行三种格式,首先他把es拆为两部分,由master和date两部分组成,master节点负责处理轻量化的查询请求,data节点负责重量级别的比如索引构建等请求,所以他把两重任务给隔离开来,master负责接入,data负责处理。因此一般而言我们的es每一个节点就是一个完整的节点,他应该拥有既能负责查询又能负责构建索引的功能,现在我们把他分成两层来分开实现,而后这也就意味着master是客户端接入的唯一入口了。如果master down了data也就没法工作了。因此一般而言我们有三个节点就可以,主要的目的是为了做冗余,万一节点宕机了我们服务还能持续进行,当然如果考虑到我们访问量较大时这三个节点不够用要横向扩展他也可以。和data互不干扰的进行扩展。考虑到都要处理数据那么他们几乎都应该使用存储卷以便于持久存储数据。
master就算是三个节点我们应该判定一旦出现节点之间集群发生分裂了找不着了我们至少要有两个节点才能让他处于正常运行状态,因此以后就不是我们弄三个节点组成es集群了而是我们做两个集群,一个是接入的一个是处理数据的。即master集群和data集群。除此之外他还需要有client集群即客户端,他其实不是真正的client而叫上载,即摄入节点。他帮忙收集任何的日志收集工具由其同一生成特定格式以后再发给我们的master节点,你也可以把它理解为logstash server。
考虑到在生产环境中我们使用妥当的方式去部署,我们如果自己去部署的话可能一个Logstash或部署多个flu也就完事了,但使用helm部署时他们开发的这个应用尽可能考虑是在生产环境中使用的,所以他们部署非常完整和完善,也就意味着我们通过helm获取到的es他就是按照这种格式来组织和部署的。因此有几个master和data节点就需要几个存储卷,因为es的master或data都是有状态的。因为每一个节点只负责一部分任务,存储数据也支持一部分,他不是复制状态的而是分布式的,同样的data也是分布式的,这么一来也就意味着他的master和后端的data都是有状态的,因此他们的存储卷每一个都是独立,一共有几个master data加起来就需要有几个 存储卷。不过考虑到此处只是测试我们就暂时关掉了。
二、部署和使用EFK
1、部署和使用es
[root@k8s-master helm]# helm repo add incubator https://mirror.azure.cn/kubernetes/charts-incubator 添加这个源,当前案例使用6.3.1的elasticsearch,对应的tgz包为1.4.1。如无法添加源,可手动从当前网站拖下来,然后上传到本地local源实现
即
[root@k8s-master helm]# helm package elasticsearch
此处我们使用第二种方法
[root@k8s-master ~]# helm serve ##开启local repo前台运行
Regenerating index. This may take a moment.
Now serving you on 127.0.0.1:8879
[root@k8s-master ~]# cd manifests/helm/
[root@k8s-master helm]# wget http://mirror.azure.cn/kubernetes/charts-incubator/elasticsearch-1.4.1.tgz
[root@k8s-master helm]# tar xf elasticsearch-1.4.1.tgz
[root@k8s-master helm]# helm package elasticsearch
[root@k8s-master helm]# cd elasticsearch/
[root@k8s-master elasticsearch]# vim values.yaml 修改副本数量,因测试节省资源此处都只用一个
22 MINIMUM_MASTER_NODES: "1"
26 replicas: 1
54 replicas: 1
56 persistence:
57 enabled: false //是否开启持久存储
84 replicas: 1
86 persistence:
87 enabled: false //是否开启持久存储
[root@k8s-master kanister-elasticsearch]# kubectl create namespace efk //创建独立的名称空间
[root@k8s-master elasticsearch]# helm install --name els1 --namespace=efk -f values.yaml local/elasticsearch //使用本地repo
##提前下载镜像
[root@k8s-master ~]# docker pull docker.elastic.co/kibana/kibana-oss:6.3.1
[root@k8s-master ~]# docker pull docker.elastic.co/elasticsearch/elasticsearch-oss:6.3.1
[root@k8s-master elasticsearch]# helm install --name els1 --namespace=efk -f values.yaml local/elasticsearch //使用本地repo安装
此处由于数据量庞大,pod状态可能处于Init状态,需要较长的时间等待。
##测试联通性
[root@k8s-master helm]# kubectl run cirror-$RANDOM --rm -it --image=cirros -- /bin/sh
/ # curl els1-elasticsearch-client.efk.svc.cluster.local:9200
{
"name" : "els1-elasticsearch-client-689878c4fd-2tn5w",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "_na_",
"version" : {
"number" : "6.3.1",
"build_flavor" : "oss",
"build_type" : "tar",
"build_hash" : "eb782d0",
"build_date" : "2018-06-29T21:59:26.107521Z",
"build_snapshot" : false,
"lucene_version" : "7.3.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
/ # curl els1-elasticsearch-client.efk.svc.cluster.local:9200/_cat //查看内容
=^.^=
/_cat/allocation
/_cat/shards
/_cat/shards/{index}
/_cat/master
/_cat/nodes
/_cat/tasks
/_cat/indices
/_cat/indices/{index}
/_cat/segments
/_cat/segments/{index}
/_cat/count
/_cat/count/{index}
/_cat/recovery
/_cat/recovery/{index}
/_cat/health
/_cat/pending_tasks
/_cat/aliases
/_cat/aliases/{alias}
/_cat/thread_pool
/_cat/thread_pool/{thread_pools}
/_cat/plugins
/_cat/fielddata
/_cat/fielddata/{fields}
/_cat/nodeattrs
/_cat/repositories
/_cat/snapshots/{repository}
/_cat/templates
/ # curl els1-elasticsearch-client.efk.svc.cluster.local:9200/_cat/nodes //查看有多少个节点
10.244.1.138 31 98 10 0.21 0.78 0.89 mi * els1-elasticsearch-master-0
10.244.2.153 11 96 6 0.61 0.67 0.62 di - els1-elasticsearch-data-0
10.244.1.139 31 98 8 0.21 0.78 0.89 i - els1-elasticsearch-client-689878c4fd-2tn5w
2、部署fluentd
[root@k8s-master helm]# wget http://mirror.azure.cn/kubernetes/charts-incubator/fluentd-elasticsearch-1.0.0.tgz
[root@k8s-master helm]# tar xf fluentd-elasticsearch-1.0.0.tgz
[root@k8s-master helm]# helm package fluentd-elasticsearch
[root@k8s-master helm]# cd fluentd-elasticsearch/
[root@k8s-master fluentd-elasticsearch]# vim values.yaml
20 elasticsearch:
21 host: 'els1-elasticsearch-client.efk.svc.cluster.local' ##此处为elasticsearch的服务地址
39 annotations:
40 prometheus.io/scrape: "true"
41 prometheus.io/port: "24231"
42
43 tolerations:
44 - key: node-role.kubernetes.io/master
45 operator: Exists
46 effect: NoSchedule
47
48 service:
49 type: ClusterIP
50 ports:
51 - name: "monitor-agent"
52 port: 24231
[root@k8s-master fluentd-elasticsearch]# helm install --name flu1 --namespace=efk -f values.yaml local/fluentd-elasticsearch
3、部署kibana
[root@k8s-master helm]# wget http://mirror.azure.cn/kubernetes/charts-incubator/kibana-0.10.0.tgz
[root@k8s-master helm]# tar xf kibana-0.10.0.tgz
[root@k8s-master helm]# helm package kibana
[root@k8s-master helm]# cd kibana/
[root@k8s-master kibana]# vim values.yaml
19 files:
20 kibana.yml:
21 ## Default Kibana configuration from kibana-docker.
22 server.name: kibana
23 server.host: "0"
24 elasticsearch.url: http://els1-elasticsearch-client.efk.svc.cluster.local:9200
32 service:
33 type: NodePort
34 externalPort: 443
35 internalPort: 5601
[root@k8s-master kibana]# helm install --name kib --namespace=efk -f values.yaml local/kibana