Kubernetes 搭建 ES 集群(存储使用 cephfs)

推荐阅读

Helm3(K8S 资源对象管理工具)视频教程:https://edu.csdn.net/course/detail/32506
Helm3(K8S 资源对象管理工具)博客专栏:https://blog.csdn.net/xzk9381/category_10895812.html

本文原文链接:https://blog.csdn.net/xzk9381/article/details/109570974,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。

一、集群规划

  1. 使用 cephfs 实现分布式存储和数据持久化
  2. ES 集群的 master 节点至少需要三个,防止脑裂。
  3. 由于 master 在配置过程中需要保证主机名固定和唯一,所以搭建 master 使用 StatefulSet 控制器
  4. node 节点需要固定的主机名和固定的物理节点以及物理节点上的本地PV,所以需要使用 StatefulSet。
  5. kibana为无状态服务,使用deployment。

二、修改 elasticsearch 镜像

为了实现 ES 各个节点将数据进行统一存储并且根据目录名称来区分各个节点,需要在容器内创建以容器主机名命名的目录,并将该目录与 ES 存储数据的目录进行软链接,这样在配置挂载数据卷的时候,实际上挂载是的以主机名命名的目录。

而且在部署 elasticsearch 的时候建议配置 memlock:true,这个要求系统必须配置ulimit。所以需要修改镜像,使其在容器内自动执行。

Dockerfile 内容如下:

FROM docker.elastic.co/elasticsearch/elasticsearch:7.3.0

MAINTAINER haha@test.com

COPY run.sh /
RUN chmod 755 /run.sh

CMD ["/run.sh"]

run.sh 脚本内容如下:

#!/bin/bash

rm -rf /usr/share/elasticsearch/data

if [ ! -e /opt/esdata/${HOSTNAME} ];then
	mkdir -p /opt/esdata/${HOSTNAME}
fi

chmod 777 -R /opt/esdata/${HOSTNAME}

ln -sf /opt/esdata/${HOSTNAME} /usr/share/elasticsearch/data

ulimit -l unlimited
 
exec su elasticsearch /usr/local/bin/docker-entrypoint.sh

elasticsearch 用户是官方镜像中已经创建好的用户

在 Dockerfile 目录中执行如下命令构建镜像:

docker build --tag elasticsearch:7.3.0 -f Dockerfile .

构建完成的镜像可以选择推送到私有镜像仓库中,也可以选择将镜像导出到本地,然后再导入到各个 k8s node 节点中。这里选择首先将镜像导出到本地:

docker save elasticsearch:7.3.0 -o elasticsearch_ulimit_7.3.0.tar

再将镜像导入到各个 node 节点中:

docker load --input elasticsearch_ulimit_7.3.0.tar

三、创建命名空间

将 ES 集群统一放到一个单独的命名空间中,yaml 文件内容如下:

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

四、创建 ServiceAccount 并绑定角色

设置 ES 使用单独的 ServiceAccount,所以需要手动创建一个并分配进群角色,yaml 文件内容如下:

---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    elastic-app: elasticsearch
  name: elasticsearch-admin
  namespace: ns-elasticsearch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: elasticsearch-admin
  labels:
    elastic-app: elasticsearch
rules: 										# 根据需要配置相应的api/资源/权限
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get","watch","list"] 
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: elasticsearch-admin
  labels:
    elastic-app: elasticsearch
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: elasticsearch-admin
    namespace: ns-elasticsearch

五、创建 cephfs 持久化存储

1. 存储规划

首先在 k8s 集群所有节点中创建 /opt/ops_ceph_data 目录,并使用内核挂载的方式,将 cephfs 挂载到该目录下:

mkdir -p /opt/ops_ceph_data
mount -t ceph 10.10.10.10:6789,10.10.10.11:6789,10.10.10.12:6789:/ /opt/ops_ceph_data -o name=admin

查看存储挂载情况:

[@k8s-master1 ~]# df -Th /opt/ops_ceph_data
文件系统                                                 类型    容量   已用  可用    已用% 挂载点
10.10.10.10:6789,10.10.10.11:6789,10.10.10.12:6789:/ ceph   25T   29G   25T    1%   /opt/ops_ceph_data

接下来在 /opt/ops_ceph_data 目录下创建如下三个目录分别用于存储 ES 不同组件和节点的数据,其中 es_kibana_data 目录需要赋予777 权限,否则 kibana 启动时会无法向挂载目录中写入数据:

mkdir -p /opt/ops_ceph_data/es/{es_master_data,es_node_data,es_kibana_data}
chmod -R 777 /opt/ops_ceph_data/es/es_kibana_data/
2. 设置 label

