API对象--Daemonset(chrono《kubernetes入门实战课》笔记整理)

【概念介绍】

学习了监管离线任务的API对象job/cronjob,监管在线任务的API对象deployment。今天学习做好守护任务的API对象DaemonSet。它会在 Kubernetes 集群的每个节点上都运行一个 Pod,就好像是 Linux 系统里的“守护进程”(Daemon)。

为什么不能用deployment来做守护任务呢,它不是也可以确保一定跑起来哪些pod么?可是我们跑pod,最终目的是为了运行我们的服务应用,有些服务应用并不适合在某些节点运行起来,甚至不能运行,那么这个pod running了,也就没有实际意义了。又比如,有些pod应该在每个节点都运行,这个需要被保证,而不只是总pod数对了就行,比如下面几个应用的pod:

1、网络应用(如 kube-proxy),必须每个节点都运行一个 Pod,否则节点就无法加入 Kubernetes 网络;

2、监控应用(如 Prometheus),必须每个节点都有一个 Pod 用来监控节点的状态,实时上报信息;

3、日志应用(如 Fluentd),必须在每个节点上运行一个 Pod,才能够搜集容器运行时产生的日志数据;

4、安全应用,同样的,每个节点都要有一个 Pod 来执行安全审计、入侵检查、漏洞扫描等工作。

这些业务如果用 Deployment 来部署就不太合适了,因为 Deployment 所管理的 Pod 数量是固定的,而且可能会在集群里“漂移”,简单说,就是只要pod运行数目对了,在哪儿运行的我就不管啦~但,实际的需求却是要在集群里的每个节点上都运行 Pod。

所以,Kubernetes 就定义了新的 API 对象 DaemonSet,它在形式上和 Deployment 类似,都是管理控制 Pod,但管理调度策略却不同。DaemonSet 的目标是在集群的每个节点上运行且仅运行一个 Pod,就好像是为节点配上一只“看门狗”,忠实地“守护”着节点,这就是 DaemonSet 名字的由来。

【如何使用 YAML 描述 DaemonSet】

DaemonSet 和 Deployment 都属于在线业务,所以它们也都是“apps”组,使用命令 kubectl api-resources 可以知道它的简称是 ds ,YAML 文件头信息应该是:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: xxx-ds

但是Kubernetes 不提供自动创建 DaemonSet YAML 样板的功能,也就是说,我们不能用命令 kubectl create 直接创建出一个 DaemonSet 对象。只能通过官网找到YAML示例,拷贝下来,如下:

复制代码
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: redis-ds
  labels:
    app: redis-ds

spec:
  selector:
    matchLabels:
      name: redis-ds

  template:
    metadata:
      labels:
        name: redis-ds
    spec:
      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - containerPort: 6379
复制代码

针对这个YAML中一些重要参数的说明:

1、DaemonSet 对象的名字是 redis-ds,镜像是 redis:5-alpine;

2、DaemonSet 相比deployment,在 spec 里没有 replicas 字段,意味着它不会在集群里创建多个 Pod 副本,而是要在每个节点上只创建出一个 Pod 实例;

除此之外,daemonset和deplyment的yaml没有什么不同,这也说明他们的工作方式是非常类似的,仅仅实在部署调度策略上不太相同,一个是重视pod的数目,一个是重视每个节点是否都运行了需要的pod。所以把daemonset理解为是deployment的特例,也是非常合理的。Chrono老师也特意画了针对这两种API对象的YAML退避图:

了解了区别之后,那么这里就有一个用create创建ds yaml样板间的方式:用 kubectl create 先创建出一个 Deployment 对象,然后把 kind 改成 DaemonSet,再删除 spec.replicas 就行了~如下,箭头处修改为DaemonSet,红框三个地方删除即可。

正确yml如下,可以复制使用:

复制代码
apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: redis-ds
  name: redis-ds
spec:
  selector:
    matchLabels:
      app: redis-ds
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: redis-ds
    spec:
      containers:
      - image: redis:5-alpine
        name: redis
        resources: {}
复制代码

kubectl apply -f ds.yml创建daemonset对象,get一下看看:

  图上有几个点要注意:

1、虽然我们没有指定 DaemonSet 里 Pod 要运行的数量,但它自己就会去查找集群里的节点,会在每个节点里创建 Pod;

2、因为我们的实验环境里只有一个 Master 一个 Worker,而 Master 默认是不跑应用的,所以 DaemonSet 就只生成了一个 Pod,运行在了“worker”节点上。但是这是怎么做到只在worker运行的呢?这是通过污点(taint)和容忍度(toleration)来实现的。describe node可以看到这个node的taint,describe pod的时候可以看到toleration。每个pod对于taint的容忍不一样,包含在容忍度列表的taint,打这个taint的节点,就可以运行pod,否则就不可以运行。如果一定要在master上运行这个pod,有两个思路:

1)去除master的taint,命令如下。但非常不建议如此,master去掉taint意味着以后所有pod都能在其上运行,这会影响master性能;

kubectl taint node master node-role.kubernetes.io/master:NoSchedule-

2)在pod的容忍度列表增加master的taint。在pod的yml文件里,增加容忍度列表,然后重新kubectl apply -f ds.yml一下,部署ds

tolerations:
- key: node-role.kubernetes.io/master
  effect: NoSchedule
  operator: Exists

完整的yml是这样的:

复制代码
apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: redis-ds
  name: redis-ds
spec:
  selector:
    matchLabels:
      app: redis-ds
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: redis-ds
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
        operator: Exists
      containers:
      - image: redis:5-alpine
        name: redis
        resources: {}
复制代码

重新部署ds,会看到在master和worker上都运行起来了这个pod:

 【静态pod】

还有一种pod,也有YAML来描述,也会跑在容器运行时上,但是不受k8s管控,不与apiserver,scheduler有任何交互,所以是静态的。只能通过kubelet管理。这类静态pod的YAML文件默认存在节点的 /etc/kubernetes/manifests 目录下,它是 Kubernetes 的专用目录。

 

 从上图可以看到,Kubernetes 的 4 个核心组件 apiserver、etcd、scheduler、controller-manager 原来都以静态 Pod 的形式存在的,这也是为什么它们能够先于 Kubernetes 集群启动的原因。(是说之前为啥这几个pod早早就running了,解惑了!)

如果你有一些 DaemonSet 无法满足的特殊的需求,可以考虑使用静态 Pod,编写一个 YAML 文件放到这个目录里,节点的 kubelet 会定期检查目录里的文件,发现变化就会调用容器运行时创建或者删除静态 Pod。

posted @   1234roro  阅读(42)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示