[云原生] K8s之pod控制器详解

Pod 是 Kubernetes 集群中能够被创建和管理的最小部署单元。所以需要有工具去操作和管理它们的生命周期,这里就需要用到控制器了。

Pod 控制器由 master 的 kube-controller-manager 组件提供,常见的此类控制器有 Replication Controller、ReplicaSet、Deployment、DaemonSet、StatefulSet、Job 和 CronJob 等,它们分别以不同的方式管理 Pod 资源对象。

一、pod控制器的相关知识

1.1 pod控制器的作用

Pod控制器,又称之为工作负载(workload),是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试进行重启,当根据重启策略无效,则会重新新建pod的资源。

按照pod的创建安方式可以将其分为两类:

  • **自主式pod:**kubernetes直接创建出来的pod,这种pod删除后就没有了,也不会重建
  • **控制器创建的pod:**通过控制器创建的pod,这种pod删除了之后还会自动重建

控制器和pod的关系:

controllers:在集群上管理和运行容器的 pod 对象, pod 通过 label-selector 相关联。
Pod 通过控制器实现应用的运维,如伸缩,升级等。

1.2 pod控制器的多种类型

(1)ReplicaSet: 代用户创建指定数量的pod副本,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能。
ReplicaSet主要三个组件组成:
1)用户期望的pod副本数量
2)标签选择器,判断哪个pod归自己管理
3)当现存的pod数量不足,会根据pod资源模板进行新建

帮助用户管理无状态的pod资源,精确反应用户定义的目标数量,但是RelicaSet不是直接使用的控制器,而是使用Deployment。

(2)Deployment:工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。
ReplicaSet 与Deployment 这两个资源对象逐步替换之前RC的作用。

(3)DaemonSet:用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。比如ELK服务
特性:服务是无状态的
服务必须是守护进程

(4)StatefulSet:管理有状态应用

(5)Job:只要完成就立即退出,不需要重启或重建

(6)Cronjob:周期性任务控制,不需要持续后台运行

1.3 pod容器中的有状态和无状态的对比

(1)有状态实例
  • 实例之间有差别,每个实例都有自己的独特性,元数据不同,例如etcd,zookeeper
  • 实例之间不对等的关系,以及依靠外部存储的应用
(2)无状态实例
  • deployment认为所有的pod都是一样的
  • 不用考虑顺序的要求
  • 不用考虑在哪个node节点上运行
  • 可以随意扩容和缩容

二、SatefulSet控制器

2.1 SatefulSet 控制器的运用

StatefulSet 是用来管理有状态应用的工作负载 API 对象。

StatefulSet 用来管理某 Pod 集合的部署和扩缩, 并为这些 Pod 提供持久存储和持久标识符。

和 Deployment 类似, StatefulSet 管理基于相同容器规约的一组 Pod。但和 Deployment 不同的是, StatefulSet 为它们的每个 Pod 维护了一个有粘性的 ID。这些 Pod 是基于相同的规约来创建的, 但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。

如果希望使用存储卷为工作负载提供持久存储,可以使用 StatefulSet 作为解决方案的一部分。 尽管 StatefulSet 中的单个 Pod 仍可能出现故障, 但持久的 Pod 标识符使得将现有卷与替换已失败 Pod 的新 Pod 相匹配变得更加容易。

2.2 SatefulSet 控制器的案例演示

  • 名为 nginx-svc 的 Headless Service 用来控制网络域名。

  • 名为 nginx-sts 的 StatefulSet 有一个 Spec,它表明将在独立的 3 个 Pod 副本中启动 nginx 容器。

  • volumeClaimTemplates 将通过 PersistentVolume 制备程序所准备的 PersistentVolumes来提供稳定的存储

    apiVersion: v1
    kind: Service
    metadata:
    name: nginx-svc
    spec:
    ports:
    - port: 80
    targetPort: 80
    clusterIP: None
    selector:
    app: nginx-sts

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
    name: nginx-sts
    spec:
    replicas: 3
    serviceName: "nginx-sts"
    selector:
    matchLabels:
    app: nginx-sts
    template:
    metadata:
    labels:
    app: nginx-sts
    spec:
    containers:
    - image: nginx:1.14
    imagePullPolicy: IfNotPresent
    name: nginx-test
    ports:
    - containerPort: 80
    protocol: TCP
    volumeMounts:
    - name: www
    mountPath: /usr/share/nginx/html
    volumeClaimTemplates:
    - metadata:
    name: www
    spec:
    accessModes: [ "ReadWriteOnce" ]
    storageClassName: "nfs-client-storageclass"
    resources:
    requests:
    storage: 2Gi

案例的更行扩容与缩容演示

复制代码
kubectl edit sts

(1) 为什么要有headless?

在deployment中,每一个pod是没有名称,是随机字符串,是无序的。而statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。

为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。

(2)为什么要有volumeClaimTemplate?

大部分有状态副本集都会用到持久存储,比如分布式系统来说,由于数据是不一样的,每个节点都需要自己专用的存储节点。而在 deployment中pod模板中创建的存储卷是一个共享的存储卷,多个pod使用同一个存储卷,而statefulset定义中的每一个pod都不能使用同一个存储卷,由此基于pod模板创建pod是不适应的,这就需要引入volumeClaimTemplate,当在使用statefulset创建pod时,会自动生成一个PVC,从而请求绑定一个PV,从而有自己专用的存储卷。

