Kubernetes五大核心控制器深度解析:从原理到实践

引言:什么是Kubernetes控制器?

  • 在Kubernetes生态系统中,控制器扮演着"智能大脑"的角色。它们持续监控集群状态,确保实际状态与期望状态保持一致。控制器模式是Kubernetes实现声明式API和自愈能力的关键机制。

控制器模式核心思想

  • 控制循环(Control Loop)

    • 每个控制器都运行一个无限循环,执行三个核心步骤:

      1. 观察(Observe) :通过API Server监视资源状态变化
      2. 分析(Diff) :比较期望状态(Spec)与实际状态(Status)
      3. 执行(Act) :采取必要操作使实际状态向期望状态收敛
  • 声明式状态管理

    • 控制器采用声明式(Declarative)而非命令式(Imperative)方法:

      • 用户声明"期望状态"
      • 控制器负责实现并维持该状态
      • 系统具备自愈能力

ReplicaSet控制器

定位与作用

ReplicaSet(RS)是Kubernetes中确保指定数量Pod副本运行的基础控制器。它是Deployment的底层实现组件,负责维护应用在集群中的副本数量,确保Pod数量始终与期望值匹配

核心特性

  • 精确维护Pod副本数量
  • 通过标签选择器识别和管理Pod
  • 提供基本的扩缩容能力
  • 自动替换失败或删除的Pod

ReplicaSet与Deployment的关系

scss 复制代码
 Deployment (上层抽象)
     ↓ 管理
 ReplicaSet (副本管理)  
     ↓ 控制
 Pod (运行实例)

示例

yaml 复制代码
 cat rs-nginx.yaml
 ​
 ​
 apiVersion: apps/v1
 kind: ReplicaSet
 metadata:
   name: nginx-rs
   labels:
     app: nginx
 spec:
   replicas: 3  # 期望的Pod副本数
   selector:    # 标签选择器,识别要管理的Pod
     matchLabels:
       app: nginx
   template:    # Pod模板,用于创建新Pod
     metadata:
       labels:
         app: nginx
     spec:
       containers:
       - name: nginx
         image: nginx:1.19
         ports:
         - containerPort: 80
         resources:     #配置资源限制
           requests:
             memory: "64Mi"
             cpu: "250m"
           limits:
             memory: "128Mi"
             cpu: "500m"
             
             
 kubectl apply -f rs-nginx.yaml

Deployment控制器

定位与作用

Deployment是Kubernetes中用于部署无状态应用的高级控制器。它建立在ReplicaSet之上,提供了声明式的更新、回滚和扩缩容能力,确保应用以可控的方式发布和运行。

核心特性

  • 管理ReplicaSet,间接控制Pod副本数
  • 支持滚动更新(Rolling Update)、蓝绿部署(Blue-Green)
  • 自动扩缩容(结合HPA(需部署metrics-server组件))

示例

yaml 复制代码
 apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: web-app
   labels:
     app: nginx
 spec:
   replicas: 3  # 期望的Pod副本数
   selector:
     matchLabels:
       app: nginx
   strategy:
     type: RollingUpdate
     rollingUpdate:
       maxSurge: 1        # 更新时最大可超出副本数
       maxUnavailable: 1  # 更新时最大不可用副本数
   template:
     metadata:
       labels:
         app: nginx
     spec:
       containers:
       - name: nginx
         image: nginx:1.19
         ports:
         - containerPort: 80
         resources:
           requests:
             memory: "64Mi"
             cpu: "250m"
           limits:
             memory: "128Mi"
             cpu: "500m"
         livenessProbe:    #配置存活性探针
           httpGet:
             path: /
             port: 80
           initialDelaySeconds: 30
           periodSeconds: 10
           
           
           
 #操作          
 # 创建Deployment
 kubectl apply -f deployment.yaml
 ​
 # 查看滚动更新状态
 kubectl rollout status deployment/web-app
 ​
 # 执行滚动更新(镜像升级)
 kubectl set image deployment/web-app nginx=nginx:1.20
 ​
 # 回滚到上一个版本
 kubectl rollout undo deployment/web-app
 ​
 # 查看更新历史
 kubectl rollout history deployment/web-app
 ​
 # 水平自动扩缩容
 kubectl autoscale deployment web-app --min=2 --max=10 --cpu-percent=80

DaemonSet控制器

定位与作用

DaemonSet确保每个节点(或满足条件的节点)上都运行一个指定的Pod副本。它适用于需要在每个节点上运行的系统级服务,如日志收集、监控代理等。

