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

一、集群规划

  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。

本文原文链接:https://blog.csdn.net/xzk9381/article/details/109571008

二、修改 elasticsearch 镜像

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

Dockerfile 内容如下:

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

MAINTAINER [email protected]

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

猜你喜欢

转载自blog.csdn.net/xzk9381/article/details/109571008