k8s搭建EFK日志管理系統

k8s搭建EFK日志管理系統

efk就是目前比較受歡迎的日志管理系統。kubernetes可以實現efk的快速部署和使用,通過statefulset控制器部署elasticsearch組件,用來存儲日志數據,

還可通過volumenclaimtemplate動態生成pv實現es數據的持久化。通過deployment部署kibana組件,實現日志的可視化管理。

通過daemonset控制器部署fluentd組件,來收集各節點和k8s集群的日志。

https://www.nnv5.cn/index.php/archives/76/ 較新

EFK組件介紹

在K8s集群上運行多個服務和應用程序時,日志收集系統可以幫助你快速分類和分析由Pod生成的大量日志數據。K8s中比較流行的日志收集解決方案是Elasticsearch、Fluentd和Kibana(EFK)技術棧,也是官方推薦的一種方案。

Elasticsearch是一個實時的,分布式的,可擴展的搜索引擎,它允許進行全文本和結構化搜索以及對日志進行分析。它通常用于索引和搜索大量日志數據,也可以用于搜索許多不同種類的文檔。

Elasticsearch通常與Kibana一起部署,kibana是Elasticsearch 的功能強大的數據可視化的dashboard(儀表板)。Kibana允許你通過Web界面瀏覽Elasticsearch日志數據,也可自定義查詢條件快速檢索出elasticccsearch中的日志數據。

Fluentd是一個流行的開源數據收集器,我們將在Kubernetes 集群節點上安裝 Fluentd,通過獲取容器日志文件、過濾和轉換日志數據,然后將數據傳遞到 Elasticsearch 集群,在該集群中對其進行索引和存儲。

我們先來配置啟動一個可擴展的 Elasticsearch 集群,然后在Kubernetes集群中創建一個Kibana應用,最后通過DaemonSet來運行Fluentd,以便它在每個Kubernetes工作節點上都可以運行一個 Pod。

資料下載

1.****下文需要的yaml文件所在的github地址如下:

https://github.com/luckylucky421/efk

下面實驗用到yaml文件大家需要從上面的github上clone和下載到本地,解壓,然后把解壓后的yaml文件傳到k8s集群的master節點上,

如果直接復制粘貼格式可能會有問題。

2.****下文里提到的efk組件需要的鏡像獲取方式在百度網盤,鏈接如下:

鏈接:https://pan.baidu.com/s/1lsP2_NrXwOzGMIsVCUHtPw

提取碼:kpg2

3.實驗之前需要把鏡像上傳到k8s集群的各個節點,通過docker load -i 解壓,這樣可以保證下面的yaml文件可以正常執行,否則會存在鏡像拉取失敗問題:

[
復制代碼

](javascript:void(0); "復制代碼")

<pre style="margin: 0px; padding: 0px; overflow: auto; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">docker load -i busybox.tar.gz
docker load -i elasticsearch_7_2_0.tar.gz
docker load -i fluentd.tar.gz
docker load -i kibana_7_2_0.tar.gz
docker load -i nfs-client-provisioner.tar.gz
docker load -i nginx.tar.gz</pre>

[
復制代碼

](javascript:void(0); "復制代碼")

正文-安裝efk組件

下面的步驟在k8s集群的master1節點操作

#****創建名稱空間

在安裝Elasticsearch集群之前,我們先創建一個名稱空間,在這個名稱空間下安裝日志收工具elasticsearch、fluentd、kibana。我們創建一個kube-logging名稱空間,將EFK組件安裝到該名稱空間中。

1.創建kube-logging名稱空間

cat kube-logging.yaml

|

kind: Namespace

apiVersion: v1

metadata:

name: kube-logging

|

kubectl apply -f kube-logging.yaml

2.查看kube-logging名稱空間是否創建成功

kubectl get namespaces | grep kube-logging

顯示如下,說明創建成功

kube-logging Active 1m

#安裝elasticsearch組件

