<返回更多

想学会K8S,DaemonSet很重要!值得收藏

2023-05-08  微信公众号  哪吒编程
加入收藏

今天分享一下【Kube.NETes】 DaemonSet 详解,丰富个人简历,提高面试level,给自己增加一点谈资,秒变面试小达人,BAT不是梦。

三分钟你将学会:

  1. DaemonSet是什么?
  2. DaemonSet的应用场景
  3. DaemonSet 对象详解
  4. DaemonSet的常见问题及解决方案

一、介绍DaemonSet

1、为什么需要DaemonSet

在 Kubernetes 集群中,通常需要在每个节点上运行守护进程来监视节点健康状态、收集日志等,这些守护进程通常称为系统级守护进程,如 Kubernetes Cluster Autoscaler 和 Kubernetes DNS。使用 Deployment 或 StatefulSet 可以创建 Pod,这些 Pod 可以被调度到任何节点上运行,但是在某些情况下,需要确保每个节点上都运行着一个 Pod 副本 版本,即需要使用 DaemonSet。

2、DaemonSet 简介

图片

DaemonSet 是 Kubernetes 中一种类型的控制器对象,用于在每个节点上运行一个 Pod 副本版本,确保每个节点上都有一个或多个 Pod 副本。DaemonSet 控制器可以保证在新增节点时自动在新增的节点上创建 Pod 副本,同时在节点删除时,自动删除该节点上的 Pod 副本。

3、DaemonSet 与其他 Kubernetes 对象的区别

DaemonSet 在运行时,会在集群中的每个节点上创建一个 Pod 副本,而其他的控制器如 Deployment 和 StatefulSet 创建的 Pod,会尽可能地让它们在集群的不同节点上运行。另外,DaemonSet 在节点加入和退出时,会自动处理 Pod 的创建和删除,因此可以保证在整个集群中的每个节点上都运行着一个 Pod 副本,适合用于运行集群服务的 daemon 容器或一些常驻内存的服务。而 Deployment 和 StatefulSet 更适用于部署需要动态扩缩容的应用程序。

图片

对象类型

说明

控制器

Pods数量

Deployment

管理多个 ReplicaSets,用于应用程序的版本控制和滚动升级

控制器

可以控制多个Pods数量

StatefulSet

用于有状态应用程序,例如数据库,确保每个实例具有唯一的网络标识符和稳定的存储

控制器

可以控制多个Pods数量

DaemonSet

用于运行守护进程(如日志收集器),它会在每个工作节点上运行一个副本

控制器

等于节点数量

Job

用于批处理任务,例如数据转换或任务调度

一次性

CronJob

用于定期执行具有固定时间间隔的任务

可以控制多个Pods数量

二、创建DaemonSet

1、使用 kubectl 命令创建 DaemonSet

使用 kubectl 命令创建 DaemonSet 的步骤如下:

(1)使用以下命令创建 YAML 文件:

apiVersion: Apps/v1
kind: DaemonSet
metadata:
  name: example-daemonset
  labels:
    app: example
spec:
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - name: example-container
        image: Nginx

在此示例中,我们创建了一个名为 "example-daemonset" 的 DaemonSet,并使用 Nginx 容器作为模板。请注意,标签 "app: example" 在这里起到关键作用,因为它将用于选择要运行此 DaemonSet 的节点。

(2)使用以下命令创建 DaemonSet:

kubectl create -f example-daemonset.yaml

这将使用先前创建的 YAML 文件创建 DaemonSet。您可以通过使用以下命令来验证是否已创建 DaemonSet:

kubectl get daemonsets

如果您看到 "example-daemonset",则表示 DaemonSet 已成功创建。

2、使用 YAML 文件创建DaemonSet

要使用 YAML 文件创建 DaemonSet,请执行以下步骤:

(1)创建一个 YAML 文件并使用以下内容:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: example-daemonset
  labels:
    app: example
spec:
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - name: example-container
        image: nginx

在此示例中,我们创建了一个名为 "example-daemonset" 的 DaemonSet,并使用 Nginx 容器作为模板。请注意,标签 "app: example" 在这里起到关键作用,因为它将用于选择要运行此 DaemonSet 的节点。

