引言:什么是Kubernetes控制器?
- 在Kubernetes生态系统中,控制器扮演着"智能大脑"的角色。它们持续监控集群状态,确保实际状态与期望状态保持一致。控制器模式是Kubernetes实现声明式API和自愈能力的关键机制。
控制器模式核心思想
控制循环(Control Loop)
每个控制器都运行一个无限循环,执行三个核心步骤:
- 观察(Observe):通过API Server监视资源状态变化
- 分析(Diff):比较期望状态(Spec)与实际状态(Status)
- 执行(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