通過上面步驟已經創建了一個名稱空間kube-logging,在這個名稱空間下去安裝日志收集組件efk,首先,我們將部署一個3節點的Elasticsearch集群。我們使用3個Elasticsearch Pods可以避免高可用中的多節點群集中發生的“裂腦”的問題。Elasticsearch腦裂可參考https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html#split-brain

1.創建一個headless service(無頭服務)

創建一個headless service的Kubernetes服務,服務名稱是elasticsearch,這個服務將為3個Pod定義一個DNS域。headless service不具備負載均衡也沒有IP。要了解有關headless service的更多信息,可參考https://kubernetes.io/docs/concepts/services-networking/service/#headless-services

cat elasticsearch_svc.yaml

kind: Service

apiVersion: v1

metadata:

name: elasticsearch

namespace``: kube-logging

labels:

app: elasticsearch

spec:

selector:

app: elasticsearch

clusterIP: None

ports:

- port: 9200

name: rest

- port: 9300

name: inter-node

|

在kube-logging名稱空間定義了一個名為 elasticsearch 的 Service服務,帶有app=elasticsearch標簽,當我們將 ElasticsearchStatefulSet 與此服務關聯時,服務將返回帶有標簽app=elasticsearch的 Elasticsearch Pods的DNS A記錄,然后設置clusterIP=None,將該服務設置成無頭服務。最后,我們分別定義端口9200、9300,分別用于與 REST API 交互,以及用于節點間通信。使用kubectl直接創建上面的服務資源對象:

kubectl apply -f elasticsearch_svc.yaml

查看elasticsearch的service是否創建成功

kubectl get services --namespace=kube-logging

看到如下,說明在kube-logging名稱空間下創建了一個名字是elasticsearch的headless service:

NAME            TYPE        CLUSTER-IP   EXTERNAL-IP  PORT(S)             AGE

現在我們已經為 Pod 設置了無頭服務和一個穩定的域名.elasticsearch.kube-logging.svc.cluster.local,接下來我們通過 StatefulSet來創建具體的 Elasticsearch的Pod 應用。

2.通過statefulset創建elasticsearch集群

Kubernetes statefulset可以為Pods分配一個穩定的標識,讓pod具有穩定的、持久的存儲。Elasticsearch需要穩定的存儲才能通過POD重新調度和重新啟動來持久化數據。更多關于kubernetes StatefulSet可參考

https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/

1)下面將定義一個資源清單文件elasticsearch_statefulset.yaml,首先粘貼以下內容:

|

apiVersion: apps/v1

kind: StatefulSet

metadata:

name: es-cluster

namespace``: kube-logging

spec:

serviceName: elasticsearch

replicas: 3

selector:

matchLabels:

app: elasticsearch

template``:

metadata:

labels:

app: elasticsearch

|

上面內容的解釋:在kube-logging的名稱空間中定義了一個es-cluster的StatefulSet。然后,我們使用serviceName 字段與我們之前創建的ElasticSearch服務相關聯。這樣可以確保可以使用以下DNS地址訪問StatefulSet中的每個Pod:,es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local,其中[0,1,2]與Pod分配的序號數相對應。我們指定3個replicas(3個Pod副本),將matchLabels selector 設置為app: elasticseach,然后在該.spec.template.metadata中指定pod需要的鏡像。該.spec.selector.matchLabels和.spec.template.metadata.labels字段必須匹配。

2)statefulset中定義pod模板,內容如下:

. . .

spec:

containers:

- name: elasticsearch

image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0

resources:

limits:

cpu: 1000m

requests:

cpu: 100m

ports:

- containerPort: 9200

name: rest

protocol: TCP

- containerPort: 9300

name: inter-node

protocol: TCP

volumeMounts:

- name: data

mountPath: /usr/share/elasticsearch/data

env:

- name: cluster.name

value: k8s-logs

- name: node.name

valueFrom:

fieldRef:

fieldPath: metadata.name

- name: discovery.seed_hosts

value:``"es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"

- name: cluster.initial_master_nodes

value:``"es-cluster-0,es-cluster-1,es-cluster-2"

