嗨各位今天過得好嗎?是不是有將Bug成功解出呢?還是當成技術債以後再來償還啊xD
昨天已經部署好 Elasticsearch 叢集,該叢集包含了三台 Master Node 以及三個 Worker Node ,今天我要接續著部署 EFK 服務中的 K-ibana 與 F-luentd ,比起 Elasticsearch 這種有狀態的叢集 Kibana 與 Fluentd 已部署的角度來說相對的簡單。
Kibana 提供一個資料視覺化的操作平台。使用者能夠透過 Kibana 快速的將 Elasticsearch 中所查詢到的資料生成圖表、表格、地圖以較為圖像式的方式呈現。
Kibana 的部署與安裝相當的簡單,這邊可以參考Kubernetes Github 中 Addons 的 yaml 設定,我也是直接從那邊改過來的,對環境若有其他要求可以依照自身需求進行更改。
apiVersion: apps/v1
kind: Deployment
metadata:
name: kibana
namespace: log
labels:
app: kibana
spec:
replicas: 1
selector:
matchLabels:
app: kibana
template:
metadata:
labels:
app: kibana
spec:
containers:
- name: kibana
image: docker.elastic.co/kibana/kibana-oss:6.4.3
env:
- name: ELASTICSEARCH_HOSTS
value: http://elasticsearch-data.log.svc.cluster.local:9200
- name: SERVER_NAME
value: kibana
ports:
- containerPort: 5601
name: dashboard
protocol: TCP
livenessProbe:
httpGet:
path: /api/status
port: ui
initialDelaySeconds: 5
timeoutSeconds: 10
readinessProbe:
httpGet:
path: /api/status
port: ui
initialDelaySeconds: 5
timeoutSeconds: 10
---
kind: Service
apiVersion: v1
metadata:
labels:
app: kibana
name: kibana
namespace: log
spec:
ports:
- port: 5601
targetPort: 5601
selector:
app: kibana
type: NodePort
部署完成後我們可以透過 kubectl 指令去檢查部署狀態,檢查是否 kibana Pod 與 Service有正確的建立完成。
$kubectl get pod,svc -n log
NAME READY STATUS RESTARTS AGE
pod/kibana-dfd49f7df-rrs8s 1/1 Running 0 29s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kibana NodePort 10.233.57.34 <none> 5601:32643/TCP 6m48s
如果看到 Kibana Pod 已經處於 Running 的狀態代表已經部署成功,我們可以透過剛剛建立的NodePort 存取這個服務,只要在瀏覽器中 url 的位置輸入http://:,即可看到 Kibina 的 Dashboard 畫面。
現在看到 Kibana 的 Dashboard 畫面應該是沒有任何 Elasticsearch 的資料,這是正常的因為我們還沒有建立 Fluentd 來將資料塞入 Elasticsearch 裡面,所以下面我們就來建立 Fluentd ,透過 Fluentd 傳遞一下簡單的資料吧~
Fluentd 是一個 Log 訊息收集的工具。支援各種不同的資料來源如:Application Logs 、 Network Protocols 、 IOT Devices Logs 等等,並有豐富的 Plugins 可以對資料進行過濾、分析、統一格式一系列的操作,最後可以將資料輸出到各式各樣的後端儲存平台上如 AWS S3 、 MySQL 、 Hadoop DFS 等儲存平台。
工作原理大概就如同下面這張圖所表示的,我們看左下角的 Kubernetes Cluster 就好不用管 AWS , Pod 裡面會有輕量級的 fluentbit ( fluentd 的一種但因為少很多套件所以他更輕量),他會將我們的 Log 資料打到一個 fluentd 身上,這個 fluentd 會決定這個 Log 資料要怎麼走,可以送到 Elasticsearch 上也可以存到 Amazon S3 (這邊的選擇可以很多元、此圖只列出部分,有興趣的朋友可以到 fluentd List of Data Outputs 去查查呦!)。
(圖片參考來源:Building an Open Data Platform: Logging with Fluentd and Elasticsearch)
這邊我們可以參考 fluentd official github,這裡面有描述如何安裝一個 Fluentd 到 Kubernetes 上,我這邊做一個簡化版部署的 yaml 檔。(小心服用,我簡化很多東西:"P)
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: fluentd
namespace: kube-system
labels:
k8s-app: fluentd-logging
version: v1
spec:
template:
metadata:
labels:
k8s-app: fluentd-logging
version: v1
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd
image: gcr.io/google-containers/fluentd-elasticsearch@sha256:5a704c386f66bb3c24e3bcf2e94269c426f1473100fcd37b31579ca8b709c558
env:
- name: FLUENTD_ARGS
value: --no-supervisor -q
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: config-volume
mountPath: /etc/fluent/config.d
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: config-volume
configMap:
name: fluentd-es-config-v0.2.0
---
kind: ConfigMap
apiVersion: v1
metadata:
name: fluentd-es-config-v0.2.0
namespace: kube-system
data:
system.conf: |-
<system>
root_dir /tmp/fluentd-buffers/
</system>
containers.input.conf: |-
<source>
@id fluentd-containers.log
@type tail
path /var/log/containers/*.log
pos_file /var/log/es-containers.log.pos
tag raw.kubernetes.*
read_from_head true
<parse>
@type multi_format
<pattern>
format json
time_key time
time_format %Y-%m-%dT%H:%M:%S.%NZ
</pattern>
<pattern>
format /^(?<time>.+) (?<stream>stdout|stderr) [^ ]* (?<log>.*)$/
time_format %Y-%m-%dT%H:%M:%S.%N%:z
</pattern>
</parse>
</source>
# Detect exceptions in the log output and forward them as one log entry.
<match raw.kubernetes.**>
@id raw.kubernetes
@type detect_exceptions
remove_tag_prefix raw
message log
stream stream
multiline_flush_interval 5
max_bytes 500000
max_lines 1000
</match>
# Concatenate multi-line logs
<filter **>
@id filter_concat
@type concat
key message
multiline_end_regexp /\n$/
separator ""
</filter>
# Fixes json fields in Elasticsearch
<filter kubernetes.**>
@id filter_parser
@type parser
key_name log
reserve_data true
remove_key_name_field true
<parse>
@type multi_format
<pattern>
format json
</pattern>
<pattern>
format none
</pattern>
</parse>
</filter>
output.conf: |-
<match **>
@id elasticsearch
@type elasticsearch
@log_level info
type_name _doc
include_tag_key true
host elasticsearch-discovery.log.svc.cluster.local
port 9200
logstash_format true
request_timeout 15s
<buffer>
@type file
path /var/log/fluentd-buffers/kubernetes.system.buffer
flush_mode interval
retry_type exponential_backoff
flush_thread_count 2
flush_interval 5s
retry_forever
retry_max_interval 30
chunk_limit_size 2M
queue_limit_length 8
overflow_action block
</buffer>
</match>
除了 fluentd 的 Deployment 之外,我們還要針對fluentd 的 input rule 、out rule 以及filter 進行設定,這邊採用 configMap 的方式設定這些 rule 。 fluentd Pod 啟動時會載入 configmap 並使用。
這邊簡單的說明一下我將 Host 上的 /var/lib/docker/containers 位置掛載到 fluentd 中的 /var/log/containers 位置上,在configmap 我們有設定 fluentd 的 input rule 將 /var/log/containers/*.log 作為輸入端,經過幾個 以及 filter rule 處理後送出到 output rule , 在 output rule 這邊 host 的位置是 elasticsearch-discovery.log.svc.cluster.local 也就是將資料送到 elasticsearch 上。
可以透過 kubectl 指令檢查當前的 EFK 環境部署狀況,如果全部都跑起來的話就沒問題拉~
$kubectl get pod,svc -n log
NAME READY STATUS RESTARTS AGE
pod/elasticsearch-master-65c699ddfd-fsrc5 1/1 Running 0 26h
pod/elasticsearch-master-65c699ddfd-lhfff 1/1 Running 0 26h
pod/elasticsearch-master-65c699ddfd-qx8j6 1/1 Running 0 26h
pod/elasticsearch-data-0 1/1 Running 0 26h
pod/elasticsearch-data-1 1/1 Running 0 26h
pod/elasticsearch-data-2 1/1 Running 0 26h
pod/kibana-dfd49f7df-rrs8s 1/1 Running 0 2h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kibana NodePort 10.233.57.34 <none> 5601:32643/TCP 2h
service/elasticsearch-discovery ClusterIP 10.233.41.249 <none> 9300/TCP,9200/TCP 26h
接著我們可以去看 Kibana 的 Dashboard 目前應該會有資料傳進來,我們可以直接查詢 Pod/Container 相關的訊息。
Kibina 有收到 elasticsearch 的資料 Dashboard 畫面呈現
接著我們可以設定資料的 index pattern , 這邊就選全部就好也就是用 * 來吃全部, time Filter 用 @timestamp 然後就可以建立我們的 index pattern囉。
目前收到的資料,為這些資料建立 index pattern
time Filter 用 @timestamp
我們的 Kubernetes Cluster 的 Container 資料就被收進 EFK 系統囉,可以從下面這張圖看到...已經收了滿多資料進系統了。
Kibina 顯示 index pattern 的資料畫面
今天我們部署完整個 EFK Log 收集系統其中包含三個開源專案分別是 Elasticsearch 、 Fluentd 和 Kibana ,部署時經歷了一些波折不過也是順利的跑了起來。不知道大家有沒有發現部署 Elasticsearch 的時候覺得非常煩躁,擴展節點的時候去算他的 minimum_master_nodes ,有沒有什麼工具能幫我們簡化這些部署活及與流程呢?明天將為各位揭曉。