核心特性

  • 确保每个节点(或满足条件的节点)运行一个Pod副本
  • 节点加入集群时自动部署Pod
  • 节点从集群移除时自动删除Pod

示例

yaml 复制代码
 apiVersion: apps/v1
 kind: DaemonSet
 metadata:
   name: filebeat
   labels:
     app: filebeat
 spec:
   selector:
     matchLabels:
       name: filebeat
   template:
     metadata:
       labels:
         app: filebeat
     spec:
       tolerations:  # 允许在污点节点上运行
       - key: node-role.kubernetes.io/master
         effect: NoSchedule   #该节点不在接受新的Pod调度,但已经调度到该节点的Pod不会被驱逐。
       containers:
       - name: filebeat
         image: docker.elastic.co/beats/filebeat:8.13.4
         resources:
           limits:
             memory: 200Mi
           requests:
             cpu: 100m
             memory: 200Mi
         volumeMounts:
         - name: varlog
           mountPath: /var/log
         - name: varlibdockercontainers
           mountPath: /var/lib/docker/containers
           readOnly: true
       terminationGracePeriodSeconds: 30
       volumes:
       - name: varlog
         hostPath:
           path: /var/log
       - name: varlibdockercontainers
         hostPath:
           path: /var/lib/docker/containers
           
           
 #terminationGracePeriodSeconds: 30
 如果在优雅终止期内容器正常退出,那么Kubernetes会立即清理Pod。如果容器在优雅终止期结束后仍然没有退出,Kubernetes会发送SIGKILL信号强制杀死容器。
 让容器有机会完成一些清理工作,比如保存状态、关闭网络连接等,从而优雅地停止,而不是被强制杀死。    
 确保容器有足够的时间完成清理工作,避免数据丢失或服务异常中断。

StatefulSet控制器

定位与作用

StatefulSet是Kubernetes中用于部署有状态应用的控制器。它为每个Pod提供稳定的唯一标识(如有序索引、固定网络标识)和持久化存储,适用于需要稳定拓扑和持久化存储的应用,如数据库、消息队列等。

核心特性

  • 稳定的、唯一的网络标识符(pod-name.service-name)(稳定的 DNS 名称和主机名)

    • 其本质对应的是一个service资源,只不过这个service没有定义VIP,称之为headless service,即"无头服务"。

    • 通过"headless service"来维护Pod的网络身份,会为每个Pod分配一个数字编号并且按照编号顺序部署。

    • 无头服务("headless service")要求满足以下两点:

      • 将svc资源的clusterIP字段设置None,即"clusterIP: None"
      • 将sts资源的serviceName字段声明为无头服务的名称
    • 稳定的DNS记录:每个Pod可以通过固定的DNS名称访问:...svc.cluster.local

  • 稳定独立且持久化的存储(PersistentVolume)

    • Statefulset的存储卷使用VolumeClaimTemplate创建,称为"存储卷申请模板"。

    • 当sts资源使用VolumeClaimTemplate创建一个PVC时,同样也会为每个Pod分配并创建唯一的pvc编号,每个pvc绑定对应pv,从而保证每个Pod都有独立的存储。

    • 持久化存储原理

      • 当Pod使用持久化存储(如PersistentVolumeClaim,PVC)时,数据实际上是存储在一个独立的存储卷(PersistentVolume,PV)中。
      • Pod通过挂载(mount)的方式访问这个存储卷。
      • 存储卷的生命周期与Pod是分离的。这意味着,删除Pod并不会自动删除存储卷。
      • 在StatefulSet中,使用volumeClaimTemplates来为每个Pod动态创建PVC。
      • 每个Pod都会获得自己独立的存储卷,这些存储卷会一直存在,直到手动删除PVC。
      • 当Pod被重新创建(例如,由于节点故障或手动删除),StatefulSet控制器会确保新Pod挂载到同一个存储卷上,因此数据不会丢失。
  • 有序的、优雅的部署和扩缩

  • 有序的、优雅的删除和终止

示例

  • statefulset-headless-nginx.yaml
