當前位置:
首頁 > 最新 > 在Kubernetes 上以Hard模式搭建EFK日誌分析平台

在Kubernetes 上以Hard模式搭建EFK日誌分析平台

在一年多之前,我曾寫過一篇文章《使用Fluentd和ElasticSearch Stack實現Kubernetes的集群Logging》,文中講解了如何在Kubernetes上利用EFK(elastic, fluentd, kibana)搭建一套可用的集中日誌分析平台。當時的k8s使用的是1.3.7版本,創建EFK使用的是kubernetes項目中cluster/addons/fluentd-elasticsearch下面的全套yaml文件,yaml中Elastic Search的volume用的還是emptyDir,並未真正持久化。

經過一年多的發展,Kubernetes發生了「翻天覆地」的變化,EFK技術棧也有了很大的進展。雖然那篇文章中的方案、步驟以及問題的解決思路仍有參考價值,但畢竟「年代」不同了,有些東西需要「與時俱進」。恰好近期在協助同事搭建一個移動互聯網醫院的演示環境時,我又一次搭建了一套「較新」版本的EFK,這裡記錄一下搭建過程、遇到的坑以及問題的解決過程,算是對之前「陳舊知識」的一個更新吧。

一. 環境和部署方案

這次部署我使用了較新的Kubernetes stable版本:1.10.3,這是一個單master node和三個worker node組成的演示環境,集群由kubeadm創建並引導啟動。經過這些年的發展和演進,kubeadm引導啟動的集群已經十分穩定了,並且搭建過程也是十分順利(集群使用的是weave network插件)。

在EFK部署方案上,我沒有再選擇直接使用kubernetes項目中cluster/addons/fluentd-elasticsearch下面的全套yaml文件,而是打算逐個組件單獨安裝的hard模式。

下面是一個部署示意圖:

雖然Kubernetes在持久化存儲方面有諸多機制和插件可用,但總體來說,目前的k8s在storage這塊依舊是短板,用起來體驗較差,希望Container Storage Interface, CSI的引入和未來發展能降低開發人員的心智負擔。因此,這次我將Elastic Search放在了k8s集群外單獨單點部署,並直接使用local file system進行數據存取;fluentd沒有變化,依舊是以DaemonSet控制的Pod的形式運行在每個k8s node上; kibana部署在集群內部,並通過ingress將服務暴露到集群外面。

二. 部署Elastic Search

按照部署方案,我們將Elastic Search部署在k8s集群外面,但我們依舊使用容器化部署方式。Elastic Search的官方鏡像倉庫已經由docker hub遷移到elasticsearch自己維護的倉庫了。

我們下載當前ElasticSearch的最新版6.2.4:

在本地創建elasticsearch的數據存儲目錄:~/es_data,修改該目錄的owner和group均為1000:

注意:務必對es_data按上述命令執行修改,否則在啟動elasticsearch容器可能會出現如下錯誤:

啟動elasticsearch容器:

如果看到下面日誌,說明elasticsearch容器啟動成功了!

檢查es健康狀態:

es工作一切健康!

三. 部署Fluentd

相比較而言,fluentd的部署相對簡單,因為fluentd官網文檔有明確的安裝說明。由於k8s默認授權機制採用了RBAC,因此我們使用fluentd-daemonset-elasticsearch.yaml來創建fluentd daemonset。

不過在創建前,我們需要打開fluentd-daemonset-elasticsearch.yaml修改一下它連接的elasticsearch的地址信息:

接下來創建fluentd:

查看某一個fluentd pod的啟動日誌如下:

沒有報錯!似乎fluentd啟動ok了。

再來通過elasticsearch日誌驗證一下:

fluentd已經成功連接上es了!

四. 部署Kibana

我們將kibana部署到Kubernetes集群內,我們使用kubernetes項目中的cluster/addons/fluentd-elasticsearch下的kibana yaml文件來創建kibana部署和服務:

創建前,我們需要修改一下kibana-deployment.yaml:

創建kibana:

查看啟動的kibana pod,看到如下錯誤日誌:

似乎與xpack有關。我們刪除kibana-deployment.yaml中的兩個環境變數:XPACK_MONITORING_ENABLED和XPACK_SECURITY_ENABLED,再重新apply。查看kibana pod日誌:

可以看到kibana啟動成功!

使用kubectl proxy啟動代理,在瀏覽器中建立sock5 proxy,然後在瀏覽器訪問:http://localhost:8001/api/v1/namespaces/kube-system/services/kibana-logging/proxy, 你應該可以看到下面的kibana首頁:

創建index pattern後,等待一會,查看邊欄中的」Discover」,如果你看到類似下面截圖中的日誌內容輸出,說明kibana可以正常從elasticsearch獲取數據了:

五. 為kibana添加ingress

使用kubectl proxy查看kibana雖然簡單,但略顯麻煩,將kibana服務暴露到集群外更為方便。下面我們就給kibana添加帶basic auth的ingress。

1. 部署ingress controller及默認後端(如果cluster已經部署過,則忽略此步驟)

我們選擇k8s官方的ingress-nginx作為ingress controller,並部署默認後端default-backend,我們把ingress-nginx controller和default-backend統統部署在kube-system命令空間下。

下載https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml

mandatory.yaml中的namespace的值都改為kube-system

此時nginx-ingress controller已經安裝完畢,nginx-ingress controller本質上就是一個nginx,目前它還沒有暴露服務埠,我們通過nodeport方式暴露nginx-ingress service到集群外面:

下載https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml

修改service-nodeport.yaml:

我們驗證一下nginx-ingress controller工作是否正常:

