Kubernetes-在Kubernetes集群上搭建Stateful Elasticsearch集群

准备工作


  1. Elasticsearch镜像,我以Elasticsearch官方镜像的5.6.10版本为基础创建的。
Dockerfile
FROM docker.elastic.co/elasticsearch/elasticsearch:5.6.10
MAINTAINER leo.lee(lis85@163.com)
WORKDIR /usr/share/elasticsearch
USER root
# copying custom-entrypoint.sh and configuration (elasticsearch.yml, log4j2.properties)
# to their respective directories in /usr/share/elasticsearch (already the WORKDIR)
COPY custom-entrypoint.sh bin/
COPY elasticsearch.yml config/
COPY log4j2.properties config/

# assuring "elasticsearch" user have appropriate access to configuration and custom-entrypoint.sh
# make sure custom-entrypoint.sh is executable
RUN chown elasticsearch:elasticsearch config/elasticsearch.yml config/log4j2.properties bin/custom-entrypoint.sh && \
    chmod +x bin/custom-entrypoint.sh

# start by running the custom entrypoint (as root)
CMD ["/bin/bash", "bin/custom-entrypoint.sh"]
custom-entrypoint.sh
#!/bin/bash
# This is expected to run as root for setting the ulimits

set -e
##################################################################################
# ensure increased ulimits - for nofile - for the Elasticsearch containers
# the limit on the number of files that a single process can have open at a time (default is 1024)
ulimit -n 65536

# ensure increased ulimits - for nproc - for the Elasticsearch containers
# the limit on the number of processes that elasticsearch can create
# 2048 is min to pass the linux checks (default is 50)
# https://www.elastic.co/guide/en/elasticsearch/reference/current/max-number-threads-check.html
ulimit -u 2048

# swapping needs to be disabled for performance and node stability
# in ElasticSearch config we are using: [bootstrap.memory_lock=true]
# this additionally requires the "memlock: true" ulimit; specifically set for each container
# -l: max locked memory 
ulimit -l unlimited

# running command to start elasticsearch
# passing all inputs of this entry point script to the es-docker startup script
# NOTE: this entry point script is run as root; but executes the es-docker
# startup script as the elasticsearch user, passing all the root environment-variables 
# to the elasticsearch user 
su elasticsearch bin/es-docker "$@"
elasticsearch.yml
# attaching the namespace to the cluster.name to differentiate different clusters
# ex. elasticsearh-acceptance, elasticsearh-production, elasticsearh-monitoring
cluster.name: "elasticsearch-${NAMESPACE}"

# we provide a node.name that is the POD_NAME-NAMESPACE
# ex. elasticsearh-0-acceptance, elasticsearh-1-acceptance, elasticsearh-2-acceptance
node.name: "${POD_NAME}-${NAMESPACE}"

network.host: ${POD_IP}

# A hostname that resolves to multiple IP addresses will try all resolved addresses 
# we provide the name for the headless service 
# which resolves to the ip addresses of all the live attached pods
# alternatively we can directly reference the hostnames of the pods
discovery.zen.ping.unicast.hosts: es-discovery-svc

# minimum_master_nodes need to be explicitly set when bound on a public IP
# set to 1 to allow single node clusters
# more info: https://github.com/elastic/elasticsearch/pull/17288
discovery.zen.minimum_master_nodes: 2

bootstrap.memory_lock: true

#-------------------------------------------------------------------------------------
# RECOVERY: https://www.elastic.co/guide/en/elasticsearch/guide/current/important-configuration-changes.html
# SETTINGS TO avoid the excessive shard swapping that can occur on cluster restarts
#-------------------------------------------------------------------------------------
# how many nodes shall be present to consider the cluster functional;
# prevents Elasticsearch from starting recovery until these nodes are available
gateway.recover_after_nodes: 2

# how many nodes are expected in the cluster
gateway.expected_nodes: 3

# how long we want to wait after [gateway.recover_after_nodes] is reached in order to start recovery process (if applicable). 
gateway.recover_after_time: 5m
#-------------------------------------------------------------------------------------

# The following settings control the fault detection process using the discovery.zen.fd prefix:
# How often a node gets pinged. Defaults to 1s.
discovery.zen.fd.ping_interval: 1s

# How long to wait for a ping response, defaults to 30s.
discovery.zen.fd.ping_timeout: 10s

# How many ping failures / timeouts cause a node to be considered failed. Defaults to 3.
discovery.zen.fd.ping_retries: 2
log4j2.properties
status = error
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n
rootLogger.level = info
rootLogger.appenderRef.console.ref = console

将这4个文件放入同一级目录下,然后在该目录下使用命令创建镜像

docker build -t [image name]:[version] .

创建完成后将镜像上传到私有镜像仓库中。

  1. ES需要用到存储,需要提前创建持久卷(PV)
persistent-volume-es.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
  name: k8s-pv-es1
  labels:
    type: local
