[单master节点k8s部署]23.构建EFK日志收集平台(二)

部署elasticsearch集群

已经完成的工作:创建存储。首先配置了nfs存储提供商(nfs-deployment.yaml),然后通过创建存储类(storageclass.yaml)来将nfs服务器与存储类绑定:

复制代码
[root@master 31efk]# cat storageclass.yaml 
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: do-block-storage
provisioner: example.com/nfs

创建了elasticsearch的服务(elasticsearch_svc.yaml),定义了两个接口,一个是对外的,一个是elasticsearch集群内部通信的。

复制代码
[root@master 31efk]# cat elasticsearch_svc.yaml 
kind: Service
apiVersion: v1
metadata:
  name: elasticsearch31
  namespace: kube-logging31
  labels:
    app: elasticsearch
spec:
  selector:
    app: elasticsearch
  clusterIP: None
  ports:
    - port: 9200
      name: rest
    - port: 9300
      name: inter-node

现在创建elasticsearch的具体pod。

这里的集群创建方式为statefulset,因为elasticsearch需要稳定的pod管理和持久化的存储。

  1. 有状态服务:Elasticsearch节点存储数据,因此需要持久化存储(即磁盘卷),并且需要保证每个节点能够持有自己特定的数据,即使在Pod重启或迁移时。

  2. 稳定的网络标识:StatefulSet为每个Pod分配一个稳定且唯一的网络标识(DNS名),这对于Elasticsearch这样的分布式系统至关重要,因为节点之间需要通过固定的名称相互通信。

  3. 顺序部署和终止:StatefulSet保证Pod按照顺序创建和删除,这有助于Elasticsearch集群的节点顺利加入和退出,确保集群的健康状态。

elasticsearch的yaml文件

第一部分

第一部分,可以看到部署在kube-logging31命名空间,匹配了elasticsearch31的service。容器内部也开放对应的端口。

对于statefulset来讲,需要持久化存储,这里定义了PVC模板,用来从storageClass进行请求PV。(当 PVC 指定了某个 StorageClass 时,Kubernetes 会使用该 StorageClass 动态创建(或供应)一个 PV,并将其绑定到 PVC 上。)这里的PVC的name是data,这里容器绑定的存储名称也是data,路径为/usr/share/elasticsearch/data。

复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: elastic-cluster31
  namespace: kube-logging31
spec:
  serviceName: elasticsearch31
  replicas: 3
  selector:
    matchLabels:
      app: elasticsearch
  volumeClaimTemplates:
  - metadata:
      name: data
      labels:
        app: elasticsearch
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: do-block-storage
      resources:
        requests:
          storage: 10Gi  
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
      - name: elasticsearch
        image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0
        imagePullPolicy: IfNotPresent
        resources:
            limits:
              cpu: 1000m
            requests:
              cpu: 100m
        ports:
        - containerPort: 9200
          name: rest
          protocol: TCP
        - containerPort: 9300
          name: inter-node
          protocol: TCP
        volumeMounts:
        - name: data
          mountPath: /usr/share/elasticsearch/data   
第二部分

container的环境变量:这里设置的环境变量主要是为了进行一个集群的搭建,这里的集群和statefulset里面的name是不一样的,具体关系如下:

  • selector 主要用于 Kubernetes 内部 ,它负责确定哪些 Pods 属于哪个 StatefulSet,或者哪些 Pods 应该由某个服务来管理。但是,selector 并不能直接影响 Elasticsearch 集群的内部逻辑,也不能用来标识 Elasticsearch 中的节点。

  • 可以说selector主要方便容器的生命周期管理,不能控制elasticsearch集群内部的逻辑。而elasticsearch需要进行节点选举等更加精确的控制,因此还需要额外的配置。

  • node.name :作用于 Elasticsearch 层,是 Elasticsearch 集群中唯一标识每个节点的配置。每个 Elasticsearch 节点必须有一个唯一的 node.name,以便 Elasticsearch 能够正确地管理和协同多节点的操作,如主节点选举、数据分片分配等。

