首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法在kubernetes上部署EFK堆栈(使用kubespray)

无法在kubernetes上部署EFK堆栈(使用kubespray)
EN

Stack Overflow用户
提问于 2020-06-08 01:05:54
回答 1查看 775关注 0票数 2

我试图在生产kubernetes集群上部署EFK堆栈(使用kubespray安装),我们有3个节点,1个主服务器+2个工作人员,我需要使用elasticsearch作为状态集,并使用主节点中的本地文件夹来存储日志(用于持久的本地存储),我的配置是:

代码语言:javascript
复制
kind: Namespace
apiVersion: v1
metadata:
  name: kube-logging

---
kind: Service
apiVersion: v1
metadata:
  name: elasticsearch
  namespace: kube-logging
  labels:
    app: elasticsearch
spec:
  selector:
    app: elasticsearch
  clusterIP: None
  ports:
    - port: 9200
      name: rest
    - port: 9300
      name: inter-node
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
  namespace: kube-logging
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: my-pv
  namespace: kube-logging
spec:
  storageClassName: local-storage
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteOnce
  hostPath:
    path: /tmp/elastic
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: es-cluster
  namespace: kube-logging
spec:
  serviceName: elasticsearch
  replicas: 2
  selector:
    matchLabels:
      app: elasticsearch
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
      - name: elasticsearch
        image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0
        resources:
            limits:
              cpu: 1000m
              memory: 2Gi
        ports:
        - containerPort: 9200
          name: rest
          protocol: TCP
        - containerPort: 9300
          name: inter-node
          protocol: TCP
        volumeMounts:
        - name: data
          mountPath: /usr/share/elasticsearch/data
        env:
          - name: cluster.name
            value: k8s-logs
          - name: node.name
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: discovery.seed_hosts
            value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"
          - name: cluster.initial_master_nodes
            value: "es-cluster-0,es-cluster-1,es-cluster-2"
          - name: ES_JAVA_OPTS
            value: "-Xms512m -Xmx512m"
      initContainers:
      - name: fix-permissions
        image: busybox
        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
        command: ["sysctl", "-w", "vm.max_map_count=262144"]
        securityContext:
          privileged: true
      - name: increase-fd-ulimit
        image: busybox
        command: ["sh", "-c", "ulimit -n 65536"]
        securityContext:
          privileged: true
  volumeClaimTemplates:
  - metadata:
      name: data
      labels:
        app: elasticsearch
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: local-storage
      resources:
        requests:
          storage: 5Gi
---

这是我的配置,但当它被应用时,弹力搜索的两个吊舱之一仍然处于待定状态。当我为这个荚描述kubectl时,这是我得到的错误:“1个节点没有找到可用的持久卷来绑定。”

我的配置正确吗?我必须使用PV +存储库+ volumeClaimTemplates吗?提前谢谢你。

这些是我的成果:

代码语言:javascript
复制
    [root@node1 nex]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                            STORAGECLASS    REASON   AGE
my-pv   5Gi        RWO            Retain           Bound    kube-logging/data-es-cluster-0   local-storage            24m
[root@node1 nex]# kubectl get pvc
NAME                STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS    AGE
data-es-cluster-0   Bound     my-pv    5Gi        RWO            local-storage   24m
data-es-cluster-1   Pending                                      local-storage   23m
[root@node1 nex]# kubectl describe pvc data-es-cluster-0
Name:          data-es-cluster-0
Namespace:     kube-logging
StorageClass:  local-storage
Status:        Bound
Volume:        my-pv
Labels:        app=elasticsearch
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      5Gi
Access Modes:  RWO
VolumeMode:    Filesystem
Mounted By:    es-cluster-0
Events:
  Type    Reason                Age   From                         Message
  ----    ------                ----  ----                         -------
  Normal  WaitForFirstConsumer  24m   persistentvolume-controller  waiting for first consumer to be created before binding
[root@node1 nex]# kubectl describe pvc data-es-cluster-1
Name:          data-es-cluster-1
Namespace:     kube-logging
StorageClass:  local-storage
Status:        Pending
Volume:
Labels:        app=elasticsearch
Annotations:   <none>
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode:    Filesystem
Mounted By:    es-cluster-1
Events:
  Type    Reason                Age                   From                         Message
  ----    ------                ----                  ----                         -------
  Normal  WaitForFirstConsumer  4m12s (x82 over 24m)  persistentvolume-controller  waiting for first consumer to be created before binding
[root@node1 nex]#
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-09 20:57:45

我的配置正确吗?我必须使用PV +存储库+ volumeClaimTemplates吗?提前谢谢你。

除了@Arghya在他的回答中已经提出的建议之外,我还想在您当前的设置中强调一件事情。

