龙空技术网

【Kubernetes】 DaemonSet 详解

小心程序猿QAQ 271

前言:

如今兄弟们对“ssdbnginx”可能比较着重,兄弟们都想要分析一些“ssdbnginx”的相关文章。那么小编同时在网络上搜集了一些关于“ssdbnginx””的相关内容,希望同学们能喜欢,兄弟们快快来学习一下吧!

一、介绍DaemonSet1.1 为什么需要DaemonSet

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

1.2 DaemonSet 简介

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

1.3 DaemonSet 与其他 Kubernetes 对象的区别

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

对象类型

说明

控制器

Pods数量

Deployment

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

控制器

可以控制多个Pods数量

StatefulSet

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

控制器

可以控制多个Pods数量

DaemonSet

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

控制器

等于节点数量

Job

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

一次性

CronJob

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

可以控制多个Pods数量

二、创建DaemonSet1.1 使用 kubectl 命令创建 DaemonSet

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

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

apiVersion: apps/v1kind: DaemonSetmetadata:  name: example-daemonset  labels:    app: examplespec:  selector:    matchLabels:      app: example  template:    metadata:      labels:        app: example    spec:      containers:      - name: example-container        image: nginx复制代码

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

使用以下命令创建 DaemonSet:

kubectl create -f example-daemonset.yaml复制代码

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

kubectl get daemonsets复制代码

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

1.2 使用 YAML 文件创建DaemonSet

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

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

apiVersion: apps/v1kind: DaemonSetmetadata:  name: example-daemonset  labels:    app: examplespec:  selector:    matchLabels:      app: example  template:    metadata:      labels:        app: example    spec:      containers:      - name: example-container        image: nginx复制代码

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

使用以下命令创建 DaemonSet:

kubectl apply -f example-daemonset.yaml复制代码

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

kubectl get daemonsets复制代码

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

1.3 使用 Terraform 创建 DaemonSet

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

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

