ES集群搭建-K8s环境

一、缘由

ES集群上K8s,主要解决横向扩展复杂的问题,次要可以节约一定的成本。

通过更改StatefulSet的副本数,可以有序横向扩展ES集群,并通过集群自动平衡数据的方法,将数据迁移到新加入的节点。

二、预备环境

  1. 阿里云ASK集群:版本1.22.15-aliyun.1

  2. ES集群:版本 elasticsearch:6.3.2

  3. 存储:阿里云SSD云盘

三、架构

部署在阿里云ASK集群的statefulset,不存在资源竞争

  • 方案1(正常方案):master节点3个,data节点N个。

  • 方案2(简单粗暴):初始3个节点,所有节点都是master节点和node节点;后续扩容不用在意discovery,保持master是初期节点即可。(本例采用

四、部署步骤

1、全部所需yaml文件预览

create-ns.yaml             # 命名空间
mhw-es-headless-svc.yaml   # 通过headless-svc配置es集群域名
mhw-storage-class.yaml     # 动态存储卷
mhw-es-statefulset.yaml    # 有状态应用ES
mhw-es-svc.yaml            # LoadBalance类型的svc,作为集群入口
mhw-kibana.yaml            # kibana

2、创建elasticsearch命名空间

新建create-ns.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: elasticsearch
  labels:
    name: elasticsearch

说明:创建专属的namespace和业务应用网络隔离,资源隔离。

3、创建headless类型的svc

新建mhw-es-headless-svc.yaml

kind: Service
apiVersion: v1
metadata:
  name: mhw-es-svc
  namespace: elasticsearch
spec:
  selector:
    app: mhw-es 
  clusterIP: None
  ports:
  - name: rest # 节点与外部通信端口
    port: 9200
  - name: inter-node # 节点内部通信端口
    port: 9300

说明:有状态应用通过headless-svc所确定的域名来相互通信。

4、创建动态存储卷storageclass

新建mhw-storage-class.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: alicloud-disk-ssd-es
provisioner: diskplugin.csi.alibabacloud.com
parameters:
  type: cloud_ssd
  fstype: ext4
  resourceGroupId: "rg-aek2q6kagvjz2zq"
volumeBindingMode: Immediate # 立即绑定,非延迟绑定
reclaimPolicy: Delete # 保留策略,不保留,删除pvc的时候删除云盘
allowVolumeExpansion: false # 是否动态扩展

说明:数据存储采用云盘,云盘可以选择类型和IOPS,就是按量付费可能略贵。具体参数见文档:[使用阿里云云盘动态存储卷](使用云盘动态存储卷 (aliyun.com))

5、创建有状态应用ES

新建mhw-es-statefulset.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mhw-es-cluster # statefuleSet的名称
  namespace: elasticsearch # 所属命名空间
spec:
  serviceName: mhw-es-svc # headless-svc的名称
  selector:
    matchLabels:
      app: mhw-es
  replicas: 3 # 3个节点
  template:
    metadata:
      labels:
        app: mhw-es # es容器标签
      annotations:
        k8s.aliyun.com/eci-use-specs : "2-8Gi" # 实例配置
    spec:
      containers:
      - name: mhw-es # es容器名称
        image: registry-vpc.cn-beijing.aliyuncs.com/zuhaowan-tools/elasticsearch:6.3.2
        resources: # 分配的资源
          requests:
            cpu: 2
            memory: 8Gi
          limits: 
            cpu: 2
            memory: 8Gi
        livenessProbe: 
          tcpSocket:
            port: 9200
          initialDelaySeconds: 40
          timeoutSeconds: 5
          periodSeconds: 5
        ports:
        - containerPort: 9200
          name: rest
          protocol: TCP
        - name: inter-node
          containerPort: 9300
          protocol: TCP
        volumeMounts: # 数据卷挂载
        - name: data
          mountPath: /usr/share/elasticsearch/data
        env:
        - name: TZ # 时区设置
          value: Asia/Shanghai
        - name: cluster.name # ES集群名称
          value: mhw-cluster
        - name: node.name # ES节点名称,来自有状态应用自身名字
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: discovery.zen.ping.unicast.hosts # 自动发现种子节点列表,用于后期选主节点
          value: "mhw-es-cluster-0.mhw-es-svc,mhw-es-cluster-1.mhw-es-svc,mhw-es-cluster-2.mhw-es-svc"
        - name: discovery.zen.minimum_master_nodes # 防止脑裂的配置
          value: "2"
        - name: ES_JAVA_OPTS # Java堆内存
          value: "-Xms4g -Xmx4g"
        - name: network.host 
          value: "0.0.0.0"
        - name: http.cors.allow-origin
          value: "*"
        - name: http.cors.enabled
          value: "true"
        - name: http.max_initial_line_length
          value: "8k"
        - name: http.max_header_size
          value: "16k"
        - name: bootstrap.memory_lock # 内存锁定
          value: "false"
      initContainers: # init容器解决es数据目录权限问题
      - name: fix-permissions
        image: busybox
        command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
        volumeMounts: # es数据目录挂载路径
          - name:  data
            mountPath:  /usr/share/elasticsearch/data
  volumeClaimTemplates:  # PVC模版,使用storageclass动态创建pv
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ] # 单节点读写
      storageClassName: alicloud-disk-ssd-es
      resources:
        requests:
          storage: 50Gi # 创建云盘的大小

