关于 Kubernetes中DeamonSet的一些笔记

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 人生真难,但不配让我认输 ---沃金(知乎)

写在前面


  • 学习k8s遇到整理笔记
  • 感觉不管是dev还是ops,离不开生命周期,钩子,守护进程这些,还是要看看底层的东西.
  • DeamonSet可以理解为特殊的ReplicaSet,即确保每个节点只运行一个pod副本pod Set
  • 生命周期与集群中nodes节点的周期相同
  • 类似 系统中的守护进程 systemd

人生真难,但不配让我认输 ---沃金(知乎)
*

daemonset

DaemonSet 确保全部节点上运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。即单实例,每个节点只跑一个pod

DaemonSet应用场景

DaemonSet 的一些典型用法:

  • 在每个Node上运行一个GlusterFS存储或者Ceph存储Daemon进程
  • 在每个Node上运行一个日志采集程序,例如Fluentd或者Logstach.
  • 在每个Node上运行一个性能监控程序,采集该Node运行性能数据,例如PrometheusNode Exporter, collectd, New Relic agent或者Ganglia gmond等。

一种简单的用法是为每种类型的守护进程在所有的节点上都启动一个 DaemonSet。 一个稍微复杂的用法是为同一种守护进程部署多个 DaemonSet;每个具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求。这句话不太懂,以后再研究下

DaemonSetPod调度策略RC类似,除了使用系统内置的算法在每台Node上进行调度,也可以在Pod的定义中使用NodeSelectorNodeAffinity来指定满足条件的Node范围进行调度。

学习环境准备

┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$dir=k8s-daemonset-create;mkdir $dir;cd $dir
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl config current-context
kubernetes-admin@kubernetes
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl  create ns liruilong-dameonset-create
namespace/liruilong-dameonset-create created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl config set-context $(kubectl config current-context) --namespace=liruilong-daemonset-create
Context "kubernetes-admin@kubernetes" modified.

kubeadm中的deamonset

使用kubeadm安装的k8s环境中是使用的DaemonSet,calico是网路相关,所有节点都需要有,kube-proxy是代理相关,用于负载均衡等操作

┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-ReplicationController]
└─$kubectl  get ds -A
NAMESPACE     NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-system   calico-node   3         3         3       3            3           kubernetes.io/os=linux   4d23h
kube-system   kube-proxy    3         3         3       3            3           kubernetes.io/os=linux   4d23h
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-ReplicationController]
└─$

Demonset的创建

这里要说明的是deamonsetdeployment只有在kind的位置不同,可以拷贝deployment的模板进行修改

apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: myds1
  name: myds1
spec:
 #replicas: 1
  selector:
    matchLabels:
      app: myds1
 #strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: myds1
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
#status: {}
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl create deployment  myds1 --image=nginx --dry-run=client -o yaml > deamonset.yaml
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$vim deamonset.yaml

我们创建一个deamonset,当前只有master节点和一个node节点正常工作
因为master节点有污点,所以会发现这里只允许一个deamonset

┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl apply -f deamonset.yaml
daemonset.apps/myds1 created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl  get nodes
NAME                         STATUS     ROLES                  AGE     VERSION
vms81.liruilongs.github.io   Ready      control-plane,master   4d22h   v1.22.2
vms82.liruilongs.github.io   Ready      <none>                 4d22h   v1.22.2
vms83.liruilongs.github.io   NotReady   <none>                 4d22h   v1.22.2
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl  get pods
NAME          READY   STATUS    RESTARTS   AGE
myds1-fbmhp   1/1     Running   0          35s
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$

节点加入集群自动新增节点pod

我们在启动一台机器,会发现,新加入的vms83.liruilongs.github.io节点自动运行一个deamonset

┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl get nodes
NAME                         STATUS   ROLES                  AGE     VERSION
vms81.liruilongs.github.io   Ready    control-plane,master   4d22h   v1.22.2
vms82.liruilongs.github.io   Ready    <none>                 4d22h   v1.22.2
vms83.liruilongs.github.io   Ready    <none>                 4d22h   v1.22.2
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl get pods
NAME          READY   STATUS    RESTARTS   AGE
myds1-prldj   1/1     Running   0          6m13s
myds1-pvwm4   1/1     Running   0          10m

Deamonset污点节点加入pod

下面我们从新修改deamonset资源文件,容忍有污点的节点

apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: myds1
  name: myds1
spec:
 #replicas: 1
  selector:
    matchLabels:
      app: myds1
 #strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: myds1
    spec:
      terminationGracePeriodSeconds: 0
      tolerations:
      - operator: Exists
      containers:
      - image: nginx
        name: nginx
        resources: {}
#status: {}
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl  apply  -f deamonsettaint.yaml
daemonset.apps/myds1 created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl get pods
NAME          READY   STATUS              RESTARTS   AGE
myds1-8tsnz   0/1     ContainerCreating   0          3s
myds1-9l6d9   0/1     ContainerCreating   0          3s
myds1-wz44b   0/1     ContainerCreating   0          3s

会发现每个节点都运行一个deamontset相关的pod

┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl describe  nodes vms81.liruilongs.github.io | grep Taint
Taints:             node-role.kubernetes.io/master:NoSchedule
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl run pod1 --image=nginx --dry-run=server -o yaml | grep -A 6 terminationGracePeriodSeconds
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute

当然,如果我们不想所以有污点的节点都运行deamonset相关pod,那么我们可以使用另一种指定kye的方式

apiVersion: apps/v1
kind: DaemonSet
metadata:
  creationTimestamp: null
  labels:
    app: myds1
  name: myds1
spec:
  selector:
    matchLabels:
      app: myds1
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: myds1
    spec:
      terminationGracePeriodSeconds: 0
      tolerations:
      - operator: Exists
        key: node-role.kubernetes.io/master
        effect: "NoSchedule"
      containers:
      - image: nginx
        name: nginx
        resources: {}

会发现deamonset可以运行在master和node节点

┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl apply -f deamonsetaint.yaml
daemonset.apps/myds1 created
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-daemonset-create]
└─$kubectl get pods
NAME          READY   STATUS              RESTARTS   AGE
myds1-f7hbb   0/1     ContainerCreating   0          4s
myds1-hksp9   0/1     ContainerCreating   0          4s
myds1-nnmzp   0/1     ContainerCreating   0          4s

Daemon Pods 是如何被调度的

DaemonSet 确保所有符合条件的节点都运行该 Pod 的一个副本。 通常,运行 Pod 的节点由 Kubernetes 调度器选择。 不过,DaemonSet PodsDaemonSet 控制器创建和调度。这就带来了以下问题:
Pod 行为的不一致性:正常 Pod 在被创建后等待调度时处于 Pending 状态, DaemonSet Pods 创建后不会处于 Pending 状态下。
Pod 抢占 由默认调度器处理。启用抢占后,DaemonSet 控制器将在不考虑 Pod 优先级和抢占 的情况下制定调度决策。这里的默认调度器即k8s中调度器。

ScheduleDaemonSetPods 允许您使用默认调度器而不是 DaemonSet 控制器来调度 DaemonSets, 方法是将 NodeAffinity 条件而不是 .spec.nodeName 条件添加到 DaemonSet Pods。 默认调度器接下来将 Pod 绑定到目标主机。

如果 DaemonSet Pod 的节点亲和性配置已存在,则被替换 (原始的节点亲和性配置在选择目标主机之前被考虑)。 DaemonSet 控制器仅在创建或修改 DaemonSet Pod 时执行这些操作, 并且不会更改 DaemonSetspec.template

nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
    - matchFields:
      - key: metadata.name
        operator: In
        values:
        - target-host-name

与 Daemon Pods 通信

