前言
kubernetes官方默認給我們提供了很多addons,其中就包括了日志處理套件EFK,包括 Elasticsearch, Fluentd 和 Kibana三個組件,其中Elasticsearch是搜索引擎,負責存盤日志并對外提供日志的查詢功能;Fluentd是一個日志收集組件,負責收集集群中的日志、并發送給Elasticsearch;Kibana是一個圖形化展示組件,負責從Elasticsearch中查詢日志,并以適當的形式展示出來
部署EFK
-
下載對應的啟動檔案
$ cd /opt/k8s/work/efk $ for file in es-service.yaml es-statefulset.yaml fluentd-es-configmap.yaml fluentd-es-ds.yaml kibana-deployment.yaml kibana-service.yaml; do wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/fluentd-elasticsearch/$file done-
Elasticsearch 以statefulset形式啟動,對應的鏡像中不包含Es的安全插件 X-Pack,因為es要求
vm.max_map_count的值不能小于262144,所以對應的啟動檔案es-statefulset.yaml中有一個init container,在es容器啟動前設定vm.max_map_count,如果系統中這個值已經設定過,可以把這個init container相關的配置去掉,通過以下命令可以查看vm.max_map_count的值$ more /proc/sys/vm/max_map_count -
Storage es-statefulset.yaml啟動檔案中es的存盤配置的是EmptyDir,所以在es重啟時存盤的資料會丟失,因此直接下載的檔案只使用于測驗,如果想在生產環境使用,要替換成永久存性的存盤卷,
-
Fluentd 以DaemonSet形式啟動,會在所有節點上啟動一個pod,依據fluentd-es-configmap.yaml中的配置會讀取kubelet、container的日志,發送給es,
-
此addon中啟動檔案,不要直接在生產環境中使用,如果想在生產環境中使用,推薦用 Helm來安裝這些組件,對應的helm地址如下
Elasticsearch
Fluentd-elasticsearch
Kibana
-
-
修改啟動檔案中對應的鏡像地址
啟動檔案中默認的鏡像Registry是quay.io,國內無法直接下載,此處用微軟的Registry代替
$ sed -i -e 's_quay.io_quay.azk8s.cn_' es-statefulset.yaml $ sed -i -e 's_quay.io_quay.azk8s.cn_' fluentd-es-ds.yaml -
啟動EFK
$ kubectl apply -f .
以上通過Kubernetes提供的EFK進行日志收集的部署就完成了,不過由于我在自己測驗環境執行時由于資源限制,ES無法同時啟動兩個,而Kubernetes提供的這個ES鏡像,至少需要兩個組建成集群才能正常使用,所以,只能采用ES官方的鏡像自己搭建EFK環境,
單節點ElasticSearch部署EFK
部署Elasticsearch
-
編輯啟動檔案
-
es組態檔
$ cat >docker.es.co-configmap.yaml<<EOF kind: ConfigMap apiVersion: v1 metadata: name: es-config-v7.6.1 namespace: kube-system labels: addonmanager.kubernetes.io/mode: Reconcile data: elasticsearch.yml: |- cluster.name: kubernetes-logging node.name: elasticsearch-logging-0 path.data: /data discovery.type: single-node network.host: 0.0.0.0 EOF- discovery.type: single-node,代表對應的es是單節點集群
- network.host: 0.0.0.0 任意IP都可以訪問
-
es啟動檔案
$ cat >docker.es.co-statefulset.yml<<EOF # Elasticsearch deployment itself apiVersion: apps/v1 kind: StatefulSet metadata: name: elasticsearch-logging namespace: kube-system labels: k8s-app: elasticsearch-logging version: v7.4.2 addonmanager.kubernetes.io/mode: Reconcile spec: serviceName: elasticsearch-logging replicas: 1 selector: matchLabels: k8s-app: elasticsearch-logging version: v7.4.2 template: metadata: labels: k8s-app: elasticsearch-logging version: v7.4.2 spec: #serviceAccountName: elasticsearch-logging containers: - image: elasticsearch:7.6.1 name: elasticsearch-logging #imagePullPolicy: Always resources: # need more cpu upon initialization, therefore burstable class limits: cpu: 1000m memory: 4Gi requests: cpu: 100m memory: 1Gi ports: - containerPort: 9200 name: db protocol: TCP - containerPort: 9300 name: transport protocol: TCP #livenessProbe: #tcpSocket: # port: transport #initialDelaySeconds: 5 #timeoutSeconds: 10 # readinessProbe: #tcpSocket: # port: transport #initialDelaySeconds: 5 #timeoutSeconds: 10 volumeMounts: - name: elasticsearch-logging mountPath: /data - name: config-volume mountPath: /usr/share/elasticsearch/config/elasticsearch.yml subPath: elasticsearch.yml env: - name: "NAMESPACE" valueFrom: fieldRef: fieldPath: metadata.namespace volumes: - name: elasticsearch-logging emptyDir: {} - name: config-volume configMap: name: es-config-v7.6.1 EOF相比較kubernetes給我們提供的啟動檔案,此處主要做了兩點改變
- 洗掉了權限相關部分,不需要進行服務發現組件集群了,
- 鏡像檔案換成了elasticsearch:7.6.1,是es官方發布在docker hub上的鏡像
- 需要注意的是volumeMounts中通過subPath: elasticsearch.yml,單獨掛載了一個檔案到容器內的一個目錄中,目錄中其他的檔案不受影響,在subPath功能提出之前,想要單獨替換某個目錄下的一個檔案,需要比較復雜的處理,如把檔案先掛載到其他地方,再通過啟動腳本將檔案復制或者鏈接到應用所用的實際配置目錄下,
-
es service檔案
$ cat >es-service.yaml<<EOF apiVersion: v1 kind: Service metadata: name: elasticsearch-logging namespace: kube-system labels: k8s-app: elasticsearch-logging kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "Elasticsearch" spec: ports: - port: 9200 protocol: TCP targetPort: db selector: k8s-app: elasticsearch-logging EOF
-
-
啟動服務
$ kubectl create -f docker.es.co-configmap.yaml $ kubectl create -f docker.es.co-statefulset.yml $ kubectl create -f es-service.yaml
部署fluentd服務
fluentd啟動檔案和kubernetes給我們提供的沒有什么變化,我本地啟動時唯一修改的地方是docker日志的目錄,在默認情況下,docker日志采用json-file這個日志driver,存盤在docker作業目錄下的containers目錄中,默認的作業目錄是/var/lib/docker,所以默認的docker 日志目錄是/var/lib/docker/containers,我自己的環境在安裝docker時將作業目錄修改成了/data/k8s/docker/data,所以需要修改啟動中的掛載目錄
-
編輯啟動檔案
-
DaemonSet檔案
$ cat>fluentd-es-ds.yaml<<EOF apiVersion: v1 kind: ServiceAccount metadata: name: fluentd-es namespace: kube-system labels: k8s-app: fluentd-es addonmanager.kubernetes.io/mode: Reconcile --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: fluentd-es labels: k8s-app: fluentd-es addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: - "" resources: - "namespaces" - "pods" verbs: - "get" - "watch" - "list" --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: fluentd-es labels: k8s-app: fluentd-es addonmanager.kubernetes.io/mode: Reconcile subjects: - kind: ServiceAccount name: fluentd-es namespace: kube-system apiGroup: "" roleRef: kind: ClusterRole name: fluentd-es apiGroup: "" --- apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd-es-v3.0.0 namespace: kube-system labels: k8s-app: fluentd-es version: v3.0.0 addonmanager.kubernetes.io/mode: Reconcile spec: selector: matchLabels: k8s-app: fluentd-es version: v3.0.0 template: metadata: labels: k8s-app: fluentd-es version: v3.0.0 # This annotation ensures that fluentd does not get evicted if the node # supports critical pod annotation based priority scheme. # Note that this does not guarantee admission on the nodes (#40573). annotations: seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-node-critical serviceAccountName: fluentd-es containers: - name: fluentd-es image: quay.azk8s.cn/fluentd_elasticsearch/fluentd:v3.0.0 env: - name: FLUENTD_ARGS value: --no-supervisor -q resources: limits: memory: 500Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /data/k8s/docker/data/containers readOnly: true - name: config-volume mountPath: /etc/fluent/config.d ports: - containerPort: 24231 name: prometheus protocol: TCP #livenessProbe: #tcpSocket: # port: prometheus #initialDelaySeconds: 5 #timeoutSeconds: 10 #readinessProbe: #tcpSocket: # port: prometheus #initialDelaySeconds: 5 #timeoutSeconds: 10 terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /data/k8s/docker/data/containers - name: config-volume configMap: name: fluentd-es-config-v0.2.0 EOF- 將對應的varlibdockercontainers掛載的hostPath修改成了/data/k8s/docker/data/containers,并且掛載到fluentd容器內的路徑也要是/data/k8s/docker/data/containers,要保持一致
-
組態檔,因為組態檔和kubernetes給我們提供的沒有做變更,此處不全部貼出,具體內容參考fluentd-es-configmap.yaml,此處只給出source部分的內容,來講解下前一步為什么我們掛載到fluentd容器內的日志目錄要和宿主機保持一致
... <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> ...這個source部分的配置中,fluentd并不是從我們掛載的容器中的docker日志目錄直接拿資料的,而是從/var/log/containers目錄下拉取日志資料的(/var/log/是我們將宿主機的/var/log目錄掛載進去的),這個是因為,Kubernetes 的kubelet組件在/var/log/目錄下創建了一個軟鏈接,并且將pod名稱,和container名稱也放到這個軟連接名稱中了,例如
/var/log/containers/fluentd-es-v3.0.0-hvbw7_kube-system_fluentd-es-ef645a4009163b41d596b68d32dbcc921f032549fa168b630d10d0ea2f98eacb.log -> /var/log/pods/kube-system_fluentd-es-v3.0.0-hvbw7_c5269d8e-8543-470a-8599-8ae3a7242a46/fluentd-es/0.log/var/log/pods/kube-system_fluentd-es-v3.0.0-hvbw7_c5269d8e-8543-470a-8599-8ae3a7242a46/fluentd-es/0.log -> /data/k8s/docker/data/containers/ef645a4009163b41d596b68d32dbcc921f032549fa168b630d10d0ea2f98eacb/ef645a4009163b41d596b68d32dbcc921f032549fa168b630d10d0ea2f98eacb-json.logkubelet通過這樣的鏈接,讀取/var/log/containers下的日志,實際上就會讀取到容器內的日志,因為鏈接的路徑資訊已經固定,所以在容器內的路徑一定要和宿主機中保持一致,
這樣做的好處也比較好理解,因為日志檔案名稱中包含了pod名稱,命名空間等kubernetes的資訊,在flutented中通過插件很容易就可將這些資訊決議出來,便于使用者在kibana中對特定應用的日志進行檢索過濾,
-
-
啟動fluentd
$ kubectl create -f fluentd-es-configmap.yaml $ kubectl create -f fluentd-es-ds.yaml
部署kibana
-
編輯啟動檔案
-
deployment檔案
cat >cat kibana-deployment.yaml<<EOF apiVersion: apps/v1 kind: Deployment metadata: name: kibana-logging namespace: kube-system labels: k8s-app: kibana-logging addonmanager.kubernetes.io/mode: Reconcile spec: replicas: 1 selector: matchLabels: k8s-app: kibana-logging template: metadata: labels: k8s-app: kibana-logging annotations: seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: containers: - name: kibana-logging image: elastic/kibana:7.2.0 resources: # need more cpu upon initialization, therefore burstable class limits: cpu: 1000m requests: cpu: 100m env: - name: ELASTICSEARCH_HOSTS value: http://elasticsearch-logging:9200 - name: SERVER_NAME value: kibana-logging - name: SERVER_BASEPATH value: /api/v1/namespaces/kube-system/services/kibana-logging/proxy - name: SERVER_REWRITEBASEPATH value: "false" ports: - containerPort: 5601 name: ui protocol: TCP EOF -
service檔案
cat >kibana-service.yaml<<EOF apiVersion: v1 kind: Service metadata: name: kibana-logging namespace: kube-system labels: k8s-app: kibana-logging kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "Kibana" spec: ports: - port: 5601 protocol: TCP targetPort: ui selector: k8s-app: kibana-logging EOF
-
-
啟動kibana
$ kubectl create -f kibana-deployment.yaml $ kubectl create -f kibana-service.yaml
啟動kubecrl proxy訪問kibana
$ kubectl proxy --accept-hosts='^*$' --address=192.168.0.107
通過界面訪問,在瀏覽器中輸入 http://192.168.0.107:8001/api/v1/namespaces/kube-system/services/kibana-logging/proxy/訪問kibana,
初次訪問需要先配置index pattern


稍等片刻,之后在Discover界面就可以查看相應的日志

可以看到,除了容器中的日志,還額外追加了許多kubernetes的資訊,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/27881.html
標籤:其他
上一篇:NTP時間同步服務器在機場航站樓網路中的應用-京準電子科技
下一篇:KVM系列教程(一)安裝KVM