为了确保 ES 节点可以在指定的机器上调度,需要对集群中的机器添加 label,这里我们对 ES 集群中所有节点添加如下 laebl:

for i in 1 2 3 4 5
do
	kubectl label nodes k8s-node${i} es-data-node=true
	kubectl label nodes k8s-node${i} es-data-master=true
	kubectl label nodes k8s-node${i} es-kibana-data=true
done
3. 创建 StorageClass

创建 StorageClass 的 yaml 文件内容如下:

---
kind: StorageClass 
apiVersion: storage.k8s.io/v1
metadata:
  name: es-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer 	# 绑定模式为等待消费者,即当Pod分配到节点后,进行与PV的绑定
4. 创建 PV 和 PVC

由于有三个服务需要进行持久化存储,所以需要创建三个 PV 和 PVC。

4.1 ES Master 存储

创建用于 ES Master 节点数据存储的 PV 和 PVC yaml 文件内容如下:

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-es-master-pv
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 500Gi
  local:
    path: /opt/ops_ceph_data/es/es_master_data
  nodeAffinity:                                 # 指定节点,对节点配置label
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: es-data-master
          operator: In
          values:
          - "true"
  persistentVolumeReclaimPolicy: Retain         # 回收策略为保留,不会删除数据,即当pod重新调度的时候,数据不会发生变化.
  storageClassName: es-storage
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: local-es-master-pvc
  namespace: ns-elasticsearch
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: es-storage
  resources:
    requests:
      storage: 500Gi
4.2 ES Node 存储

创建用于 ES Node 节点数据存储的 PV 和 PVC yaml 文件内容如下:

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-es-node-pv
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 4096Gi
  local:
    path: /opt/ops_ceph_data/es/es_node_data    # 需要在指定的节点创建相应的目录
  nodeAffinity:                                 # 指定节点,对节点配置label
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: es-data-node
          operator: In
          values:
          - "true"
  persistentVolumeReclaimPolicy: Retain         # 回收策略为保留,不会删除数据,即当pod重新调度的时候,数据不会发生变化.
  storageClassName: es-storage
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: local-es-node-pvc
  namespace: ns-elasticsearch
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: es-storage
  resources:
    requests:
      storage: 4096Gi
4.3 Kibana 存储

创建用于 Kibana 节点数据存储的 PV 和 PVC yaml 文件内容如下:

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-kibana-pv
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 2Gi
  local:
    path: /opt/ops_ceph_data/es/es_kibana_data  # 需要在指定的节点创建相应的目录
  nodeAffinity:                                 # 指定节点,对节点配置label
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: es-kibana-data
          operator: In
          values:
          - "true"
  persistentVolumeReclaimPolicy: Retain         # 回收策略为保留,不会删除数据,即当pod重新调度的时候,数据不会发生变化.
  storageClassName: local-es-storage
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: local-kibana-pvc
  namespace: ns-elasticsearch
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-es-storage
  resources:
    requests:
      storage: 2Gi

六、创建 ES Master 节点

1. 创建 StatefulSet

Master 主节点采用三个节点的方式,避免出现脑裂的情况,由于Master所占资源较低,可以配置其容忍 k8s 主节点的污点并调度到该节点上,yaml 文件内容如下:

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    elastic-app: elasticsearch
    role: master
  name: elasticsearch-master
  namespace: ns-elasticsearch
spec:
  replicas: 3
  serviceName: elasticsearch-discovery          # 用于给每一个pod提供一个podname.serviceName的域名进行访问.
  selector:
    matchLabels:
      elastic-app: elasticsearch
      role: master
  template:
    metadata:
      labels:
        elastic-app: elasticsearch
        role: master
    spec:
      serviceAccountName: elasticsearch-admin
      restartPolicy: Always
      containers:
        - name: elasticsearch-master
          image: elasticsearch:7.3.0
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              memory: "20480Mi"
              cpu: "1000m"
          securityContext:
            privileged: true                   # 获取root权限,这样才能进行初始化命令执行.
          lifecycle:
            postStart:                         # 初始化命令,配置系统参数
              exec:
                command:
                - /bin/bash
                - -c
                - sysctl -w vm.max_map_count=262144; ulimit -l unlimited;
          ports:                               # 开放端口一个是集群端口,一个是数据端口
            - containerPort: 9200
              protocol: TCP
            - containerPort: 9300
              protocol: TCP
          env:                                 # 环境变量,非容器下在配置文件配置的,这里对应配置为环境变量就可以了
            - name: cluster.name
              value: "es_cluster"
            - name: bootstrap.memory_lock
              value: "true"
            - name: node.master
              value: "true"
            - name: node.data
              value: "false"
            - name: discovery.seed_hosts
              value: "elasticsearch-discovery"
            - name: cluster.initial_master_nodes
              value: "elasticsearch-master-0,elasticsearch-master-1,elasticsearch-master-2"
            - name: node.ingest
              value: "false"
            - name: ES_JAVA_OPTS
              value: "-Xms10g -Xmx10g"
          volumeMounts:
            - name: es-master-data
              mountPath: /opt/esdata
      volumes:
      - name: es-master-data
        persistentVolumeClaim:
          claimName: local-es-master-pvc
      tolerations:                             # 使其可以运行在k8s主节点上
      - effect: NoSchedule
        key: node-role.kubernetes.io/master