说明:

  • ES6集群不需要配置集群初始化时引导选择主节点的配置,所以这个配置cluster.initial_master_nodes 可以不写。

  • 这个集群三个节点默认都是master和data节点。

  • discovery.zen.ping.unicast.hosts 只在最开始配置三个节点即可,后续节点不用再添加进来,永远使用这三个选一个当主节点的意思。

  • 注意指定时区

6、创建ES集群入口SLB

创建mhw-es-svc.yaml

apiVersion: v1
kind: Service
metadata:
  annotations: # 创建按量付费的SLB
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-connect-port: '9200'
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-flag: 'on'
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-interval: '3'
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-health-check-type: tcp
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-healthy-threshold: '4'
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-scheduler: wlc
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-instance-charge-type: "PayByCLCU"
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-unhealthy-threshold: '4'
    service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-name: "mhw-es"
  name: mhw-es-svc-slb
  namespace: elasticsearch 
spec:
  ports:
    - name: http
      port: 9200 
      protocol: TCP
      targetPort: 9200 
  selector:
    app: mhw-es
  type: LoadBalancer

说明:因为本实例中ES集群和业务应用分属于不同namespace,网络隔离了,通过headless-svc名称无法访问通。所以需要一个集群外的访问入口,这里使用私网SLB。

7、创建Kibana

创建mhw-kibana.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mhw-kibana-deployment
  namespace: elasticsearch
  labels:
    app: mhw-kibana
spec:
  minReadySeconds: 15
  replicas: 1
  selector:
    matchLabels:
      app: mhw-kibana
  template:
    metadata:
      labels:
        app: mhw-kibana
      annotations:
        k8s.aliyun.com/eci-use-specs : "1-2Gi"
    spec:
      terminationGracePeriodSeconds: 40
      containers:
      - name: mhw-kibana
        image: registry-vpc.cn-beijing.aliyuncs.com/zuhaowan-tools/kibana:6.3.2
        ports:
        - containerPort: 5601
        resources:
          requests:
            cpu: 1
            memory: 2Gi
          limits: 
            cpu: 1
            memory: 2Gi
        livenessProbe:
          tcpSocket:
            port: 5601
          initialDelaySeconds: 40
          timeoutSeconds: 5
          periodSeconds: 5
        env:
        - name: TZ # 时区
          value: "Asia/Shanghai"
        - name: ELASTICSEARCH_URL # ES集群的地址
          value: "http://mhw-es-svc:9200"
        - name: XPACK.MONITORING.UI.CONTAINER.ELASTICSEARCH.ENABLED # 关闭x-pack
          value: "false"
        - name: I18N.DEFAULTLOCALE # 本地化
          value: "zh-CN"
      imagePullSecrets:          
      - name: zhw-user-secret

说明:

  • 注意连接ES集群地址的变量配置即可,ES6和ES7可能不一样。

  • 可以直接使用容器IP或者创建nodeport和loadblance类型的svc来访问kibana。

  • 本例是部署在ASK集群,集群内网是打通的,故直接使用容器IP访问Kibana。

五、遇到的问题

1、交换分区memory_lock问题

在ES的配置文件中,官方建议不使用交换分区(使用交换分区会使ES性能急剧下降),将bootstrap.memory_lock设置为true,或者最本质方法彻底禁用交换内存。

在本例中,ASK集群的底层是ECI主机,默认交换分区是禁用的(阿里云ECS交换分区默认也是禁用的)。故可以在配置文件中将bootstrap.memory_lock设置为false。

2、缩容PVC释放问题

  • 缩容的时候PVC默认是保留的,同样对应的PV和云盘都是保留的。

  • 上面storageclass设置的PVC删除的时候PV和云盘是同时删除的。

  • 基于以上,如果确认不再使用对应的PVC(存储),需要手动删除,云盘会立刻释放。

3、版本问题

  • 以上是基于ES6部署的配置文件,如果是ES7或者ES8集群,可能会有所差别。

  • 以上是基于阿里云ASK集群,如果是阿里云ACK集群(普通K8s集群),yaml文件可能有差别。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 lxwno.1@163.com

×

喜欢就点赞,疼爱就打赏