開發者在面對 kubernetes 分布式集群下的日志需求時,常常會感到頭疼,既有容器自身特性的原因,也有現有日志采集工具的桎梏,主要包括:
- 容器本身特性:
- 采集目標多:容器本身的特性導致采集目標多,需要采集容器內日志、容器 stdout。對於容器內部的文件日志采集,現在並沒有一個很好的工具能夠去動態發現采集。針對每種數據源都有對應的采集軟件,但缺乏一站式的工具。
- 彈性伸縮難:kubernetes 是分布式的集群,服務、環境的彈性伸縮對於日志采集帶來了很大的困難,無法像傳統虛擬機環境下那樣,事先配置好日志的采集路徑等信息,采集的動態性以及數據完整性是非常大的挑戰。
- 現有日志工具的一些缺陷:
- 缺乏動態配置的能力。目前的采集工具都需要事先手動配置好日志采集方式和路徑等信息,因為它無法能夠自動感知到容器的生命周期變化或者動態漂移,所以它無法動態地去配置。
- 日志采集重復或丟失的問題。因為現在的一些采集工具基本上是通過 tail 的方式來進行日志采集的,那么這里就可能存在兩個方面的問題:一個是可能導致日志丟失,比如采集工具在重啟的過程中,而應用依然在寫日志,那么就有可能導致這個窗口期的日志丟失;而對於這種情況一般保守的做法就是,默認往前多采集 1M 日志或 2M 的日志,那么這就又會可能引起日志采集重復的問題。
- 未明確標記日志源。因為一個應用可能有很多個容器,輸出的應用日志也是一樣的,那么當我們將所有應用日志收集到統一日志存儲后端時,在搜索日志的時候,我們就無法明確這條日志具體是哪一個節點上的哪一個應用容器產生的。
本文檔將介紹一種 Docker 日志收集工具 log-pilot,結合 Elasticsearch 和 kibana 等工具,形成一套適用於 kubernetes 環境下的一站式日志解決方案。
log-pilot 介紹
log-Pilot 是一個智能容器日志采集工具,它不僅能夠高效便捷地將容器日志采集輸出到多種存儲日志后端,同時還能夠動態地發現和采集容器內部的日志文件。
針對前面提出的日志采集難題,log-pilot 通過聲明式配置實現強大的容器事件管理,可同時獲取容器標准輸出和內部文件日志,解決了動態伸縮問題,此外,log-pilot 具有自動發現機制,CheckPoint 及句柄保持的機制,自動日志數據打標,有效應對動態配置、日志重復和丟失以及日志源標記等問題。
目前 log-pilot 在 Github 完全開源,項目地址是 https://github.com/AliyunContainerService/log-pilot 。您可以深入了解更多實現原理。
針對容器日志的聲明式配置
Log-Pilot 支持容器事件管理,它能夠動態地監聽容器的事件變化,然后依據容器的標簽來進行解析,生成日志采集配置文件,然后交由采集插件來進行日志采集。
在 kubernetes 下,Log-Pilot 可以依據環境變量 aliyun_logs_$name = $path
動態地生成日志采集配置文件,其中包含兩個變量:
- $name 是我們自定義的一個字符串,它在不同的場景下指代不同的含義,在本場景中,將日志采集到 ElasticSearch 的時候,這個 $name 表示的是 Index。
- 另一個是 $path,支持兩種輸入形式,stdout 和容器內部日志文件的路徑,對應日志標准輸出和容器內的日志文件。
- 第一種約定關鍵字 stdout 表示的是采集容器的標准輸出日志,如本例中我們要采集 tomcat 容器日志,那么我們通過配置標簽
aliyun.logs.catalina=stdout
來采集 tomcat 標准輸出日志。 - 第二種是容器內部日志文件的路徑,也支持通配符的方式,通過配置環境變量
aliyun_logs_access=/usr/local/tomcat/logs/*.log
來采集 tomcat 容器內部的日志。當然如果你不想使用 aliyun 這個關鍵字,Log-Pilot 也提供了環境變量 PILOT_LOG_PREFIX 可以指定自己的聲明式日志配置前綴,比如PILOT_LOG_PREFIX: "aliyun,custom"
。
- 第一種約定關鍵字 stdout 表示的是采集容器的標准輸出日志,如本例中我們要采集 tomcat 容器日志,那么我們通過配置標簽
此外,Log-Pilot 還支持多種日志解析格式,通過 aliyun_logs_$name_format=<format>
標簽就可以告訴 Log-Pilot 在采集日志的時候,同時以什么樣的格式來解析日志記錄,支持的格式包括:none、json、csv、nginx、apache2 和 regxp。
Log-Pilot 同時支持自定義 tag,我們可以在環境變量里配置 aliyun_logs_$name_tags="K1=V1,K2=V2"
,那么在采集日志的時候也會將 K1=V1 和 K2=V2 采集到容器的日志輸出中。自定義 tag 可幫助您給日志產生的環境打上 tag,方便進行日志統計、日志路由和日志過濾。
日志采集模式
本文檔采用 node 方式進行部署,通過在每台機器上部署一個 log-pilot 實例,收集機器上所有 Docker 應用日志。
前提條件
您已經開通容器服務,並創建了一個 kubernetes 集群。本示例中,創建的 Kubernetes 集群位於華東 1 地域。
步驟1 部署 elasticsearch
- 連接到您的 Kubernetes 集群。具體操作參見通過SSH訪問Kubernetes集群 或 通過 kubectl 連接 Kubernetes 集群。
- 首先部署 elasticsearch 相關服務,該編排模板包含一個 elasticsearch-api 的服務、elasticsearch-discovery 的服務和 elasticsearch 的狀態集,這些對象都會部署在 kube-system 命名空間下。
kubectl apply -f https://acs-logging.oss-cn-hangzhou.aliyuncs.com/elasticsearch.yml
- 部署成功后,kube-system 命名空間下會出現相關對象,執行以下命令查看運行情況。
$ kubectl get svc,StatefulSet -n=kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE svc/elasticsearch-api ClusterIP 172.21.5.134 <none> 9200/TCP 22h svc/elasticsearch-discovery ClusterIP 172.21.13.91 <none> 9300/TCP 22h ... NAME DESIRED CURRENT AGE statefulsets/elasticsearch 3 3 22h
步驟2 部署 log-pilot 和 kibana 服務
- 部署 log-pilot 日志采集工具,如下所示:
kubectl apply -f https://acs-logging.oss-cn-hangzhou.aliyuncs.com/log-pilot.yml
- 部署 kibana 服務,該編排示例包含一個 service 和一個 deployment。
kubectl apply -f https://acs-logging.oss-cn-hangzhou.aliyuncs.com/kibana.yml
步驟3 部署測試應用 tomcat
在 elasticsearch + log-pilot + Kibana 這套日志工具部署完畢后,現在開始部署一個日志測試應用 tomcat,來測試日志是否能正常采集、索引和顯示。
編排模板如下。
apiVersion: v1 kind: Pod metadata: name: tomcat namespace: default labels: name: tomcat spec: containers: - image: tomcat name: tomcat-test volumeMounts: - mountPath: /usr/local/tomcat/logs name: accesslogs env: - name: aliyun_logs_catalina value: "stdout" ##采集標准輸出日志 - name: aliyun_logs_access value: "/usr/local/tomcat/logs/catalina.*.log" ## 采集容器內日志文件 volumes: - name: accesslogs emptyDir: {}
tomcat 鏡像屬於少數同時使用了 stdout 和文件日志的 Docker 鏡像,適合本文檔的演示。在上面的編排中,通過在 pod 中定義環境變量的方式,動態地生成日志采集配置文件,環境變量的具體說明如下:
aliyun_logs_catalina=stdout
表示要收集容器的 stdout 日志。aliyun_logs_access=/usr/local/tomcat/logs/catalina.*.log
表示要收集容器內 /usr/local/tomcat/logs/ 目錄下所有名字匹配 catalina.*.log 的文件日志。
在本方案的 elasticsearch 場景下,環境變量中的 $name
表示 Index,本例中 $name
即是 catalina 和 access 。
步驟 4 將 kibana 服務暴露到公網
上面部署的 kibana 服務的類型采用 NodePort,默認情況下,不能從公網進行訪問,因此本文檔配置一個 ingress 實現公網訪問 kibana,來測試日志數據是否正常索引和顯示。
- 通過配置 ingress 來實現公網下訪問 kibana 。本示例選擇簡單的路由服務來實現,您可參考Ingress 支持 獲取更多方法。該 ingress 的編排模板如下所示。
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: kibana-ingress namespace: kube-system #要與 kibana 服務處於同一個 namespace spec: rules: - http: paths: - path: / backend: serviceName: kibana #輸入 kibana 服務的名稱 servicePort: 80 #輸入 kibana 服務暴露的端口
- 創建成功后,執行以下命令,獲取該 ingress 的訪問地址。
$ kubectl get ingress -n=kube-system NAME HOSTS ADDRESS PORTS AGE shared-dns * 120.55.150.30 80 5m
- 在瀏覽器中訪問該地址,如下所示。
- 單擊左側導航欄中的management ,然后單擊
您也可以執行以下命令,進入 elasticsearch 對應的 pod,在 index 下列出 elasticsearch 的所有索引。
$ kubectl get pods -n=kube-system #找到 elasticsearch 對應的 pod ... $ kubectl exec -it elasticsearch-1 bash #進入 elasticsearch 的一個 pod ... $ curl 'localhost:9200/_cat/indices?v' ## 列出所有索引 health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open .kibana x06jj19PS4Cim6Ajo51PWg 1 1 4 0 53.6kb 26.8kb green open access-2018.03.19 txd3tG-NR6-guqmMEKKzEw 5 1 143 0 823.5kb 411.7kb green open catalina-2018.03.19 ZgtWd16FQ7qqJNNWXxFPcQ 5 1 143 0 915.5kb 457.5kb
- 索引創建完畢后,單擊左側導航欄中的Discover,然后選擇前面創建的 Index,選擇合適的時間段,在搜索欄輸入相關字段,就可以查詢相關的日志。
至此,在阿里雲 Kubernetes 集群上,我們已經成功測試基於 log-pilot、elasticsearch 和 kibana 的日志解決方案,通過這個方案,我們能有效應對分布式 kubernetes 集群日志需求,可以幫助提升運維和運營效率,保障系統持續穩定運行。
實例配置:
阿里雲k8s 應用日志服務添加配置
連接 ealsticsearch pod 查看 索引index [root@k8s-hd-master03 ~]# kubectl exec -it elasticsearch-0 /bin/bash -n kube-system elasticsearch@elasticsearch-0:/usr/share/elasticsearch$ curl 'localhost:9200/_cat/indices?v' health status index uuid pri rep docs.count docs.deleted store.size pri.store.size green open .kibana CjKmfxiNSnm00rEw0Oqqqg 1 1 3 0 41.5kb 20.7kb green open imagetrain-dev-2019.01.16 h_U5hNK7Q5uqUzxXElRS3w 5 1 744 0 1.3mb 689.2kb 7118 0 10.7mb 5.3mb green open audit-c48ec13c7dbc94c6fba92748baaf296fc-2019.01.15 _pK_EcUbQYW_zAzeCx6vHA 5 1 1317843 0 2.4gb 1.2gb
在kibana 配置查看 相應的日志信息
對 kibana 域名訪問添加密碼,用戶認證
kibana 服務配置類型改為 負載均衡 內網ip 的方式
配置nginx 代理到負載均衡的訪問地址 ,nginx配置一層用戶認證,需要密碼輸入, 域名解析再解析到 nginx的代理服務器
具體配置如下: server { listen 8000; server_name localhost; location / { auth_basic "kibana auth"; auth_basic_user_file /etc/nginx/conf.d/.htpasswd; proxy_pass http://192.168.0.139; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
yum install -y httpd (安裝 htpasswd命令) 類似apache創建密碼文件 htpasswd -c /etc/nginx/conf.d/.htpasswd weifeng New password:123456 nginx -t nginx -s reload
訪問效果如下:
打開頁面時需要用戶驗證