[单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
相关推荐
wuxingge2 小时前
k8s1.30.0高可用集群部署
云原生·容器·kubernetes
志凌海纳SmartX3 小时前
趋势洞察|AI 能否带动裸金属 K8s 强势崛起?
云原生·容器·kubernetes
锅总3 小时前
nacos与k8s service健康检查详解
云原生·容器·kubernetes
BUG弄潮儿3 小时前
k8s 集群安装
云原生·容器·kubernetes
意疏3 小时前
【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行
linux·docker
墨鸦_Cormorant3 小时前
使用docker快速部署Nginx、Redis、MySQL、Tomcat以及制作镜像
redis·nginx·docker
Code_Artist4 小时前
Docker镜像加速解决方案:配置HTTP代理,让Docker学会科学上网!
docker·云原生·容器
颜淡慕潇5 小时前
【K8S系列】kubectl describe pod显示ImagePullBackOff,如何进一步排查?
后端·云原生·容器·kubernetes
wanmei0025 小时前
Dockerfile复制目录进入镜像里
docker
inter_peng5 小时前
[Docker-显示所有容器IP] 显示docker-compose.yml中所有容器IP的方法
tcp/ip·docker·eureka