摘要:ES叢集是進行大資料儲存和分析,快速檢索的利器,本文簡述了ES的叢集架構,並提供了在Kubernetes中快速部署ES叢集的樣例;對ES叢集的監控運維工具進行了介紹,並提供了部分問題定位經驗,最後總結了常用ES叢集的API呼叫方法。
本文分享自華為雲社群《Kubernetes中部署ES叢集及運維》,原文作者:minucas。
ES叢集架構:
ES叢集分為單點模式和叢集模式,其中單點模式一般在生產環境不推薦使用,推薦使用叢集模式部署。其中叢集模式又分為Master節點與Data節點由同一個節點承擔,以及Master節點與Data節點由不同節點承擔的部署模式。Master節點與Data節點分開的部署方式可靠性更強。下圖為ES叢集的部署架構圖:
採用K8s進行ES叢集部署:
1、採用k8s statefulset部署,可快速的進行擴縮容es節點,本例子採用 3 Master Node + 12 Data Node 方式部署
2、通過k8s service配置了對應的域名和服務發現,確保叢集能自動聯通和監控
kubectl -s http://ip:port create -f es-master.yaml kubectl -s http://ip:port create -f es-data.yaml kubectl -s http://ip:port create -f es-service.yaml
es-master.yaml:
apiVersion: apps/v1 kind: StatefulSet metadata: labels: addonmanager.kubernetes.io/mode: Reconcile k8s-app: es kubernetes.io/cluster-service: "true" version: v6.2.5 name: es-master namespace: default spec: podManagementPolicy: OrderedReady replicas: 3 revisionHistoryLimit: 10 selector: matchLabels: k8s-app: es version: v6.2.5 serviceName: es template: metadata: labels: k8s-app: camp-es kubernetes.io/cluster-service: "true" version: v6.2.5 spec: containers: - env: - name: NAMESPACE valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - name: ELASTICSEARCH_SERVICE_NAME value: es - name: NODE_MASTER value: "true" - name: NODE_DATA value: "false" - name: ES_HEAP_SIZE value: 4g - name: ES_JAVA_OPTS value: -Xmx4g -Xms4g - name: cluster.name value: es image: elasticsearch:v6.2.5 imagePullPolicy: Always name: es ports: - containerPort: 9200 hostPort: 9200 name: db protocol: TCP - containerPort: 9300 hostPort: 9300 name: transport protocol: TCP resources: limits: cpu: "6" memory: 12Gi requests: cpu: "4" memory: 8Gi securityContext: capabilities: add: - IPC_LOCK - SYS_RESOURCE volumeMounts: - mountPath: /data name: es - command: - /bin/elasticsearch_exporter - -es.uri=http://localhost:9200 - -es.all=true image: elasticsearch_exporter:1.0.2 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /health port: 9108 scheme: HTTP initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 name: es-exporter ports: - containerPort: 9108 hostPort: 9108 protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /health port: 9108 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 resources: limits: cpu: 100m memory: 128Mi requests: cpu: 25m memory: 64Mi securityContext: capabilities: drop: - SETPCAP - MKNOD - AUDIT_WRITE - CHOWN - NET_RAW - DAC_OVERRIDE - FOWNER - FSETID - KILL - SETGID - SETUID - NET_BIND_SERVICE - SYS_CHROOT - SETFCAP readOnlyRootFilesystem: true dnsPolicy: ClusterFirst initContainers: - command: - /sbin/sysctl - -w - vm.max_map_count=262144 image: alpine:3.6 imagePullPolicy: IfNotPresent name: elasticsearch-logging-init resources: {} securityContext: privileged: true restartPolicy: Always schedulerName: default-scheduler securityContext: {} volumes: - hostPath: path: /Data/es type: DirectoryOrCreate name: es
es-data.yaml
apiVersion: apps/v1 kind: StatefulSet metadata: labels: addonmanager.kubernetes.io/mode: Reconcile k8s-app: es kubernetes.io/cluster-service: "true" version: v6.2.5 name: es-data namespace: default spec: podManagementPolicy: OrderedReady replicas: 12 revisionHistoryLimit: 10 selector: matchLabels: k8s-app: es version: v6.2.5 serviceName: es template: metadata: labels: k8s-app: es kubernetes.io/cluster-service: "true" version: v6.2.5 spec: containers: - env: - name: NAMESPACE valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - name: ELASTICSEARCH_SERVICE_NAME value: es - name: NODE_MASTER value: "false" - name: NODE_DATA value: "true" - name: ES_HEAP_SIZE value: 16g - name: ES_JAVA_OPTS value: -Xmx16g -Xms16g - name: cluster.name value: es image: elasticsearch:v6.2.5 imagePullPolicy: Always name: es ports: - containerPort: 9200 hostPort: 9200 name: db protocol: TCP - containerPort: 9300 hostPort: 9300 name: transport protocol: TCP resources: limits: cpu: "8" memory: 32Gi requests: cpu: "7" memory: 30Gi securityContext: capabilities: add: - IPC_LOCK - SYS_RESOURCE volumeMounts: - mountPath: /data name: es - command: - /bin/elasticsearch_exporter - -es.uri=http://localhost:9200 - -es.all=true image: elasticsearch_exporter:1.0.2 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 3 httpGet: path: /health port: 9108 scheme: HTTP initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 name: es-exporter ports: - containerPort: 9108 hostPort: 9108 protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /health port: 9108 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 resources: limits: cpu: 100m memory: 128Mi requests: cpu: 25m memory: 64Mi securityContext: capabilities: drop: - SETPCAP - MKNOD - AUDIT_WRITE - CHOWN - NET_RAW - DAC_OVERRIDE - FOWNER - FSETID - KILL - SETGID - SETUID - NET_BIND_SERVICE - SYS_CHROOT - SETFCAP readOnlyRootFilesystem: true dnsPolicy: ClusterFirst initContainers: - command: - /sbin/sysctl - -w - vm.max_map_count=262144 image: alpine:3.6 imagePullPolicy: IfNotPresent name: elasticsearch-logging-init resources: {} securityContext: privileged: true restartPolicy: Always schedulerName: default-scheduler securityContext: {} volumes: - hostPath: path: /Data/es type: DirectoryOrCreate name: es
es-service.yaml
apiVersion: v1 kind: Service metadata: labels: addonmanager.kubernetes.io/mode: Reconcile k8s-app: es kubernetes.io/cluster-service: "true" kubernetes.io/name: Elasticsearch name: es namespace: default spec: clusterIP: None ports: - name: es port: 9200 protocol: TCP targetPort: 9200 - name: exporter port: 9108 protocol: TCP targetPort: 9108 selector: k8s-app: es sessionAffinity: None type: ClusterIP
ES叢集監控
工欲善其事必先利其器,中介軟體的運維首先要有充分的監控手段,ES叢集的監控常用的三種監控手段:exporter、eshead、kopf,由於ES叢集是採用k8s架構部署,很多特性都會結合k8s來開展
Grafana監控
通過k8s部署es-exporter將監控metrics匯出,prometheus採集監控資料,grafana定製dashboard展示
ES-head元件
github地址:https://github.com/mobz/elasticsearch-head
ES-head元件可通過谷歌瀏覽器應用商店搜尋安裝,使用Chrome外掛可檢視ES叢集的情況
Cerebro(kopf)元件
github地址:https://github.com/lmenezes/cerebro
ES叢集問題處理
ES配置
資源配置:關注ES的CPU、Memory以及Heap Size,Xms Xmx的配置,建議如機器是8u32g記憶體的情況下,堆記憶體和Xms Xmx配置為50%,官網建議單個node的記憶體不要超過64G
索引配置:由於ES檢索通過索引來定位,檢索的時候ES會將相關的索引資料裝載到記憶體中加快檢索速度,因此合理的對索引進行設定對ES的效能影響很大,當前我們通過按日期建立索引的方法(個別資料量小的可不分割索引)
ES負載
CPU和Load比較高的節點重點關注,可能的原因是shard分配不均勻,此時可手動講不均衡的shard relocate一下
shard配置
shard配置最好是data node數量的整數倍,shard數量不是越多越好,應該按照索引的資料量合理進行分片,確保每個shard不要超過單個data node分配的堆記憶體大小,比如資料量最大的index單日150G左右,分為24個shard,計算下來單個shard大小大概6-7G左右
副本數建議為1,副本數過大,容易導致資料的頻繁relocate,加大叢集負載
刪除異常index
curl -X DELETE "10.64.xxx.xx:9200/szv-prod-ingress-nginx-2021.05.01"
索引名可使用進行正則匹配進行批量刪除,如:-2021.05.*
節點負載高的另一個原因
在定位問題的時候發現節點資料shard已經移走但是節點負載一直下不去,登入節點使用top命令發現節點kubelet的cpu佔用非常高,重啟kubelet也無效,重啟節點後負載才得到緩解
ES叢集常規運維經驗總結(參考官網)
檢視叢集健康狀態
ES叢集的健康狀態分為三種:Green、Yellow、Red。
- Green(綠色):叢集健康;
- Yellow(黃色):叢集非健康,但在負載允許範圍內可自動rebalance恢復;
- Red(紅色):叢集存在問題,有部分資料未就緒,至少有一個主分片未分配成功。
可通過API查詢叢集的健康狀態及未分配的分片:
GET _cluster/health { "cluster_name": "camp-es", "status": "green", "timed_out": false, "number_of_nodes": 15, "number_of_data_nodes": 12, "active_primary_shards": 2176, "active_shards": 4347, "relocating_shards": 0, "initializing_shards": 0, "unassigned_shards": 0, "delayed_unassigned_shards": 0, "number_of_pending_tasks": 0, "number_of_in_flight_fetch": 0, "task_max_waiting_in_queue_millis": 0, "active_shards_percent_as_number": 100 }
檢視pending tasks:
GET /_cat/pending_tasks
其中 priority 欄位則表示該 task 的優先順序
檢視分片未分配原因
GET _cluster/allocation/explain
其中reason 欄位表示哪種原因導致的分片未分配,detail 表示詳細未分配的原因
檢視所有未分配的索引和主分片:
GET /_cat/indices?v&health=red
檢視哪些分片出現異常
curl -s http://ip:port/_cat/shards | grep UNASSIGNED
重新分配一個主分片:
POST _cluster/reroute?pretty" -d '{ "commands" : [ { "allocate_stale_primary" : { "index" : "xxx", "shard" : 1, "node" : "12345...", "accept_data_loss": true } } ] }
其中node為es叢集節點的id,可以通過curl ‘ip:port/_node/process?pretty’ 進行查詢
降低索引的副本的數量
PUT /szv_ingress_*/settings { "index": { "number_of_replicas": 1 } }