es master 节点数据丢失导致数据节点加入集群失败的灾难恢复

前情提要

部署的架构可以看我之前的博客:k8s 使用 helm 文件部署 8.12.2 es 分角色集群,当时部署 master 角色的时候,没有给节点配置持久化,导致所有节点都下线后重新启动,data 节点无法加入集群,data 节点会有类似下面这样的报错(报错的内容非常的长,这里只截取关键的信息)

This node previously joined a cluster with UUID [n9CFoZ_yTi6zkdJcHq6ZbQ] and is now trying to join a different cluster with UUID [bGyuhfljQxyT5oEMrWH-aA]. This is forbidden and usually indicates an incorrect discovery or cluster bootstrapping configuration. Note that the cluster UUID persists across restarts and can only be changed by deleting the contents of the node's data paths [] which will also remove any data held by this node
  • 报错的原因是 master 节点和 data 节点都需要做数据持久化,因为这两个角色都会保存集群元数据,可以看官方的 Node data path settings 里面写的 Every data and master-eligible node requires access to a data directory where shards and index and cluster metadata will be stored

解决方案

解决流程

  • 停止所有 es 集群的服务
    • 相关的依赖服务都要停止,比如 logstash,filebeat 这种 output 是 es 的,都需要停止
  • 给 master 节点增加 pvc ,对数据目录增加持久化功能
  • 新建一个 pod 挂载所有数据节点的 pvc
  • 使用 elasticsearch-node detach-cluster 命令清除掉集群元数据(集群的 _cluster/setting 也会被清除)
  • 使用 dangling api 还原本地磁盘的数据到 data 节点

实践过程

这里是拿自己的学习环境来模拟的,毕竟这种场景也是百分百复现的,也能完美做到数据脱敏的效果

停止 es 节点
  • data 节点一定要停了,才可以操作 elasticsearch-node detach-cluster 命令,前面提到的上下游依赖,记得都停了,避免造成数据丢失
  • 下面是我环境的内容,大家替换成自己环境的相关信息,作用是把 statefulset 的副本数改为 0,让服务实现下线的场景(直接 yaml 来 delete 和 apply 是一件非常危险的事情,但凡有 edit 的操作没更新 yaml 的,重启之后就废了)
k scale sts -n es-logs es-cluster-data --replicas=0
master 节点增加数据持久化

这一步就不细致拆解了,参考我之前的 helm 部署博客,创建好 pv 和 pvc,然后把 persistence.enabled 配置成 true,然后执行 helm upgrade xxx -f xxx 来更新 master 节点就可以了

新建 es-node-tools pod
  • 利用 es 官方镜像和 pvc 挂载来实现集群元数据的清除操作
    • 我这边是挂的 local-path 类型的 pv,并且做了节点绑定的,所以我没办法一个 pod 挂载多个 pvc
    • 如果大家的环境是共享存储的,如果做了 subPathExpr 的配置,记得下面的 yaml 里面自己增加一下,把对应的共享存储路径全部挂载到一个 pod 里面,方便操作
    • 注意 namespace 和 image 的替换
    • 如果本地数据比较大的话,建议把 limits 配置的和数据节点的一样
apiVersion: v1
kind: Pod
metadata:
  annotations:
  labels:
    app: es-node-tools
  name: es-node-tools
  namespace: es-logs
spec:
  automountServiceAccountToken: true
  containers:
  - image: docker.elastic.co/elasticsearch:8.12.2
    imagePullPolicy: IfNotPresent
    name: elasticsearch
    args: ["bash","-c","tail -f /dev/null"]
    resources:
      limits:
        cpu: "1"
        memory: 2Gi
      requests:
        cpu: 100m
        memory: 1Gi
    securityContext:
      capabilities:
        drop:
        - ALL
      runAsNonRoot: true
      runAsUser: 1000
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /usr/share/elasticsearch/data/data-0
      name: data0
   # - mountPath: /usr/share/elasticsearch/data/data-1
   #   name: data1
   # - mountPath: /usr/share/elasticsearch/data/data-2
   #   name: data2
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext:
    fsGroup: 1000
    runAsUser: 1000
  terminationGracePeriodSeconds: 120
  volumes:
  - name: data0
    persistentVolumeClaim:
      claimName: es-cluster-data-es-cluster-data-0
 # - name: data1
 #   persistentVolumeClaim:
 #     claimName: es-cluster-data-es-cluster-data-1
 # - name: data2
 #   persistentVolumeClaim:
 #     claimName: es-cluster-data-es-cluster-data-2

创建 pod

k apply -f es-node-tools.yaml

进入 pod