spec:
  storageClassName: gce-standard-sc
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/usr/share/elasticsearch/data"
  persistentVolumeReclaimPolicy: Recycle
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: k8s-pv-es2
  labels:
    type: local
spec:
  storageClassName: gce-standard-sc
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/usr/share/elasticsearch/data"
  persistentVolumeReclaimPolicy: Recycle
---
kind: PersistentVolume
apiVersion: v1
metadata:
  name: k8s-pv-es3  
  labels:
    type: local
spec:
  storageClassName: gce-standard-sc
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/usr/share/elasticsearch/data"
  persistentVolumeReclaimPolicy: Recycle

使用如下命令创建

kubectl create -f persistent-volume-es.yaml
create pv

部署Elasticsearch集群


elasticsearch.yaml
#create the statefulset headless service
apiVersion: v1
kind: Service
metadata:
  name: es-discovery-svc
  labels:
    app: es-discovery-svc
spec:
  # the set of Pods targeted by this Service are determined by the Label Selector
  selector:
    app: elasticsearch
  # exposing elasticsearch transport port (only)
  # this service will be used by es-nodes for discovery;
  # communication between es-nodes happens through 
  # the transport port (9300)
  ports:
  - protocol: TCP
    # port exposed by the service (service reacheable at)
    port: 9300
    # port exposed by the Pod(s) the service abstracts (pod reacheable at) 
    # can be a string representing the name of the port @the pod (ex. transport)
    targetPort: 9300
    name: transport
  # specifying this is a headless service by providing ClusterIp "None"
  clusterIP: None
---
#create the cluster-ip service
apiVersion: v1
kind: Service
metadata:
  name: es-ia-svc
  labels:
    app: es-ia-svc
spec:
  selector:
    app: elasticsearch
  ports:
  - name: http
    port: 9200
    protocol: TCP
  - name: transport
    port: 9300
    protocol: TCP
---
#create the stateful set
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: elasticsearch
  labels:
    app: elasticsearch
spec:
  # the headless-service that governs this StatefulSet
  # responsible for the network identity of the set.
  serviceName: es-discovery-svc
  replicas: 3
  # Template is the object that describes the pod that will be created
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      securityContext:
        # allows read/write access for mounted volumes  
        # by users that belong to a group with gid: 1000
        fsGroup: 1000
      initContainers:
      # init-container for setting the mmap count limit
      - name: sysctl
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sysctl", "-w", "vm.max_map_count=262144"]
        securityContext:
          privileged: true
      containers:
      - name: elasticsearch
        securityContext:
          # applying fix in: https://github.com/kubernetes/kubernetes/issues/3595#issuecomment-287692878 
          # https://docs.docker.com/engine/reference/run/#operator-exclusive-options
          capabilities:
            add:
              # Lock memory (mlock(2), mlockall(2), mmap(2), shmctl(2))
              - IPC_LOCK  
              # Override resource Limits
              - SYS_RESOURCE
        image: registry.docker.uih/library/leo-elsticsearch:5.6.10
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9300
          name: transport
          protocol: TCP
        - containerPort: 9200
          name: http
          protocol: TCP
        env:
        # environment variables to be directly refrenced from the configuration
        - name: NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        # elasticsearch heapsize (to be adjusted based on need)
        - name: "ES_JAVA_OPTS"
          value: "-Xms2g -Xmx2g"
        # mounting storage persistent volume completely on the data dir
        volumeMounts:
        - name: es-data-vc
          mountPath: /usr/share/elasticsearch/data
  # The StatefulSet guarantees that a given [POD] network identity will 
  # always map to the same storage identity
  volumeClaimTemplates:
  - metadata:
      name: es-data-vc
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          # elasticsearch mounted data directory size (to be adjusted based on need)
          storage: 20Gi
      storageClassName: gce-standard-sc
      # no LabelSelector  defined
      # claims can specify a label selector to further filter the set of volumes
      # currently, a PVC with a non-empty selector can not have a PV dynamically provisioned for it
      # no volumeName is provided

使用如下命令进行部署

kubectl create -f elasticsearch.yaml

部署完后发现还没运行起来,通过日志查出是用户对文件夹【/usr/share/elasticsearch】没有权限引起的,文件夹的权限是root用户,这里可以在外面通过root用户手动修改文件夹权限,将文件夹权限赋给普通用户即可。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,733评论 6 342
  • Elastic+logstash+head简单介绍 一. 概述 ElasticSearch是一个基于Lucene的...
    柒月失凄阅读 4,235评论 0 4
  • 因为我不知道还有几个十五年在等着我,我也不知道下一个十五年还有什么在等待着我去经历,但我知道我是他的妈妈,我在一天...
    心里住着一个girl阅读 330评论 0 1
  • 妈妈的这个“职称”背后都有很多心酸的故事,姐妹们一起回忆孩子们的小时候,唤醒我们心中那份最无私的爱!尽量和孩子态度...
    糖月阳阅读 360评论 2 2