一、集群规划

  1. 由于当前环境中没有分布式存储,所以只能使用本地 PV 的方式来实现数据持久化。
  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.0

MAINTAINER haha@xxx.com

COPY run.sh /
RUN chmod 755 /run.sh CMD ["/run.sh"]

run.sh 脚本内容如下:

#!/bin/bash

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

五、创建本地持久化存储

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=true 标签;
kubectl label nodes k8s-node3 es-kibana-data=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

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
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

Kubernetes 搭建 ES 集群(存储使用 local pv)的更多相关文章

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

    一.集群规划 使用 cephfs 实现分布式存储和数据持久化 ES 集群的 master 节点至少需要三个,防止脑裂. 由于 master 在配置过程中需要保证主机名固定和唯一,所以搭建 master ...

  2. 本地虚拟机搭建ES集群

    一.环境说明 1.物理机信息(主要): 内存:8G 系统/主频:Win7(旗舰版)64位/3.70GHZ 2.虚拟机信息: VMware Workstation 14 Pro 下载地址: 链接:htt ...

  3. 搭建ES集群

    服务版本选择 TEG的ctsdb当前最高版本采用的是es的6.4.3版本,为了日后与ctsdb衔接方便,部署开源版es时也采用该版本.6.4.3版本的es依赖的jdk版本要求在8u181以上,测试环境 ...

  4. ELK搭建<一>:搭建ES集群

    1.首先进入官网下载ES,如果下载最新之前的版本 点击past releases就行了. 2.解压后进入config修改配置文件elasticsearch.yml #集群名称 cluster.name ...

  5. Docker搭建ES集群

    Spring Boot连接ES,spring-boot-starter-data-elasticsearch. 必须为集群方式!否则报错! 报错: None of the configured nod ...

  6. elasticsearch系列八:ES 集群管理(集群规划、集群搭建、集群管理)

    一.集群规划 搭建一个集群我们需要考虑如下几个问题: 1. 我们需要多大规模的集群? 2. 集群中的节点角色如何分配? 3. 如何避免脑裂问题? 4. 索引应该设置多少个分片? 5. 分片应该设置几个 ...

  7. ES 集群管理(集群规划、集群搭建、集群管理)

    一.集群规划 搭建一个集群我们需要考虑如下几个问题: 1. 我们需要多大规模的集群? 2. 集群中的节点角色如何分配? 3. 如何避免脑裂问题? 4. 索引应该设置多少个分片? 5. 分片应该设置几个 ...

  8. elasticsearch 集群管理(集群规划、集群搭建、集群管理)

    一.集群规划 搭建一个集群我们需要考虑如下几个问题: 1. 我们需要多大规模的集群? 2. 集群中的节点角色如何分配? 3. 如何避免脑裂问题? 4. 索引应该设置多少个分片? 5. 分片应该设置几个 ...

  9. 通过docker搭建ELK集群

    单机ELK,另外两台服务器分别有一个elasticsearch节点,这样形成一个3节点的ES集群. 可以先尝试单独搭建es集群或单机ELK https://www.cnblogs.com/lz0925 ...

随机推荐

  1. [BJDCTF2020]EzPHP

    [BJDCTF2020]EzPHP 解码:http://794983a5-f5dc-4a13-bc0b-ca7140ba23f3.node3.buuoj.cn/1nD3x.php 源代码: <? ...

  2. RectTransform简析

    UGUI简述   UGUI主要提供了两个能力 UI元素的渲染与适配(其中UI元素的Mesh中的position信息就是通过RectTransform生成的,本文重点) 设备事件的响应与处理(Event ...

  3. 网络端口及nmap扫描

    端口: 计算机与外界交流的出口,在渗透测试当中常用的端口号: 21号端口FTP:文件传输协议 23号端口Telent :远程登录接口 53号端口 DNS: 域名端口 80号端口HTTP:超文本传输协议 ...

  4. Tomcat 8.5集群配置

    示例 <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions= ...

  5. #ifdef _DEBUG/ #define new DEBUG_NEW/ #endif的作用

    转载:https://blog.csdn.net/minghui_/article/details/80748142 转自:#ifdef _DEBUG #define new DEBUG_NEW #e ...

  6. vue超出8个字符,显示省略号

    显示的数据

  7. php中 ob_函数 例:ob_start();用法

    ob,输出缓冲区,是output buffering的简称,而不是output cache.ob用对了,是能对速度有一定的帮助,但是盲目的加上ob函数,只会增加CPU额外的负担 ob的基本原则:如果o ...

  8. 本文介绍如何使用 Docker Swarm 来部署 Nebula Graph 集群,并部署客户端负载均衡和高可用

    本文作者系:视野金服工程师 | 吴海胜 首发于 Nebula Graph 论坛:https://discuss.nebula-graph.com.cn/t/topic/1388 一.前言 本文介绍如何 ...

  9. 多测师讲解python _string_高级讲师肖sir

    import stringprint (string.ascii_letters )#大小写英文:'#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW ...

  10. day58 Pyhton 框架Django 01

    内容回顾 python基础    网路编程    并发编程    数据库    前端     osi7层           tcp/ip 5层模型    应用层    表示层             ...