less 复制代码
 apiVersion: v1
 kind: Service
 metadata:
   name: svc-headless
 spec:
   ports:
   - port: 80
     name: web
   # 将clusterIP字段设置为None表示为一个无头服务,即svc将不会分配VIP。
   clusterIP: None
   selector:
     app: nginx
 ​
 ​
 ---
 ​
 apiVersion: apps/v1
 kind: StatefulSet
 metadata:
   name: sts-nginx
 spec:
   selector:
     matchLabels:
       app: nginx
   # 声明无头服务    
   serviceName: svc-headless
   replicas: 3 
   template:
     metadata:
       labels:
         app: nginx
     spec:
       containers:
       - name: nginx
         image: nginx:1.19
         imagePullPolicy: Always
         
         
         
         
         
 #测试输出
 [root@master51]# kubectl get sts,svc,po -o wide
 NAME                           READY   AGE   CONTAINERS   IMAGES
 statefulset.apps/sts-nginx   3/3     8s    nginx        nginx:1.19
 ​
 NAME                   TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
 service/kubernetes     ClusterIP   10.200.0.1   <none>        443/TCP   10d   <none>
 service/svc-headless   ClusterIP   None         <none>        80/TCP    8s    app=nginx
 ​
 NAME                READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
 pod/sts-nginx-0   1/1     Running   0          8s    10.100.203.186   worker52   <none>           <none>
 pod/sts-nginx-1   1/1     Running   0          6s    10.100.140.87    worker53   <none>           <none>
 pod/sts-nginx-2   1/1     Running   0          4s    10.100.160.134   master51   <none>           <none>
 ​
 ​
  • statefulset-headless-volumeClaimTemplates.yaml
less 复制代码
 apiVersion: v1
 kind: Service
 metadata:
   name: svc-headless
 spec:
   ports:
   - port: 80
     name: web
   clusterIP: None
   selector:
     app: nginx
 ---
 apiVersion: apps/v1
 kind: StatefulSet
 metadata:
   name: sts-nginx
 spec:
   selector:
     matchLabels:
       app: nginx
   serviceName: svc-headless
   replicas: 3 
   template:
     metadata:
       labels:
         app: nginx
     spec:
       containers:
       - name: nginx
         image: nginx:1.19
         ports:
         - containerPort: 80
           name: nginx
         volumeMounts:
         - name: data
           mountPath: /usr/share/nginx/html      
   # 卷声明模板,会为每个Pod去创建唯一的pvc并与之关联
   volumeClaimTemplates:
   - metadata:
       name: data
     spec:
       accessModes: [ "ReadWriteOnce" ]   # 单节点读写
       # 声明自定义的动态存储类,即sc资源。
       storageClassName: "sc01"
       resources:
         requests:
           storage: 2Gi
 ---
 apiVersion: v1
 kind: Service
 metadata:
   name: svc-sts-nginx
 spec:
   type: ClusterIP
   clusterIP: 10.200.0.200
   selector:
      app: nginx
   ports:
   - port: 80
     targetPort: nginx
 ​
 ​
 ​
 ​
 #测试与输出
 [root@master51 statefulsets]# kubectl get sts,svc,po -o wide
 NAME                           READY   AGE   CONTAINERS   IMAGES
 statefulset.apps/sts-nginx   3/3     6s    nginx        nginx:1.19
 ​
 NAME                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE   SELECTOR
 service/kubernetes        ClusterIP   10.200.0.1     <none>        443/TCP   10d   <none>
 service/svc-headless      ClusterIP   None           <none>        80/TCP    6s    app=nginx
 service/svc-sts-nginx     ClusterIP   10.200.0.200   <none>        80/TCP    6s    app=nginx
 ​
 NAME                READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
 pod/sts-nginx-0   1/1     Running   0          6s    10.100.203.163   worker52   <none>           <none>
 pod/sts-nginx-1   1/1     Running   0          5s    10.100.140.92    worker53   <none>           <none>
 pod/sts-nginx-2   1/1     Running   0          3s    10.100.160.132   master51   <none>           <none>
 ​
 ​
 ​
 #进入pod 中向nginx默认静态页面输入
 [root@master51 statefulsets]# kubectl exec -it sts-xiuxian-0  -- sh
 / # echo "shic zhen shuai" > /usr/share/nginx/html/index.html
 以此类推........
 ​
 [root@master51 statefulsets]# for i in `seq 10`; do curl 10.200.0.200; done
 shic zhen niu
 shic zhen meng
 shic zhen shuai
 shic zhen niu
 shic zhen meng
 shic zhen shuai
 shic zhen niu
 shic zhen meng
 shic zhen shuai
 shic zhen niu
 ​
 [root@master51 statefulsets]# kubectl delete pods --all
 pod "sts-nginx-0" deleted
 pod "sts-nginx-1" deleted
 pod "sts-nginx-2" deleted
 ​
 ​
 [root@master51 statefulsets]# kubectl get pods -o wide
 NAME            READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
 sts-nginx-0   1/1     Running   0          6s    10.100.203.171   worker52   <none>           <none>
 sts-nginx-1   1/1     Running   0          4s    10.100.140.99    worker53   <none>           <none>
 sts-nginx-2   1/1     Running   0          3s    10.100.160.178   master51   <none>           <none>
 ​
 [root@master51 statefulsets]# for i in `seq 10`; do curl 10.200.0.200; done
 shic zhen niu
 shic zhen meng
 shic zhen shuai
 shic zhen niu
 shic zhen meng
 shic zhen meng
 shic zhen niu
 shic zhen meng
 shic zhen shuai
 shic zhen niu
 ​
 ​
 #验证后端存储
 [root@master51 statefulsets]# kubectl get pvc -l app=nginx  | awk 'NR>=2{print $3}' | xargs kubectl describe pv  | grep VolumeHandle
     VolumeHandle:      10.0.0.51#data/nfs-server/sc01#pvc-dafd74ce-50b0-475d-94e1-2a64512c62ed##
     VolumeHandle:      10.0.0.51#data/nfs-server/sc01#pvc-a10dcb52-cd54-4d14-b666-068238359f0e##
     VolumeHandle:      10.0.0.51#data/nfs-server/sc01#pvc-8c84e2d8-3da8-4ecb-8902-e11bd8bd33b0##
 [root@master51 statefulsets]#     
 [root@master51 statefulsets]# cat  /data/nfs-server/sc01/pvc-dafd74ce-50b0-475d-94e1-2a64512c62ed/index.html 
 shic zhen shuai
 [root@master51 statefulsets]# 
 [root@master51 statefulsets]# cat  /data/nfs-server/sc01/pvc-a10dcb52-cd54-4d14-b666-068238359f0e/index.html 
 shic zhen meng
 [root@master51 statefulsets]# 
 [root@master51 statefulsets]# cat  /data/nfs-server/sc01/pvc-8c84e2d8-3da8-4ecb-8902-e11bd8bd33b0/index.html 
 shic zhen niu
 [root@master51 statefulsets]# 
 ​
  • statefuleset-updateStrategy.yaml