DaemonSet 中的 Pod 进行通信的几种可能模式如下:
推送(Push):配置 DaemonSet 中的 Pod,将更新发送到另一个服务,例如统计数据库。 这些服务没有客户端。
NodeIP 和已知端口:DaemonSet 中的 Pod 可以使用 hostPort,从而可以通过节点 IP 访问到 Pod。客户端能通过某种方法获取节点 IP 列表,并且基于此也可以获取到相应的端口。
DNS:创建具有相同 Pod 选择算符的 无头服务, 通过使用 endpoints 资源或从 DNS 中检索到多个 A 记录来发现 DaemonSet。
Service:创建具有相同 Pod 选择算符的服务,并使用该服务随机访问到某个节点上的 守护进程(没有办法访问到特定节点)。

更新 DaemonSet

如果节点的标签被修改,DaemonSet 将立刻向新匹配上的节点添加 Pod, 同时删除不匹配的节点上的 Pod。你可以修改 DaemonSet 创建的 Pod。不过并非 Pod 的所有字段都可更新。 下次当某节点(即使具有相同的名称)被创建时,DaemonSet 控制器还会使用最初的模板。

你可以修改 DaemonSet 创建的 Pod。不过并非 Pod 的所有字段都可更新。 下次当某节点(即使具有相同的名称)被创建时,DaemonSet 控制器还会使用最初的模板。

您可以删除一个 DaemonSet。如果使用 kubectl 并指定 --cascade=orphan 选项, 则 Pod 将被保留在节点上。接下来如果创建使用相同选择算符的新 DaemonSet, 新的 DaemonSet 会收养已有的 Pod。 如果有 Pod 需要被替换,DaemonSet 会根据其 updateStrategy 来替换。

DaemonSet 的替代方案

init 脚本

直接在节点上启动守护进程(例如使用 init、upstartd systemd)的做法当然是可行的。 不过,基于 DaemonSet 来运行这些进程有如下一些好处:

  • 像所运行的其他应用一样,DaemonSet 具备为守护进程提供监控和日志管理的能力。
  • 为守护进程和应用所使用的配置语言和工具(如 Pod 模板、kubectl)是相同的。
  • 在资源受限的容器中运行守护进程能够增加守护进程和应用容器的隔离性。 然而,这一点也可以通过在容器中运行守护进程但却不在 Pod 中运行之来实现。 例如,直接基于 Docker 启动。

裸 Pod

直接创建 Pod并指定其运行在特定的节点上也是可以的。 然而,DaemonSet 能够替换由于任何原因(例如节点失败、例行节点维护、内核升级) 而被删除或终止的 Pod。 由于这个原因,你应该使用 DaemonSet 而不是单独创建 Pod。

静态 Pod

通过在一个指定的、受 kubelet 监视的目录下编写文件来创建 Pod 也是可行的。 这类 Pod 被称为静态 Pod。 不像 DaemonSet,静态 Pod 不受 kubectl 和其它 Kubernetes API 客户端管理。 静态 Pod 不依赖于 API 服务器,这使得它们在启动引导新集群的情况下非常有用。 此外,静态 Pod 在将来可能会被废弃。

Deployments

DaemonSetDeployments 非常类似, 它们都能创建 Pod,并且 Pod 中的进程都不希望被终止(例如,Web 服务器、存储服务器)。建议为无状态的服务使用 Deployments,比如前端服务。 对这些服务而言,对副本的数量进行扩缩容、平滑升级,比精确控制 Pod 运行在某个主机上要重要得多。 当需要 Pod 副本总是运行在全部或特定主机上,并且当该 DaemonSet 提供了节点级别的功能(允许其他 Pod 在该特定节点上正确运行)时, 应该使用 DaemonSet。

例如,网络插件通常包含一个以 DaemonSet 运行的组件。 这个 DaemonSet 组件确保它所在的节点的集群网络正常工作

┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-ReplicationController]
└─$kubectl  get ds -A
NAMESPACE     NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
kube-system   calico-node   3         3         3       3            3           kubernetes.io/os=linux   4d23h
kube-system   kube-proxy    3         3         3       3            3           kubernetes.io/os=linux   4d23h
┌──[root@vms81.liruilongs.github.io]-[~/ansible/k8s-ReplicationController]
└─$
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
5月前
|
Kubernetes Shell API
技术笔记:K8s中大量Pod是Evicted状态,这是咋回事?
技术笔记:K8s中大量Pod是Evicted状态,这是咋回事?
297 0
|
弹性计算 资源调度 Kubernetes
阿里大佬力荐K8s项目实战笔记!图文并茂带你深度解析Kubernetes
Kubernetes(简称K8S)是开源的容器集群管理系统,可以实现容器集群的自动化部署、自动扩缩容、维护等功能。它既是一款容器编排工具,也是全新的基于容器技术的分布式架构领先方案。在Docker技术的基础上,为容器化的应用提供部署运行、资源调度、服务发现和动态伸缩等功能,提高了大规模容器集群管理的便捷性。【Kubernetes是容器集群管理工具】
|
Kubernetes 监控 Devops
大厂直通车!GitHub独一份的Jenkins+k8s核心知识笔记(全彩版)
随着容器的兴起和迅速发展,Kubernetes(K8s)应运而生,现在不仅京东、阿里、谷歌、百度等大公司在使用,就连中小型企业也开始把业务迁移到了k8s上。 K8s在如下图的领域中占据了重要的地位,数万的企业和用户都选择使用K8s。任何一个招聘网站上和K8s相关的职位,月薪都是2w以上,或者更多。
|
运维 Kubernetes 监控
正道的光!阿里爆款Jenkins+K8s笔记终于全网开源了
前段时间公司的服务大升级使用Jenkins+Docker+K8S自动化部署之后,感觉用起来有点大快人心之感。 攻城狮本地开发,开发完成后提交代码到代码仓库,自动触发jenkins进行持续集成与部署,部署完成会收到结果邮件。项目运行过程中可通过日志系统查看程序日志,有异常会触发监控系统发送报警。从编码到上线后结果反馈都可以攻城狮自主完成,形成完整闭环,完整流程的工具链及协助异常情况的处理,工作量减少了,效率也高了。
|
Kubernetes jenkins 持续交付
膜拜!阿里内部爆款K8s+Docker+Jenkins实战笔记,不能再详细了!
膜拜!阿里内部爆款K8s+Docker+Jenkins实战笔记,不能再详细了!
|
存储 缓存 资源调度
深入理解 K8S 资源管理和调度|青训营笔记
本篇文章首先讲解K8S的整体架构,介绍各个模块的功能,在此基础上梳理K8S使用各个组件完成项目部署时涉及的资源管理和调度方式
254 0
深入理解 K8S 资源管理和调度|青训营笔记
|
存储 Kubernetes 关系型数据库
关于K8s中Ansible AWX(awx-operator)平台Helm部署的一些笔记
整理一些K8s中通过Helm的方式部署AWX的笔记分享给小伙伴 博文内容为部署过程和遇到问题的解决过程 食用方式: 需要了解K8s 需要预置的K8s+Helm环境 需要科学上网 理解不足小伙伴帮忙指正 嗯,疫情快点结束吧 ^_^
1112 0
关于K8s中Ansible AWX(awx-operator)平台Helm部署的一些笔记
|
Kubernetes 安全 Docker
Kubernetes CKS 2021 Complete Course + Simulator笔记【1】---k8s架构介绍
Kubernetes CKS 2021 Complete Course + Simulator笔记【1】---k8s架构介绍
Kubernetes CKS 2021 Complete Course + Simulator笔记【1】---k8s架构介绍
|
缓存 Kubernetes 网络协议
k8s安装笔记
k8s安装笔记
k8s安装笔记
|
存储 弹性计算 Kubernetes
轻松玩转Kubernetes笔记分享
轻松玩转Kubernetes笔记分享
405 0