十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
作者:哪吒 2023-05-08 08:11:55
云计算
云原生 在 Kubernetes 集群中,通常需要在每个节点上运行守护进程来监视节点健康状态、收集日志等,这些守护进程通常称为系统级守护进程,如 Kubernetes Cluster Autoscaler 和 Kubernetes DNS。 

今天分享一下【Kubernetes】 DaemonSet 详解,丰富个人简历,提高面试level,给自己增加一点谈资,秒变面试小达人,BAT不是梦。
三分钟你将学会:
在 Kubernetes 集群中,通常需要在每个节点上运行守护进程来监视节点健康状态、收集日志等,这些守护进程通常称为系统级守护进程,如 Kubernetes Cluster Autoscaler 和 Kubernetes DNS。使用 Deployment 或 StatefulSet 可以创建 Pod,这些 Pod 可以被调度到任何节点上运行,但是在某些情况下,需要确保每个节点上都运行着一个 Pod 副本 版本,即需要使用 DaemonSet。
DaemonSet 是 Kubernetes 中一种类型的控制器对象,用于在每个节点上运行一个 Pod 副本版本,确保每个节点上都有一个或多个 Pod 副本。DaemonSet 控制器可以保证在新增节点时自动在新增的节点上创建 Pod 副本,同时在节点删除时,自动删除该节点上的 Pod 副本。
DaemonSet 在运行时,会在集群中的每个节点上创建一个 Pod 副本,而其他的控制器如 Deployment 和 StatefulSet 创建的 Pod,会尽可能地让它们在集群的不同节点上运行。另外,DaemonSet 在节点加入和退出时,会自动处理 Pod 的创建和删除,因此可以保证在整个集群中的每个节点上都运行着一个 Pod 副本,适合用于运行集群服务的 daemon 容器或一些常驻内存的服务。而 Deployment 和 StatefulSet 更适用于部署需要动态扩缩容的应用程序。
| 对象类型 | 说明 | 控制器 | Pods数量 | 
| Deployment | 管理多个 ReplicaSets,用于应用程序的版本控制和滚动升级 | 控制器 | 可以控制多个Pods数量 | 
| StatefulSet | 用于有状态应用程序,例如数据库,确保每个实例具有唯一的网络标识符和稳定的存储 | 控制器 | 可以控制多个Pods数量 | 
| DaemonSet | 用于运行守护进程(如日志收集器),它会在每个工作节点上运行一个副本 | 控制器 | 等于节点数量 | 
| Job | 用于批处理任务,例如数据转换或任务调度 | 无 | 一次性 | 
| CronJob | 用于定期执行具有固定时间间隔的任务 | 无 | 可以控制多个Pods数量 | 
使用 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 已成功创建。
要使用 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 已成功创建。
使用 Terraform 创建 DaemonSet 是一种自动化部署和管理 Kubernetes 应用程序的方法。Terraform 是一种基础设施即代码工具,允许您编写代码来定义和管理基础设施。
要使用 Terraform 创建 DaemonSet,您需要做以下几步:
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 最常见的应用场景之一是在节点上部署系统级守护进程。例如,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 的模板,包括容器、挂载的卷和命令参数等。
在 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 目录下。这样,该容器就可以从节点上的日志文件中收集日志。
另一个常见的 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 挂载了配置文件,并开启了特权模式。
除了守护进程、普通容器和控制器之外,还可以使用 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 是 Kubernetes 中一种类型的控制器对象,用于在每个节点上运行一个 Pod 副本版本,确保每个节点上都有一个或多个 Pod 副本。DaemonSet 控制器可以保证在新增节点时自动在新增的节点上创建 Pod 副本,同时在节点删除时,自动删除该节点上的 Pod 副本。
在 DaemonSet 对象中,有以下几个部分:
其中,spec 部分是 DaemonSet 对象中最重要的部分,它包含了以下几个字段:
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 副本。
更新策略用于确定如何更新 DaemonSet 对象的 Pod 副本。在 Kubernetes 中,有以下三种更新策略可供选择:
更新策略可以在 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 时,您可能会遇到以下错误:
Error creating: pods "XXX" is forbidden: node "YYY" cannot be used because it is unschedulable这个错误消息表示,调度程序无法在某个节点上安排 DaemonSet Pod 的运行。通常,这是因为节点处于不可调度的状态,例如它被标记为“已维护”或“故障”。
要解决这个问题,您需要检查节点的状态。您可以使用以下命令来检查节点的状态:
kubectl get nodes如果节点的状态是“维护”或“故障”,您需要将其恢复为可用状态。您可以使用以下命令来将节点重新调度:
kubectl uncordon 当您更新 DaemonSet 时,您可能会遇到以下错误:
Update failed. First seen error: error updating status for daemonset这个错误消息表示,DaemonSet 更新失败。通常,这是因为某个节点上的 Pod 处于不可用状态,例如节点故障或容器崩溃。
要解决这个问题,您需要检查节点和 Pod 的状态。您可以使用以下命令来检查节点和 Pod 的状态:
kubectl get nodes
kubectl get pods -n 如果您发现节点或 Pod 处于不可用状态,您需要将其恢复为可用状态。您可以使用以下命令来重新启动节点或 Pod:
kubectl delete pod  -n  当您创建 DaemonSet 时,您可能会遇到以下错误:
Failed to create pod: 
Error syncing pod 这个错误消息表示,Pod 同步失败。通常,这是因为网络配置不正确。
要解决这个问题,您需要检查网络配置。您可以使用以下命令来检查网络配置:
kubectl describe pod  -n  如果您发现网络配置不正确,您需要更新它。您可以使用以下命令来更新网络配置:
kubectl edit pod  -n  在 Kubernetes 中,监视 DaemonSet 的运行状态可以通过以下几种方式实现:
kubectl 命令行工具提供了多种监视 DaemonSet 运行状态的命令,如下所示:
Kubernetes Dashboard 提供了一个用户友好的 Web 界面,可用于监视 DaemonSet 的运行状态。在 Kubernetes Dashboard 中,可以查看所有 DaemonSet 和它们的 Pod,还可以查看各个 Pod 的详细信息,包括 Pod 的日志输出。
Prometheus 和 Grafana 是流行的监视和指标收集工具,可以用于监视 DaemonSet 的运行状态。通过 Prometheus 收集集群中的指标,使用 Grafana 可视化这些指标。可视化的指标包括 DaemonSet 的 Pod 数量、节点上的 CPU 使用情况和内存使用情况等。
在使用 DaemonSet 过程中,可能会遇到各种问题。以下是一些常见的问题及其解决方案。
当 DaemonSet 中的 Pod 处于 Pending 状态时,有以下几种可能的原因:
当 DaemonSet 中的 Pod 启动失败时,有以下几种可能的原因:
当 DaemonSet 中的 Pod 运行时出现错误时,有以下几种可能的原因:
在排除问题和调试时,可以使用以下方法:
本文转载自微信公众号「哪吒编程」,可以通过以下二维码关注。转载本文请联系哪吒编程公众号。