- name: ES_JAVA_OPTS

value:``"-Xms512m -Xmx512m"

|

上面內容解釋:在statefulset中定義了pod,容器的名字是elasticsearch,鏡像是docker.elastic.co/elasticsearch/elasticsearch:7.2.0。使用resources字段來指定容器需要保證至少有0.1個vCPU,并且容器最多可以使用1個vCPU(這在執行初始的大量提取或處理負載高峰時限制了Pod的資源使用)。了解有關資源請求和限制,可參考https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/。暴漏了9200和9300兩個端口,名稱要和上面定義的 Service 保持一致,通過volumeMount聲明了數據持久化目錄,定義了一個data數據卷,通過volumeMount把它掛載到容器里的/usr/share/elasticsearch/data目錄。我們將在以后的YAML塊中為此StatefulSet定義VolumeClaims。

最后,我們在容器中設置一些環境變量:

cluster.name

Elasticsearch 集群的名稱,我們這里是 k8s-logs。

|

node.name

節點的名稱,通過metadata.name來獲取。這將解析為 es-cluster-[0,1,2],取決于節點的指定順序。

****discovery.zen.ping.unicast.hosts****

|

此字段用于設置在Elasticsearch集群中節點相互連接的發現方法。

我們使用 unicastdiscovery方式,它為我們的集群指定了一個靜態主機列表。

由于我們之前配置的無頭服務,我們的 Pod 具有唯一的DNS域es-cluster-[0,1,2].elasticsearch.logging.svc.cluster.local,

因此我們相應地設置此變量。由于都在同一個``namespace 下面,所以我們可以將其縮短為es-cluster-[0,1,2].elasticsearch。

要了解有關 Elasticsearch 發現的更多信息,請參閱 Elasticsearch 官方文檔:https:``//www.elastic.co/guide/en/elasticsearch/reference/current/modules-discovery.html。

|

discovery.zen.minimum_master_nodes

我們將其設置為(N/2) + 1,N是我們的群集中符合主節點的節點的數量。

我們有3個Elasticsearch 節點,因此我們將此值設置為2(向下舍入到最接近的整數)。

要了解有關此參數的更多信息,請參閱官方 Elasticsearch 文檔:https:``//www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html#split-brain。

|

ES_JAVA_OPTS

這里我們設置為-Xms512m -Xmx512m,告訴JVM使用512MB的最小和最大堆。

你應該根據群集的資源可用性和需求調整這些參數。

要了解更多信息,請參閱設置堆大小的相關文檔:https:``//www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html。

|

3****)initcontainer內容

|

. . .

initContainers:

- name: fix-permissions

image: busybox

command: [``"sh"``,``"-c"``,``"chown -R 1000:1000 /usr/share/elasticsearch/data"``]

securityContext:

privileged:``true

volumeMounts:

- name: data

mountPath: /usr/share/elasticsearch/data

- name: increase-vm-max-map

image: busybox

command: [``"sysctl"``,``"-w"``,``"vm.max_map_count=262144"``]

securityContext:

privileged:``true

- name: increase-fd-ulimit

image: busybox

command: [``"sh"``,``"-c"``,``"ulimit -n 65536"``]

securityContext:

privileged:``true

|

這里我們定義了幾個在主應用程序之前運行的Init 容器,這些初始容器按照定義的順序依次執行,執行完成后才會啟動主應用容器。第一個名為 fix-permissions 的容器用來運行 chown 命令,將 Elasticsearch 數據目錄的用戶和組更改為1000:1000(Elasticsearch 用戶的 UID)。因為默認情況下,Kubernetes 用 root 用戶掛載數據目錄,這會使得 Elasticsearch 無法方法該數據目錄,可以參考 Elasticsearch 生產中的一些默認注意事項相關文檔說明:https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#_notes_for_production_use_and_defaults

