一、集群规划

  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

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

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

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

    一.集群规划 由于当前环境中没有分布式存储,所以只能使用本地 PV 的方式来实现数据持久化. ES 集群的 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. Elasticsearch-6.7.0系列(二)ES集群安装与验证

    准备3台centos7机器/虚拟机,每台都安装上elasticsearch6.7.0 ,安装过程参考我的另一篇博客<Elasticsearch-6.7.0系列(一)9200端口 .tar.gz版 ...

随机推荐

  1. 如何将炫酷的报表直接截图发送邮件——在Superset 0.37使用Schedule Email功能

    Superset的图表是非常炫酷的,但是原来的版本只能在web端查看,而最新的0.37版本,可以将图表截图直接发送成邮件,非常的方便. 本文将详细介绍Superset 0.37 定时邮件功能.安装过程 ...

  2. Java基于POI实现excel任意多级联动下拉列表——支持从数据库查询出多级数据后直接生成【附源码】

     Excel相关知识点 (1)名称管理器--Name Manager [CoderBaby]首先需要创建多个名称(包含key及value),作为下拉列表的数据源,后续通过名称引用.可通过菜单:&quo ...

  3. Hbuilder MUI 下拉选择与时间选择器

    一. Hbuilder 下拉选择 <link rel="stylesheet" href="../../../assets/mui/css/mui.picker.m ...

  4. 商品现货数据不好拿?商品季节性难跟踪?一键解决没烦恼的Python爬虫分享

    更多精彩内容,欢迎关注公众号:数量技术宅.探讨数据分析.量化投资问题,请加技术宅微信:sljsz01 季节性在大宗商品的交易中至关重要 大宗商品交易中,特别是在期货市场,由于商品价格周期的存在,季节性 ...

  5. C# Redis分布式锁(RedLock) - 多节点

    Redis单节点的分布式锁只需要注意三点就可以了: 1.加锁并设置锁的过期时间必须是原子操作; 2.锁的value值必须要有唯一性; 3.释放锁的时候要验证其value值,不是自己加的锁不能释放. 但 ...

  6. 003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程

    003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程 Java程序长啥样? 首先编写一个Java程序 记事本编写程序 打开记事本 1.wi ...

  7. 《C++ primer plus》第3章练习题

    注:有的题设条件自己改动了一下,比如英寸英尺改成米和厘米,部分题目自己加了点额外要求. 1.要求用户输入身高(m),用下划线提示用户输入,将身高转化成"米"加"厘米&qu ...

  8. 对do{ }while();一直以来的误解 -----如何理解do{ }while( );语句

    在do{ }while( ); 语句中,我之前的理解是:先执行一次do{ },然后判断while( )中的内容,一般里面都是字符串或者数值作比较嘛,所以理解是:如果判断的这个东西,在这个范围中(等于这 ...

  9. 如何部署MongoDB并开启远程访问Docker版

    Docker安装 安装方法 pull最新版本mongo docker pull mongo 运行 --name设置名称 -v挂载数据 -p端口映射 -d后台运行 mkdir ~/mongo #随便啦自 ...

  10. git检出某文件的指定版本

    比如当时文件所处的版本id是27e6266d86de3e6da6e1e7a8c43a8b51d6a87032 文件名是system/models/waimai/huodongdiscount.mdl. ...