所以下面的container的环境变量就是规定了elasticsearch的集群名称,以及node.name

由于在statefulset中,创建的pod的名字是固定的,名称格式是<statefulset-name>-<ordinal> 。由于statefulset的名称是es-cluster,所以pod的名称就是es-cluster31-0,es-cluster31-1,es-cluster31-2。而这里的discovery.seed_hosts是每一个pod的DNS地址,每一个pod的DNS地址格式为:

复制代码
<pod-name>.<service-name>.<namespace>.svc.cluster.local

所以看到 discovery.seed_hosts:"es-cluster31-0.elasticsearch31.kube-logging31.svc.cluster.local,es-cluster31-1.elasticsearch31.kube-logging31.svc.cluster.local,es-cluster31-2.elasticsearch31.kube-logging31.svc.cluster.local"

复制代码
          env:
          - name: cluster.name
            value: k8s-logs
          - name: node.name
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: discovery.seed_hosts
            value: "elastic-cluster31-0.elasticsearch31.kube-logging31.svc.cluster.local,elastic-cluster31-1.elasticsearch31.kube-logging31.svc.cluster.local,elastic-cluster31-2.elasticsearch31.kube-logging31.svc.cluster.local"
          - name: cluster.initial_master_nodes
            value: "elastic-cluster31-0,elastic-cluster31-1,elastic-cluster31-2"
          - name: ES_JAVA_OPTS
            value: "-Xms512m -Xmx512m"
第三部分

这里的三个初始化容器是为了更好的准备elasticsearch的容器环境,确保在elasticsearch启动之前,所有的权限都已经配置正确。

fix-permission

第一个fix-permission是为了修复数据目录的权限。这里需要介绍pod的创建顺序。initcontainers和主容器都是 Pod 的一部分。当 Kubernetes 创建 Pod 时,会按照以下顺序执行操作:

  1. 创建 Pod :Kubernetes 会首先创建整个 Pod 实体,包括其描述的所有容器(initContainers 和主容器)。
  2. 挂载卷(PVC) :当 Pod 被创建时,Kubernetes 会根据 Pod 的定义(包括 volumeMountsPersistentVolumeClaim)将所需的持久卷挂载到 Pod 中的指定路径。这一步是 在所有容器启动之前 完成的。
  3. 启动 initContainers :卷挂载完成后,Kubernetes 会启动 initContainers,这些容器可以访问 Pod 中已经挂载的卷。
  4. 启动主容器 :当 所有 initContainers 成功运行完成 后,Kubernetes 才会启动主容器(即 Elasticsearch 容器)。

所以可以看到,在initContainer启动之前,持久卷的挂载已经到了pod的指定路径。但是Kubernetes 动态分配的存储卷(通过 PVC 申请的持久卷)可能默认具有不适合 Elasticsearch 的文件权限。

Elasticsearch 容器通常以特定用户身份(如 UID 1000)运行,而持久卷可能以 root 用户(UID 0)创建。为了让 Elasticsearch 拥有正确的访问权限,initContainer 需要修改挂载卷的数据目录权限。因此第一个initContainer:fix-permissions 容器的运行确保数据目录的权限是正确的(chown -R 1000:1000),这样 Elasticsearch 主容器启动时能够正常访问和写入数据。

复制代码
initContainers:
      - name: fix-permissions
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
        securityContext:
          privileged: true
        volumeMounts:
        - name: data
          mountPath: /usr/share/elasticsearch/data
      - name: increase-vm-max-map
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sysctl", "-w", "vm.max_map_count=262144"]
        securityContext:
          privileged: true
      - name: increase-fd-ulimit
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ["sh", "-c", "ulimit -n 65536"]
        securityContext:
          privileged: true
increase-vm-max-map