less 复制代码
 apiVersion: v1
 kind: Service
 metadata:
   name: sts-headless
 spec:
   ports:
   - port: 80
     name: web
   clusterIP: None
   selector:
     app: web
 ​
 ---
 ​
 apiVersion: apps/v1
 kind: StatefulSet
 metadata:
   name: sts-web
 spec:
   # 指定sts资源的更新策略
   updateStrategy:
     # 配置滚动更新
     rollingUpdate:
       # 当编号小于3时不更新,也是就是说Pod编号大于等于3的Pod会被更新
       partition: 3
   selector:
     matchLabels:
       app: web
   serviceName: sts-headless
   replicas: 5
   template:
     metadata:
       labels:
         app: web
     spec:
       containers:
       - name: c1
         ports:
         - containerPort: 80
           name: nginx     
         image: nginx:1.19
 ---
 apiVersion: v1
 kind: Service
 metadata:
   name: sts-svc
 spec:
   selector:
      app: web
   ports:
   - port: 80
     targetPort: nginx
 ​
 ​
 ​
 #测试验证
 [root@master51 statefulsets]# kubectl get pods -o wide
 NAME                  READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
 sts-web-0   1/1     Running   0          30s   10.100.203.183   worker52   <none>           <none>
 sts-web-1   1/1     Running   0          28s   10.100.140.102   worker53   <none>           <none>
 sts-web-2   1/1     Running   0          28s   10.100.160.180   master51   <none>           <none>
 sts-web-3   1/1     Running   0          26s   10.100.203.185   worker52   <none>           <none>
 sts-web-4   1/1     Running   0          25s   10.100.140.93    worker53   <none>           <none>
 [root@master51 statefulsets]# 
 [root@master51 statefulsets]# kubectl get pods -l app=web -o yaml | grep "- image:"
     - image: nginx:1.19
     - image: nginx:1.19
     - image: nginx:1.19
     - image: nginx:1.19
     - image: nginx:1.19
 [root@master51 statefulsets]# 
 [root@master51 statefulsets]# 
 [root@master51 statefulsets]# sed -i '/nginx/s#1.19#1.20#' statefuleset-updateStrategy.yaml 
 [root@master51 statefulsets]# 
 [root@master51 statefulsets]# grep image statefuleset-updateStrategy.yaml 
         image: nginx:1.20
 [root@master51 statefulsets]# 
 [root@master51 statefulsets]# kubectl apply -f statefuleset-updateStrategy.yaml
 service/sts-headless unchanged
 statefulset.apps/sts-web configured
 service/sts-svc unchanged
 [root@master51 statefulsets]# 
 [root@master51 statefulsets]# kubectl get pods -o wide
 NAME                  READY   STATUS    RESTARTS   AGE     IP               NODE        NOMINATED NODE   READINESS GATES
 sts-web-0   1/1     Running   0          2m23s   10.100.203.183   worker52   <none>           <none>
 sts-web-1   1/1     Running   0          2m21s   10.100.140.102   worker53   <none>           <none>
 sts-web-2   1/1     Running   0          2m21s   10.100.160.180   master51   <none>           <none>
 sts-web-3   1/1     Running   0          12s     10.100.203.174   worker52   <none>           <none>
 sts-web-4   1/1     Running   0          14s     10.100.140.101   worker53   <none>           <none>
 [root@master51 statefulsets]# 
 [root@master51 statefulsets]# kubectl get pods -l app=web -o yaml | grep "- image:"
     - image: nginx:1.19
     - image: nginx:1.19
     - image: nginx:1.19
     - image: nginx:1.20
     - image: nginx:1.20
 [root@master51 statefulsets]# 