第二個名為increase-vm-max-map 的容器用來增加操作系統對mmap計數的限制,默認情況下該值可能太低,導致內存不足的錯誤,要了解更多關于該設置的信息,可以查看 Elasticsearch 官方文檔說明:https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html。最后一個初始化容器是用來執行ulimit命令增加打開文件描述符的最大數量的。此外 Elastisearch Notes for Production Use 文檔還提到了由于性能原因最好禁用 swap,當然對于 Kubernetes 集群而言,最好也是禁用 swap 分區的。現在我們已經定義了主應用容器和它之前運行的Init Containers 來調整一些必要的系統參數,接下來我們可以添加數據目錄的持久化相關的配置。

****4****)在 StatefulSet 中,使用volumeClaimTemplates來定義volume 模板即可:****

. . .

volumeClaimTemplates:

- metadata:

name: data

labels:

app: elasticsearch

spec:

accessModes: [``"ReadWriteOnce" ]

storageClassName:``do``-block-storage

resources:

requests:

storage: 10Gi

|

我們這里使用 volumeClaimTemplates 來定義持久化模板,Kubernetes 會使用它為 Pod 創建 PersistentVolume,設置訪問模式為ReadWriteOnce,這意味著它只能被 mount到單個節點上進行讀寫,然后最重要的是使用了一個名為do-block-storage的 StorageClass 對象,所以我們需要提前創建該對象,我們這里使用的 NFS 作為存儲后端,所以需要安裝一個對應的 provisioner驅動。

5****)創建storageclass,實現nfs做存儲類的動態供給 #****安裝nfs服務,選擇k8s集群的master1節點,k8s****集群的master1節點的ip是192.168.0.6:

yum****安裝nfs

yum install nfs-utils -y

systemctl start nfs

chkconfig nfs on

在master1上創建一個nfs共享目錄

mkdir /data/v1 -p

cat /etc/exports

/data/v1 192.168.0.0/24(rw,no_root_squash)

exportfs -arv

使配置文件生效

systemctlrestart nfs

#****實現nfs做存儲類的動態供給

創建運行nfs-provisioner的sa賬號

cat serviceaccount.yaml

apiVersion: v1

kind: ServiceAccount

metadata:

name: nfs-provisioner

|

kubectl apply -f serviceaccount.yaml

對sa賬號做rbac授權

cat rbac.yaml

kind: ClusterRole

apiVersion: rbac.authorization.k8s.io/v1

metadata:

name: nfs-provisioner-runner

rules:

- apiGroups: [``""``]

resources: [``"persistentvolumes"``]

verbs: [``"get"``,``"list"``,``"watch"``,``"create"``,``"delete"``]

- apiGroups: [``""``]

resources: [``"persistentvolumeclaims"``]

verbs: [``"get"``,``"list"``,``"watch"``,``"update"``]

- apiGroups: [``"storage.k8s.io"``]

resources: [``"storageclasses"``]

verbs: [``"get"``,``"list"``,``"watch"``]

- apiGroups: [``""``]

resources: [``"events"``]

verbs: [``"create"``,``"update"``,``"patch"``]

- apiGroups: [``""``]

resources: [``"services"``,``"endpoints"``]

verbs: [``"get"``]

- apiGroups: [``"extensions"``]

resources: [``"podsecuritypolicies"``]

resourceNames: [``"nfs-provisioner"``]

verbs: [``"use"``]

---

kind: ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

name: run-nfs-provisioner

subjects:

- kind: ServiceAccount

name: nfs-provisioner

namespace``:``default

roleRef:

kind: ClusterRole

name: nfs-provisioner-runner

apiGroup: rbac.authorization.k8s.io

---

kind: Role

apiVersion: rbac.authorization.k8s.io/v1

metadata:

name: leader-locking-nfs-provisioner

rules:

- apiGroups: [``""``]

resources: [``"endpoints"``]

verbs: [``"get"``,``"list"``,``"watch"``,``"create"``,``"update"``,``"patch"``]

---

kind: RoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

name: leader-locking-nfs-provisioner

subjects:

- kind: ServiceAccount

name: nfs-provisioner

namespace``:``default

roleRef:

kind: Role