本文原文链接:https://blog.csdn.net/xzk9381/article/details/109570974,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。

2. 创建 Service

Master 主节点不需要对外暴露端口,所以 yaml 文件内容如下:

---
kind: Service
apiVersion: v1
metadata:
  labels:
    elastic-app: elasticsearch
  name: elasticsearch-discovery
  namespace: ns-elasticsearch
spec:
  ports:
    - port: 9300
      targetPort: 9300
  selector:
    elastic-app: elasticsearch
    role: master

七、创建 ES Data 节点

1. 创建 StatefulSet

Data 节点用于存储收集到的日志信息,为了便于部署,此次实施将 Ingest 和 Data 节点部署在一起(在配置文件中同时启动 data 和 ingest),yaml 文件内容如下:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    elastic-app: elasticsearch
    role: node
  name: elasticsearch-node
  namespace: ns-elasticsearch
spec:
  replicas: 5
  serviceName: elasticsearch-service
  selector:
    matchLabels:
      elastic-app: elasticsearch
      role: node
  template:
    metadata:
      labels:
        elastic-app: elasticsearch
        role: node
    spec:
      serviceAccountName: elasticsearch-admin
      restartPolicy: Always
      containers:
        - name: elasticsearch-node
          lifecycle:
            postStart:
              exec:
                command: ["/bin/bash", "-c", "sysctl -w vm.max_map_count=262144; ulimit -l unlimited;"]
          image: elasticsearch:7.3.0
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              memory: "30720Mi"
              cpu: "2000m"
          securityContext:
            privileged: true
          ports:
            - containerPort: 9200
              protocol: TCP
            - containerPort: 9300
              protocol: TCP
          env:
            - name: cluster.name
              value: "es_cluster"
            - name: "bootstrap.memory_lock"
              value: "true"
            - name: node.master
              value: "false"
            - name: node.data
              value: "true"
            - name: discovery.seed_hosts
              value: "elasticsearch-discovery"
            - name: cluster.initial_master_nodes
              value: "elasticsearch-master-0,elasticsearch-master-1,elasticsearch-master-2"
            - name: node.ingest
              value: "true"
            - name: ES_JAVA_OPTS
              value: "-Xms10g -Xmx10g"
          volumeMounts:
            - name: es-node-data
              mountPath: /opt/esdata
      volumes:
      - name: es-node-data
        persistentVolumeClaim:
          claimName: local-es-node-pvc
2. 创建 Service

需要将 Data 节点的 9200 端口暴露出来,同时也用于 Ingest 接收 Filebeat 传送过来的日志信息,yaml 文件内容如下:

---
kind: Service
apiVersion: v1
metadata:
  labels:
    elastic-app: elasticsearch-service
  name: elasticsearch-service
  namespace: ns-elasticsearch
spec:
  ports:
  - port: 9200
    protocol: TCP
    targetPort: 9200
  selector:
    elastic-app: elasticsearch
  type: NodePort

八、创建 Kibana

1. 创建 Deployment

Kibana 作为一个无状态服务,直接使用 Deployment 创建即可,yaml 文件内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kibana
  labels:
    elastic-app: kibana
  namespace: ns-elasticsearch
spec:
  replicas: 1
  selector:
    matchLabels:
      elastic-app: kibana
  template:
    metadata:
      name: kibana
      labels:
        elastic-app: kibana
    spec:
      serviceAccountName: elasticsearch-admin
      restartPolicy: Always
      containers:
      - name: kibana
        image: kibana:7.3.0
        imagePullPolicy: IfNotPresent
        env:
          - name: SERVER_NAME
            value: "kibana"
          - name: SERVER_HOST
            value: "0.0.0.0"
          - name: ELASTICSEARCH_HOSTS
            value: "http://elasticsearch-service.ns-elasticsearch:9200"
          - name: I18N_LOCALE
            value: zh-CN
        volumeMounts:
            - name: kibana-data
              mountPath: /usr/share/kibana/data
      volumes:
      - name: kibana-data
        persistentVolumeClaim:
          claimName: local-kibana-pvc
2. 创建 Service

需要将 Kibana 的 5601 端口暴露出来,yaml 文件内容如下:

