引言:什么是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的关系


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

示例


 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组件))

示例


 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

示例


 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

 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

 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

 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
    • 确保定时任务按计划自动执行
    • 提供任务并发策略和历史记录管理

示例


 # 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

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