name: leader-locking-nfs-provisioner

apiGroup: rbac.authorization.k8s.io

|

kubectl apply -f rbac.yaml

通過deployment創建pod用來運行nfs-provisioner

cat deployment.yaml

kind: Deployment

apiVersion: apps/v1

metadata:

name: nfs-provisioner

spec:

selector:

matchLabels:

app: nfs-provisioner

replicas: 1

strategy:

type: Recreate

template``:

metadata:

labels:

app: nfs-provisioner

spec:

serviceAccount: nfs-provisioner

containers:

- name: nfs-provisioner

image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner:latest

imagePullPolicy: IfNotPresent

volumeMounts:

- name: nfs-client-root

mountPath: /persistentvolumes

env:

- name: PROVISIONER_NAME

value: example.com/nfs

- name: NFS_SERVER

value: 192.168.0.6

- name: NFS_PATH

value: /data/v1

volumes:

- name: nfs-client-root

nfs:

server: 192.168.0.6

path: /data/v1

|

kubectl apply -f deployment.yaml

kubectl get pods

看到如下,說明上面的yaml文件創建成功:

NAME READY STATUS RESTARTS AGE

nfs-provisioner-595dcd6b77-rkvjl 1/1 Running 0 6s

|

注:上面yaml文件說明:

- name: PROVISIONER_NAME

value: example.com/nfs

|

PROVISIONER_NAME是example.com/nfs,example.com/nfs需要跟后面的storageclass的provisinoer保持一致

- name: NFS_SERVER

value: 192.168.0.6

|

這個需要寫nfs服務端所在的ip地址,大家需要寫自己的nfs地址

- name: NFS_PATH

value: /data/v1

|

這個是nfs服務端共享的目錄

volumes:

- name: nfs-client-root

nfs:

server: 192.168.0.6

|

這個是nfs服務端的ip,大家需要寫自己的nfs地址

path: /data/v1 #這個是nfs服務端的共享目錄

創建storageclass

cat class.yaml

apiVersion: storage.k8s.io/v1

kind: StorageClass

metadata:

name:``do``-block-storage

provisioner: example.com/nfs

|

kubectl apply -f class.yaml

注:

provisioner:example.com/nfs #該值需要和provisioner配置的保持一致

|

6)最后,我們指定了每個 PersistentVolume 的大小為 10GB,我們可以根據自己的實際需要進行調整該值。最后,完整的elasticsaerch-statefulset.yaml資源清單文件內容如下:

****cat elasticsaerch-statefulset.yaml****

apiVersion: apps/v1

kind: StatefulSet

metadata:

name: es-cluster

namespace``: kube-logging

spec:

serviceName: elasticsearch

replicas: 3

selector:

matchLabels:

app: elasticsearch

template``:

metadata:

labels:

app: elasticsearch

spec:

containers:

- name: elasticsearch

image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0

imagePullPolicy: IfNotPresent

resources:

limits:

cpu: 1000m

requests:

cpu: 100m

ports:

- containerPort: 9200

name: rest

protocol: TCP

- containerPort: 9300

name: inter-node

protocol: TCP

volumeMounts:

- name: data

mountPath: /usr/share/elasticsearch/data

env:

- name: cluster.name

value: k8s-logs

- name: node.name

valueFrom:

fieldRef:

fieldPath: metadata.name

- name: discovery.seed_hosts

value:``"es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"

- name: cluster.initial_master_nodes

value:``"es-cluster-0,es-cluster-1,es-cluster-2"

- name: ES_JAVA_OPTS

value:``"-Xms512m -Xmx512m"

initContainers:

- name: fix-permissions

image: busybox

imagePullPolicy: IfNotPresent

command: [``"sh"``,``"-c"``,``"chown -R 1000:1000 /usr/share/elasticsearch/data"``]

securityContext:

privileged:``true

volumeMounts:

- name: data

mountPath: /usr/share/elasticsearch/data

- name: increase-vm-max-map

image: busybox

imagePullPolicy: IfNotPresent