---
apiVersion: v1
kind: Service
metadata:
  name: kibana-service
  labels:
    elastic-app: kibana-service
  namespace: ns-elasticsearch
spec:
  ports:
  - port: 5601
    targetPort: 5601
  selector:
    elastic-app: kibana
  type: NodePort

Kibana 创建完成后查看 Service 信息:

[@k8s-master1 ~]# kubectl get svc -n ns-elasticsearch
NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
elasticsearch-discovery   ClusterIP   10.102.167.126   <none>        9300/TCP         77m
elasticsearch-service     NodePort    10.101.60.203    <none>        9200:30187/TCP   74m
kibana-service            NodePort    10.98.206.184    <none>        5601:31837/TCP   73m

可以看到将 Kibana 的 5601 端口映射到 31837 端口中,直接在浏览器中使用 NodeIP:31837 即可访问 Kibana 页面。

九、启动 Filebeat 收集日志

在此次实施过程中没有在 K8S 的 POD 中安装 filebeat,所以直接使用物理机中已有的 filebeat 服务。

首先在 /opt/filebeat-7.3.0/conf 目录下(需提前在 /opt 目录下安装 filebeat)创建一个名为 ES-test.yml 的配置文件,内容如下:

filebeat.idle_timeout: 2s
filebeat.inputs:
- backoff: 1s
  backoff_factor: 2
  close_inactive: 1h
  enabled: true
  encoding: plain
  harvester_buffer_size: 262144
  max_backoff: 10s
  max_bytes: 10485760
  paths:
  - /opt/test.log
  scan_frequency: 10s
  tail_lines: true
  type: log
filebeat.name: filebeat-shiper
filebeat.spool_zie: 50000
output.elasticsearch:
  bulk_max_size: 8192
  hosts:
  - k8s-node1:30187
  index: es-test
  workers: 4
processors:
- drop_fields:
    fields:
    - agent.ephemeral_id
    - agent.hostname
    - agent.id
    - agent.type
    - agent.version
    - ecs.version
    - input.type
    - log.offset
    - version
- decode_json_fields:
    fields:
    - message
    max_depth: 1
    overwrite_keys: true
setup.ilm.enabled: false
setup.template.name: es-test
setup.template.pattern: es-test-*

启动 filebeat:

nohup /opt/filebeat-7.3.0/filebeat run -c /opt/filebeat-7.3.0/conf/ES-test.yml -httpprof 0.0.0.0:18521 -path.logs /opt/filebeat-7.3.0/logs/filebeat_18521 &

此时在 kibana 中可以看到新建了一个名为 es-test 的索引,根据这个索引创建对应的索引模式,即可查看收集的相关日志。

十、查看 ES 集群状态

通过查看 Service 信息可以看到 ES Data node 节点暴露出来的端口号信息:

[@k8s-master1 ~]# kubectl get svc -n ns-elasticsearch
NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
elasticsearch-discovery   ClusterIP   10.102.167.126   <none>        9300/TCP         77m
elasticsearch-service     NodePort    10.101.60.203    <none>        9200:30187/TCP   74m
kibana-service            NodePort    10.98.206.184    <none>        5601:31837/TCP   73m

9200 对外映射的端口为 30187,在浏览器中输入 NodeIP:30187/_cat/nodes?v 可以查看到各个节点的信息:

[@k8s-master1 ~]# curl http://10.11.16.211:30187/_cat/nodes?v
ip              heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
100.111.156.90            59          29   2    0.25    0.28     0.48 di        -      elasticsearch-node-0
100.102.107.215           11          33   2    0.43    0.51     0.70 di        -      elasticsearch-node-4
100.67.139.19              1          17   1    0.40    0.39     0.59 m         *      elasticsearch-master-0
100.100.52.26              1          17   1    0.31    0.36     0.60 m         -      elasticsearch-master-1
100.67.139.20             39          17   2    0.40    0.39     0.59 di        -      elasticsearch-node-2
100.102.107.214            1          33   2    0.43    0.51     0.70 m         -      elasticsearch-master-2
100.100.52.27             30          17   1    0.31    0.36     0.60 di        -      elasticsearch-node-3
100.64.169.149            53          26   2    0.69    0.74     0.79 di        -      elasticsearch-node-1

在浏览器中输入 NodeIP:30187/_cat/health?v 可以查看集群的健康信息:

[@k8s-master1 ~]# curl http://10.11.16.211:30187/_cat/health?v
epoch      timestamp cluster    status node.total node.data shards pri relo init unassign pending_tasks
1594709799 06:56:39  es_cluster green           8         5     34  17    0    0        0             0

本文原文链接:https://blog.csdn.net/xzk9381/article/details/109570974,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

店伙计

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值