Job/CronJob控制器

定位与作用

Job用于运行一次性任务,确保任务成功完成。CronJob基于时间调度,周期性地运行Job,适用于定时任务和批处理作业。

核心特性

  • Job

    • 确保指定数量的Pod成功完成任务后退出
    • 支持并行执行和顺序控制的任务处理
    • 提供任务失败重试和超时管理机制
  • CronJob

    • 基于时间表(Cron表达式)周期性地创建Job
    • 确保定时任务按计划自动执行
    • 提供任务并发策略和历史记录管理

示例

yaml 复制代码
 # Job示例
 apiVersion: batch/v1
 kind: Job
 metadata:
   name: data-processor
 spec:
   completions: 5     # 需要完成的Pod数量。默认为1,当成功完成的Pod数量达到completions时,Job才算完成。
   parallelism: 2     # 并行执行的Pod数量。控制Job的并行度,以避免同时启动太多Pod造成资源过载。
   backoffLimit: 3    # 任务异常失败重试次数,重试也是重新创建新的Pod,如果不指定,默认次数是6.
   template:
     spec:
       containers:
       - name: processor
         image: data-processor:latest
         command: ["python", "/app/process.py"]
         resources:
           requests:
             memory: "64Mi"
             cpu: "250m"
       restartPolicy: Never  # Job不能使用Always
 ​
 ---
 # CronJob示例
 apiVersion: batch/v1
 kind: CronJob
 metadata:
   name: daily-report
 spec:
   schedule: "0 2 * * *"  # 每天凌晨2点执行
   startingDeadlineSeconds: 600
   concurrencyPolicy: Forbid  # 禁止并发执行
   jobTemplate:
     spec:
       template:
         spec:
           containers:
           - name: report-generator
             image: report-tool:latest
             command: ["python", "/app/generate_report.py"]
           restartPolicy: OnFailure
相关推荐
牛奔1 小时前
Kubernetes 节点安全维护全流程:从驱逐 Pod 到彻底清理残留
java·安全·云原生·容器·kubernetes
伞啊伞2 小时前
k8s(三)操作管理
云原生·容器·kubernetes
x10n92 小时前
理解K8s动态准入控制器-基于Admission Webhook实现Sidecar自动注入检验等
云原生·容器·kubernetes·k8s准入控制器
LucidX2 小时前
Kubernetes集群架构与组件
容器·架构·kubernetes
2501_939909053 小时前
Kubernetes 操作管理概述与项目生命周期管理
云原生·容器·kubernetes
星环处相逢3 小时前
K8s 实战笔记:3 种发布策略 + YAML 配置全攻略
java·docker·kubernetes
LucidX3 小时前
Kubernetes 1.20 集群部署完整教程
云原生·容器·kubernetes
轩辰q4 小时前
Docker 容器化技术核心知识笔记
云原生·eureka
没有bug.的程序员4 小时前
Istio 架构全景解析:控制面 vs 数据面、核心组件与流量路径深度拆解
微服务·云原生·架构·istio·架构设计·envoy·servicemesh
思绪漂移4 小时前
从云原生到CNB实践:云原生开发与云原生构建的使用姿势
云原生·腾讯云