command: [``"sysctl"``,``"-w"``,``"vm.max_map_count=262144"``]

securityContext:

privileged:``true

- name: increase-fd-ulimit

image: busybox

imagePullPolicy: IfNotPresent

command: [``"sh"``,``"-c"``,``"ulimit -n 65536"``]

securityContext:

privileged:``true

volumeClaimTemplates:

- metadata:

name: data

labels:

app: elasticsearch

spec:

accessModes: [``"ReadWriteOnce" ]

storageClassName:``do``-block-storage

resources:

requests:

storage: 10Gi

apiVersion: apps/v1

kind: StatefulSet

metadata:

name: es-cluster

namespace``: kube-logging

spec:

serviceName: elasticsearch

replicas: 3

selector:

matchLabels:

app: elasticsearch

template``:

metadata:

labels:

app: elasticsearch

spec:

containers:

- name: elasticsearch

image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0

imagePullPolicy: IfNotPresent

resources:

limits:

cpu: 1000m

requests:

cpu: 100m

ports:

- containerPort: 9200

name: rest

protocol: TCP

- containerPort: 9300

name: inter-node

protocol: TCP

volumeMounts:

- name: data

mountPath: /usr/share/elasticsearch/data

env:

- name: cluster.name

value: k8s-logs

- name: node.name

valueFrom:

fieldRef:

fieldPath: metadata.name

- name: discovery.seed_hosts

value:``"es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"

- name: cluster.initial_master_nodes

value:``"es-cluster-0,es-cluster-1,es-cluster-2"

- name: ES_JAVA_OPTS

value:``"-Xms512m -Xmx512m"

initContainers:

- name: fix-permissions

image: busybox

imagePullPolicy: IfNotPresent

command: [``"sh"``,``"-c"``,``"chown -R 1000:1000 /usr/share/elasticsearch/data"``]

securityContext:

privileged:``true

volumeMounts:

- name: data

mountPath: /usr/share/elasticsearch/data

- name: increase-vm-max-map

image: busybox

imagePullPolicy: IfNotPresent

command: [``"sysctl"``,``"-w"``,``"vm.max_map_count=262144"``]

securityContext:

privileged:``true

- name: increase-fd-ulimit

image: busybox

imagePullPolicy: IfNotPresent

command: [``"sh"``,``"-c"``,``"ulimit -n 65536"``]

securityContext:

privileged:``true

volumeClaimTemplates:

- metadata:

name: data

labels:

app: elasticsearch

spec:

accessModes: [``"ReadWriteOnce" ]

storageClassName:``do``-block-storage

resources:

requests:

storage: 10Gi

|

kubectl apply -f elasticsaerch-statefulset.yaml

kubectl get pods -n kube-logging

顯示如下,說明es創建成功了:

NAME READY STATUS RESTARTS AGE

es-cluster-0 1/1 Running 0 2m8s

es-cluster-1 1/1 Running 0 117s

es-cluster-2 1/1 Running 0 107s

|

kubectl get svc -n kube-logging

顯示如下

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 33m

|

pod部署完成之后,可以通過REST API檢查elasticsearch集群是否部署成功,使用下面的命令將本地端口9200轉發到 Elasticsearch 節點(如es-cluster-0)對應的端口:

kubectl port-forward es-cluster-0 9200:9200 --``namespace``=kube-logging

|

然后,在另外的終端窗口中,執行如下請求,新開一個master1終端:

|

1

|

curl http:``//localhost:9200/_cluster/state?pretty

|

輸出如下:

