推荐阅读
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,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。
一、集群规划
- 由于当前环境中没有分布式存储,所以只能使用本地 PV 的方式来实现数据持久化,如果希望了解使用 cephfs 搭建 ES 集群,可以参考我的另外两篇文章:CentOS 7 搭建 Ceph 集群(nautilus 版本) 和 Kubernetes 搭建 ES 集群(存储使用 cephfs)。
- ES 集群的 master 节点至少需要三个,防止脑裂。
- 由于 master 在配置过程中需要保证主机名固定和唯一,所以搭建 master 使用 StatefulSet 控制器
- node 节点需要固定的主机名和固定的物理节点以及物理节点上的本地PV,所以需要使用 StatefulSet,配合 StorageClass 来固定。
- 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
本文原文链接: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
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/109571008,转载请注明出处。如有发现文章中的任何问题,欢迎评论区留言。