基于K8S部署生产高可用的ES集群(附迁移方案)


ECK简介

https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-quickstart.html

Elastic Cloud on Kubernetes (ECK) 是一个官方提供的用于在 Kubernetes 集群中简化部署、管理和操作 Elastic Stack(包括 Elasticsearch 和 Kibana)的扩展。

ECK 是一个 Kubernetes Operator,它管理和自动化 Elastic Stack 的生命周期。通过使用 ECK,可以在 Kubernetes 环境中快速实现以下功能:

  1. 部署和管理 Elasticsearch 和 Kibana 实例,包括创建、删除、扩展和升级。
  2. 配置和调整 Elastic Stack 组件以满足特定需求。
  3. 自动处理故障检测、恢复和备份。
  4. 保护 Elasticsearch 集群,通过安全配置、证书管理和安全通信来确保数据安全。
  5. 监控 Elastic Stack 的性能和资源使用,从而优化集群性能。

支持的版本

  • Kubernetes 1.26-1.30(ECK2.14.0,低版本可以支持低版本的K8S,请自行到官网查看。)
  • Elasticsearch, Kibana, APM Server: 6.8+, 7.1+, 8+
  • Beats: 7.0+, 8+
  • Logstash: 8.7+

    部署 operator

kubectl create -f https://download.elastic.co/downloads/eck/2.14.0/crds.yaml
kubectl apply -f https://download.elastic.co/downloads/eck/2.14.0/operator.yaml

部署 ES

部署版本:

  • 7.17.24

部署模式:

  • 3master节点,master,data共用节点。
  • HTTP模式
  • basic认证
  • hostNetwork
  • local-path
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: casslogs
  namespace: elastic-system
spec:
  version: 7.17.24
  http:
    tls:
      selfSignedCertificate:
        disabled: true
  nodeSets:
  - name: data
    count: 3
    # 禁用认证需要增加以下配置
    #config:
    #  xpack.security.authc:
    #    anonymous:
    #      username: anonymous
    #      roles: superuser
    #      authz_exception: false
    podTemplate:
      spec:
        initContainers:
        - name: sysctl
          securityContext:
            privileged: true
            runAsUser: 0
          command: ['sh', '-c', 'sysctl -w vm.max_map_count=262144']
        containers:
        - name: elasticsearch
          env:
          - name: ES_JAVA_OPTS
            value: "-Xms16g -Xmx16g"
          - name: ES_SETTING_CLUSTER_MAX__SHARDS__PER__NODE
            value: '90000'
          - name: ES_SETTING_HTTP_MAX__CONTENT__LENGTH
            value: 300MB
          - name: ES_SETTING_HTTP_MAX__INITIAL__LINE__LENGTH
            value: 20KB
          - name: ES_SETTING_HTTP_MAX__HEADER__SIZE
            value: 32KB
          - name: ES_SETTING_THREAD__POOL_WRITE_QUEUE__SIZE
            value: '2000'
          - name: ES_SETTING_THREAD__POOL_SEARCH_QUEUE__SIZE
            value: '2000'
          - name: ES_SETTING_THREAD__POOL_GET_QUEUE__SIZE
            value: '2000'
          resources:
            limits:
              cpu: 8
              memory: 32Gi
            requests:
              cpu: 500m
              memory: 512Mi
          volumeMounts:
          - name: timezone-volume
            mountPath: /etc/localtime
            readOnly: true
        volumes:
        - name: timezone-volume
          hostPath:
            path: /usr/share/zoneinfo/Asia/Shanghai
        affinity:
          podAntiAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  elasticsearch.k8s.elastic.co/cluster-name: casslogs
              topologyKey: kubernetes.io/hostname
        hostNetwork: true
        dnsPolicy: ClusterFirstWithHostNet
    volumeClaimTemplates:
    - metadata:
        name: elasticsearch-data
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 3000Gi
        storageClassName: local-path