{

"cluster_name" :``"k8s-logs"``,

"compressed_size_in_bytes" : 348,

"cluster_uuid" :``"QD06dK7CQgids-GQZooNVw"``,

"version" : 3,

"state_uuid" :``"mjNIWXAzQVuxNNOQ7xR-qg"``,

"master_node" :``"IdM5B7cUQWqFgIHXBp0JDg"``,

"blocks" : { },

"nodes" : {

"u7DoTpMmSCixOoictzHItA" : {

"name" :``"es-cluster-1"``,

"ephemeral_id" :``"ZlBflnXKRMC4RvEACHIVdg"``,

"transport_address" :``"10.244.8.2:9300"``,

"attributes" : { }

},

"IdM5B7cUQWqFgIHXBp0JDg"``: {

"name" :``"es-cluster-0"``,

"ephemeral_id" :``"JTk1FDdFQuWbSFAtBxdxAQ"``,

"transport_address" :``"10.244.44.3:9300"``,

"attributes" : { }

},

"R8E7xcSUSbGbgrhAdyAKmQ" : {

"name" :``"es-cluster-2"``,

"ephemeral_id" :``"9wv6ke71Qqy9vk2LgJTqaA"``,

"transport_address" :``"10.244.40.4:9300"``,

"attributes" : { }

}

},

...

|

看到上面的信息就表明我們名為 k8s-logs的Elasticsearch 集群成功創建了3個節點:es-cluster-0,es-cluster-1,和es-cluster-2,當前主節點是 es-cluster-0。

#安裝kibana組件

elasticsearch安裝成功之后,開始部署kibana

cat kibana.yaml

apiVersion: v1

kind: Service

metadata:

name: kibana

namespace``: kube-logging

labels:

app: kibana

spec:

ports:

- port: 5601

selector:

app: kibana

---

apiVersion: apps/v1

kind: Deployment

metadata:

name: kibana

namespace``: kube-logging

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:7.2.0

imagePullPolicy: IfNotPresent

resources:

limits:

cpu: 1000m

requests:

cpu: 100m

env:

- name: ELASTICSEARCH_URL

value: http:``//elasticsearch:9200

ports:

- containerPort: 5601

|

上面我們定義了兩個資源對象,一個Service和Deployment,為了測試方便,我們將 Service 設置為了 NodePort 類型,Kibana Pod 中配置都比較簡單,唯一需要注意的是我們使用ELASTICSEARCH_URL 這個環境變量來設置Elasticsearch 集群的端點和端口,直接使用 Kubernetes DNS 即可,此端點對應服務名稱為 elasticsearch,由于是一個 headless service,所以該域將解析為3個 Elasticsearch Pod 的 IP 地址列表。

配置完成后,直接使用 kubectl工具創建:

kubectl apply -f kibana.yaml

kubectl get pods -n kube-logging

顯示如下,說明kibana也已經部署成功了

NAME READY STATUS RESTARTS AGE

es-cluster-0 1/1 Running 0 170m

es-cluster-1 1/1 Running 0 170m

es-cluster-2 1/1 Running 0 170m

kibana-5749b5778b-c9djr 1/1 Running 0 4m3s

|

kubectl get svc -n kube-logging

顯示如下:

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 3h28m

kibana ClusterIP 10.104.159.24 <none> 5601/TCP 11m

|

修改service的type類型為NodePort:

kubectl edit svc kibana -n kube-logging

把type:ClusterIP變成type: NodePort

保存退出之后

kubectlget svc -n kube-logging

顯示如下:

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

elasticsearchClusterIP None <none> 9200/TCP,9300/TCP 3h50m

kibana NodePort 10.104.159.24 <none> 5601:32462/TCP 34m

|

在瀏覽器中打開http://<任意節點IP>:32462即可,如果看到如下歡迎界面證明 Kibana 已經成功部署到了Kubernetes集群之中。

image

#****安裝fluentd組件

我們使用daemonset控制器部署fluentd組件,這樣可以保證集群中的每個節點都可以運行同樣fluentd的pod副本,這樣就可以收集k8s集群中每個節點的日志,在k8s集群中,容器應用程序的輸入輸出日志會重定向到node節點里的json文件中,fluentd可以tail和過濾以及把日志轉換成指定的格式發送到elasticsearch集群中。

除了容器日志,fluentd也可以采集kubelet、kube-proxy、docker的日志。

cat fluentd.yaml

apiVersion: v1

kind: ServiceAccount

metadata:

name: fluentd

namespace``: kube-logging

labels:

app: fluentd

---

apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRole

metadata:

name: fluentd

labels:

app: fluentd

rules:

- apiGroups:

-``""

resources:

- pods

- namespaces

verbs:

- get

- list

- watch

---

kind: ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

name: fluentd

roleRef:

kind: ClusterRole

name: fluentd

apiGroup: rbac.authorization.k8s.io

subjects:

- kind: ServiceAccount

name: fluentd

namespace``: kube-logging

---

apiVersion: apps/v1

kind: DaemonSet

metadata:

name: fluentd

namespace``: kube-logging

labels:

app: fluentd

spec:

selector:

matchLabels:

app: fluentd

template``:

metadata:

labels:

app: fluentd

spec:

serviceAccount: fluentd

serviceAccountName: fluentd

tolerations:

- key: node-role.kubernetes.io/master

effect: NoSchedule

containers:

- name: fluentd

image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1

imagePullPolicy: IfNotPresent

env:

- name: FLUENT_ELASTICSEARCH_HOST

value:``"elasticsearch.kube-logging.svc.cluster.local"

- name: FLUENT_ELASTICSEARCH_PORT

value:``"9200"

- name: FLUENT_ELASTICSEARCH_SCHEME

value:``"http"

- name: FLUENTD_SYSTEMD_CONF

value: disable

resources:

limits:

memory: 512Mi

requests:

cpu: 100m

memory: 200Mi

volumeMounts:

- name: varlog

mountPath: /var/``log

- name: varlibdockercontainers

mountPath: /var/lib/docker/containers

readOnly:``true

terminationGracePeriodSeconds: 30

volumes:

- name: varlog

hostPath:

path: /var/``log

- name: varlibdockercontainers

hostPath:

path: /var/lib/docker/containers

|

kubectl apply -f fluentd.yaml

查看是否部署成功

kubectl get pods -n kube-logging

顯示如下,看到status狀態是running,說明部署成功:

NAME READY STATUS RESTARTS AGE

es-cluster-0 1/1 Running 6 57m

es-cluster-1 1/1 Running 5 57m

es-cluster-2 1/1 Running 0 45m

fluentd-fs54n 1/1 Running 0 37m

fluentd-ghgqf 1/1 Running 0 37m

kibana-5749b5778b-zzgbc 1/1 Running 0 39m

|

Fluentd啟動成功后,我們可以前往 Kibana 的 Dashboard 頁面中,點擊左側的Discover,可以看到如下配置頁面:

image

在這里可以配置我們需要的 Elasticsearch 索引,前面 Fluentd 配置文件中我們采集的日志使用的是 logstash 格式,這里只需要在文本框中輸入logstash-*即可匹配到 Elasticsearch集群中的所有日志數據,然后點擊下一步,進入以下頁面:

image

點擊next step,出現如下

image

選擇@timestamp,創建索引

點擊左側的discover,可看到如下:

image

#****測試容器日志

cat pod.yaml

apiVersion: v1

kind: Pod

metadata:

name: counter

spec:

containers:

- name: count

image: busybox

imagePullPolicy: IfNotPresent

args: [/bin/sh, -c,``'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done'``]

|

kubectl apply -f pod.yaml

登錄到kibana的控制面板,在discover處的搜索欄中輸入kubernetes.pod_name:counter,這將過濾名為的Pod的日志數據counter,如下所示:

image

通過上面幾個步驟,我們已經在k8s集群成功部署了elasticsearch,fluentd,kibana,這里使用的efk系統包括3個Elasticsearch Pod,一個Kibana Pod和一組作為DaemonSet部署的Fluentd Pod。

要了解更多關于elasticsearch可參考:https://www.elastic.co/cn/blog/small-medium-or-large-scaling-elasticsearch-and-evolving-the-elastic-stack-to-fit

Kubernetes中還允許使用更復雜的日志系統,要了解更多信息,可參考https://kubernetes.io/docs/concepts/cluster-administration/logging/

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內容