安装 Terraform 工具:请根据您的操作系统在 Terraform 官方网站(…创建一个 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 映像。

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

$ terraform init复制代码
配置 Terraform 项目:使用以下命令配置 Terraform 项目。
$ terraform apply复制代码

此命令将使用 Terraform 创建 DaemonSet。

三、DaemonSet的应用场景1.1 在节点上部署系统级守护进程

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

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

apiVersion: apps/v1kind: DaemonSetmetadata:  name: kube-proxy  namespace: kube-system  labels:    k8s-app: kube-proxyspec:  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:        - --config=/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 的模板,包括容器、挂载的卷和命令参数等。

1.2 在节点上运行普通容器

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

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

apiVersion: apps/v1kind: DaemonSetmetadata:  name: fluentdspec:  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 目录下。这样,该容器就可以从节点上的日志文件中收集日志。

1.3 维护集群状态

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

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

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

apiVersion: apps/v1kind: DaemonSetmetadata:  name: kube-flannel-ds-amd64  namespace: kube-system  labels:    tier: node    app: flannelspec:  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 挂载了配置文件,并开启了特权模式。

1.4 在节点上运行工具

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

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

apiVersion: apps/v1kind: DaemonSetmetadata:  name: diagnostic-toolspec:  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.1 DaemonSet的结构及其各个部分的作用

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

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

metadata:元数据部分包含了对象的名称、命名空间、标签等信息。spec:规格部分包含了 DaemonSet 对象的规格,如选择器、Pod 模板等。status:状态部分包含了 DaemonSet 对象的当前状态信息,如运行中的 Pod 数量等。

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

selector:指定了哪些节点需要运行 Pod 副本。可以使用节点标签选择器指定节点的标签,也可以使用节点名称选择器指定节点的名称。template:指定了要运行在节点上的 Pod 模板。模板中可以指定容器镜像、启动命令等信息。updateStrategy:指定了 DaemonSet 的更新策略。默认情况下,DaemonSet 会在每个节点上运行一个 Pod 副本,如果需要更新 Pod 版本,则会逐个节点进行更新。可以使用 RollingUpdate 策略实现平滑的更新过程,也可以使用 OnDelete 策略实现在节点删除时更新 Pod 版本。1.2 DaemonSet 的生命周期

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

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

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

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

apiVersion: apps/v1kind: DaemonSetmetadata:  name: my-daemonset  labels:    app: my-appspec:  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 副本。

1.3 DaemonSet 的更新策略

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

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

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

apiVersion: apps/v1kind: DaemonSetmetadata:  name: nginx-daemonsetspec:  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 的运行。通常,这是因为节点处于不可调度的状态,例如它被标记为“已维护”或“故障”。

解决方案

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

kubectl get nodes复制代码

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

kubectl uncordon <node-name>复制代码
1.2 更新失败问题描述

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

Update failed. First seen error: error updating status for daemonset复制代码

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

解决方案

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

kubectl get nodeskubectl get pods -n <namespace>复制代码

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

kubectl delete pod <pod-name> -n <namespace>复制代码
1.3 网络配置问题问题描述

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

Failed to create pod: <pod-name>Error syncing pod复制代码

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

解决方案

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

kubectl describe pod <pod-name> -n <namespace>复制代码

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

kubectl edit pod <pod-name> -n <namespace>复制代码
1.4 如何监视 DaemonSet 运行状态

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

1.4.1 使用 kubectl 命令行工具

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

kubectl get daemonset:列出当前集群中所有的 DaemonSet。kubectl describe daemonset <daemonset-name>:查看指定 DaemonSet 的详细信息,包括 Pod 的状态、事件和控制器的状态等。kubectl rollout status daemonset <daemonset-name>:查看 DaemonSet 的升级进度和状态。kubectl logs <pod-name>:查看 Pod 的日志输出。1.4.2 使用 Kubernetes Dashboard

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

1.4.3 使用 Prometheus 和 Grafana

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

1.5 如何排除问题和调试

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

1.5.1 Pod 处于 Pending 状态

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

节点资源不足:Pod 需要的资源(例如 CPU、内存等)超出了节点可用资源。解决方法是添加更多的节点或调整 Pod 的资源请求。节点标签不匹配:如果 DaemonSet 指定了节点选择器,但节点没有匹配的标签,则 Pod 将处于 Pending 状态。解决方法是为节点添加匹配的标签。Pod 调度失败:如果没有足够的节点满足 Pod 的调度要求,则 Pod 将处于 Pending 状态。解决方法是添加更多的节点或调整 Pod 的调度要求。1.5.2 Pod 启动失败

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

容器镜像拉取失败:Pod 配置中指定的容器镜像不存在或拉取失败。解决方法是确认容器镜像的可用性,并检查 Pod 配置中的容器镜像名称和版本是否正确。容器启动命令或参数不正确:如果容器的启动命令或参数不正确,则容器将无法启动。解决方法是检查 Pod 配置中的容器的启动命令和参数是否正确。容器配置错误:如果容器的配置文件存在错误,则容器可能无法启动或启动后立即崩溃。解决方法是检查容器的配置文件是否正确,并重新启动 Pod。1.5.3 Pod 运行时错误

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

容器内部错误:容器内部可能会发生错误,例如进程崩溃或配置文件错误。解决方法是检查容器日志,确定错误原因,并修复容器内部问题。节点故障:如果节点出现故障,则节点上运行的所有 Pod 可能会受到影响。解决方法是检查节点的健康状况,并在必要时重启节点。网络问题:如果 Pod 无法与其他服务或资源通信,则可能存在网络问题。解决方法是检查网络配置,确保 Pod 能够访问所需的服务或资源。1.5.4 如何排除问题和调试

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

查看日志:使用 kubectl logs 命令查看容器的日志,以了解容器内部发生的错误和故障。使用 kubectl describe 命令:使用 kubectl describe 命令查看 Pod 和其他相关对象的详细信息,以确定问题所在。使用 kubectl exec 命令:使用 kubectl exec 命令在容器内部运行命令,以检查容器的状态和配置文件。使用 kubectl get 命令:使用 kubectl get 命令查看集群中的对象,以确定节点和 Pod 的状态。使用 kubectl events 命令:使用 kubectl events 命令查看 Kubernetes 事件,以了解 Pod 和其他对象的状态变化。

作者:陈书予

链接:

标签: #ssdbnginx