Kubernetes|Kubernetes 搭建 ES 集群(存储使用 local pv)

推荐阅读
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/109571008,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。
一、集群规划
  1. 由于当前环境中没有分布式存储,所以只能使用本地 PV 的方式来实现数据持久化,如果希望了解使用 cephfs 搭建 ES 集群,可以参考我的另外两篇文章:CentOS 7 搭建 Ceph 集群(nautilus 版本) 和 Kubernetes 搭建 ES 集群(存储使用 cephfs)。
  2. ES 集群的 master 节点至少需要三个,防止脑裂。
  3. 由于 master 在配置过程中需要保证主机名固定和唯一,所以搭建 master 使用 StatefulSet 控制器
  4. node 节点需要固定的主机名和固定的物理节点以及物理节点上的本地PV,所以需要使用 StatefulSet,配合 StorageClass 来固定。
  5. kibana为无状态服务,使用deployment。
二、修改 elasticsearch 镜像
在部署 elasticsearch 的时候建议配置 memlock:true,这个要求系统必须配置ulimit。所以需要修改镜像,使其在容器内自动执行。
Dockerfile 内容如下:
FROM docker.elastic.co/elasticsearch/elasticsearch:7.3.0MAINTAINER haha@xxx.comCOPY run.sh / RUN chmod 755 /run.shCMD ["/run.sh"]

run.sh 脚本内容如下:
#!/bin/bashulimit -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

五、创建本地持久化存储
1. 存储规划 首先在 k8s-node1 至 k8s-node5 节点中创建 /opt/es/es-node-data 目录,用于存储 ES Data 节点的数据。在 k8s-node3 至 k8s-node5 节点中创建 /opt/es/es-master-data 目录用于存储 ES Master 节点的数据。在 k8s-node3 节点中创建 /opt/es/kibana-data 目录用于存储 kibana 数据。需要注意的是,es-node-data、es-master-data、kibana-data 这三个目录都需要设置 777 权限。
2. 设置 label 为了确保 Pod 调度到指定机器中,需要设置以下 label:
  • 为 k8s-node1 至 k8s-node5 节点添加 es-data-node=true 标签;
kubectl label nodes k8s-node1 es-data-node=true kubectl label nodes k8s-node2 es-data-node=true kubectl label nodes k8s-node3 es-data-node=true kubectl label nodes k8s-node4 es-data-node=true kubectl label nodes k8s-node5 es-data-node=true

  • 为 k8s-node3 至 k8s-node5 节点添加 es-data-master=true 标签;
kubectl label nodes k8s-node3 es-data-master=true kubectl label nodes k8s-node4 es-data-master=true kubectl label nodes k8s-node5 es-data-master=true

  • 为 k8s-node3 节点添加 es-kibana-data=https://www.it610.com/article/true 标签;
kubectl label nodes k8s-node3 es-kibana-data=https://www.it610.com/article/true

3. 创建 StorageClass 创建 StorageClass 的 yaml 文件内容如下:
--- kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: local-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: 200Gi local: path: /opt/es/es-master-data# 需要在指定的节点创建相应的目录 nodeAffinity:# 指定节点,对节点配置label required: nodeSelectorTerms: - matchExpressions: - key: es-data-master operator: In values: - "true" persistentVolumeReclaimPolicy: Retain# 回收策略为保留,不会删除数据,即当pod重新调度的时候,数据不会发生变化. storageClassName: local-es-storage--- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: local-es-master-pvc namespace: ns-elasticsearch spec: accessModes: - ReadWriteOnce storageClassName: local-es-storage resources: requests: storage: 200Gi

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

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/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: /usr/share/elasticsearch/data 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/109571008,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。
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,elasticsearch-master-3,elasticsearch-master-4" - name: node.ingest value: "true" - name: ES_JAVA_OPTS value: "-Xms10g -Xmx10g" volumeMounts: - name: es-node-data mountPath: /usr/share/elasticsearch/data# 需要localPV绑定到该目录,这个官方指定的容器内数据目录 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 NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE elasticsearch-discoveryClusterIP10.102.167.1269300/TCP77m elasticsearch-serviceNodePort10.101.60.2039200:30187/TCP74m kibana-serviceNodePort10.98.206.1845601:31837/TCP73m

可以看到将 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 NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE elasticsearch-discoveryClusterIP10.102.167.1269300/TCP77m elasticsearch-serviceNodePort10.101.60.2039200:30187/TCP74m kibana-serviceNodePort10.98.206.1845601:31837/TCP73m

9200 对外映射的端口为 30187,在浏览器中输入 NodeIP:30187/_cat/nodes?v 可以查看到各个节点的信息:
[@k8s-master1 ~]# curl http://10.11.16.211:30187/_cat/nodes?v ipheap.percent ram.percent cpu load_1m load_5m load_15m node.role master name 100.111.156.90592920.250.280.48 di-elasticsearch-node-0 100.102.107.215113320.430.510.70 di-elasticsearch-node-4 100.67.139.1911710.400.390.59 m*elasticsearch-master-0 100.100.52.2611710.310.360.60 m-elasticsearch-master-1 100.67.139.20391720.400.390.59 di-elasticsearch-node-2 100.102.107.21413320.430.510.70 m-elasticsearch-master-2 100.100.52.27301710.310.360.60 di-elasticsearch-node-3 100.64.169.149532620.690.740.79 di-elasticsearch-node-1

在浏览器中输入 NodeIP:30187/_cat/health?v 可以查看集群的健康信息:
[@k8s-master1 ~]# curl http://10.11.16.211:30187/_cat/health?v epochtimestamp clusterstatus node.total node.data shards pri relo init unassign pending_tasks 1594709799 06:56:39es_cluster green8534170000

【Kubernetes|Kubernetes 搭建 ES 集群(存储使用 local pv)】本文原文链接:https://blog.csdn.net/xzk9381/article/details/109571008,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。

    推荐阅读