`

部署Kibana

apiVersion: kibana.k8s.elastic.co/v1
kind: Kibana
metadata:
  name: kibana
  namespace: elastic-system
spec:
  version: 7.17.24
  count: 3
  elasticsearchRef:
    name: casslogs
    namespace: elastic-system
  # 禁用认证需要增加以下配置
  #config:
  #  xpack.security.enabled: false
  http:
    service:
      spec:
        type: NodePort
    tls:
      selfSignedCertificate:
        disabled: true
  podTemplate:
    spec:
      containers:
      - name: kibana
        env:
        - name: NODE_OPTIONS
          value: "--max-old-space-size=2048"
        - name: I18N_LOCALE
          value: zh-CN
        - name: SERVER_PUBLICBASEURL
          value: "http://log.casstime.cn"
        resources:
          requests:
            memory: 100Mi
            cpu: 0.5
          limits:
            memory: 4Gi
            cpu: 2
        # 禁用认证需要修改健康检查接口
        #readinessProbe:
        #  failureThreshold: 3
        #  initialDelaySeconds: 10
        #  periodSeconds: 10
        #  successThreshold: 1
        #  timeoutSeconds: 5
        #  TCP健康检查方式
        #  tcpSocket:
        #    port: 5601
        #  HTTP健康检查方式
        #  httpGet:
        #    path: /
        #    port: 5601
        #    scheme: HTTP
        volumeMounts:
        - name: timezone-volume
          mountPath: /etc/localtime
          readOnly: true
      volumes:
      - name: timezone-volume
        hostPath:
          path: /usr/share/zoneinfo/Asia/Shanghai
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                elasticsearch.k8s.elastic.co/name: kibana
            topologyKey: kubernetes.io/hostname
      hostNetwork: true
      dnsPolicy: ClusterFirstWithHostNet

用户管理

方式1
# 解析: Secret: casslogs-es-elastic-user
# 获取elastic的密码
# 登录kibana在Stack Management,安全管理中进行用户管理
http://10.1.0.26:5601/app/management/security/users
方式2
# 编辑部署ES的yaml文件
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: casslogs
  namespace: elastic-system
spec:
  version: 7.17.24
  # 增加账号管理
  auth:
    fileRealm:
    - secretName: es-users-secret
# 新增用户es-users-secret,设置组为超级管理员
kind: Secret
apiVersion: v1
metadata:
  name: es-users-secret
  namespace: elastic-system
stringData:
  # 格式是 账号:密码
  # 可以同时增加多个用户并设置对应的组
  users: |-
    casslogs:cfsa3fsdfs3s
  users_roles: |-
    superuser:casslogs

kibana配置优化

# 日期格式
MM-DD@HH:mm:ss.SSS
# 默认列
message
# 时间筛选速选范围
[
  {
    "from": "now-15m",
    "to": "now",
    "display": "最近 15 分钟"
  },
  {
    "from": "now-30m",
    "to": "now",
    "display": "最近 30 分钟"
  },
  {
    "from": "now-1h",
    "to": "now",
    "display": "最近 1 小时"
  },
  {
    "from": "now-3h",
    "to": "now",
    "display": "最近 3 小时"
  },
  {
    "from": "now-5h",
    "to": "now",
    "display": "最近 5 小时"
  },
  {
    "from": "now-9h",
    "to": "now",
    "display": "最近 9 小时"
  },
  {
    "from": "now-25h",
    "to": "now",
    "display": "最近 25 小时"
  },
    {
    "from": "now/d",
    "to": "now/d",
    "display": "今日"
  },
  {
    "from": "now-3d",
    "to": "now",
    "display": "最近 3 天"
  },
  {
    "from": "now/w",
    "to": "now/w",
    "display": "本周"
  }
]

ES数据迁移

| 方案 | elasticsearch-dump | esm | reindex | logstash | snapshot | | ---------------------- | ----------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | -------------------------------------------------- | ------------------------------------------------------------ | | 基本原理 | 逻辑备份,类似mysqldump将数据一条一条导出后再执行导入 | ESM 是 medcl 开源的派生自:Elasticsearch Dumper 的工具,基于 go 语言开发。 | reindex 是 Elasticsearch 提供的一个 API 接口,可以把数据从一个集群迁移到另外一个集群 | 从一个集群中读取数据然后写入到另一个集群 | 从源集群通过Snapshot API 创建数据快照,然后在目标集群中进行恢复 | | 网络要求 | 无网络互通要求 | 无网络互通要求 | 网络需要互通 | 网络需要互通 | 无网络互通要求 | | 迁移速度 | 最慢 | 很慢 | 一般 | 很快 | 最快 | | 适合场景 | 适用于数据量小的离线场景 | 适用于数据量小的离线场景 | 适用于数据量中等,在线迁移数据的场景 | 适用于数据量很大,实时数据传输的场景 | 适用于数据量特大,离线数据迁移的场景 | | 配置复杂度 | 简单 | 简单 | 中等 | 中等 | 复杂 | | 缺点 | 速度全宇宙最慢,没有之一 | 跨大版本不能迁移mapping,需要手动迁移 | 需要设置集群白名单,重启elasticsearch服务 | logstash对资源要求较高,建议单独的一台服务器运行。 | 在快照还原过程中无法修改分片数,分片数取决于源集群索引设置。 | | 迁移时长(1100万条数据) | 3小时 | 1小时10分钟 | 15分钟 | 8分钟 | 2分钟 |

reindex

设置索引模板,保证写入速率最大化
# 完成迁移后在索引管理中将number_of_replicas和refresh_interval参数设置为合适的值即可。
PUT _template/hwprod
{
  "index_patterns": [
    "hwprod*"
  ],
  "order": 999,
  "settings": {
    "refresh_interval": "-1",
    "number_of_shards": "3",
    "translog": {
      "sync_interval": "60s",
      "durability": "async"
    },
    "number_of_replicas": "0"
  }
}
配置集群白名单,新增源数据集群es地址
# 修改配置文件方式
vim /etc/elasticsearch/elasticsearch.yml 
reindex.remote.whitelist: "10.1.72.33:9200"
systemctl restart elasticsearch.service 

# K8S部署环境变量模式
- name: ES_SETTING_REINDEX_REMOTE_WHITELIST
  value: 10.1.72.33:9200
执行reindex迁移
# 请求
# size: 每批次的数据量
# slice: 切片数量, 和节点数一致
# wait_for_completion=false: 异步执行
POST _reindex?wait_for_completion=false
{
  "source": {
    "remote": {
      "host": "http://10.1.72.33:9200",
      "username": "elastic",
      "password": "asdf1234"
    },
    "index": "hwprod-2024.9.1",
    "size": 10000,
    "slice": {
      "id": 0,
      "max": 3
    }
  },
  "dest": {
    "index": "hwprod-2024.9.1"
  }
}

# 响应
{
  "task": "PuSABDEeTsSXUiW7U--uAw:40193"
}

# 查询异步任务
GET _tasks/PuSABDEeTsSXUiW7U--uAw:40193