(2)使用以下命令创建 DaemonSet:

kubectl apply -f example-daemonset.yaml

这将使用先前创建的 YAML 文件创建 DaemonSet。您可以通过使用以下命令来验证是否已创建 DaemonSet:

kubectl get daemonsets

如果您看到 "example-daemonset",则表示 DaemonSet 已成功创建。

3、使用 Terraform 创建 DaemonSet

使用 Terraform 创建 DaemonSet 是一种自动化部署和管理 Kubernetes 应用程序的方法。Terraform 是一种基础设施即代码工具,允许您编写代码来定义和管理基础设施。

要使用 Terraform 创建 DaemonSet,您需要做以下几步:

  1. 安装 Terraform 工具:请根据您的操作系统在 Terraform 官方网站(https://www.terraform.io/downloads.html)上查找相应的安装指南。
  2. 创建一个 Terraform 项目:在一个新的目录中,创建一个 main.tf 文件,并添加以下内容。
provider "kubernetes" {
  config_context_cluster = "my-k8s-cluster"
}

resource "kubernetes_daemonset" "my-daemonset" {
  metadata {
    name = "my-daemonset"
  }

  spec {
    selector {
      match_labels = {
        app = "my-daemonset"
      }
    }

    template {
      metadata {
        labels = {
          app = "my-daemonset"
        }
      }

      spec {
        containers {
          name = "my-container"
          image = "nginx:1.19.0-alpine"
          ports {
            name = "http"
            container_port = 80
          }
          volume_mounts {
            name = "html"
            mount_path = "/usr/share/nginx/html"
          }
        }

        volumes {
          name = "html"
          config_map {
            name = "my-daemonset-configmap"
            items {
              key = "index.html"
              path = "index.html"
            }
          }
        }
      }
    }
  }
}

此代码将创建一个名为 my-daemonset 的 DaemonSet,该 DaemonSet 包含一个名为 my-container 的容器,并使用 Nginx 映像。

(3)初始化 Terraform 项目:使用以下命令初始化 Terraform 项目。

$ terraform init

(4)配置 Terraform 项目:使用以下命令配置 Terraform 项目。

$ terraform apply

此命令将使用 Terraform 创建 DaemonSet。

三、DaemonSet的应用场景

1、在节点上部署系统级守护进程

DaemonSet 最常见的应用场景之一是在节点上部署系统级守护进程。例如,Kubernetes 官方提供的 kube-proxy 和 kube-dns 组件都是以 DaemonSet 的形式运行在每个节点上的。这些组件是 Kubernetes 集群中非常重要的系统级进程,需要在每个节点上运行,以确保 Kubernetes 集群的正常运行。

图片

以下是部署 kube-proxy DaemonSet 的示例 YAML 文件:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-proxy
  namespace: kube-system
  labels:
    k8s-app: kube-proxy
spec:
  selector:
    matchLabels:
      k8s-app: kube-proxy
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        k8s-app: kube-proxy
    spec:
      containers:
      - name: kube-proxy
        image: k8s.gcr.io/kube-proxy:v1.22.0
        securityContext:
          privileged: true
        command:
        - /usr/local/bin/kube-proxy
        args:
        - --cnotallow=/var/lib/kube-proxy/config.conf
        volumeMounts:
        - name: kube-proxy-config
          mountPath: /var/lib/kube-proxy
      volumes:
      - name: kube-proxy-config
        configMap:
          name: kube-proxy

在这个 YAML 文件中,我们使用 apps/v1 API 版本创建了一个名为 kube-proxy 的 DaemonSet。它的 selector 字段指定了需要运行这个 DaemonSet 的 Pod 的标签,updateStrategy 指定了更新策略,这里使用的是滚动更新。template 字段定义了 Pod 的模板,包括容器、挂载的卷和命令参数等。

2、在节点上运行普通容器

在 Kubernetes 集群中,通常有许多需要在每个节点上运行的容器,例如日志收集代理、监控代理、安全代理等。使用 DaemonSet 控制器,可以方便地在每个节点上运行这些容器。

图片

下面是一个运行 fluentd 日志收集代理的 DaemonSet 的示例 YAML 文件:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  selector:
    matchLabels:
      name: fluentd
  template:
    metadata:
      labels:
        name: fluentd
    spec:
      containers:
      - name: fluentd
        image: fluent/fluentd:v1.7-1
        volumeMounts:
        - name: varlog
          mountPath: /var/log
      volumes:
      - name: varlog
        hostPath:
          path: /var/log

在上面的 YAML 文件中,我们定义了一个名为 fluentd 的 DaemonSet。该 DaemonSet 会在每个节点上运行一个名为 fluentd 的容器。

该容器使用 fluent/fluentd:v1.7-1 镜像,并将主机节点上的 /var/log 目录挂载到容器中的 /var/log 目录下。这样,该容器就可以从节点上的日志文件中收集日志。

3、维护集群状态

另一个常见的 DaemonSet 应用场景是维护集群状态。在 Kubernetes 集群中,有许多需要在每个节点上运行的控制器,例如网络插件、存储插件、DNS 插件等。这些控制器通常需要在每个节点上运行,以维护集群状态。

图片

例如,CNI(Container Network Interface)插件负责为 Kubernetes 集群中的容器分配 IP 地址和路由信息,因此需要在每个节点上运行。Kubernetes 官方提供的 CNI 插件就是以 DaemonSet 的形式运行在每个节点上的。

下面是部署 CNI 插件的示例 YAML 文件:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds-amd64
  namespace: kube-system
  labels:
    tier: node
    app: flannel
spec:
  selector:
    matchLabels:
      app: flannel
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: flannel
    spec:
      containers:
      - name: kube-flannel
        image: quay.io/coreos/flannel:v0.14.0
        command:
        - /opt/bin/flanneld
        args:
        - --ip-masq
        - --kube-subnet-mgr
        - --iface=enp0s8  # 这里需要根据实际网络接口修改
        securityContext:
          privileged: true
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: flannel-cfg
          mountPath: /etc/kube-flannel/
      hostNetwork: true
      volumes:
      - name: flannel-cfg
        configMap:
          name: kube-flannel-cfg

在这个 YAML 文件中,我们使用 apps/v1 API 版本创建了一个名为 kube-flannel-ds-amd64 的 DaemonSet。它的 selector 字段指定了需要运行这个 DaemonSet 的 Pod 的标签,updateStrategy 指定了更新策略,这里使用的是滚动更新。template 字段定义了 Pod 的模板,包括容器、挂载的卷和命令参数等。

这个 YAML 文件中定义了一个名为 kube-flannel 的容器,使用 quay.io/coreos/flannel:v0.14.0 镜像,并将容器的网络接口设置为 enp0s8。该容器还从 configMap 挂载了配置文件,并开启了特权模式。

4、在节点上运行工具

除了守护进程、普通容器和控制器之外,还可以使用 DaemonSet 在每个节点上运行工具。这些工具通常用于调试、监控和诊断集群状态。

图片

例如,使用 DaemonSet在每个节点上运行诊断工具的示例 YAML 文件如下所示:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: diagnostic-tool
spec:
  selector:
    matchLabels:
      app: diagnostic-tool
  template:
    metadata:
      labels:
        app: diagnostic-tool
    spec:
      containers:
      - name: diagnostic-tool
        image: your-Docker-image
        command:
        - sh
        - -c
        - |
          while true; do
            # do some diagnostic tasks
            sleep 60
          done
        volumeMounts:
        - name: host-var-run
          mountPath: /host/var/run
          readOnly: true
      volumes:
      - name: host-var-run
        hostPath:
          path: /var/run

在这个 YAML 文件中,我们定义了一个名为 diagnostic-tool 的 DaemonSet。该 DaemonSet 会在每个节点上运行一个名为 diagnostic-tool 的容器。

该容器使用一个自定义的 Docker 镜像,并执行一个 while 循环,在其中执行一些诊断任务。此外,容器还将节点上的 /var/run 目录挂载到容器中的 /host/var/run 目录下,以便读取节点上的运行时信息。

使用 DaemonSet 运行诊断工具可以快速定位节点和集群级别的问题,例如网络问题、存储问题和性能问题等。

四、DaemonSet 对象详解

1、DaemonSet的结构及其各个部分的作用

DaemonSet 是 Kubernetes 中一种类型的控制器对象,用于在每个节点上运行一个 Pod 副本版本,确保每个节点上都有一个或多个 Pod 副本。DaemonSet 控制器可以保证在新增节点时自动在新增的节点上创建 Pod 副本,同时在节点删除时,自动删除该节点上的 Pod 副本。

图片

在 DaemonSet 对象中,有以下几个部分:

其中,spec 部分是 DaemonSet 对象中最重要的部分,它包含了以下几个字段:

2、DaemonSet 的生命周期

图片

DaemonSet 的生命周期包括以下几个阶段:

  1. 创建 DaemonSet:使用 kubectl apply 或 kubectl create 命令创建一个 DaemonSet 对象。
  2. DaemonSet 控制器创建 Pod:当 DaemonSet 被创建时,DaemonSet 控制器会根据 Pod 模板创建 Pod 副本,并在每个节点上运行一个 Pod 副本。
  3. 新节点加入集群:当新的节点加入集群时,DaemonSet 控制器会自动在新节点上创建一个 Pod 副本,确保每个节点上都有一个 Pod 副本。
  4. 节点被删除:当一个节点被删除时,DaemonSet 控制器会自动删除该节点上的 Pod 副本,以确保每个节点上都有一个 Pod 副本。
  5. 更新 DaemonSet:当需要更新 DaemonSet 时,可以使用 kubectl apply 或 kubectl edit 命令修改 DaemonSet 对象的配置。这会导致 DaemonSet 控制器创建新的 Pod 副本,并逐步替换旧的 Pod 副本,以确保每个节点上都有一个新的 Pod 副本。
  6. 删除 DaemonSet:当不再需要 DaemonSet 时,可以使用 kubectl delete 命令删除 DaemonSet 对象。此时,DaemonSet 控制器会删除所有的 Pod 副本。

3、DaemonSet 的选择器

选择器是 DaemonSet 对象的一部分,用于确定在哪些节点上运行该 DaemonSet 的 Pod 副本。我们可以使用 Pod 模板中的标签或注释,或者在 DaemonSet 对象的选择器中指定标签或注释,来确定选择器。

以下是一个示例 DaemonSet YAML 文件,其中使用标签选择器来确定在哪些节点上运行该 DaemonSet 的 Pod 副本:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: my-daemonset
  labels:
    app: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-container
          image: my-image
          command: [ "sh", "-c", "echo Hello from the DaemonSet pod && sleep 3600" ]
      nodeSelector:
        disktype: ssd

在这个示例中,我们使用 nodeSelector 来指定只在磁盘类型为 ssd 的节点上运行该 DaemonSet 的 Pod 副本。

4、DaemonSet 的更新策略

更新策略用于确定如何更新 DaemonSet 对象的 Pod 副本。在 Kubernetes 中,有以下三种更新策略可供选择:

  1. RollingUpdate:滚动更新。这是默认的更新策略。它允许您将 DaemonSet 的 Pod 副本版本逐个更新。即首先更新一个节点上的 Pod,然后等待它的更新成功后再更新下一个节点上的 Pod,以此类推。这种策略确保了在更新期间至少有一个 Pod 副本可用,从而最小化了服务的中断时间。
  2. OnDelete:当 DaemonSet 对象的 Pod 副本有更新时,不会自动对旧的 Pod 副本进行更新。相反,旧的 Pod 副本将在删除后自动被新的 Pod 副本替换。这种策略适用于不需要连续更新的应用程序。
  3. Pause:暂停更新。这种策略将停止 DaemonSet 的自动更新,直到您手动恢复更新。这种策略适用于需要手动控制更新过程的应用程序。

更新策略可以在 DaemonSet 对象的 spec 字段中进行配置。以下是一个使用 RollingUpdate 策略的 DaemonSet 示例:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nginx-daemonset
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
      terminationGracePeriodSeconds: 30
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1

在这个 YAML 文件中,我们定义了一个名为 nginx-daemonset 的 DaemonSet。该 DaemonSet 会在每个节点上运行一个名为 nginx 的容器。

该容器使用了最新版本的 Nginx 镜像。容器在终止时有 30 秒的 grace period,以确保正在进行的请求可以完成。

该 DaemonSet 对象使用 RollingUpdate 策略,并指定了 maxUnavailable 选项,该选项指定了在更新期间最多允许一个 Pod 副本不可用。这确保了在更新期间始终有至少一个 Pod 副本可用。

五、DaemonSet 的常见问题及解决方案

1、容器无法在节点上创建

(1)问题描述

当您创建 DaemonSet 时,您可能会遇到以下错误:

Error creating: pods "XXX" is forbidden: node "YYY" cannot be used because it is unschedulable

这个错误消息表示,调度程序无法在某个节点上安排 DaemonSet Pod 的运行。通常,这是因为节点处于不可调度的状态,例如它被标记为“已维护”或“故障”。

(2)解决方案

图片

要解决这个问题,您需要检查节点的状态。您可以使用以下命令来检查节点的状态:

kubectl get nodes

如果节点的状态是“维护”或“故障”,您需要将其恢复为可用状态。您可以使用以下命令来将节点重新调度:

kubectl uncordon <node-name>

2、更新失败

(1)问题描述

当您更新 DaemonSet 时,您可能会遇到以下错误:

Update failed. First seen error: error updating status for daemonset

这个错误消息表示,DaemonSet 更新失败。通常,这是因为某个节点上的 Pod 处于不可用状态,例如节点故障或容器崩溃。

(2)解决方案

图片

要解决这个问题,您需要检查节点和 Pod 的状态。您可以使用以下命令来检查节点和 Pod 的状态:

kubectl get nodes
kubectl get pods -n <namespace>

如果您发现节点或 Pod 处于不可用状态,您需要将其恢复为可用状态。您可以使用以下命令来重新启动节点或 Pod:

kubectl delete pod <pod-name> -n <namespace>

3、网络配置问题

(1)问题描述

当您创建 DaemonSet 时,您可能会遇到以下错误:

Failed to create pod: <pod-name>
Error syncing pod

这个错误消息表示,Pod 同步失败。通常,这是因为网络配置不正确。

(2)解决方案

要解决这个问题,您需要检查网络配置。您可以使用以下命令来检查网络配置:

kubectl describe pod <pod-name> -n <namespace>

如果您发现网络配置不正确,您需要更新它。您可以使用以下命令来更新网络配置:

kubectl edit pod <pod-name> -n <namespace>
 

4、如何监视 DaemonSet 运行状态

在 Kubernetes 中,监视 DaemonSet 的运行状态可以通过以下几种方式实现:

(1)使用 kubectl 命令行工具

kubectl 命令行工具提供了多种监视 DaemonSet 运行状态的命令,如下所示:

(2)使用 Kubernetes Dashboard

Kubernetes Dashboard 提供了一个用户友好的 Web 界面,可用于监视 DaemonSet 的运行状态。在 Kubernetes Dashboard 中,可以查看所有 DaemonSet 和它们的 Pod,还可以查看各个 Pod 的详细信息,包括 Pod 的日志输出。

(3)使用 Prometheus 和 Grafana

Prometheus 和 Grafana 是流行的监视和指标收集工具,可以用于监视 DaemonSet 的运行状态。通过 Prometheus 收集集群中的指标,使用 Grafana 可视化这些指标。可视化的指标包括 DaemonSet 的 Pod 数量、节点上的 CPU 使用情况和内存使用情况等。

5、如何排除问题和调试

在使用 DaemonSet 过程中,可能会遇到各种问题。以下是一些常见的问题及其解决方案。

(1)Pod 处于 Pending 状态

当 DaemonSet 中的 Pod 处于 Pending 状态时,有以下几种可能的原因:

(2)Pod 启动失败

当 DaemonSet 中的 Pod 启动失败时,有以下几种可能的原因:

(3)Pod 运行时错误

当 DaemonSet 中的 Pod 运行时出现错误时,有以下几种可能的原因:

(4)如何排除问题和调试

在排除问题和调试时,可以使用以下方法:

本文转载自微信公众号「哪吒编程

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>