容器本质上是一个轻量级的隔离环境,在容器中运行的应用程序实际上是一个linux进程。一般来讲,linux会限制每一个进程的内存映射数量,从而限制这个进程对资源的消耗。

Luence是elasticsearch的核心技术,是一个全文检索技术。Luence通过使用操作系统的 内存映射(memory-mapped I/O) 技术来高效访问索引文件,尤其是在处理大规模的索引时。内存映射允许 Lucene 将磁盘上的索引文件映射为进程的虚拟内存空间,因此可以像访问普通内存一样访问这些文件。

但是对于elasticsearch这种日志收集的容器,linux给的 65530个内存映射区域是不够的**,** 当 Elasticsearch/Lucene 达到系统允许的最大内存映射区域数量时,操作系统会拒绝为新的索引文件或数据文件创建内存映射。这会导致Lucene 无法加载新的索引文件,从而影响搜索和查询的执行。

所以这个increase-vm-max-map的容器,把vm-max-count的数量增加到了262144。

increase-fd-ulimit

这个容器用来提升进程可以打开的最大文件描述符的限制。

elasticsearch部署

随后进行elasticsearch的部署,发现三个容器正常启动:

复制代码
[root@master 31efk]# kubectl get pods -n kube-logging31 -owide
NAME                  READY   STATUS    RESTARTS   AGE    IP               NODE    NOMINATED NODE   READINESS GATES
elastic-cluster31-0   1/1     Running   0          114s   10.244.104.62    node2   <none>           <none>
elastic-cluster31-1   1/1     Running   0          110s   10.244.166.184   node1   <none>           <none>
elastic-cluster31-2   1/1     Running   0          103s   10.244.104.63    node2   <none>           <none>

由于elasticsearch没有对外暴露端口,可以进行端口映射,然后在集群外面访问

复制代码
kubectl port-forward elastic-cluster31-0 9200:9200 -n kube-logging31

然后打开另一个端口,进行访问,可以看到很多内容。

