kubernetes--Pod控制器详解

目录

一、Pod控制器及其功用:

二、pod控制器的多种类型:

1、ReplicaSet:

[1.1 ReplicaSet主要三个组件组成:](#1.1 ReplicaSet主要三个组件组成:)

2、Deployment:

3、DaemonSet:

4、StatefulSet:

5、Job:

6、Cronjob:

三、Deployment控制器:

示例:

查看控制器配置

查看历史版本

四、SatefulSet:

[1. 示例:](#1. 示例:)

[2. StatefulSet的组成部分:](#2. StatefulSet的组成部分:)

[3. 为什么要有headless:](#3. 为什么要有headless:)

[4. 为什么要有volumeClaimTemplate:](#4. 为什么要有volumeClaimTemplate:)

[5. 常规service和无头服务区别:](#5. 常规service和无头服务区别:)

[6. 总结:](#6. 总结:)

五、DaemonSet:

[1. DaemonSet 的一些典型用法:](#1. DaemonSet 的一些典型用法:)

[2. 示例:](#2. 示例:)

[3. 总结:](#3. 总结:)

六、Job:

[1. 示例:](#1. 示例:)

[2. 参数解释](#2. 参数解释)

[3. backoffLimit:](#3. backoffLimit:)

[4. 总结:](#4. 总结:)

[七、CronJob :](#七、CronJob :)

[1. 示例:](#1. 示例:)

[2. cronjob其它可用参数的配置:](#2. cronjob其它可用参数的配置:)

[3. 总结:](#3. 总结:)


一、Pod控制器及其功用:

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

二、pod控制器的多种类型:

1、ReplicaSet:

代用户创建指定数量的pod副本,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能。

1.1 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:

周期性任务控制,不需要持续后台运行

三、Deployment控制器:

  • 部署无状态应用
  • 管理Pod和ReplicaSet
  • 具有上线部署、副本设定、滚动升级、回滚等功能
  • 提供声明式更新,例如只更新一个新的image
  • 应用场景:web服务

示例:

bash 复制代码
vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx	
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15.4
        ports:
        - containerPort: 80

kubectl create -f nginx-deployment.yaml

kubectl get pods,deploy,rs

查看控制器配置

bash 复制代码
kubectl edit deployment/nginx-deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  creationTimestamp: "2021-04-19T08:13:50Z"
  generation: 1
  labels:
    app: nginx					#Deployment资源的标签
  name: nginx-deployment
  namespace: default
  resourceVersion: "167208"
  selfLink: /apis/extensions/v1beta1/namespaces/default/deployments/nginx-deployment
  uid: d9d3fef9-20d2-4196-95fb-0e21e65af24a
spec:
  progressDeadlineSeconds: 600
  replicas: 3					#期望的pod数量,默认是1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 25%				#升级过程中会先启动的新Pod的数量不超过期望的Pod数量的25%,也可以是一个绝对值
      maxUnavailable: 25%		#升级过程中在新的Pod启动好后销毁的旧Pod的数量不超过期望的Pod数量的25%,也可以是一个绝对值
    type: RollingUpdate			#滚动升级
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx				#Pod副本关联的标签
    spec:
      containers:
      - image: nginx:1.15.4				#镜像名称
        imagePullPolicy: IfNotPresent	#镜像拉取策略
        name: nginx
        ports:
        - containerPort: 80				#容器暴露的监听端口
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always				#容器重启策略
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
......

查看历史版本

bash 复制代码
kubectl rollout history deployment/nginx-deployment
deployment.apps/nginx-deployment
REVISION  CHANGE-CAUSE
1         <none>

四、SatefulSet:

  • 部署有状态应用
  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
  • 稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
  • 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
  • 有序收缩,有序删除(即从N-1到0)

常见的应用场景:数据库

https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/

1. 示例:

bash 复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None     #不创建custerip,也就是无头服务的service
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx 
  serviceName: "nginx"
  replicas: 3   #三个副本
  template:     #定义容器的模板
    metadata:
      labels:
        app: nginx 
    spec:
      terminationGracePeriodSeconds: 10   #10秒内pod没关闭,就强制杀死
      containers:
      - name: nginx
        image: nginx:1.14.1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:   #容器内挂载
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:   #存储卷的申请模板
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]   #可读可写,仅能一个节点挂载
      storageClassName: "nfs-client-storageclass"  #使用动态创建的pv
      resources:   #设置请求的资源大小
        requests:
          storage: 2Gi

由于StatefulSet资源依赖于一个实现存在的Headless类型的Service资源,所以需要先定义一个名为nginx的Headless Service资源,用于为关联到每个Pod资源创建DNS资源记录。接着定义了一个名为web的StatefulSet资源,它通过Pod模板创建了3个Pod资源副本,并基于volumeClaimTemplates向存储类进行了请求大小为2Gi的专用存储卷。

2. StatefulSet的组成部分:

  • Headless Service(无头服务):用于为Pod资源标识符生成可解析的DNS记录。
  • volumeClaimTemplates(存储卷申请模板):基于静态或动态PV供给方式为Pod资源提供专有的固定存储。
  • StatefulSet:用于管控Pod资源。

3. 为什么要有headless:

在deployment中,每一个pod是没有名称,是随机字符串,是无序的。而statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。

4. 为什么要有volumeClaimTemplate:

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

5. 常规service和无头服务区别:

  • service:一组Pod访问策略,提供cluster-IP群集之间通讯,还提供负载均衡和服务发现。
  • Headless service:无头服务,不需要cluster-IP,而是直接以DNS记录的方式解析出被代理Pod的IP地址。

6. 总结:

  • 部署有状态应用(有实时的数据需要存储)
  • 每个Pod名称标识都是唯一且固定不变的
  • 每个Pod都可以有自己专属的持久化存储(基于PVC模板volumeClaimTemplates实现的)
  • 需要提前创建一个Headless Service资源(无头服务,ClusterIP可以为Node),并在StatefulSet资源清单配置中使用serviceName字段指定Headless Service资源名称
  • 可以在Pod内通过<Pod名称>.<svc名称>.<命名空间>[.svc.cluster.local]格式解析出PodIP(基于Headless Service和CoreDNS实现的)
  • 创建、滚动升级、扩容、缩容Pod副本时都是有序进行的(默认为串行执行的,由spec.podManagementPolicy字段决定的,默认值为OrderedReady,为Parallel则并行执行)
  • 创建、扩容是升序执行的(顺序为Pod标识号从0到n-1) 滚动升级、缩容是倒序执行的(顺序为Pod标识号从n-1到0)

五、DaemonSet:

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

1. DaemonSet 的一些典型用法:

  • 运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph。
  • 在每个 Node 上运行日志收集 daemon,例如fluentd、logstash。
  • 在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond。

应用场景:Agent

//官方案例(监控)

https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/

2. 示例:

bash 复制代码
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.15.4
        ports:
        - containerPort: 80
bash 复制代码
kubectl apply -f ds.yaml

//DaemonSet会在每个node节点都创建一个Pod

3. 总结:

  • 通常用于部署daemon级别的无状态应用
  • 理论上可以在K8S所有node节点上创建相同的Pod资源,无论node节点什么时候加入到K8S集群(需要考虑到污点和cordon不可调度的影响)
  • 不需要配置Pod副本数字段replicas

六、Job:

Job分为普通任务(Job)和定时任务(CronJob),常用于运行那些仅需要执行一次的任务

应用场景:数据库迁移、批处理脚本、kube-bench扫描、离线数据处理,视频解码等业务

https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/

1. 示例:

bash 复制代码
vim job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4

2. 参数解释

.spec.template.spec.restartPolicy该属性拥有三个候选值:OnFailure,Never和Always。默认值为Always。它主要用于描述Pod内容器的重启策略。在Job中只能将此属性设置为OnFailure或Never,否则Job将不间断运行。

.spec.backoffLimit用于设置job失败后进行重试的次数,默认值为6。默认情况下,除非Pod失败或容器异常退出,Job任务将不间断的重试,此时Job遵循 .spec.backoffLimit上述说明。一旦.spec.backoffLimit达到,作业将被标记为失败。

  • 在所有node节点下载perl镜像,因为镜像比较大,所以建议提前下载好
bash 复制代码
docker pull perl

kubectl apply -f job.yaml 

kubectl get pods


//结果输出到控制台
kubectl logs pi-bqtf7
3.14159265......

//清除job资源
kubectl delete -f job.yaml 

3. backoffLimit:

bash 复制代码
vim job-limit.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: busybox
spec:
  template:
    spec:
      containers:
        - name: busybox
          image: busybox
          imagePullPolicy: IfNotPresent
          command: ["/bin/sh", "-c", "sleep 10;date;exit 1"]
      restartPolicy: Never
  backoffLimit: 2
bash 复制代码
kubectl apply -f job-limit.yaml

kubectl get job,pods
NAME                COMPLETIONS   DURATION   AGE
job.batch/busybox   0/1           4m34s      4m34s

NAME                READY   STATUS   RESTARTS   AGE
pod/busybox-dhrkt   0/1     Error    0          4m34s
pod/busybox-kcx46   0/1     Error    0          4m
pod/busybox-tlk48   0/1     Error    0          4m21s

kubectl describe job busybox
......
Warning  BackoffLimitExceeded  43s    job-controller  Job has reached the specified backoff limit

4. 总结:

  • 部署一次性的短期任务的Pod资源,Pod不会持久运行
  • 任务正常完成后Pod容器会正常退出且不再重启(restartPolicy字段需要设置为Never或OnFailure),并也不会再重建Pod
  • 如果任务执行失败导致Pod容器异常退出,Job会根据backoffLimit字段决定重建Pod重试任务的次数(默认值为6)

七、CronJob :

周期性任务 类似Linux的Crontab。

应用场景:通知,备份

https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/

1. 示例:

bash 复制代码
//每分钟打印hello
vim cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

2. cronjob其它可用参数的配置:

bash 复制代码
spec:
  concurrencyPolicy: Allow			#声明了 CronJob 创建的任务执行时发生重叠如何处理(并发性规则仅适用于相同 CronJob 创建的任务)。spec仅能声明下列规则中的一种:
                                         ●Allow (默认):CronJob 允许并发任务执行。
                                         ●Forbid:CronJob 不允许并发任务执行;如果新任务的执行时间到了而老任务没有执行完,CronJob 会忽略新任务的执行。
                                         ●Replace:如果新任务的执行时间到了而老任务没有执行完,CronJob 会用新任务替换当前正在运行的任务。
  startingDeadlineSeconds: 15		#它表示任务如果由于某种原因错过了调度时间,开始该任务的截止时间的秒数。过了截止时间,CronJob 就不会开始任务,且标记失败.如果此字段未设置,那任务就没有最后期限。
  successfulJobsHistoryLimit: 3		#要保留的成功完成的任务数(默认为3)
  failedJobsHistoryLimit:1         #要保留多少已完成和失败的任务数(默认为1)
  suspend:true                     #如果设置为 true ,后续发生的执行都会被挂起。 这个设置对已经开始的执行不起作用。默认是 false。
  schedule: '*/1 * * * *'			#必需字段,作业时间表。在此示例中,作业将每分钟运行一次
  jobTemplate:						#必需字段,作业模板。这类似于工作示例
bash 复制代码
kubectl create -f cronjob.yaml 

kubectl get cronjob
NAME    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello   */1 * * * *   False     0        <none>          25s

3. 总结:

  • 部署周期性的短期任务的Pod资源,Pod不会持久运行
  • 任务正常完成后Pod容器会正常退出且不再重启(restartPolicy字段需要设置为Never或OnFailure),并也不会再重建Pod
  • 必须要配置schedule字段设置任务执行的周期表,格式为 "分 时 日 月 周"
相关推荐
孔令飞7 分钟前
Go:终于有了处理未定义字段的实用方案
人工智能·云原生·go
玄明Hanko27 分钟前
Quarkus+Docker最全面完整教程:手把手搞定Java云原生
后端·docker·云原生
SimonLiu0091 小时前
清理HiNas(海纳斯) Docker日志并限制日志大小
java·docker·容器
高峰君主4 小时前
Docker容器持久化
docker·容器·eureka
能来帮帮蒟蒻吗4 小时前
Docker安装(Ubuntu22版)
笔记·学习·spring cloud·docker·容器
言之。8 小时前
别学了,打会王者吧
java·python·mysql·容器·spark·php·html5
秦始皇爱找茬11 小时前
docker部署Jenkins工具
docker·容器·jenkins
hoho不爱喝酒14 小时前
微服务Nacos组件的介绍、安装、使用
微服务·云原生·架构
樽酒ﻬق15 小时前
Kubernetes 常用运维命令整理
运维·容器·kubernetes
Golinie16 小时前
Docker底层原理浅析 | namespace+cgroups+文件系统
docker·容器·文件系统·cgroups·unionfs