服务发现:就是应用服务之间相互定位的过程。
应用场景:
●动态性强:Pod会飘到别的node节点
●更新发布频繁:互联网思维小步快跑,先实现再优化,老板永远是先上线再慢慢优化,先把idea变成产品挣到钱然后再慢慢一点一点优化
●支持自动伸缩:一来大促,肯定是要扩容多个副本

K8S里服务发现的方式---DNS,使K8S集群能够自动关联Service资源的"名称"和"CLUSTER-IP",从而达到服务被集群自动发现的目的。

实现K8S里DNS功能的插件:
●skyDNS:Kubernetes 1.3之前的版本
●kubeDNS:Kubernetes 1.3至Kubernetes 1.11
●CoreDNS:Kubernetes 1.11开始至今

(3)对StatefulSet控制的总结

1、部署有状态应用的
2、每个Pod的名称是唯一且固定不变的,而且每个Pod应该拥有自己专属的持久化存储(基于PVC模板volumeClaimTemplates绑定PV)
3、需要关联 Headless Service(ClusterIP为None),在K8S集群内部可通过 <pod_name>.<svc.name>.<namespace_name>.svc.cluster.local 的格式解析出 PodIP (基于无头服务和CoreDNS实现)
4、创建、删除、升级、扩缩容Pod都是有序进行的(默认为串行执行的):
创建、升级,扩容是升序执行的(顺序为Pod标识序号0..n-1),删除是逆序执行的(顺序为 n-1..0)
缩容和回滚都是逆序执行的(顺序为 n-1..0),会先删除旧Pod,再创建新Pod

三、DaemonSet控制器

3.1 DaemonSet控制器的运用

DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。

使用 DaemonSet 的一些典型用法:
●运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph。
●在每个 Node 上运行日志收集 daemon,例如fluentd、logstash。
●在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond。
应用场景:Agent
官方案例(监控):
DaemonSet | Kubernetes

3.2 DaemonSet控制器的案例演示

复制代码
vim ds.yaml 
apiVersion: apps/v1
kind: DaemonSet 
metadata:
  name: nginx-daemonSet
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14
        ports:
        - containerPort: 80
 
 
kubectl apply -f ds.yaml

守护进程控制器会在每一个node节点上创建一个相同的pod

DaemonSet
1、理论上可以在K8S集群的所有Node节点上创建同类型的Pod资源(无论Node节点什么加入到K8S集群)
2、会受到Node节点上的污点或者cordon不可调度设置的影响。可以在Pod配置中设置容忍忽略污点,设置uncordon解除不可调度
3、不需要设置副本数replicas

总结:

Pod控制器

1)Deployment + ReplicaSet

部署无状态应用(没有实时的数据需要存储)

负责创建和管理ReplicaSet,维护Pod副本数与预期值保持一致

负责创建和删除控制器管理的Pod资源,有多个Pod副本时是并行创建启动的,升级策略默认为滚动更新的方式

2)StatefulSet

部署有状态应用(有实时的数据需要存储)

每个Pod名称标识都是唯一且固定不变的

每个Pod都可以有自己专属的持久化存储(基于PVC模板volumeClaimTemplates实现的)

需要提前创建一个Headless Service资源(无头服务,ClusterIP为Node的service资源),在StatefulSet资源配置中使用serviceName字段指定Headless Service资源名称

K8S集群的Pod可以通过<Pod名称>.<svc名称>.<命名空间>格式解析出StatefulSet控制器管理的Pod资源的PodIP(基于Headless Service和CoreDNS实现的)

创建、滚动升级、扩容、缩容Pod副本时都是有序进行的(由spec.podManagementPolicy字段决定的,默认为OrderedReady,如果设置为Parallel则并行的管理Pod)

创建、扩容是升序进行的(顺序为Pod标识号从0到n-1) 滚动升级、缩容是倒序进行的(顺序为Pod标识号从n-1到0)

Service资源的类型:4个常规类型(ClusterIP NodePort LoadBalancer ExternalName)+ 1个特殊类型(Headless Service)

3)DaemonSet

通常用于部署daemon(守护进程)级别的无状态应用

理论上可以在K8S集群所有node节点上都创建一个相同的Pod副本,无论node节点何时加入到K8S集群(需要考虑到污点taint和cordon不可调度的影响)

DaemonSet资源配置不需要设置Pod副本数字段replicas

4)Job

一次性的部署短期任务的Pod资源,Pod不会持续运行,并要求任务执行完毕后容器成功退出且不再重启

Job资源配置的容器重启策略要求不能设置为Always,一般推荐设置为Never

如果任务执行失败导致Pod容器异常退出,Job会根据backoffLimit字段的值决定重建Pod来重试任务的次数(默认为6)

5)CronJob

周期性的部署短期任务的Pod资源,Pod不会持续运行,并要求任务执行完毕后容器成功退出且不再重启

Pod容器重启策略要求不能设置为Always,一般推荐设置为Never

要配置schedule字段设置任务执行的周期表,格式为"分 时 日 月 周"

相关推荐
用户0328472220709 小时前
如何搭建本地yum源(上)
运维
武子康10 小时前
调查研究-183 Apple container:Mac 上用轻量 VM 跑 Linux 容器,Swift 会改写本地容器体验吗?
docker·容器·apple
秋播16 小时前
国内本地WSL2编译rancher源码
云原生
小猿姐2 天前
MySQL Top 10 热点问题 AI 运维实战:从内核诊断到云原生运维
mysql·云原生·aiops
阿里云云原生3 天前
深入内核:拆解 OpenTelemetry eBPF 探针如何优雅地“透视”多语言微服务?
云原生
大树883 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质3 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工3 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智3 天前
ARP代理--工作原理
运维·网络·arp·arp代理