K8s DaemonSet 运维:集群级服务的部署与管理

K8s DaemonSet 运维:集群级服务的部署与管理,让你的应用像章鱼一样覆盖整个集群!🐙

各位观众,各位听众,各位码农,大家好!我是今天的主讲人,一个在K8s世界里摸爬滚打了多年的老兵。今天我们要聊的话题,是K8s中的一个重要角色,一个能让你的应用像章鱼一样覆盖整个集群的强大工具——DaemonSet

如果你还对Pod、Deployment这些概念比较陌生,没关系,你可以把它们想象成乐高积木,而DaemonSet,就是一种特殊的拼搭方式,一种能让你的积木自动、均匀地分布在你的整个乐高世界里的魔法。

一、 DaemonSet:集群守护神的真面目

首先,让我们来扒一扒DaemonSet的底裤,看看它到底是个什么玩意儿。

简单来说,DaemonSet保证在每一个(或者符合你选择条件的)节点上都运行一个Pod的副本。 想象一下,你的集群是一个浩瀚的星系,而DaemonSet就像是遍布整个星系的星际导航仪,确保每个星球上都安装了一个,随时提供导航服务。

这听起来是不是很酷?但你可能会问,为什么我们需要这种东西呢?Deployment不是也可以实现应用的部署吗?

答案是:Deployment专注于应用的规模弹性,它更关心的是总共有多少个副本,以及如何根据负载进行伸缩。而DaemonSet则更关心应用的覆盖率,它必须保证在每个节点上都有一个副本运行,无论集群规模如何变化。

举个栗子:

  • 日志收集 (Fluentd, Logstash):每个节点都需要收集日志并发送到中央存储,DaemonSet保证每个节点都有一个日志收集器在运行,就像每个城市都有一个垃圾处理站,保证环境的清洁。
  • 监控代理 (Prometheus Node Exporter):每个节点都需要暴露监控指标,供Prometheus抓取,DaemonSet保证每个节点都有一个监控代理,就像每个房间都有一个温度计,随时监控环境温度。
  • 网络插件 (Calico, Flannel):每个节点都需要运行网络插件,才能实现Pod之间的网络通信,DaemonSet保证每个节点都有一个网络插件,就像每个城市都有公路,保证交通的畅通。

所以,你可以把DaemonSet看作是集群的守护神,它默默地守护着集群的每一个角落,确保一些关键的服务始终可用。

二、 DaemonSet的威力:为何如此受欢迎?

DaemonSet之所以如此受欢迎,是因为它解决了传统运维中的一些痛点:

  • 自动化部署:无需手动在每个节点上安装和配置服务,DaemonSet会自动完成部署,省时省力,就像流水线生产一样,效率倍增。
  • 自动修复:如果节点上的Pod崩溃或被删除,DaemonSet会自动在同一个节点上创建一个新的Pod,保证服务的持续可用,就像不死鸟一样,浴火重生。
  • 滚动更新:DaemonSet支持滚动更新,可以逐步替换旧版本的Pod,而不会影响服务的正常运行,就像汽车换轮胎一样,无需停车。
  • 节点选择:DaemonSet可以通过nodeSelectornodeNametolerations等字段来选择特定的节点运行Pod,实现更精细的控制,就像狙击手一样,精准打击。

三、 DaemonSet的YAML:解密守护神的咒语

接下来,让我们一起解读DaemonSet的YAML文件,看看这个守护神的咒语到底是怎么写的。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  labels:
    app: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true  # 允许访问主机网络
      hostPID: true      # 允许访问主机PID命名空间
      containers:
      - name: node-exporter
        image: prom/node-exporter:latest
        ports:
        - containerPort: 9100
          hostPort: 9100
        securityContext:
          privileged: true # 允许特权访问

让我们逐行解读这个YAML文件:

  • apiVersion: apps/v1:指定API版本。
  • kind: DaemonSet:声明这是一个DaemonSet资源。
  • metadata.name: node-exporter:DaemonSet的名字,就像人的名字一样,用于标识这个守护神。
  • metadata.labels: app: node-exporter:标签,用于标识这个DaemonSet,方便查询和管理。
  • spec.selector.matchLabels: app: node-exporter:选择器,用于匹配需要管理的Pod,就像警察抓坏人一样,需要先确定目标。
  • spec.template:Pod模板,定义了DaemonSet创建的Pod的配置,就像房子的设计图一样,决定了房子的结构和功能。
  • spec.template.spec.hostNetwork: true:允许Pod访问主机网络,一些监控工具需要访问主机网络才能获取指标。
  • spec.template.spec.hostPID: true:允许Pod访问主机PID命名空间,一些工具需要访问主机PID命名空间才能获取进程信息。
  • spec.template.spec.containers:容器列表,定义了Pod中运行的容器,就像房子里的房间一样,每个房间都有不同的功能。
  • spec.template.spec.containers.name: node-exporter:容器的名字,就像房间的名字一样,用于标识这个容器。
  • spec.template.spec.containers.image: prom/node-exporter:latest:容器的镜像,就像房间里的家具一样,决定了房间的功能。
  • spec.template.spec.containers.ports:端口映射,将容器内部的端口映射到主机端口,允许外部访问容器,就像房子的窗户一样,方便通风。
  • spec.template.spec.containers.securityContext.privileged: true:允许容器以特权模式运行,一些工具需要特权模式才能访问主机资源。

