K8s-Pod控制器

一、Pod控制器概述

Pod 控制器(Controller) 又称为 工作负载(Workload) ,是 Kubernetes 中用于 管理 Pod 的中间层。 它的职责是确保集群中的 Pod 资源始终符合用户定义的"期望状态"。

功能

  • 保证 Pod 副本数量与期望一致

  • Pod 异常退出时,自动根据重启策略重建

  • 支持伸缩(扩容/缩容)、滚动更新、回滚

二、Pod控制器的类型

控制器 功能 应用场景
ReplicaSet 保证指定数量的 Pod 副本存在,支持滚动扩缩容。通常不直接使用,由 Deployment 管理。 无状态应用
Deployment 管理 ReplicaSet,实现声明式部署、滚动升级、回滚等。 Web 服务
StatefulSet 管理有状态应用,提供稳定的网络标识与存储。 数据库、Zookeeper
DaemonSet 每个 Node 上运行一个 Pod。 日志、监控、Agent
Job 执行一次性任务。 批处理、数据库迁移
CronJob 周期性任务(类似 Crontab)。 定期备份、通知

三、Deployment控制器

3.1 特点

  • 管理无状态应用

  • 支持滚动更新与回滚

  • 声明式配置更新

  • 与 ReplicaSet 协作使用

3.2 案例

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

3.3 查看控制器配置

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
......

##查看历史版本
[root@master01 ~]# kubectl rollout history deployment nginx-deployment 
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
1         <none>

四、StatefulSet控制器(有状态)

4.1 特点

  • 稳定存储:基于 PVC 实现,每个 Pod 独立存储
  • 稳定网络标识:Pod 名称和 DNS 名称固定
  • 有序部署/删除 :从 0 → N-1 创建,从 N-1 → 0 删除
  • 依赖 Headless Service

4.2 三个核心组件

  1. Headless Service(无头服务):用于为Pod资源标识符生成可解析的DNS记录。

  2. volumeClaimTemplates(存储卷申请模板):基于静态或动态PV供给方式为Pod资源提供专有的固定存储。

  3. StatefulSet:用于管控Pod资源。

为什么要有headless?

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

为什么要有volumeClainTemplate?

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

4.3 StatefulSet+NFS持久卷(案例)

4.3.1 定义Headless Service

bash 复制代码
vim  stateful-headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: myapp-pod
    
kubectl apply -f stateful-headless.yaml

4.3.2 定义StatefulSet动态

bash 复制代码
vim stateful-demo.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myapp
spec:
  serviceName: myapp-svc
  replicas: 3
  selector:
    matchLabels:
      app: myapp-pod
  template:
    metadata:
      labels:
        app: myapp-pod
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: myappdata
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: myappdata
	  annotations:          #动态PV创建时,使用annotations在PVC里声明一个StorageClass对象的标识进行关联
        volume.beta.kubernetes.io/storage-class: nfs-client-storageclass
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 2Gi

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

4.3.3 创建与验证

bash 复制代码
kubectl apply -f stateful-demo.yaml
kubectl get sts,pvc,pv,pods

4.3.4 滚动更新

bash 复制代码
//StatefulSet 控制器将在 StatefulSet 中删除并重新创建每个 Pod。它将以与 Pod 终止相同
的顺序进行(从最大的序数到最小的序数),每次更新一个 Pod。在更新其前身之前,它将等待正
在更新的 Pod 状态变成正在运行并就绪。如下操作的滚动更新是按照2-0的顺序更新。
# 修改镜像版本
kubectl edit sts myapp
kubectl get pods -w  # 观察按序更新 2→1→0

4.3.5 pod的名称解析

bash 复制代码
kubectl exec -it myapp-0 /bin/sh
Name:      myapp-0.myapp-svc.default.svc.cluster.local
Address 1: 10.244.2.27 myapp-0.myapp-svc.default.svc.cluster.local
/ # nslookup myapp-1.myapp-svc.default.svc.cluster.local
nslookup: can't resolve '(null)': Name does not resolve

Name:      myapp-1.myapp-svc.default.svc.cluster.local
Address 1: 10.244.1.14 myapp-1.myapp-svc.default.svc.cluster.local
/ # nslookup myapp-2.myapp-svc.default.svc.cluster.local
nslookup: can't resolve '(null)': Name does not resolve

Name:      myapp-2.myapp-svc.default.svc.cluster.local
Address 1: 10.244.2.26 myapp-2.myapp-svc.default.svc.cluster.local

//从上面的解析,我们可以看到在容器当中可以通过对Pod的名称进行解析到ip。其解析的域名格式如下:
(pod_name).(service_name).(namespace_name).svc.cluster.local


//总结
无状态:
1)deployment 认为所有的pod都是一样的
2)不用考虑顺序的要求
3)不用考虑在哪个node节点上运行
4)可以随意扩容和缩容 