k exec -it -n es-logs es-node-tools bash
使用 elasticsearch-node 命令

-E path.data 指定 pvc 挂载的目录,如果是多个 pvc 都挂载到 pod 里面的不同地址的时候,这个参数就可以不用频繁的修改 pod 的挂载地址一个个处理了

elasticsearch-node detach-cluster -E path.data=/usr/share/elasticsearch/data/data-0

正常情况下,会返回下面这样的输出,输入 y 然后回车,会返回 Node was successfully detached from the cluster

------------------------------------------------------------------------

    WARNING: Elasticsearch MUST be stopped before running this tool.

Jul 21, 2024 10:37:09 AM org.apache.lucene.store.MemorySegmentIndexInputProvider <init>
INFO: Using MemorySegmentIndexInput with Java 21; to disable start with -Dorg.apache.lucene.store.MMapDirectory.enableMemorySegments=false
------------------------------------------------------------------------

You should only run this tool if you have permanently lost all of the
master-eligible nodes in this cluster and you cannot restore the cluster
from a snapshot, or you have already unsafely bootstrapped a new cluster
by running `elasticsearch-node unsafe-bootstrap` on a master-eligible
node that belonged to the same cluster as this node. This tool can cause
arbitrary data loss and its use should be your last resort.

Do you want to proceed?

Confirm [y/N]
  • 如果上面的命令执行,出现了 oom 的情况,可以使用下面的命令,然后再次执行 elasticsearch-node detach-cluster 命令
  • 官方默认 CLI 工具的 jvm 是 64MB,可以通过增加 jvm 来解决 oom 的问题
export CLI_JAVA_OPTS="-Xmx1g"

每一个 data 节点的数据目录,都需要执行上面的操作,都执行完成后,可以把 es-node-tools 这个 pod 下线了

k delete -f es-node-tools.yaml

启动 es 数据节点

千万别照搬,注意自己环境的 statefulset 的名字和副本数量

k scale sts -n es-logs es-cluster-data --replicas=3

es 节点验证

# 进入 es 的 pod
k exec -it -n es-logs es-cluster-master-0 bash
# 查看节点信息
curl -s -u "${ELASTIC_USERNAME}:${ELASTIC_PASSWORD}" "localhost:9200/_cat/nodes?v"
# 查看集群健康
curl -s -u "${ELASTIC_USERNAME}:${ELASTIC_PASSWORD}" "localhost:9200/_cat/health?v"
dangling 悬空索引
  • 有 kibana 的话,就执行下面的 GET 命令,没有的话,建议装一个 kibana,或者使用下面的 curl 命令,把输出的内容,想办法做 json 格式化
# kibana 执行
GET /_dangling
# curl 执行
curl -s -u "${ELASTIC_USERNAME}:${ELASTIC_PASSWORD}" localhost:9200/_dangling

导入 dangling 悬空索引,<index-uuid> 就是上面 GET /_dangling 里面获取到的 index_uuid 字段

POST /_dangling/<index-uuid>?accept_data_loss=true

基于格式化过的 json 格式,可以借鉴下面的命令直接生成 curl 命令,然后放到 pod 里面执行就可以了

awk -F '"' '/index_uuid/ {print "curl -s -XPOST -u ""${ELASTIC_USERNAME}:${ELASTIC_PASSWORD} " "localhost:9200/_dangling/"$4"?accept_data_loss=true"}' xxx.json

剩下就是无尽的等待

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 22:28:05       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 22:28:05       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 22:28:05       45 阅读
  4. Python语言-面向对象

    2024-07-21 22:28:05       55 阅读

热门阅读

  1. 数学建模--灰色关联分析法

    2024-07-21 22:28:05       19 阅读
  2. 什么是 MLPerf?

    2024-07-21 22:28:05       20 阅读
  3. Docker

    2024-07-21 22:28:05       17 阅读
  4. 代码改进,模型优化,强化深度学习

    2024-07-21 22:28:05       19 阅读
  5. python 基础知识点(一)

    2024-07-21 22:28:05       18 阅读
  6. Python利用psutil库进行监控进程和资源

    2024-07-21 22:28:05       18 阅读
  7. SpringBoot RestHighLevelClient 按版本更新

    2024-07-21 22:28:05       20 阅读
  8. 跨域问题几种解决方法

    2024-07-21 22:28:05       21 阅读
  9. Python面试整理-文件处理

    2024-07-21 22:28:05       15 阅读
  10. 分式

    2024-07-21 22:28:05       18 阅读
  11. Spring WebFlux 介绍与效果演示示例

    2024-07-21 22:28:05       18 阅读
  12. django 需要修改的文件

    2024-07-21 22:28:05       22 阅读