写点什么

教你在 Kubernetes 中快速部署 ES 集群

发布于: 2021 年 06 月 10 日

​​​​摘要: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.yamlkubectl -s http://ip:port create -f es-data.yamlkubectl -s http://ip:port create -f es-service.yaml
复制代码

es-master.yaml:


apiVersion: apps/v1kind: StatefulSetmetadata:  labels:    addonmanager.kubernetes.io/mode: Reconcile    k8s-app: es    kubernetes.io/cluster-service: "true"    version: v6.2.5  name: es-master  namespace: defaultspec:  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/v1kind: StatefulSetmetadata:  labels:    addonmanager.kubernetes.io/mode: Reconcile    k8s-app: es    kubernetes.io/cluster-service: "true"    version: v6.2.5  name: es-data  namespace: defaultspec:  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: v1kind: Servicemetadata:  labels:    addonmanager.kubernetes.io/mode: Reconcile    k8s-app: es    kubernetes.io/cluster-service: "true"    kubernetes.io/name: Elasticsearch  name: es  namespace: defaultspec:  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  }}
复制代码


点击关注,第一时间了解华为云新鲜技术~

发布于: 2021 年 06 月 10 日阅读数: 25
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
教你在Kubernetes中快速部署ES集群