在任意一個集群node上:

2. 為kibana添加ingress

ingress是一種抽象。對於nginx ingress controller來說,創建一個ingress相當於在nginx.conf中添加一個server入口,並nginx -s reload生效。

我們創建kibana的ingress yaml:

由於ingress中的host只能是域名,這裡用 kibana.tonybai.com,然後在/etc/hosts中增加該域名的ip地址映射。

創建kibana-logging-ingress:

我們再次用curl試一下:

這顯然不是我們預想的結果。我們查看一下kibana pod對應的日誌,並對比了一下使用kubectl proxy訪問kibana的日誌:

通過ingress訪問的錯誤日誌:

{"type":"response","@timestamp":"2018-06-11T10:20:55Z","tags":[],"pid":1,"method":"get","statusCode":404,"req":{"url":"/api/v1/namespaces/kube-system/services/kibana-logging/proxy/app/kibana","method":"get","headers":{"host":"kibana.tonybai.com:30080","connection":"close","x-request-id":"b066d69c31ce3c9e89efa6264966561c","x-real-ip":"192.168.16.1","x-forwarded-for":"192.168.16.1","x-forwarded-host":"kibana.tonybai.com:30080","x-forwarded-port":"80","x-forwarded-proto":"http","x-original-uri":"/api/v1/namespaces/kube-system/services/kibana-logging/proxy/app/kibana","x-scheme":"http","cache-control":"max-age=0","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8","accept-language":"zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7"},"remoteAddress":"192.168.20.5","userAgent":"192.168.20.5"},"res":{"statusCode":404,"responseTime":4,"contentLength":9},"message":"GET /api/v1/namespaces/kube-system/services/kibana-logging/proxy/app/kibana 404 4ms - 9.0B"}

通過kubectl proxy訪問的正確日誌:

{"type":"response","@timestamp":"2018-06-11T10:20:43Z","tags":[],"pid":1,"method":"get","statusCode":304,"req":{"url":"/ui/fonts/open_sans/open_sans_v13_latin_regular.woff2","method":"get","headers":{"host":"localhost:8001","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36","accept":"*/*","accept-encoding":"gzip, deflate, br","accept-language":"zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7","if-modified-since":"Thu, 12 Apr 2018 20:57:06 GMT","if-none-match":""afc44700053c9a28f9ab26f6aec4862ac1d0795d"","origin":"http://localhost:8001","referer":"http://localhost:8001/api/v1/namespaces/kube-system/services/kibana-logging/proxy/app/kibana","x-forwarded-for":"127.0.0.1, 172.16.66.101","x-forwarded-uri":"/api/v1/namespaces/kube-system/services/kibana-logging/proxy/ui/fonts/open_sans/open_sans_v13_latin_regular.woff2"},"remoteAddress":"192.168.16.1","userAgent":"192.168.16.1","referer":"http://localhost:8001/api/v1/namespaces/kube-system/services/kibana-logging/proxy/app/kibana"},"res":{"statusCode":304,"responseTime":3,"contentLength":9},"message":"GET /ui/fonts/open_sans/open_sans_v13_latin_regular.woff2 304 3ms - 9.0B"}

我們看到通過ingress訪問,似乎將/api/v1/namespaces/kube-system/services/kibana-logging/proxy/app/kibana這個url path也傳遞給後面的kibana了,而kibana卻無法處理。

我們回頭看一下kibana-deployment.yaml,那裡面有一個env var:

問題似乎就出在這裡。我們去掉這個env var,並重新apply kibana-deployment.yaml。然後再用瀏覽器訪問:http://kibana.tonybai.com:30080/app/kibana,kibana的頁面就會出現在眼前了。

但是這樣更新後,通過kubectl proxy方式似乎就無法正常訪問kibana了,這裡也只能二選一了,我們選擇ingress訪問。

3. 添加basic auth for kibana-logging ingress

雖然kibana ingress生效了,但目前kibana ingress目前在「裸奔」,我們還是要適當加上一些auth的,我們選擇basic auth,從原理上講這是加到nginx上的basic auth,kibana自身並沒有做basic auth:

我們藉助htpasswd工具生成用戶名和密碼,並基於此創建secret對象:

在kibana-logging-ingress.yaml中增加有關auth的annotations:

apply kibana-logging-ingress.yaml後,我們再次訪問:kibana.tonybai.com:30080

至此,一個演示環境下的EFK日誌平台就搭建完畢了。相信有了這種hard way的安裝搭建經驗,我們可以靈活應對針對其中某個組件的變種部署了(比如將elasticsearch放到k8s中部署)。

51簡訊平台:企業級簡訊平台定製開發專家 https://51smspush.com/

smspush : 可部署在企業內部的定製化簡訊平台,三網覆蓋,不懼大並發接入,可定製擴展; 簡訊內容你來定,不再受約束, 介面豐富,支持長簡訊,簽名可選。

著名雲主機服務廠商DigitalOcean發布最新的主機計劃,入門級Droplet配置升級為:1 core CPU、1G內存、25G高速SSD,價格5$/月。有使用DigitalOcean需求的朋友,可以打開這個鏈接地址:https://m.do.co/c/bff6eed92687 開啟你的DO主機之路。

我的聯繫方式:

微博:https://weibo.com/bigwhite20xx

微信公眾號:iamtonybai

博客:tonybai.com

github: https://github.com/bigwhite

商務合作方式:撰稿、出書、培訓、在線課程、合夥創業、諮詢、廣告合作。

? 2018, bigwhite. 版權所有.

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 TonyBai 的精彩文章:

TAG:TonyBai |