部署 Kubernetes 集群日志插件 Fluentd、Elasticsearch、Kibana
2017-11-06 10:10
1351 查看
目录
Kubernetes 日志架构介绍
环境、软件准备
启动 Fluentd
启动 Elasticsearch
启动 Kibana
浏览器添加证书
RBAC 认证模式介绍
1、Kubernetes 日志架构介绍
对于任何基础架构或者服务系统,日志重要性不言而喻,当然 Kubernetes 也少不了对 Logging 的支持,集群中各个资源以及服务日志如何很好的集中查看并分析,官方给出了 Cluster-level Logging 的架构,其中就提供使用 EFK 框架作为集群日志解决方案。当然 EFK / ELK 在业内也是相对成熟作为日志集中分析平台,ELK 在 Kubernetes 集群中以 Pod 方式运行,丝毫不影响集群中其他 Pod,而且不需要修改其他 Pod 配置,非常方便。
Kubernetes 官网给出的 Cluster-level Logging 参考架构如下:
从图上可以看出,它是采用 Node Logging Agent 的方式,通过在集群每个节点上部署一个 Agent 代理 Pod 服务,收集该 Node 上的日志并 Push 到后端,当然 Logging agent 是以容器方式运行,并且有权限进入该节点上所有服务容器的日志目录。上边提到的 Logging-agent 就可以采用 Fluentd,而 Logging Backend 就可以采用 Elasticsearch,简单理解就是,通过 Fluentd 作为 Logging-agent 收集并 Push 日志到后端 Elasticsearch,最终通过 Kibana 图形化展现出来。
2、环境、软件准备
部署 Fluentd、Elasticsearch、Kibana 到 Kubernetes 集群中,前提我们需要有一个正常运行的集群服务,这里我采用 kubeadm 搭建的 Kubernetes 集群,具体搭建步骤可以参考我上一篇文章 国内使用 kubeadm 在 Centos 7 搭建 Kubernetes 集群 讲述的比较详细,这里就不做演示了。不过还是要说一下的就是国内翻墙问题,由于这三个服务所需要的 images 在国外,国内用户可以去 Docker Hub 下载指定版本的镜像替代,下载完成后,通过
本次演示所依赖的各个镜像列表如下:
说明一下,这里我没有使用最新版本的镜像,因为我的 Kubernetes 版本为 v1.6.2,所以我选择了Github kubernetes 下该版本对应的组件,回头再试下更新成最新版本的试试看。
可使用下边脚本,分别替换以上镜像。
3、启动 Fluentd
Fluentd 是以 DaemonSet 的形式运行在 Kubernetes 集群中,这样就可以保证集群中每个 Node 上都会启动一个 Fluentd,我们在 Master 节点创建 Fluented 服务,最终会在各个 Node 上运行,可以通过 Yaml 文件的方式。
命令创建 Fluentd 后,默认会将启动日志输出到 Node 节点的 /var/log/fluented.log 文件里面去。但是,当我们去 Node 节点上执行
首先查看一下 Pod 没有创建,通过
接着我们查看下 fluentd-es-ds.yaml 信息
通过输出我们可以看到,确实没有启动起来,不过我们发现
不甘心的我,决定看下我集群中 Node 节点是否有这个标签,
好吧,这下死心了,确实没有这个标签,那就给该 Node 补上这个标签,然后重新运行下 fluentd。
好了,这下启动成功了,这下在去看下 Node 节点 /var/log/fluented.log 文件,这下有日志输出啦。
最后的一行输出又是什么鬼?获取不到容器 fluentd 在 /var/log/containers/fluentd-es-xxxxxx 下的日志输出。果断去该目录 /var/log/containers/ 下看下确实没有任何容器日志文件,好吧,分析觉得很有可能是 Docker 输出日志的位置跟 Fluentd 监听的日志的位置不一致。
原来是去 /var/lib/docker/containers 和 /var/log 目录去找日志。我查看那一下机器Docker 的日志驱动配置
原来这个节点 安装的 Docker 默认日志驱动为 journald,那么所有的日志都会通过系统的 journal进行统一处理,输出到 /var/log/messages 下边了。怪不得提示 /var/log/containers/ 下没有任何容器日志文件呢。解决办法就是修改 Docker 的日志驱动为 json-file 方式。
好了,现在去看下 /var/log/containers/fluentd-es-xxxxxx 终于有日志输出了。
这下输出终于正常了,不过最后输出
4、启动 Elasticsearch
经过一番折腾,作为 Logging-agent 的 Fluentd 启动好了,现在要启动作为 Logging Backend 的 Elasticsearch 了,Elasticsearch 的主要作用是将日志信息进行分割,建立索引,配合下边 Kibana 展示数据使用。它也是通过 Yaml 文件创建。
看样子是启动成功了,不放心还是看下日志输出吧!
都
显示连接成功,这一次还挺顺利的哈。接下来该启动 Kibana 服务来图形化查看收集的日志信息了。
5、启动 Kibana
Kibana 是一个开源的分析与可视化平台,与 Elasticsearch 一起使用的,可以用 Kibana 搜索、查看、交互存放在 Elasticsearch 索引里的数据,很直观的在浏览器页面图形化展示出来,非常方便,它也是通过 Yaml 文件创建。
显示启动成功,查看下日志输出,显示需要花费几分钟优化缓存 Kibana 和状态页。
稍等几分钟(有的可能需要更长时间,我的 5 分钟左右),再来查看日志,就显示启动成功了。
又看到熟悉的
Kubernetes 日志架构介绍
环境、软件准备
启动 Fluentd
启动 Elasticsearch
启动 Kibana
浏览器添加证书
RBAC 认证模式介绍
1、Kubernetes 日志架构介绍
对于任何基础架构或者服务系统,日志重要性不言而喻,当然 Kubernetes 也少不了对 Logging 的支持,集群中各个资源以及服务日志如何很好的集中查看并分析,官方给出了 Cluster-level Logging 的架构,其中就提供使用 EFK 框架作为集群日志解决方案。当然 EFK / ELK 在业内也是相对成熟作为日志集中分析平台,ELK 在 Kubernetes 集群中以 Pod 方式运行,丝毫不影响集群中其他 Pod,而且不需要修改其他 Pod 配置,非常方便。
Kubernetes 官网给出的 Cluster-level Logging 参考架构如下:
从图上可以看出,它是采用 Node Logging Agent 的方式,通过在集群每个节点上部署一个 Agent 代理 Pod 服务,收集该 Node 上的日志并 Push 到后端,当然 Logging agent 是以容器方式运行,并且有权限进入该节点上所有服务容器的日志目录。上边提到的 Logging-agent 就可以采用 Fluentd,而 Logging Backend 就可以采用 Elasticsearch,简单理解就是,通过 Fluentd 作为 Logging-agent 收集并 Push 日志到后端 Elasticsearch,最终通过 Kibana 图形化展现出来。
2、环境、软件准备
部署 Fluentd、Elasticsearch、Kibana 到 Kubernetes 集群中,前提我们需要有一个正常运行的集群服务,这里我采用 kubeadm 搭建的 Kubernetes 集群,具体搭建步骤可以参考我上一篇文章 国内使用 kubeadm 在 Centos 7 搭建 Kubernetes 集群 讲述的比较详细,这里就不做演示了。不过还是要说一下的就是国内翻墙问题,由于这三个服务所需要的 images 在国外,国内用户可以去 Docker Hub 下载指定版本的镜像替代,下载完成后,通过
docker tag ...命令修改成指定名称的镜像即可。
本次演示所依赖的各个镜像列表如下:
Image Name | Version | Des ( * 必需) |
---|---|---|
gcr.io/google_containers/elasticsearch | v2.4.1-1 | * |
gcr.io/google_containers/kibana | v4.6.1-1 | * |
gcr.io/google_containers/fluentd-elasticsearch | 1.22 | * |
可使用下边脚本,分别替换以上镜像。
#!/bin/bash images=( elasticsearch:v2.4.1-1 kibana:v4.6.1-1 fluentd-elasticsearch:1.22) for imageName in ${images[@]} ; do docker pull docker.io/bigwhite/$imageName docker tag docker.io/bigwhite/$imageName gcr.io/google_containers/$imageName docker rmi docker.io/bigwhite/$imageName done
3、启动 Fluentd
Fluentd 是以 DaemonSet 的形式运行在 Kubernetes 集群中,这样就可以保证集群中每个 Node 上都会启动一个 Fluentd,我们在 Master 节点创建 Fluented 服务,最终会在各个 Node 上运行,可以通过 Yaml 文件的方式。
$ cd /home/wanyang3/k8s/ $ git clone https://github.com/kubernetes/kubernetes.git $ git checkout v1.6.2 $ cd cluster/addons/fluentd-elasticsearch $ ls -l *.yaml -rw-r--r--. 1 root root 1246 11月 1 16:55 es-controller.yaml -rw-r--r--. 1 root root 382 11月 1 14:44 es-service.yaml -rw-r--r--. 1 root root 1626 11月 1 14:46 fluentd-es-ds.yaml -rw-r--r--. 1 root root 986 11月 1 14:46 kibana-controller.yaml -rw-r--r--. 1 root root 354 11月 1 14:44 kibana-service.yaml $ kubectl create -f fluentd-es-ds.yaml
命令创建 Fluentd 后,默认会将启动日志输出到 Node 节点的 /var/log/fluented.log 文件里面去。但是,当我们去 Node 节点上执行
tail -f /var/log/fluented.log时,却发现提示并没有该文件,难道没启动成功?
首先查看一下 Pod 没有创建,通过
kubectl get pods -n kube-system命令查看并没有Running 或者 Pendding 中的 fluentd,那就是没有创建成功,这是为啥呢?
接着我们查看下 fluentd-es-ds.yaml 信息
$ kubectl get -f fluentd-es-ds.yaml NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE-SELECTOR AGE fluentd-es-v1.22 0 0 0 0 0 beta.kubernetes.io/fluentd-ds-ready=true 1m
通过输出我们可以看到,确实没有启动起来,不过我们发现
NODE-SELECTOR选项为
beta.kubernetes.io/fluentd-ds-ready=true,这下就明白为什么了,原来 fluentd 只会调度设置了标签 beta.kubernetes.io/fluentd-ds-ready=true 的 Node 节点。
不甘心的我,决定看下我集群中 Node 节点是否有这个标签,
$ kubectl describe nodes node0.localdomain Name: node0.localdomain Role: Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux kubernetes.io/hostname=node0.localdomain ...
好吧,这下死心了,确实没有这个标签,那就给该 Node 补上这个标签,然后重新运行下 fluentd。
# Node 节点打标签 $ kubectl label node node0.localdomain beta.kubernetes.io/fluentd-ds-ready=true # 重新运行 fluentd $ kubectl apply -f fluentd-es-ds.yaml # 查看 Pod 是否启动成功 $ kubectl get pods -n kube-system NAME READY STATUS RESTARTS AGE fluentd-es-v1.22-4g2zl 1/1 Running 1 5m ...
好了,这下启动成功了,这下在去看下 Node 节点 /var/log/fluented.log 文件,这下有日志输出啦。
$ tail -f /var/log/fluented.log 2017-11-01 08:37:44 +0000 [info]: reading config file path="/etc/td-agent/td-agent.conf" 2017-11-01 08:37:44 +0000 [info]: starting fluentd-0.12.31 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-mixin-config-placeholders' version '0.4.0' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-mixin-plaintextformatter' version '0.2.6' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-docker_metadata_filter' version '0.1.3' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-elasticsearch' version '1.5.0' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-kafka' version '0.4.1' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-kubernetes_metadata_filter' version '0.24.0' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-mongo' version '0.7.16' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-rewrite-tag-filter' version '1.5.5' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-s3' version '0.8.0' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-scribe' version '0.10.14' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-td' version '0.10.29' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-td-monitoring' version '0.2.2' 2017-11-01 08:37:44 +0000 [info]: gem 'fluent-plugin-webhdfs' version '0.4.2' 2017-11-01 08:37:44 +0000 [info]: gem 'fluentd' version '0.12.31' 2017-11-01 08:37:44 +0000 [info]: adding match pattern="fluent.**" type="null" ... 2017-11-01 08:37:46 +0000 [warn]: /var/log/containers/fluentd-es-v1.22-4g2zl_kube-system_fluentd-es-5632cf09917eda0637a911be6a7bb2738d490216c8f0b56a0f74b4b8c91e191c.log unreadable. It is excluded and would be examined next time.
最后的一行输出又是什么鬼?获取不到容器 fluentd 在 /var/log/containers/fluentd-es-xxxxxx 下的日志输出。果断去该目录 /var/log/containers/ 下看下确实没有任何容器日志文件,好吧,分析觉得很有可能是 Docker 输出日志的位置跟 Fluentd 监听的日志的位置不一致。
$ cat fluentd-es-ds.yaml ... volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers
原来是去 /var/lib/docker/containers 和 /var/log 目录去找日志。我查看那一下机器Docker 的日志驱动配置
$ docker info ... Logging Driver: journald Cgroup Driver: systemd ...
原来这个节点 安装的 Docker 默认日志驱动为 journald,那么所有的日志都会通过系统的 journal进行统一处理,输出到 /var/log/messages 下边了。怪不得提示 /var/log/containers/ 下没有任何容器日志文件呢。解决办法就是修改 Docker 的日志驱动为 json-file 方式。
$ vim /etc/sysconfig/docker 增加 OPTIONS='--selinux-enabled --log-driver=json-file --signature-verification=false' $ systemctl daemon-reload $ systemctl restart docker
好了,现在去看下 /var/log/containers/fluentd-es-xxxxxx 终于有日志输出了。
2017-11-01 08:49:25 +0000 [info]: reading config file path="/etc/td-agent/td-agent.conf" 2017-11-01 08:49:25 +0000 [info]: starting fluentd-0.12.31 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-mixin-config-placeholders' version '0.4.0' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-mixin-plaintextformatter' version '0.2.6' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-docker_metadata_filter' version '0.1.3' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-elasticsearch' version '1.5.0' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-kafka' version '0.4.1' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-kubernetes_metadata_filter' version '0.24.0' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-mongo' version '0.7.16' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-rewrite-tag-filter' version '1.5.5' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-s3' version '0.8.0' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-scribe' version '0.10.14' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-td' version '0.10.29' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-td-monitoring' version '0.2.2' 2017-11-01 08:49:25 +0000 [info]: gem 'fluent-plugin-webhdfs' version '0.4.2' 2017-11-01 08:49:25 +0000 [info]: gem 'fluentd' version '0.12.31' 2017-11-01 08:49:25 +0000 [info]: adding match pattern="fluent.**" type="null" ... 2017-11-01 08:49:39 +0000 [warn]: suppressed same stacktrace 2017-11-01 08:49:48 +0000 [warn]: temporarily failed to flush the buffer. next_retry=2017-11-01 08:50:03 +0000 error_class="Fluent::ElasticsearchOutput::ConnectionFailure" error="Can not reach Elasticsearch cluster ({:host=>\"elasticsearch-logging\", :port=>9200, :scheme=>\"http\"})!" plugin_id="object:3ff062495470"
这下输出终于正常了,不过最后输出
error="Can not reach Elasticsearch cluster这个错误,可以先不用管,因为 Elasticsearch 服务我们还没启动呢,连接不上是正常的,下边启动完毕之后,就正常了。
4、启动 Elasticsearch
经过一番折腾,作为 Logging-agent 的 Fluentd 启动好了,现在要启动作为 Logging Backend 的 Elasticsearch 了,Elasticsearch 的主要作用是将日志信息进行分割,建立索引,配合下边 Kibana 展示数据使用。它也是通过 Yaml 文件创建。
$ kubectl create -f es-controller.yaml $ kubectl create -f es-service.yaml $ kubectl get pods --all-namespaces -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE kube-system elasticsearch-logging-v1-1rt61 1/1 Running 0 10s 10.96.2.28 node0.localdomain kube-system elasticsearch-logging-v1-gbq8p 1/1 Running 0 10s 10.96.2.29 node0.localdomain kube-system fluentd-es-v1.22-4g2zl 1/1 Running 1 20m 10.96.2.24 node0.localdomain ...
看样子是启动成功了,不放心还是看下日志输出吧!
$ kubectl logs -f pod/elasticsearch-logging-v1-1rt61 -n kube-system [2017-11-01 08:58:04,774][INFO ][node ] [elasticsearch-logging-v1-1rt61] version[2.4.1], pid[13], build[c67dc32/2016-09-27T18:57:55Z] [2017-11-01 08:58:04,788][INFO ][node ] [elasticsearch-logging-v1-1rt61] initializing ... [2017-11-01 08:58:06,218][INFO ][plugins ] [elasticsearch-logging-v1-1rt61] modules [reindex, lang-expression, lang-groovy], plugins [], sites [] [2017-11-01 08:58:06,367][INFO ][env ] [elasticsearch-logging-v1-1rt61] using [1] data paths, mounts [[/data (/dev/mapper/cl-root)]], net usable_space [22.4gb], net total_space [32.7gb], spins? [possibly], types [xfs] [2017-11-01 08:58:06,367][INFO ][env ] [elasticsearch-logging-v1-1rt61] heap size [1015.6mb], compressed ordinary object pointers [true] [2017-11-01 08:58:12,117][INFO ][node ] [elasticsearch-logging-v1-1rt61] initialized [2017-11-01 08:58:12,117][INFO ][node ] [elasticsearch-logging-v1-1rt61] starting ... [2017-11-01 08:58:12,688][INFO ][transport ] [elasticsearch-logging-v1-1rt61] publish_address {10.96.2.28:9300}, bound_addresses {[::]:9300} [2017-11-01 08:58:12,706][INFO ][discovery ] [elasticsearch-logging-v1-1rt61] kubernetes-logging/9bdsRkUYTCKI5DNKGZXmxw [2017-11-01 08:58:15,828][INFO ][cluster.service ] [elasticsearch-logging-v1-1rt61] new_master {elasticsearch-logging-v1-1rt61}{9bdsRkUYTCKI5DNKGZXmxw}{10.96.2.28}{10.96.2.28:9300}{master=true}, added {{elasticsearch-logging-v1-gbq8p}{clJyWOTlRx6qn5nHeFEinw}{10.96.2.29}{10.96.2.29:9300}{master=true},}, reason: zen-disco-join(elected_as_master, [1] joins received) [2017-11-01 08:58:15,948][INFO ][http ] [elasticsearch-logging-v1-1rt61] publish_address {10.96.2.28:9200}, bound_addresses {[::]:9200} [2017-11-01 08:58:15,948][INFO ][node ] [elasticsearch-logging-v1-1rt61] started [2017-11-01 08:58:16,059][INFO ][gateway ] [elasticsearch-logging-v1-1rt61] recovered [0] indices into cluster_state [2017-11-01 08:58:44,750][INFO ][cluster.metadata ] [elasticsearch-logging-v1-1rt61] [logstash-2017.11.01] creating index, cause [auto(bulk api)], templates [], shards [5]/[1], mappings [] [2017-11-01 08:58:46,296][INFO ][cluster.routing.allocation] [elasticsearch-logging-v1-1rt61] Cluster health status changed from [RED] to [YELLOW] (reason: [shards started [[logstash-2017.11.01][0], [logstash-2017.11.01][0]] ...]). [2017-11-01 08:58:46,434][INFO ][cluster.metadata ] [elasticsearch-logging-v1-1rt61] [logstash-2017.11.01] create_mapping [fluentd] [2017-11-01 08:58:46,578][INFO ][cluster.metadata ] [elasticsearch-logging-v1-1rt61] [logstash-2017.11.01] update_mapping [fluentd] [2017-11-01 08:58:46,697][INFO ][cluster.metadata ] [elasticsearch-logging-v1-1rt61] [logstash-2017.11.01] update_mapping [fluentd] [2017-11-01 08:58:47,059][INFO ][cluster.routing.allocation] [elasticsearch-logging-v1-1rt61] Cluster health status changed from [YELLOW] to [GREEN] (reason: [shards started [[logstash-2017.11.01][0]] ...]).
都
[YELLOW] to [GREEN]了,妥妥没问题了。在去 Node 节点看下上边安装完 Fluentd 最后的 error 如何了。
$ tail -f /var/log/fluented.log ... 2017-11-01 08:58:44 +0000 [info]: Connection opened to Elasticsearch cluster => {:host=>"elasticsearch-logging", :port=>9200, :scheme=>"http"} 2017-11-01 08:58:47 +0000 [warn]: retry succeeded. plugin_id="object:3ff062495470" 2017-11-01 09:00:26 +0000 [info]: following tail of /var/log/containers/kibana-logging-3757371098-dkjsg_kube-system_kibana-logging-e60bec3a2f87ba6d85952bf4d73f301b912cf797b97ca545340a429747c4351a.log
显示连接成功,这一次还挺顺利的哈。接下来该启动 Kibana 服务来图形化查看收集的日志信息了。
5、启动 Kibana
Kibana 是一个开源的分析与可视化平台,与 Elasticsearch 一起使用的,可以用 Kibana 搜索、查看、交互存放在 Elasticsearch 索引里的数据,很直观的在浏览器页面图形化展示出来,非常方便,它也是通过 Yaml 文件创建。
$ kubectl create -f kibana-controller.yaml $ kubectl create -f kibana-service.yaml $ kubectl get pods --all-namespaces -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE kube-system elasticsearch-logging-v1-1rt61 1/1 Running 0 2m 10.96.2.28 node0.localdomain kube-system elasticsearch-logging-v1-gbq8p 1/1 Running 0 2m 10.96.2.29 node0.localdomain kube-system fluentd-es-v1.22-4g2zl 1/1 Running 1 22m 10.96.2.24 node0.localdomain kube-system kibana-logging-3757371098-dkjsg 1/1 Running 0 8s 10.96.2.30 node0.localdomain
显示启动成功,查看下日志输出,显示需要花费几分钟优化缓存 Kibana 和状态页。
$ kubectl logs -f pod/kibana-logging-3757371098-dkjsg -n kube-system ELASTICSEARCH_URL=http://elasticsearch-logging:9200 server.basePath: /api/v1/proxy/namespaces/kube-system/services/kibana-logging {"type":"log","@timestamp":"2017-11-01T09:00:40Z","tags":["info","optimize"],"pid":5,"message":"Optimizing and caching bundles for kibana and statusPage. This may take a few minutes"}
稍等几分钟(有的可能需要更长时间,我的 5 分钟左右),再来查看日志,就显示启动成功了。
$ kubectl logs -f pod/kibana-logging-3757371098-dkjsg -n kube-system ELASTICSEARCH_URL=http://elasticsearch-logging:9200 server.basePath: /api/v1/proxy/namespaces/kube-system/services/kibana-logging {"type":"log","@timestamp":"2017-11-01T09:00:40Z","tags":["info","optimize"],"pid":5,"message":"Optimizing and caching bundles for kibana and statusPage. This may take a few minutes"}
{"type":"log","@timestamp":"2017-11-01T09:06:52Z","tags":["info","optimize"],"pid":5,"message":"Optimization of bundles for kibana and statusPage complete in 371.83 seconds"}
{"type":"log","@timestamp":"2017-11-01T09:06:52Z","tags":["status","plugin:kibana@1.0.0","info"],"pid":5,"state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
{"type":"log","@timestamp":"2017-11-01T09:06:53Z","tags":["status","plugin:elasticsearch@1.0.0","info"],"pid":5,"state":"yellow","message":"Status changed from uninitialized to yellow - Waiting for Elasticsearch","prevState":"uninitialized","prevMsg":"uninitialized"}
{"type":"log","@timestamp":"2017-11-01T09:06:53Z","tags":["status","plugin:kbn_vislib_vis_types@1.0.0","info"],"pid":5,"state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
{"type":"log","@timestamp":"2017-11-01T09:06:53Z","tags":["status","plugin:markdown_vis@1.0.0","info"],"pid":5,"state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
{"type":"log","@timestamp":"2017-11-01T09:06:53Z","tags":["status","plugin:metric_vis@1.0.0","info"],"pid":5,"state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
{"type":"log","@timestamp":"2017-11-01T09:06:53Z","tags":["status","plugin:spyModes@1.0.0","info"],"pid":5,"state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
{"type":"log","@timestamp":"2017-11-01T09:06:53Z","tags":["status","plugin:statusPage@1.0.0","info"],"pid":5,"state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
{"type":"log","@timestamp":"2017-11-01T09:06:53Z","tags":["status","plugin:table_vis@1.0.0","info"],"pid":5,"state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
{"type":"log","@timestamp":"2017-11-01T09:06:53Z","tags":["listening","info"],"pid":5,"message":"Server running at http://0.0.0.0:5601"} {"type":"log","@timestamp":"2017-11-01T09:06:59Z","tags":["status","plugin:elasticsearch@1.0.0","info"],"pid":5,"state":"yellow","message":"Status changed from yellow to yellow - No existing Kibana index found","prevState":"yellow","prevMsg":"Waiting for Elasticsearch"}
{"type":"log","@timestamp":"2017-11-01T09:07:08Z","tags":["status","plugin:elasticsearch@1.0.0","info"],"pid":5,"state":"green","message":"Status changed from yellow to green - Kibana index ready","prevState":"yellow","prevMsg":"No existing Kibana index found"}
又看到熟悉的
yellow to green了,妥妥没问题。不过后边同时显示
"prevMsg":"No existing Kibana index found",这个没啥影响,初次启动,Kibana 没有默认给我们创建好索引,我们可以到 Kibana Web 页面去设置索引。但是如何获取 Kibana 服务访问地址呢?可以通过获取 cluster-info 查看
$ kubectl cluster-info Kubernetes master is running at https://10.236.65.76:6443 Elasticsearch is running at https://10.236.65.76:6443/api/v1/proxy/namespaces/kube-system/services/elasticsearch-logging Heapster is running at https://10.236.65.76:6443/api/v1/proxy/namespaces/kube-system/services/heapster Kibana is running at https://10.236.65.76:6443/api/v1/proxy/namespaces/kube-system/services/kibana-logging KubeDNS is running at https://10.236.65.76:6443/api/v1/proxy/namespaces/kube-system/services/kube-dns monitoring-grafana is running at https://10.236.65.76:6443/api/v1/proxy/namespaces/kube-system/services/monitoring-grafana monitoring-influxdb is running at https://10.236.65.76:6443/api/v1/proxy/namespaces/kube-system/services/monitoring-influxdb[/code]
也就是https://<api_server_ip>:<api_server_ secure_port>/api/v1/proxy/namespaces/kube-system/services/kibana-logging这个访问地址,不过当我们满心欢喜的将这个地址在浏览器中打开时,并没有显示出来页面,而是显示:
这个主要是因为访问地址为 Https,但是没有导入 Kubernetes 证书所致。然而 Kubernetes 证书从哪里得来呢?有两种方式,一种是自己生成然后拷贝到各个机器上,配置 Kubernetes 使用,并导入到浏览器中,另一种使用现成的证书,下边说一下如何导入现成的证书到浏览器中。
使用 kubeadm 安装的 Kubernetes 集群,默认会生成一系列证书供 kubelet 使用,默认生成证书到 /etc/kubernetes/pki/ 目录。$ /etc/kubernetes/pki/ 总用量 48 -rw-r--r--. 1 root root 1237 10月 30 10:19 apiserver.crt -rw-------. 1 root root 1675 10月 30 10:19 apiserver.key -rw-r--r--. 1 root root 1099 10月 30 10:19 apiserver-kubelet-client.crt -rw-------. 1 root root 1679 10月 30 10:19 apiserver-kubelet-client.key -rw-r--r--. 1 root root 1025 10月 30 10:19 ca.crt -rw-------. 1 root root 1675 10月 30 10:19 ca.key -rw-r--r--. 1 root root 1025 10月 30 10:19 front-proxy-ca.crt -rw-------. 1 root root 1679 10月 30 10:19 front-proxy-ca.key -rw-r--r--. 1 root root 1050 10月 30 10:19 front-proxy-client.crt -rw-------. 1 root root 1675 10月 30 10:19 front-proxy-client.key -rw-------. 1 root root 1675 10月 30 10:19 sa.key -rw-------. 1 root root 451 10月 30 10:19 sa.pub
这里每个证书和对应的 key 都有不同的用处,我们可以从 kubelet 进程中可以看到这些证书在启动时已经指定加载进去了。$ ps -ef | grep kubelet root 2045 1 1 11月02 ? 00:31:53 /usr/bin/kubelet --kubeconfig=/etc/kubernetes/kubelet.conf --require-kubeconfig=true --pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true --network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin --cluster-dns=10.96.0.10 --cluster-domain=cluster.local --authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt --cgroup-driver=systemd root 5139 5126 1 08:50 ? 00:05:33 kube-controller-manager --use-service-account-credentials=true --kubeconfig=/etc/kubernetes/controller-manager.conf --root-ca-file=/etc/kubernetes/pki/ca.crt --service-account-private-key-file=/etc/kubernetes/pki/sa.key --cluster-signing-key-file=/etc/kubernetes/pki/ca.key --address=127.0.0.1 --insecure-experimental-approve-all-kubelet-csrs-for-group=system:bootstrappers --controllers=*,bootstrapsigner,tokencleaner --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt --leader-elect=true --allocate-node-cidrs=true --cluster-cidr=10.96.0.0/12 root 5704 5692 0 08:52 ? 00:03:24 kube-apiserver --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key --secure-port=6443 --storage-backend=etcd3 --requestheader-allowed-names=front-proxy-client --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --requestheader-group-headers=X-Remote-Group --requestheader-extra-headers-prefix=X-Remote-Extra- --service-cluster-ip-range=10.96.0.0/12 --service-account-key-file=/etc/kubernetes/pki/sa.pub --client-ca-file=/etc/kubernetes/pki/ca.crt --tls-cert-file=/etc/kubernetes/pki/apiserver.crt --allow-privileged=true --requestheader-username-headers=X-Remote-User --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --tls-private-key-file=/etc/kubernetes/pki/apiserver.key --insecure-port=0 --experimental-bootstrap-token-auth=true --authorization-mode=RBAC --advertise-address=10.236.65.76 --etcd-servers=http://127.0.0.1:2379 root 29063 28044 0 14:51 pts/2 00:00:00 grep --color=auto kubelet
这里我们主要看一下 kube-apiserver,毕竟我们大部分操作都是需要请求它来完成,格式化一下:kube-apiserver --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key --secure-port=6443 --storage-backend=etcd3 --requestheader-allowed-names=front-proxy-client --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --requestheader-group-headers=X-Remote-Group --requestheader-extra-headers-prefix=X-Remote-Extra- --service-cluster-ip-range=10.96.0.0/12 --service-account-key-file=/etc/kubernetes/pki/sa.pub --client-ca-file=/etc/kubernetes/pki/ca.crt --tls-cert-file=/etc/kubernetes/pki/apiserver.crt --allow-privileged=true --requestheader-username-headers=X-Remote-User --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt --tls-private-key-file=/etc/kubernetes/pki/apiserver.key --insecure-port=0 --experimental-bootstrap-token-auth=true --authorization-mode=RBAC --advertise-address=10.236.65.76 --etcd-servers=http://127.0.0.1:2379
从上边可以看出默认开启的是 secure-port 的方式,以及一系列的证书。其中客户端证书--client-ca-file=/etc/kubernetes/pki/ca.crt就是我们需要的证书。下边演示下在 Mac 上如何将 ca.crt 证书导入到浏览器中。
5.1 浏览器添加证书
打开 应用程序 —> 实用工具 —> 钥匙串访问,点击 “+” 选择 ca.crt 证书。
不过添加的 Kubernetes 证书,显示此根证书不被信任,可以点击右键 “显示简介”,弹框中点击 “信任”,在使用此证书时这一栏选择 “始终信任” 即可。
此时,重新打开浏览器,或者刷新浏览器,就正常了。
好了,https 证书的问题解决了,这下应该可以了吧。在次打开https://<api_server_ip>:<api_server_ secure_port>/api/v1/proxy/namespaces/kube-system/services/kibana-logging这个访问地址,还是没有显示 Kibana 页面,而是显示:User "system:anonymous" cannot proxy services in the namespace "kube-system".
OMG,这又是为啥。。。原来 Kubernetes 从 v1.6 开始,默认的认证模式变成了 RBAC 方式了,从上边--authorization-mode=RBAC也可以看出,那 RBAC 模式又是个啥?
5.2 RBAC 认证模式介绍
从官网文档 RBAC Support in Kubernetes 中的一张图片可以窥探 RBAC 究竟。
从图中我们可以看出 RBAC 中对各个角色进行绑定授权操作。也就是 Role 为 pod-reader 拥有对 Pod 的 get 和 list 权限,然后通过 RoleBinding 操作将该 Role 类型授权给 User、Group 和 ServiceAccount。也就是说,我们在创建 Pod 时,要通过 RoleBinding 操作将具有特定权限的 Role 授权给该 Pod 创建的 User、Group 或 ServiceAccount。我们可以在最新官网 kubernetes-dashboard 1.7 的 Yaml 文件中得到验证。# kubernetes-dashboard.yaml # ------------------- Dashboard Service Account ------------------- # apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard namespace: kube-system --- # ------------------- Dashboard Role & Role Binding ------------------- # kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: kubernetes-dashboard-minimal namespace: kube-system rules: # Allow Dashboard to create and watch for changes of 'kubernetes-dashboard-key-holder' secret. - apiGroups: [""] resources: ["secrets"] verbs: ["create", "watch"] - apiGroups: [""] resources: ["secrets"] # Allow Dashboard to get, update and delete 'kubernetes-dashboard-key-holder' secret. resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"] verbs: ["get", "update", "delete"] # Allow Dashboard to get metrics from heapster. - apiGroups: [""] resources: ["services"] resourceNames: ["heapster"] verbs: ["proxy"] --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: RoleBinding metadata: name: kubernetes-dashboard-minimal namespace: kube-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: kubernetes-dashboard-minimal subjects: - kind: ServiceAccount name: kubernetes-dashboard namespace: kube-system ---
从 Yaml 描述文件中大体可以看出,首先创建了一个 kubernetes-dashboard 的 ServiceAccount,然后创建一个 kubernetes-dashboard-minimal 的 Dashboard Role,最后通过 RoleBinding 将 Role:ubernetes-dashboard-minimal 授权给 ServiceAccount:kubernetes-dashboard,而且他们至始至终都在同一个命令空间下 namespace: kube-system。这样就可以完成 RBAC 的认证过程。
同时 Kubernetes API Server 还更新了一个–anonymous-auth选项,允许匿名请求访问 secure port,就像我上边访问地址报错一样,属于匿名请求。这样的匿名请求的 username 默认为 “system:anonymous”, 归属的组默认为 “system:unauthenticated”,所以当我们请求上边命名空间为 kube-system 的服务时,是肯定访问不了的。
好吧,原因找到了,还扯了这么多,到底该如何解决这个问题呢?有三种方法解决。
一、修改 Yaml 文件,为 Kibana 创建符合 RBAC 的配置。可以参考上边 kubernetes-dashboard.yaml 方式配置。
二、使用非安全端口访问 kube-apiserver,也即使用 insecure-port 方式访问,这种方式没有任何安全限制。使用该方式需要修改 kubelet apiserver 配置文件 /etc/kubernetes/manifests/kube-apiserver.yaml,指定insecure-bind-address和insecure-port$ vim /etc/kubernetes/manifests/kube-apiserver.yaml ... spec: containers: - command: ... - --insecure-bind-address=0.0.0.0 - --insecure-port=8080 ...
配置完成后,就可以通过http://10.236.65.76:8080/api/v1/proxy/namespaces/kube-system/services/kibana-logging地址访问了,当然这种方式不安全的哈。
三、使用 kubectl proxy 创建代理。这种方式是最简单的,不需要修改 kubelet 配置,只需要启动代理即可。$ kubectl proxy --address='10.236.65.76' --port=8085 --accept-hosts='^*$'
执行完毕,就可以通过http://10.236.65.76:8085/api/v1/proxy/namespaces/kube-system/services/kibana-logging地址访问了。
好了,现在 Kibana 页面也成功打开了,我们需要创建一个索引,解决日志中"prevMsg":"No existing Kibana index found"的问题。 点击导航栏 “Setting” -> “Configure an index pattern”,选中 “Index contains time-based events” 选项,“Index name or pattern” 默认为 logstash-* 即可,“Time-field name” 默认 @timestamp,最后点击 “Create” 即可完成索引创建。
稍等一段时间,就可以看到有日志展示出来啦!如上图所示。不过默认显示的栏目只有 Time 和 _source,这看着很不直观,我们可以点开下边任何一个日志记录,将 Table 展示左侧列,有需要添加到展示栏的项,点击右侧类似打开的书的图标,就可以展示了。这里我选择了关键性栏目,如:kubernetes.container_name、kubernetes.host、kubernetes.namespace_name、log,这下看起来是不是就直观了很多。
好了,服务都启动起来了,最后我们要验证一下是否集群中 Pod 发生变化时,日志能够实时发送过来。这里简单的启动一个 Pod,我们可以从 Dashboard 中创建一个部署,以示区别我们同时为这个部署指定到一个新的 Namespace 下,还以之前的 redis 为例,指定命名空间为 my-kube,看下启动完毕,在 Kibana 上能否看到对应的日志信息吧。
码字太多了。。。这个就不演示如何在 Dashboard 上创建这个 redis 实例了。看下通过日志收集并分析,最终呈现到 Kibana 上的图吧!证明是可以实时获取到的!
好了,Kibana 其他功能的用法,我还没研究完,等研究后在补充吧!
参考资料
Logging Architecture
Logging Using Elasticsearch and Kibana
RBAC Support in Kubernetes
Github Kubernetes
相关文章推荐
- kubernetes上部署Fluentd+Elasticsearch+kibana日志收集系统
- fluentd结合kibana、elasticsearch实时搜索分析hadoop集群日志
- 搭建ELK(ElasticSearch+Logstash+Kibana)日志分析系统(十) elasticsearch集群部署
- fluentd结合kibana、elasticsearch实时搜索分析hadoop集群日志<转>
- fluentd结合kibana、elasticsearch实时搜索分析hadoop集群日志
- fluentd结合kibana、elasticsearch实时搜索分析hadoop集群日志
- fluentd结合kibana、elasticsearch实时搜索分析hadoop集群日志
- Elasticsearch-ES 5.x (Head,Kibana,X-Pack) 集群的部署、配置、测试
- Elasticsearch、Fluentd与Kibana:开源的日志搜索与可视化方案
- Kubernetes Fluentd+Elasticsearch+Kibana统一日志管理平台搭建的填坑指南
- 20-linux下ElasticSearch.6.2.2集群安装与head、Kibana、X-Pack..插件的配置安装
- ELK( ElasticSearch+ Logstash+ Kibana)分布式日志系统部署文档
- CentOS7 安装EFK(elasticsearch、fluent、kibana)进行Docker下日志搜集 - The magic of fingertips - CSDN博客
- elasticsearch集群部署与插件使用
- Elasticsearch5.1集群+kibana部署
- CentOS7 安装EFK(elasticsearch、fluent、kibana)进行Docker下日志搜集
- kibana显示elasticsearch集群中flume到入的日志
- 部署 elk 日志系统 elasticsearch、logstash、 kibana
- ELK(日志分析系统): Elasticsearch + Logstash + Kibana集群环境部署及应用
- Kubernetes Fluentd+Elasticsearch+Kibana统一日志管理平台搭建的填坑指南