在个人电脑上使用Kubernetes验证Elasticsearch的动态日志基础架构
在跟踪 CNCF 教程示例:向 PHP / Redis 留言簿示例中添加日志和指标的过程中,通过读取日志并将其存储到 Elasticsearch 中,确认可以使用 Kibana 进行日志分析。
为了进行这个教程,需要掌握Docker的15个步骤,使用在电脑上开发的Kubernetes集群作为学习环境。这个集群是为了使用GitHub公开并供任何人使用的,并且能够通过Vagrant + VirtualBox + Ansible和上游的Kubernetes进行构建,这样任何人都可以免费自由地使用它作为学习环境。通过Vagrant和VirtualBox,在Windows10、macOS和Linux上可以使用相同的代码和操作进行运行。
通过掌握上游Kubernetes代码,可以将其视为云供应商和软件产品的核心,从而将其作为理解各种Kubernetes的基础知识。
在这个教程中,我们将使用Elasticseach的BEATS工具。BEATS被描述为一组轻量级的数据传输工具,用于将数据从源GuestBook或Worker节点发送到Elasticseach或Logstash。在本教程中,我们将使用以下三种工具。
-
- Filebeat : auditd、Apache、NGINX、System、MySQLなどのログ形式の対応したログファイル転送することで一括管理を実現
-
- Metricbeat : システムレベルでのCPU使用状況、メモリ、ファイルシステム、ディスクI/O、ネットワークI/Oなど、システム上で実行中のすべてのプロセスの統計情報を一括収集。Apache、Jolokia、NGINX、MongoDB、MySQL、PostgreSQL、Prometheusをはじめ、さまざまなサービスからメトリックを収集する専用モジュールも提供
- Packetbeat : HTTPのようなネットワークプロトコルでは、アプリケーションの遅延やエラー、応答時間、SLA、ユーザーアクセスのパターン、傾向などの状況を把握
在Kubernetes集群上设置这些工具,并构建一个基础设施来收集来自GuestBook和Kubernetes集群基础设施的数据,并确保其可靠性。
![overview.png](https://cdn.silicloud.com/blog-img/blog/img/657d43b837434c4406c9cf41/6-0.png)
启动虚拟机
这次,Elasteicsearch默认部署为三个节点,所以我们增加一个工作节点,形成三个工作节点和一个主节点的配置。此外,每个Elasteicsearch的Pod需要2GB内存,所以我们也增加了每个工作节点的内存。
由於需要大量使用記憶體,我們決定在 Vagrant + VirtualBox 的虛擬機主機上使用 Linux 伺服器。從 GitHub 上使用以下指令將程式碼複製到本地環境中。
$ git clone -b 1.16_3n https://github.com/takara9/vagrant-kubernetes k8s-1.16-3nodes
這是一段程式碼用於在使用三個節點的基礎架構上,使用 Kubernetes 1.16 作為 git 分支的創建,因為書中採用的 Kubernetes 1.14 版本已經終止支援。
$ cd k8s-1.16-3nodes
$ vi Vagrantfile
希望自己操作的人,请编辑文件并添加外部LAN侧的I/F,调整CPU核心数和内存大小。顺便提一下,工作节点的内存为4GB,vCPU为x2。主节点的内存为2GB,vCPU为x2。因此,总共使用16GB RAM和8个vCPU。在运行状态下,实际内存使用量为15GB。
使用vagrant up命令启动需大约12分钟。
$ vagrant up
<中略>
$ kubectl get node
NAME STATUS ROLES AGE VERSION
master Ready master 87s v1.16.3
node1 Ready <none> 48s v1.16.3
node2 Ready <none> 61s v1.16.3
node3 Ready <none> 48s v1.16.3
安装HELM v3
根据ElasticSearch的Git仓库上的说明,它不支持HELM V3,但我亲自尝试后并没有任何问题,因此我决定使用安装简便的HELM V3。由于我正在使用Linux,所以按照以下方法安装HELM客户端。
Linux安装示例
$ curl https://get.helm.sh/helm-v3.0.2-linux-amd64.tar.gz | tar zx
$ sudo mv linux-amd64/helm /usr/local/bin
如果要使用Ubuntu Linux 18.04的软件包管理器进行安装,请参考以下示例安装方法。
$ sudo snap install helm --classic
helm 3.0.2 from Snapcrafters installed
安装后确认,使用的HELM版本为3.0.2。
$ helm version
version.BuildInfo{Version:"v3.0.2", GitCommit:"19e47ee3283ae98139d98460de796c1be1e3975f", GitTreeState:"clean", GoVersion:"go1.13.5"}
为了验证功能并添加HELM图表库,可以执行以下操作。要使helm命令正常工作,必须确保kubectl命令可用。因此,如果在设置kubectl命令后需要使用helm命令,则需要先设置kubectl命令。
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
创建命名空间
在这个教程中,我们将使用GustBook教程作为我们的监视对象应用程序,并将其分别放置在两个命名空间中。因此,我们将按照以下方式创建命名空间。
kubectl create ns elasticsearch
kubectl create ns guestbook
创建背景
为避免在每次执行命令时都需指定命名空间而感到麻烦,我们可以创建一个上下文并切换默认的命名空间来使用。为此,可以使用kubectl config来创建上下文。
kubectl config set-context es --namespace=elasticsearch --cluster=kubernetes --user=kubernetes-admin
kubectl config set-context gs --namespace=guestbook --cluster=kubernetes --user=kubernetes-admin
kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
es kubernetes kubernetes-admin elasticsearch
gs kubernetes kubernetes-admin guestbook
* kubernetes-admin@kubernetes kubernetes kubernetes-admin
引入留言簿的功能
请安装GustBook。这里不是为了解释目的,所以我不会进行说明。我已写了一篇关于这个教程的文章,希望能一并参考。
将名称空间切换到留言簿,并应用所有必要的清单。
kubectl config use-context gs
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-master-deployment.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-master-service.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-slave-deployment.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-slave-service.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml
kubectl get svc,po
当所有的pod都处于Running状态时,准备工作完成。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/frontend NodePort 10.32.0.188 <none> 80:32213/TCP 12s
service/redis-master ClusterIP 10.32.0.74 <none> 6379/TCP 50s
service/redis-slave ClusterIP 10.32.0.194 <none> 6379/TCP 32s
NAME READY STATUS RESTARTS AGE
pod/frontend-6cb7f8bd65-9kjhp 1/1 Running 0 22s
pod/frontend-6cb7f8bd65-wkrt5 1/1 Running 0 22s
pod/frontend-6cb7f8bd65-xt2mt 1/1 Running 0 22s
pod/redis-master-7db7f6579f-7pgjl 1/1 Running 0 60s
pod/redis-slave-7664787fbc-76zn9 1/1 Running 0 40s
pod/redis-slave-7664787fbc-qxg6x 1/1 Running 0 40s
由于GuestBook网页使用NodePort进行公开,请使用上述service/frontend的30000端口号和虚拟服务器的局域网IP地址来访问。以下是一个使用命令尝试的示例,但建议从计算机浏览器进行访问。
$ curl http://192.168.1.93:32213
<html ng-app="redis">
<head>
<title>Guestbook</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script>
<以下省略>
引入ElasticSearch。
作为进行教程准备的一部分,需要启动Elasticsearch和Kibana。为了实现这一点,需要添加HELM的存储库。
$ helm repo add elastic https://helm.elastic.co
切换上下文,将命名空间 elasticsearch 设置为默认值。
$ kubectl config use-context es
在这里,不使用永久卷,而是使用每个节点的临时卷。在用于学习的GlusterFs环境中,无法满足要求,导致ElasticSearch的Pod出现故障,因此需要使用临时卷。为此,需要设置–set persistence.enabled=false。
helm install elasticsearch elastic/elasticsearch --set persistence.enabled=false
以下是在终端上运行的结果。在部署完成之前,helm命令会退出,因此我们可以使用kubectl get pods –namespace=default -l app=elasticsearch-master -w等待该应用程序的pod进入Running状态,然后再继续进行下一步。
$ helm install elasticsearch elastic/elasticsearch --set persistence.enabled=false
NAME: elasticsearch
LAST DEPLOYED: Mon Jan 13 00:40:29 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Watch all cluster members come up.
$ kubectl get pods --namespace=default -l app=elasticsearch-master -w
2. Test cluster health using Helm test.
$ helm test elasticsearch
$ kubectl get pods --namespace=default -l app=elasticsearch-master -w
NAME READY STATUS RESTARTS AGE
elasticsearch-master-0 0/1 Running 0 10s
elasticsearch-master-1 0/1 Running 0 10s
elasticsearch-master-2 0/1 Running 0 10s
elasticsearch-master-2 1/1 Running 0 49s
elasticsearch-master-1 1/1 Running 0 49s
elasticsearch-master-0 1/1 Running 0 50s
接下来进行测试以进行确认。
^tkr@luigi:~/k8s-1.16-3nodes/gfs/k8s-yaml$ helm test elasticsearch
Pod elasticsearch-wispd-test pending
Pod elasticsearch-wispd-test succeeded
NAME: elasticsearch
LAST DEPLOYED: Mon Jan 13 00:40:29 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: elasticsearch-wispd-test
Last Started: Mon Jan 13 00:41:59 2020
Last Completed: Mon Jan 13 00:42:00 2020
Phase: Succeeded
<以下省略>
在中文中进行原生的改写:
安装Kibana
作为前端UI工具,安装Kibana。由于不与负载均衡器配合,因此通过–set service.type=NodePort来设置NodePort,并添加–set service.nodePort=31920,以确保端口号固定,并进行安装。
tkr@luigi:~/k8s-1.16$ helm install kibana elastic/kibana --set service.type=NodePort --set service.nodePort=31920
NAME: kibana
LAST DEPLOYED: Sun Jan 12 15:40:55 2020
NAMESPACE: elasticsearch
STATUS: deployed
REVISION: 1
TEST SUITE: None
预计需要1到2分钟才能完成启动,启动后可以通过指定的端口号和虚拟服务器的外部局域网IP地址访问。
http://192.168.1.92:31920/app/kibana
初始界面如下所示。在这里没有特别的设置,可以继续下一步。
![kibana-1.png](https://cdn.silicloud.com/blog-img/blog/img/657d43b837434c4406c9cf41/57-0.png)
以下是有关参数等的参考URL:
* https://github.com/elastic/helm-charts
教程
在这之前的工作中,最终,准备工作已经做好了,例如:为 PHP/Redis 留言板示例添加日志和指标。
按照教程,执行集群的角色绑定。这项工作是为了在使用Google GCP时向GCP用户授予执行权限,但由于在桌面的本地环境中执行没有问题,所以直接执行即可。
kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=takara9@gmail.com
kube-state-metrics 的部署方式
kube-state-metrics 提供一个 REST API,从 Kubernetes API 对象中提供度量数据。通过添加的 API,可以从 Kubernetes API 公开原始运行数据。用户可以获取所有运行数据,并根据启发式算法理解当前状况。
这是一个REST-API,以HTTP端点/metrics提供监听端口。它专门设计用于Prometheus客户端和兼容的抓取器可进行利用。https://github.com/kubernetes/kube-state-metrics
git clone https://github.com/kubernetes/kube-state-metrics.git kube-state-metrics
cd kube-state-metrics
kubectl create -f examples/standard
只要 kube-state-metrics 的 Pod 为 Running 状态,就可以认为已经启动成功。
kubectl get pods -n kube-system -l app.kubernetes.io/name=kube-state-metrics
NAME READY STATUS RESTARTS AGE
kube-state-metrics-7b678f986c-kd7bq 1/1 Running 0 63s
准备引进动态记录工具
这些是方便的工具,例如,通过搭建httpd服务器和Redis来自动收集访问日志、错误日志、指标信息和网络流量信息,并将它们集中到ElastiSearch中。在本教程中,我们将使用这个工具来在Kibana中显示日志、指标和流量。
从Git上下载工具,然后切换到相应的目录。
$ git clone https://github.com/elastic/examples.git
cd ../examples/beats-k8s-send-anywhere
请编辑以下这四个大写字母的文件,生成一个“秘密”(secret)。
kubectl create secret generic dynamic-logging \
--from-file=./ELASTICSEARCH_HOSTS \
--from-file=./ELASTICSEARCH_PASSWORD \
--from-file=./ELASTICSEARCH_USERNAME \
--from-file=./KIBANA_HOST \
--namespace=kube-system
请在每个文件中显示内容。详细信息请参阅教程正文。
$ cat ELASTICSEARCH_PASSWORD
<>:
$ cat ELASTICSEARCH_USERNAME
<>:
$ cat ELASTICSEARCH_HOSTS
["http://elasticsearch-master.elasticsearch.svc.cluster.local:9200"]
$ cat KIBANA_HOST
"kibana-kibana.elasticsearch.svc.cluster.local:5601"
部署 Filebeat
最初部署Filebeat。这个工具会引用后续的密码并发送信息。
kubectl create -f filebeat-kubernetes.yaml
由于这个清单是基于 Kubernetes 1.16 之前的API规范,所以需要对清单进行修改。
---
apiVersion: apps/v1 #extensions/v1beta1 <-- apps/v1へ変更
kind: DaemonSet
metadata:
name: filebeat-dynamic
namespace: kube-system
labels:
k8s-app: filebeat-dynamic
kubernetes.io/cluster-service: "true"
spec:
selector: <-- ここから3行を追加
matchLabels:
k8s-app: filebeat-dynamic <-- このキーと値は、metadata.labelsからコピーする
template:
metadata:
labels:
如果应用程序经过适用后,状态变为“运行”,则继续执行下一步。
$ kubectl get pods -n kube-system -l k8s-app=filebeat-dynamic
NAME READY STATUS RESTARTS AGE
filebeat-dynamic-kstlx 1/1 Running 0 2m27s
filebeat-dynamic-lxzms 1/1 Running 0 2m27s
filebeat-dynamic-vx65n 1/1 Running 0 2m27s
Filebeat的运行操作
Filebeat的pod会挂载/var/lib/docker/containers目录,并从工作节点的容器执行环境读取容器内的文件。通过这种方式,在不使用pod的sidecar、在工作节点中安装代理的情况下,可以读取pod内的中间件文件和日志。
在OpenShift中,由于需要以特权运行容器,因此需要在清单中添加额外的配置。
FileBeat参考URL:
* 在Kubernetes上运行Filebeat,https://www.elastic.co/guide/en/beats/filebeat/master/running-on-kubernetes.html#running-on-kubernetes
* Filebeat概述编辑,https://www.elastic.co/guide/en/beats/filebeat/master/filebeat-overview.html#filebeat-overview
* 配置Filebeat编辑,https://www.elastic.co/guide/en/beats/filebeat/master/configuring-howto-filebeat.html#configuring-howto-filebeat
* Red Hat OpenShift配置编辑,https://www.elastic.co/guide/en/beats/filebeat/master/running-on-kubernetes.html
障害解决的案例
如果Filebeat的Pod重复出现错误和运行状态的情况下,需要补充解释关于如何判断原因的方法。
$ kubectl get pods -n kube-system -l k8s-app=filebeat-dynamic
NAME READY STATUS RESTARTS AGE
filebeat-dynamic-g48gv 0/1 Error 0 44s
filebeat-dynamic-kzkbd 0/1 Error 0 44s
filebeat-dynamic-zmqpb 0/1 Error 0 44s
$ kubectl get pods -n kube-system -l k8s-app=filebeat-dynamic
NAME READY STATUS RESTARTS AGE
filebeat-dynamic-g48gv 0/1 CrashLoopBackOff 1 53s
filebeat-dynamic-kzkbd 0/1 CrashLoopBackOff 1 53s
filebeat-dynamic-zmqpb 0/1 CrashLoopBackOff 1 53s
以下是使用指定的pod来转储日志的方法。在其中,查找错误并寻找原因。
在这里,显示找不到主机lookup elasticsearch-master.elasticsearch.svc.cluster.local,并且可以看出它未在Kubernetes的内部DNS中注册。在此情况下,由于ElasticSearch部署到了默认命名空间中,导致出现了这样的问题。
$ kubectl logs filebeat-dynamic-g48gv
<中略>
al": lookup elasticsearch-master.elasticsearch.svc.cluster.local: no such host
2020-01-12T16:18:44.805Z ERROR elasticsearch/elasticsearch.go:252 Error connecting to Elasticsearch at http://elasticsearch-master.elasticsearch.svc.cluster.local:9200: Get http://elasticsearch-master.elasticsearch.svc.cluster.local:9200: lookup elasticsearch-master.elasticsearch.svc.cluster.local: no such host
2020-01-12T16:18:44.807Z INFO [monitoring] log/log.go:152 Total non-zero metrics {"monitoring": {"metrics": {"beat":{"cpu":{"system":{"ticks":10,"time":{"ms":12}},"total":{"ticks":50,"time":{"ms":60},"value":50},"user":{"ticks":40,"time":{"ms":48}}},"handles":{"limit":{"hard":1048576,"soft":1048576},"open":9},"info":{"ephemeral_id":"f62e797e-0fd8-4f61-bfcd-6def1894bca7","uptime":{"ms":45}},"memstats":{"gc_next":4779472,"memory_alloc":2494672,"memory_total":6717840,"rss":27881472}},"filebeat":{"harvester":{"open_files":0,"running":0}},"libbeat":{"config":{"module":{"running":0}},"output":{"type":"elasticsearch"},"pipeline":{"clients":0,"events":{"active":0}}},"registrar":{"states":{"current":0}},"system":{"cpu":{"cores":3},"load":{"1":0.38,"15":0.27,"5":0.32,"norm":{"1":0.1267,"15":0.09,"5":0.1067}}}}}}
2020-01-12T16:18:44.807Z INFO [monitoring] log/log.go:153 Uptime: 46.059403ms
2020-01-12T16:18:44.807Z INFO [monitoring] log/log.go:130 Stopping metrics logging.
2020-01-12T16:18:44.807Z INFO instance/beat.go:393 filebeat stopped.
2020-01-12T16:18:44.807Z ERROR instance/beat.go:906 Exiting: Error importing Kibana dashboards: fail to create the Elasticsearch loader: Error creating Elasticsearch client: Couldn't connect to any of the configured Elasticsearch hosts. Errors: [Error connection to Elasticsearch http://elasticsearch-master.elasticsearch.svc.cluster.local:9200: Get http://elasticsearch-master.elasticsearch.svc.cluster.local:9200: lookup elasticsearch-master.elasticsearch.svc.cluster.local: no such host]
Exiting: Error importing Kibana dashboards: fail to create the Elasticsearch loader: Error creating Elasticsearch client: Couldn't connect to any of the configured Elasticsearch hosts. Errors: [Error connection to Elasticsearch http://elasticsearch-master.elasticsearch.svc.cluster.local:9200: Get http://elasticsearch-master.elasticsearch.svc.cluster.local:9200: lookup elasticsearch-master.elasticsearch.svc.cluster.local: no such host]
度量指标采集器
引入收集以下度量指标的工具。同样,只要实施相同的引入即可。
kubectl create -f metricbeat-kubernetes.yaml
该清单也是以旧版本编写的,适用于Deployment和DaemonSet,所以必须进行API标记和spec.selector的添加。一旦清单应用后,如果Pod变为Running状态,则表示完成。
$ kubectl get pods -n kube-system -l k8s-app=metricbeat
NAME READY STATUS RESTARTS AGE
metricbeat-585bd7d6c9-kc47c 1/1 Running 0 4m30s
metricbeat-c4q76 1/1 Running 0 4m31s
metricbeat-qcmmg 1/1 Running 0 4m31s
metricbeat-vr5n7 1/1 Running 0 4m31s
Metricbeat参考URL:
* 概述,https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-overview.html
* Redis模块编辑,https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-module-redis.html#metricbeat-module-redis
数据包采集
使用最终工具来部署Packetbeat。由于DaemonSet的API使用了旧的规范,所以请对其进行同样的修正并应用。如果应用后所有的Pod都能达到Running状态,则任务完成。
$ kubectl create -f packetbeat-kubernetes.yaml
这样教程的设置就完成了。
Packetbeat参考链接:
* Packetbeat参考文档, https://www.elastic.co/guide/en/beats/packetbeat/current/index.html
内存使用量
由于ElasticSearch是用Java编写的,所以我们会担心它需要多少内存。在运行了大约2个小时后,内存的使用量约为3GB。因此,我们认为分配给节点的最小内存应该是4GB。
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master 87m 4% 1141Mi 60%
node1 134m 6% 2607Mi 67%
node2 153m 7% 2813Mi 73%
node3 159m 7% 2743Mi 71%
Kibana界面
不需要自定义,介绍一个简单易看的界面。
在“发现”页面上,您可以以每个时间单位为单位查看事件的发生量,并以列表形式查看每个事件的内容。您还可以查看按索引单词聚合的统计信息。
![kibana-2.png](https://cdn.silicloud.com/blog-img/blog/img/657d43b837434c4406c9cf41/110-0.png)
下一个是指标的界面。说到ElasticSearch,它是一个有名的搜索引擎。利用这个特性,它也被用作日志分析工具,但同时也能展示指标的功能。虽然不及Grafana和Prometheus那样强大,但在这里也能看到所需的时序信息。通过点击这块磁贴,可以查看CPU、内存等的时序图表。
![kibana-3.png](https://cdn.silicloud.com/blog-img/blog/img/657d43b837434c4406c9cf41/112-0.png)
通过时间序列,可以了解到CPU、内存、网络等的使用情况。
![kibana-4.png](https://cdn.silicloud.com/blog-img/blog/img/657d43b837434c4406c9cf41/114-0.png)
以下是在工作节点间进行监视的文件,相当于在命令行中使用 “tail -f 文件名” 命令进行显示。例如,Apache2的访问日志和Syslog的信息都会混合在同一个屏幕上显示。无论工作节点或者Pod的数量有多少,即使添加了新的节点,也无需修改配置,它们会自动地被添加到这个屏幕上。
![kibana-5.png](https://cdn.silicloud.com/blog-img/blog/img/657d43b837434c4406c9cf41/116-0.png)
总结
CNCF Kubernetes文档的教程是为公共云(如GCP)使用而编写的。然而,由于也适用于本地计算机上的上游Kubernetes,因此人们希望它也可以在本地环境或者OpenShift中使用。
Elastic 公司提供软件支持的订阅服务。我们在这个教程中使用的 Elasticsearch 和 Kibana 等相关软件也可以免费使用,但如果需要获得支持,则需要与 Elastic 公司签订订阅合约。
OpenShift具有集成了Elasticsearch的功能,并且可以通过Red Hat来获得OpenShift作为一部分的支持。在OpenShift中,甚至包含了这个功能强大的日志分析工具,而且在OpenShift 4中还配备了运营支持的Operator,所以OpenShift可能是非常划算的。
其它参考网址:
* https://www.ibm.com/support/knowledgecenter/ja/SSBS6K_2.1.0.3/manage_metrics/logging_elk.html
* https://www.elastic.co/guide/en/beats/filebeat/master/running-on-kubernetes.html
* https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-getting-started.html
* http://docs.docker.jp/v1.12/engine/userguide/storagedriver/imagesandcontainers.html
* https://docs.docker.com/storage/