• K8S中的DaemonSet
  • 发布于 2个月前
  • 347 热度
    0 评论
Daemonset
使用 Deployment 存在了一个问题,尽管它可以创建任意多的副本,但是无法指定 Pod 运行在哪个宿主机上,对于大多数业务来说,这样不会有问题。但是如果 有一些应用,他们需要在每个宿主机上都存在,例如监控应用、日志应用等,如果还使用 Deployment ,就无法保证每个宿主机上都存在。

DaemonSet 就是 K8s 为了解决这种情况而配置的对象,它在形式上和 Deployment 类似,都是管理控制 Pod,但是 DaemonSet 最终是在集群的每个节点上运行且仅运行一个 Pod。

Yaml 模板
K8s 无法通过 kubectl create 创建一个 Daemonset 的模板,我们可以到 K8s 的官网去查看:DaemonSet。还是以之前的 back-test 为例, yaml 内容大致如下:
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: back-daemonset
  name: back-daemonset
spec:
  selector:
    matchLabels:
      app: back-app
  template:
    metadata:
      labels:
        app: back-app
    spec:
      containers:
      - image: back-test:latest
        name: back-test
        imagePullPolicy: Never
        ports: 
        - containerPort: 80
可以看到,DaemonSet 与 Deployment 除了 kind 和 spec.replicas 处不同外,没有什么区别。所以我们完全可以通过创建一个 Deployment yaml文件,然后手动修改 kind 和 spec.replicas,以得到一个 DaemonSet 的模板。

实操
DaemonSet 的创建一如既往,使用 kubectl apply命令即可,通过 kubectl get po 命令可以发现,本地已经存在一个 back-daemonset-xxx 的Pod了,但是此时我们是无法在集群外访问到,我们需要为它绑定一个Service,整个 yaml 的文件大致如下:
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: back-daemonset
  name: back-daemonset
  
spec:
  selector:
    matchLabels:
      app: back-app
  template:
    metadata:
      labels:
        app: back-app
    spec:
      containers:
      - image: back-test:latest
        name: back-test
        imagePullPolicy: Never
        ports: 
        - containerPort: 80


---

apiVersion: v1
kind: Service
metadata:
  labels:
    app: back-app-svc
  name: back-app-svc
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30002
  selector:
    app: back-app
  type: NodePort
yaml 修改完毕后,通过 kubectl apply 进行应用生效,接下来我们就可以通过本地 30002 端口进行访问了:
curl 127.0.0.1:30002/api/guid
通过 Rancher Desktop 搭建的本地环境这样使用自然是没有问题的,但是如果是生产环境,你可能会发现 Master 节点并没有这样的一个 Pod 存在,只有 Work 节点存在 DaemonSet 的 Pod。这是因为 K8s 的 Master 节点默认只能运行控制面相关 Pod。为了解决这个问题,我们需要在 DaemonSet 的 spec.template.spec 添加tolerations字段:
apiVersion: apps/v1
kind: DaemonSet
...
  
spec:
  template:
    ...
    spec:
     tolerations:
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule
        operator: Exists
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
        operator: Exists
      containers:
        ...
Taint & Toleration:污点和容忍度
污点 (Taint) 是 K8s 用于 Node 排斥 Pod 的一种手段,例如生产环境下 Master 节点会存在 node-role.kubernetes.io/master 的污点,我们可以通过 kubectl describe no [NodeName] 查看得到,它的效果 (effect) 就是 NoSchedule——拒绝 Pod 调度到本节点。

但是有些 Pod,我们需要运行存在污点的节点上,这个我们就需要为 Pod 添加容忍度,只要 Pod 的容忍度通过校验,则 Pod 就可以运行在这个节点上。

污点效果
污点效果有3个:
NoSchedule:禁止调度 Pod 到该节点,除非添加容忍度。
PreferNoSchedule :尽量不要调度 Pod 到该节点

NoExecute:类似于NoSchedule,但是如果 Pod 不存在这个容忍度,会被立即驱逐出该节点。当宿主机故障的时候可以使用该效果。


容忍度校验
容忍度的校验规则 operator 有两种:Equal 和 Exists,默认是 Equal 。
先来看下 Taint 的添加与删除:
# 添加,指定value
kubectl taint nodes NodeName key1=value1:NoSchedule
# 添加,不指定value
kubectl taint nodes NodeName key1:NoSchedule
# 删除 (添加后面多个-)
kubectl taint nodes NodeName key1=value1:NoSchedule-
添加污点的命令含义是:给NodeName节点添加一个污点,它的键名是 key1,键值是 value1,效果是 NoSchedule。当然,我们可以不指定value。

这样,对于容忍度的校验规则 Equal 来说,除了校验污点的 key 外,还会去校验容忍度中的 value 是否和 污点的一致,一致了才可以进行调度到该节点。
tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
而对于 Exists 来说,只要这个污点 key 存在即可进行调度。
tolerations:
- key: "key1"
  operator: "Exists"
  effect: "NoSchedule"

用户评论