如果您认为您的Elasticsearch Pods只会调度在一个特定的节点上(在您的例子中是您的主节点),那么您仍然可以使用本地卷类型。但是,不要将其与hostPath混淆。在您的PV定义中,我注意到您使用了hostPath键,因此很可能您还没有完全意识到这两个概念之间的差异。虽然它们非常相似,但本地类型比hostPath具有更大的功能和一些不可否认的优势。

正如您可以在文档中看到的那样

本地卷表示安装的本地存储设备,如磁盘、分区或目录。

因此,这意味着,除了特定的目录之外,您还可以挂载本地磁盘或分区(/dev/sdb/dev/sdb5等)。它可以是一个具有严格定义容量的LVM分区。请记住,在挂载本地目录时,您无法强制执行实际使用的容量,因此即使定义了5Gi,即使超出了这个值,也可以将日志写入本地目录。但是logical volume的情况并非如此,因为您可以定义它的容量,并确保它不会占用比您提供的更多的磁盘空间。

第二个区别是:

hostPath卷相比,local卷可以以一种持久和可移植的方式使用,而无需手动将Pods调度到节点,因为系统通过查看PersistentVolume上的节点关联来了解卷的节点约束。

在本例中,是PersistentVolume定义了节点关联,因此使用后续local-storage存储类和相应PersistenVolume的任何Pod (可以由StatefulSet管理)都将自动调度到正确的节点上。

正如您可以进一步阅读的那样,nodeAffinity实际上是此类PV中所需的字段。

使用本地卷时需要PersistentVolume nodeAffinity。它使Kubernetes调度程序能够使用本地卷正确地调度Pods到正确的节点。

据我所知,您的kubernetes集群是在本地/在前提下建立的。在这种情况下,NFS可能是一个正确的选择。

如果您使用了一些云环境,那么您可以使用特定云提供商(如GCEPersistentDiskAWSElasticBlockStore )提供的持久存储。库伯奈特斯目前支持的持久卷类型的完整列表,您可以找到这里

因此,同样,如果您担心StatefulSet中的节点级冗余,并且希望您的2 Elasticsearch Pods总是被调度在不同的节点上,就像@Arghya已经建议的那样,使用NFS或其他一些非本地存储。

但是,如果您不关心节点级的冗余,而且您完全同意两个Elasticsearch Pods都运行在同一个节点上(在您的示例中是节点),请跟随我:)

正如@Arghya Sadhu正确指出的那样:

即使已经绑定到PVC的PV有备用容量,也不能再绑定到另一个PVC,因为它是PV和PVC之间的一对一映射。

虽然PVPVC之间总是一对一的映射,但这并不意味着您不能在许多Pods中使用单个PVC

注意,在您的StatefulSet示例中,您使用了volumeClaimTemplates,这基本上意味着,每次创建由StatefulSet管理的新Pod时,都会根据该模板创建一个新的相应的PersistentVolumeClaim。因此,如果您定义了例如10Gi PersistentVolume,那么无论您在声明中请求所有10Gi还是其中的一半,只有第一个PVC才能成功地绑定到您的PV

但是,与使用volumeClaimTemplates和为每个有状态Pod创建单独的PVC不同,您可以让它们使用单个手动定义的PVC。请查看以下示例:

我们首先需要的是一个存储类。它看起来非常类似于您的客户中的一个:

代码语言:javascript
复制
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

这个设置和您的设置之间的第一个区别是在PV定义中。我们使用的不是hostPath,而是本地卷:

代码语言:javascript
复制
apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /var/tmp/test ### path on your master node
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - your-master-node-name

注意,除了定义local路径之外,我们还定义了nodeAffinity规则,以确保获得此特定PV的所有Pods都将自动调度在主节点上。

然后我们就有了手动应用的PVC

代码语言:javascript
复制
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 10Gi
  storageClassName: local-storage

这个PVC现在可以用于由StatefulSet管理的所有Pods (在您的示例2中)。

代码语言:javascript
复制
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 2 # by default is 1
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: mypd
          mountPath: /usr/share/nginx/html
      volumes:
      - name: mypd
        persistentVolumeClaim:
          claimName: myclaim

请注意,在上面的示例中,我们不再使用volumeClaimTemplates,而是使用一个单独的PersistentVolumeClaim,它可以被我们所有的Pods使用。豆荚仍然是唯一的,因为它们是由StatefulSet管理的,但是它们使用的不是唯一的PVCs,而是通用的。由于这种方法,两个Pods可以同时将日志写入单个卷。

在我的示例中,我使用了nginx服务器,使每个想要快速尝试它的人都能尽可能轻松地复制,但我相信您可以很容易地根据您的需要调整它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62253584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档