重点提示:

  • hostNetwork: truehostPort 的使用需要谨慎,如果你的应用不需要访问主机网络或监听主机端口,应该避免使用这些配置,以提高安全性。
  • securityContext: privileged: true 的使用更加需要谨慎,只有在必要的情况下才应该使用特权模式,否则可能会带来安全风险。

四、 DaemonSet的运维:守护神的日常维护

DaemonSet的运维涉及到创建、更新、删除等操作。下面我们来分别介绍这些操作。

1. 创建DaemonSet

创建DaemonSet非常简单,只需要将YAML文件应用到K8s集群即可:

kubectl apply -f node-exporter.yaml

执行完这个命令后,K8s会自动在每个节点上创建一个node-exporter Pod。你可以使用以下命令查看DaemonSet的状态:

kubectl get daemonset node-exporter
kubectl get pods -l app=node-exporter -o wide

2. 更新DaemonSet

更新DaemonSet也非常简单,只需要修改YAML文件,然后再次应用到K8s集群即可:

kubectl apply -f node-exporter.yaml

DaemonSet会自动执行滚动更新,逐步替换旧版本的Pod,而不会影响服务的正常运行。

你可以使用以下命令查看DaemonSet的更新状态:

kubectl rollout status daemonset/node-exporter

3. 删除DaemonSet

删除DaemonSet也非常简单,只需要执行以下命令即可:

kubectl delete daemonset node-exporter

删除DaemonSet后,K8s会自动删除所有由DaemonSet创建的Pod。

五、 DaemonSet的高级用法:玩转守护神的各种姿势

除了基本用法之外,DaemonSet还有一些高级用法,可以让你更好地控制守护神的行为。

1. nodeSelector:指定节点运行

如果你只想在特定的节点上运行DaemonSet,可以使用nodeSelector字段。例如,如果你只想在具有disktype=ssd标签的节点上运行node-exporter,可以这样配置:

spec:
  template:
    spec:
      nodeSelector:
        disktype: ssd
      containers:
      - name: node-exporter
        image: prom/node-exporter:latest

2. nodeName:指定单个节点运行

如果你只想在特定的单个节点上运行DaemonSet,可以使用nodeName字段。例如,如果你只想在名为node1的节点上运行node-exporter,可以这样配置:

spec:
  template:
    spec:
      nodeName: node1
      containers:
      - name: node-exporter
        image: prom/node-exporter:latest

注意: 使用nodeName后,DaemonSet的行为会退化成单个Pod,如果节点出现故障,Pod不会自动迁移到其他节点。 因此,除非有特殊需求,否则不建议使用nodeName

3. tolerations:容忍污点

如果你的节点上设置了污点(Taint),DaemonSet默认情况下是无法调度到这些节点上的。如果你希望DaemonSet能够容忍这些污点,可以使用tolerations字段。

例如,如果你的节点上设置了node.kubernetes.io/unreachable:NoExecute污点,你可以这样配置:

spec:
  template:
    spec:
      tolerations:
      - key: "node.kubernetes.io/unreachable"
        operator: "Exists"
        effect: "NoExecute"
      containers:
      - name: node-exporter
        image: prom/node-exporter:latest

tolerations 允许 Pod 容忍污点,operator: "Exists" 表示容忍所有具有指定 key 的污点,effect: "NoExecute" 表示容忍 NoExecute 效果的污点。

4. updateStrategy:控制更新策略

DaemonSet支持两种更新策略:

  • RollingUpdate (默认):滚动更新,逐步替换旧版本的Pod,不会影响服务的正常运行。
  • OnDelete:删除旧版本的Pod后,才会创建新版本的Pod,可能会导致服务中断。

你可以使用updateStrategy字段来控制更新策略。例如,如果你想使用OnDelete更新策略,可以这样配置:

spec:
  updateStrategy:
    type: OnDelete
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      containers:
      - name: node-exporter
        image: prom/node-exporter:latest

六、 DaemonSet的注意事项:避免踩坑指南

在使用DaemonSet时,需要注意以下几点:

  • 资源限制: DaemonSet会在每个节点上运行Pod,因此需要合理设置Pod的资源限制,避免节点资源耗尽。
  • 版本兼容性: 在更新DaemonSet时,需要注意新版本的Pod是否与旧版本的Pod兼容,避免服务中断。
  • 监控和告警: 需要对DaemonSet进行监控和告警,及时发现和解决问题,保证服务的稳定运行。
  • 正确理解hostNetworkhostPort的使用: 不恰当的使用可能导致端口冲突或安全问题。仔细评估你的应用是否真的需要访问主机网络。
  • 谨慎使用privileged模式: 除非绝对必要,否则避免使用特权模式。 如果必须使用,请确保你了解其潜在的安全风险。

七、 总结:DaemonSet,你值得拥有!

总而言之,DaemonSet是K8s中一个非常强大的工具,它可以让你轻松地在每个节点上部署和管理集群级服务。 掌握DaemonSet的使用,可以大大提高你的运维效率,让你的应用像章鱼一样覆盖整个集群!🐙

希望今天的讲解对你有所帮助。如果你有任何问题,欢迎在评论区留言,我会尽力解答。

感谢大家的收听! 我们下次再见! 👋

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注