有状态
1)实例之间有差别,每个实例都有自己的独特性,元数据不同,例如etcd,zookeeper
2)实例之间不对等的关系,以及依靠外部存储的应用。

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

五、DaemonSet控制器

5.1 功能

确保每个 Node 上都运行一个 Pod 副本,常用于运行系统级后台任务(守护进程)。

典型场景:

  • Fluentd / Logstash 日志收集

  • Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond 监控代理

  • 存储服务如 Ceph、GlusterFS

5.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
DaemonSet会在每个node节点都创建一个Pod
kubectl get pods

六、Job控制器

6.1 功能

用于执行一次性任务,任务完成后即退出。

应用场景:

  • 数据迁移

  • 批处理

  • 安全扫描

  • 离线数据处理

6.2 案例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
kubectl apply -f job.yaml
kubectl logs job/pi
#参数解释
.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镜像,因为镜像比较大,所以建议提前下载好
docker pull perl

kubectl apply -f job.yaml 

kubectl get pods
pi-bqtf7                 0/1     Completed   0          41s

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

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

6.3 案例2

bash 复制代码
//backoffLimit
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
  
kubectl apply -f job-limit.yaml


command: ["/bin/sh", "-c", "sleep 10;date;exit 1"]
容器启动后执行的命令:
    sleep 10 → 先睡眠 10 秒
    date → 打印当前日期
    exit 1 → 以 退出码 1 结束容器(即任务失败)

七、CronJob控制器

7.1 功能

周期性任务(类似 Linux Crontab)。

应用场景:

  • 定期备份

  • 定时通知

  • 日志清理

7.2 案例

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
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
          
//cronjob其它可用参数的配置
spec:
  concurrencyPolicy: Allow			#要保留的失败的完成作业数(默认为1)
  schedule: '*/1 * * * *'			#作业时间表。在此示例中,作业将每分钟运行一次
  startingDeadlineSeconds: 15		#pod必须在规定时间后的15秒内开始执行,若超过该时间未执行,则任务将不运行,且标记失败
  successfulJobsHistoryLimit: 3		#要保留的成功完成的作业数(默认为3)
  terminationGracePeriodSeconds: 30	#job存活时间 默认不设置为永久
  jobTemplate:						#作业模板。这类似于工作示例          
          
 
          
kubectl create -f cronjob.yaml 



//如果报错:Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log hello-1621587780-c7v54)
//解决办法:绑定一个cluster-admin的权限
kubectl create clusterrolebinding system:anonymous --clusterrole=cluster-admin --user=system:anonymous

八、无状态vs有状态应用对比

对比项 无状态(Deployment) 有状态(StatefulSet)
Pod 名称 随机生成 固定、有序(0→N-1)
存储 共享存储或无持久卷 每个 Pod 独立 PVC
网络标识 不固定 稳定 DNS 名称
扩缩容顺序 无序 有序(依次创建/删除)
应用示例 Web、API MySQL、ZooKeeper

九、常规Service与Headless Service对比

类型 是否有 ClusterIP 访问方式 作用
Service 负载均衡 + 服务发现 集群统一访问入口
Headless Service 直接解析到 Pod IP StatefulSet 中 DNS 定位

十、服务发现机制

Kubernetes 内置 DNS 机制:

  • 1.3 以前:SkyDNS

  • 1.3 ~ 1.11:KubeDNS

  • 1.11 以后:CoreDNS

Pod 间通信域名格式:(pod_name).(service_name).(namespace).svc.cluster.local

十一、总结

控制器 是否有状态 功能简述
Deployment 无状态应用部署、滚动升级
ReplicaSet 保证副本数量,通常由 Deployment 管理
StatefulSet 有状态应用,稳定网络与存储
DaemonSet 每个节点运行一个 Pod
Job 一次性任务
CronJob 周期性任务
相关推荐
追梦者12321 小时前
k8s项目实战篇 kubesphere安装
云原生·容器·kubernetes
-L71 天前
【Kubernetes】常见面试题汇总(二十五)
云原生·容器·kubernetes
努力搬砖的咸鱼1 天前
Node.js 和 Java 项目怎么写 Dockerfile
java·开发语言·docker·云原生·容器·node.js
二进制coder1 天前
Kubernetes全景解读:从云原生基石到卓越实践
云原生·容器·kubernetes
凯子坚持 c1 天前
Docker 深度解析:从虚拟化到新一代应用构建、运行与交付
运维·docker·容器
伊成1 天前
细说Docker命令
docker·容器·eureka
java_logo1 天前
vllm-openai Docker 部署手册
运维·人工智能·docker·ai·容器
jiyuzzz1 天前
Docker部署WordPress及相关配置
运维·docker·容器
风清再凯2 天前
05-k8s网络
网络·容器·kubernetes