复制代码
[root@master 31efk]# curl http://localhost:9200/_cluster/state?pretty
{
  "cluster_name" : "k8s-logs",
  "cluster_uuid" : "4fuxJ67HSxSBsVDfKIA8Qg",
  "version" : 17,
  "state_uuid" : "PpwhJDXlQvarKzCMhUy2Og",
  "master_node" : "UWRrJRlCQ-uDcqZ3M6Y4YQ",
  "blocks" : { },
  "nodes" : {
    "UWRrJRlCQ-uDcqZ3M6Y4YQ" : {
      "name" : "elastic-cluster31-1",
      "ephemeral_id" : "S3NLgNGrRBOjWuoNC1CcHw",
      "transport_address" : "10.244.166.185:9300",
      "attributes" : {
        "ml.machine_memory" : "3953741824",
        "ml.max_open_jobs" : "20",
        "xpack.installed" : "true"
      }
    },
    "PlT4KVDFSI2qztJqF99eYw" : {
      "name" : "elastic-cluster31-2",
      "ephemeral_id" : "z1akgw8xTjurYdq1_DZ7-Q",
      "transport_address" : "10.244.104.1:9300",
      "attributes" : {
        "ml.machine_memory" : "3953741824",
        "ml.max_open_jobs" : "20",
        "xpack.installed" : "true"
      }
    },
    "XXd95XfcRgW69C1ls0ZFTw" : {
      "name" : "elastic-cluster31-0",
      "ephemeral_id" : "aKjaY6m0TbCTnynDPdD7JA",
      "transport_address" : "10.244.104.2:9300",
      "attributes" : {
        "ml.machine_memory" : "3953741824",
        "ml.max_open_jobs" : "20",
        "xpack.installed" : "true"
      }
    }
  },
  "metadata" : {
    "cluster_uuid" : "4fuxJ67HSxSBsVDfKIA8Qg",
    "cluster_coordination" : {
      "term" : 1,
      "last_committed_config" : [
        "UWRrJRlCQ-uDcqZ3M6Y4YQ",
        "PlT4KVDFSI2qztJqF99eYw",
        "XXd95XfcRgW69C1ls0ZFTw"
      ],
      "last_accepted_config" : [
        "UWRrJRlCQ-uDcqZ3M6Y4YQ",
        "PlT4KVDFSI2qztJqF99eYw",
        "XXd95XfcRgW69C1ls0ZFTw"
      ],
...

其实如果不进行端口映射,在elasticsearch的内部也可以进行访问。可以看到elasticsearch的三个pod,他们之间可以互相发现。

复制代码
[root@master 31efk]# kubectl exec -it elastic-cluster31-0 -n kube-logging31 -- /bin/bash
Defaulted container "elasticsearch" out of: elasticsearch, fix-permissions (init), increase-vm-max-map (init), increase-fd-ulimit (init)
[root@elastic-cluster31-0 elasticsearch]# curl http://localhost:9200/_cat/nodes?v
ip             heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
10.244.166.185           18          95   1    0.13    0.20     0.18 mdi       *      elastic-cluster31-1
10.244.104.1             17          88   0    0.02    0.05     0.08 mdi       -      elastic-cluster31-2
10.244.104.2             23          88   0    0.02    0.05     0.08 mdi       -      elastic-cluster31-0
pv和pvc
复制代码
[root@master 31efk]# kubectl get pv --all-namespaces -owide
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                     STORAGECLASS       REASON   AGE    VOLUMEMODE
pvc-124274e8-1977-4e46-895d-d6b9449682f7   10Gi       RWO            Delete           Bound    kube-logging31/data-elastic-cluster31-1   do-block-storage            145m   Filesystem
pvc-677221e5-ed6a-417b-ac69-6b90304afa4e   10Gi       RWO            Delete           Bound    kube-logging31/data-elastic-cluster31-0   do-block-storage            148m   Filesystem
pvc-944a372c-1c0d-442d-998a-b62c5be7ca21   10Gi       RWO            Delete           Bound    kube-logging31/data-elastic-cluster31-2   do-block-storage            144m   Filesystem
[root@master 31efk]# kubectl get pvc --all-namespaces -owide
NAMESPACE        NAME                       STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE    VOLUMEMODE
kube-logging31   data-elastic-cluster31-0   Bound    pvc-677221e5-ed6a-417b-ac69-6b90304afa4e   10Gi       RWO            do-block-storage   149m   Filesystem
kube-logging31   data-elastic-cluster31-1   Bound    pvc-124274e8-1977-4e46-895d-d6b9449682f7   10Gi       RWO            do-block-storage   145m   Filesystem
kube-logging31   data-elastic-cluster31-2   Bound    pvc-944a372c-1c0d-442d-998a-b62c5be7ca21   10Gi       RWO            do-block-storage   145m   Filesystem
相关推荐
coppher1 小时前
Ubuntu 22.04 amd64 离线安装 Docker 完整教程
linux·docker
虚伪的空想家3 小时前
k8s集群configmap和secrets备份脚本
linux·容器·kubernetes
SXJR3 小时前
k8s中的Pod
云原生·容器·kubernetes
文静小土豆3 小时前
K8s 滚动更新在 Java 应用中的实践与优化
java·容器·kubernetes
w6100104663 小时前
CKA-2026-Ingress
云原生·容器·kubernetes·cka
bloglin999994 小时前
docker logs 如何一直监听日志输出
运维·docker·容器
说实话起个名字真难啊4 小时前
Docker 入门之网络基础
网络·docker·php
❀͜͡傀儡师5 小时前
使用 Docker 部署 Neko 自托管虚拟浏览器(Firefox)
docker·容器·firefox
0xDevNull5 小时前
Linux Docker 安装与使用详细教程
linux·运维·docker
工具罗某人5 小时前
docker compose 部署MySQL InnoDB Cluster + Router 高可用集群-亲测可用
mysql·docker·容器