原 荐 基于Kubernetes的ESaaS

概述

ESaaS(ElasticSearch as a Service)是ElasticSearch on Kubernetes的产品实现,是利用DockerKubernetes等容器虚拟化和编排调度系统,将ElasticSearch抽象为CaaS(Container as a Service)平台上的一种服务,实现秒级创建和扩缩容一个用户自定义的ElasticSerach集群,并且保证高可用和数据安全等方面。

关键组件

  • ElasticSearch 2.x
  • Kubernetes 1.9
  • Docker 1.12.6

方案细节和注意事项

  1. ES集群中,某个data/master/client节点挂了之后,分别该怎么办? PS:我的环境中,所有data节点都是client,不会独立部署client。
    • 如果独立部署client,那么client挂了recreate一个新的即可,注意要清理旧的/data数据。
    • master /data保存集群元数据,某个master down了recreate一个新的即可,新的master node 其实可以利用旧的master node的/data数据,也可以不用。调度上不需要干预。但是建议要清理/data数据。
    • data节点挂了后,不允许利用原来的数据进行重启,需要recreate一个新的空白的data node。调度上需要干预,确保新的这个data node没有用之前的老的data node的/data数据。其实删除旧data Node挂了之后,需要清理/data目录的,新的data node也利用不了老的数据。但是为了防止删除数据失败,还是建议调度到不同的服务器。
  2. client和master的/data目录都有持久化的数据吗?
    • client /data也有元数据信息,作为“smart router”来接受集群请求并转发。
    • master的/data目录也有集群元数据,不能和data node共享/data目录。
  3. 如何保证data node的HA?跨服务器,跨机架。
    • 首先给服务器打上机柜机架的Lable(esaas.hosts.rack=${rack_id})
    • 通过Pod Anti-affinity做Pod调度的反亲和性; podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: es-cluster-name operator: In values: - ${es-cluster-name} topologyKey: esaas.hosts.rack=${rack_id}
    • 注意使用requiredDuringSchedulingIgnoredDuringExecution类型的pod anti-affinity时,需要k8s admission controller disable LimitPodHardAntiAffinityTopology,否则会默认使用topologyKey: kubernetes.io/hostname,而不能使用自定义topologyKey。
    • 线上按照上面的方式进行跨机架部署,在开发测试环境,跨服务器部署就行了,使用topologyKey: kubernetes.io/hostname.
  4. 如何设置ES容器的vm属性vm.max_map_count
    • 通过init container进行设置,要求init contaienr的privilege为true。
    • 所有类型的node(client, master, data)都默认使用一样的vm配置。 initContainers: - name: init-sysctl image: busybox imagePullPolicy: IfNotPresent command: ["sysctl", "-w", "vm.max_map_count=262144"] securityContext: privileged: true
  5. 如何关闭ES swap的配置?
    • 方法1:关闭物理服务器的swap;
    • 方法2:配置每个ES node的配置项bootstrap.mlockall: true,要求es容器添加CAP_IPC_LOCK,SYS_RESOURCE这两个Linux Capacity。 securityContext: privileged: false capabilities: add: - IPC_LOCK - SYS_RESOURCE
  6. ES配置项minimum_master_nodes设置也是通过env注入,然后在容器启动脚本run.sh中重新生成elasticsearch.yml。
    • POD中注入环境变量NUMBER_OF_MASTERS
    • 如果集群scale up/down后,可能需要动态设置这个环境变量;
    • 个人觉得,不人为设定ES集群的minimum_master_nodes配置项,由ES集群触发选举时自己根据master node数动态调整。
  7. 修改file descriptors,建议212644(64K)。
    • 修改容器内/etc/security/limits.conf, 也应该是需要privilege,或者对应Linux capability。
  8. es data通过K8S StatefulSet部署,每个es data Pod都会通过volumeClaimTemplates创建对应的PV, 将宿主机上的/data/${es_cluster_name}挂载到es data容器内的/data目录。容器漂移或者recreate时,旧的服务器上es垃圾数据需要做清理。
    • HostPath PV支持Recycle这种Reclain Policy。(目前只有HostPath和NFS支持Recycle)
    • Recycle —> basic scrub (rm -rf /thevolume/*)
  9. scale down 和 scale up时具体分别该如何操作?
    • scale down/up es-clients,直接按照HA的思路进行scale,无需其他操作;
    • scale down/up es-masters,按照HA的思路进行scale后,需要调ES接口修改minimum_master_nodes
    • scale down/up es-datas, 按照HA的思路进行scale up后,无需其他操作;scale down时,需要将对应hostpath上的目录(数据)进行清理。每次缩容只允许减1个es data node,scale down操作前需要检查:
      • ES集群的监控状态是green;
      • 确保缩容后,max(index1.replicas, index2.replicas,…) + 1 < data-node-num
      • 其他检查
  10. 某个物理服务器要下线,该如何操作?
    • 第3点提到HA方案,可以保证每个服务器上最多只会存在某个ES集群中的单个cient/master/data节点,因此服务器下线最多只会down掉ES集群的单个cient/master/data节点,对于正规的ES集群是不影响的。这种情况,直接在服务器上执行kubectl drain将deployment,StatefulSet pods驱逐出去,并会自动在其他合适的服务器上recreate一个新的cient/master/data节点。ES集群在整个过程中始终保持正常工作。
    • 如果用户部署的是单节点的ES实例,那么按照上面的步骤,必然会导致用户的数据丢失,ES服务长时间不能用。因此需要对用户进行风险提示,并建议先进行扩容,然后待新节点同步数据完成后,才能干掉原来的es实例。
  11. 某个服务器突然down了,接下来是什么自动流程?
    • 服务器down了以后,由于调度部署时考虑了HA,因此不会影响正规的ES集群的使用。
    • 接着大概5min(通过pod-eviction-timeout设置)时间,会在新的Node上recreate新的client/master/data容器。这样就继续维持原有ES集群的规模。
  12. ES插件的安装流程?
    • CaaS集群内部提供ElastcSearch Plugin仓库,存放常用插件提供下载;
    • 用户在初始化部署ES集群时可以选择想要安装plugins(支持site和jar类型),在init container中下载插件文件到plugin-volume,ES启动时自动加载这些plugins;
    • 如果在ES集群使用过程中用户想安装plugins,对于site类型的plugin,调用Kubernetes exec接口下载对应Site plugin文件到对应的插件目录即可;对于jar类型的plugin,同样的先现在插件到对应的plugin-volume目录,由于需要重启ES实例,通过执行kubectl exec POD_NAME -c CONTAINER_NAME reboot 或者 docker kill $containerName来重启ES容器而不用recreate Pod。
    • 由于多个ES不能共享同一个plugin目录,因此需要给每个ES实例都划分独立的plugin-volume,挂载宿主机上不同的hostpath;
    • 对于ES管理类plugin,需要指定插件部署到哪个ES node上(建议部署在某个master node上),后面访问该plugin只能通过访问该ES node的plugin API;
    • 对于ES功能类plugin(比如ik分词器),需要在所有ES集群 nodes(client, master, data)上安装该plugin。
    • 安装jar插件重启es节点前,必须检查es集群健康状态为green。
    • es节点重启时,注意ES的Fault Detection机制,配置discovery.zen.fd.ping_interval(1s), ping_timeout(30s),ping_retries(3),也就是说默认90s内没ping通就认为节点失败,然后进行分片迁移。我们关注这个配置,有需要可以适当调大。
    • 讨论决定,先只支持jar类型的插件,后续考虑sites类的插件(比如通过ESaaS本地存放sites plugin,所有ES集群共用)
  13. 自研ES监控工具如何与ES集群对接?
    • 监控工具支持API动态增加ES集群信息,只需要把集群中任一node(client/master/data)的IP和Port(9200)添加到监控工具中,有client就给client的信息,如果只有data node,则给data node的9200到监控工具;
    • ESaaS创建ES集群时,配置是否自动添加到监控平台,如果是,则部署完ES集群后回调监控平台的”ADD_ES_CLUSTER“接口;
    • ESaaS页面提供到监控平台的跳转链接,由监控平台做好监控信息的权限管理。监控添加ES集群时需要带上用户的ID。
  14. Kibana服务的部署如何与ES集群对接?
    • 初始化部署ES集群时,用户可以勾选是否一并自动创建对应的Kibana服务;
    • 也提供单独创建Kibana服务的页面入口,要求用户选择对接的ES集群;
    • 通过注入环境变量ELASTICSEARCH_URL: http://es-client.namespace-1.svc.pro.es::9200
  15. 所有ES nodes的elasticsearch.yaml中的discovery hosts只需要配置master nodes的域名或者IP列表,当然如果配置所有的(client, data, master nodes)IP列表,也不会有异常。
  16. 初始化创建ES集群的时候,注意确保成功启动所有master nodes后,再去创建data nodes。client nodes的创建顺序没有要求。
  17. ES node的JVM内存配置,支持8,16,32g。最大不允许超过32g,否则反而会因为GC问题等导致性能更差。
  18. ES集群的日志收集,接入EFK日志系统。同时提供ES集群各个容器的web console能力,让用户能在web console查看(慢)日志等操作。
  19. ES zen discovery我们通过域名(K8S Service Name)来解析es master IP List, 需要注意hosts.resolve_timeout,默认5s。
  20. ES 2.x和5.x,6.x在node角色划分不一样,目前我只考了2.x版本,5.x和6.x需做适度调整。
  21. 引导检查
    • Heap size check 堆大小检查
    • File descriptor check 文件描述符(文件句柄)检查
      • 启动报错:max file descriptors [65535] for elasticsearch process likely too low, increase to at least [65536]
      • 解决方式:ulimit -n 65536 或者 vi /etc/security/limits.conf soft nofile 65536 hard nofile 65536
    • Memory lock check 内存锁住检查
    • Maximum number of threads check 线程最大值检查
      • 启动报错:max number of threads [1024] for user [push] is too low, increase to at least [2048]
      • 解决方法:vi /etc/security/limits.d/90-nproc.conf soft nproc 2048
    • Maximum size virtual memory check 虚拟内存最大值检查
    • Maximum map count check map count最大值检查
      • 启动报错:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
      • 解决方法:vi /etc/sysctl.conf vm.max_map_count=262144 sysctl -p
    • Client JVM check JVM客户端检查
    • Use serial collector check
    • System call filter check
      • 启动报错:system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk
      • 解决方法:elasticsearch.yml加上bootstrap.system_call_filter: false
    • OnError and OnOutOfMemoryError checks
    • Early-access check
    • G1GC check G1垃圾回收器检查
  22. 用户在ESaaS Portal上自助申请ES集群时,除了指定每个nodes的cpu,mem之外,还需要指定需要的本地存储空间大小,Kubernetes 1.9在调度时需要考虑服务器存储空间是否能满足需求。