k8s学习笔记6——Controller控制器

  • k8s内建多种controller,相当于状态机,用来控制pod的具体状态和行为
  • k8s有5种控制器,分别对应处理 无状态应用、有状态应用、守护型应用和批处理应用
  1. Deployment 
  2. StatefulSet
  3. DaemonSet
  4. Job
  5. CronJob

 

一. Deployment

  • 无状态服务控制器,由Deployment、ReplicaSet、Pod组成,支持集群扩缩容、滚动更新、版本回滚以及自动维护Pod可用性和副本数量 等功能
  • ReplicaSet和Pod 由 Deployment 自动管理,用户无需干预

image

需要了解的配置项就是spec下面几个选项:

  • replicas:指定副本数量,其实就是当前rs创建出来的pod的数量,默认为1
  • selector:选择器,它的作用是建立pod控制器和pod之间的关联关系,采用的Label Selector机制,在pod模板上定义label,在控制器上定义选择器,就可以表明当前控制器能管理哪些pod了
  • template:模板,就是当前控制器创建pod所使用的模板

 

imagePullPolicy: 是确保容器总是使用最新版本的镜像

  • IfNotPresent: 仅当镜像在本地不存在时,才被拉取
  • Never: 设镜像已经存在于本地,不会尝试拉取镜像
  • always: 确保每次容器启动时都会拉取最新的镜像

 

1)Deployment控制器的资源清单文件:

 1 [root@master ~]# vim mydeploy.yaml
 2 ---
 3 kind: Deployment              # 资源对象类型
 4 apiVersion: apps/v1           # 版本
 5 metadata:                     # 元数据
 6   name: myweb                 # 名称
 7 spec:                         # 详细定义
 8   replicas: 2                 # 副本数量
 9   strategy:                   # 策略
10     type: RollingUpdate       # 滚动更新策略
11     rollingUpdate:            # 滚动更新
12       maxSurge: 30%           # 最大额外可以存在的副本数,可以为百分比,也可以为整数
13       maxUnavailable: 30%     # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
14   selector:                   # 定义标签选择器
15     matchLabels:              # 支持 matchExpressions 表达式语法
16       app: httpd              # 通过标签来确定那个 Pod 由它来管理
17   template:                   # 定义用来创建 Pod 的模板,以下为 Pod 定义
18     metadata:                 # Pod元数据
19       labels:                 # 名称由控制器生成
20         app: httpd            # 这里只能定义标签
21   spec:                       # Pod的详细定义
22     restartPolicy: Always     # 重启策略
23     containers:               # 容器定义
24       - name: webserver       # 容器名称
25       image: myos:httpd       # 创建容器使用的容器
26       imagePullPolicy: Always # 镜像下载策略

 

 2)扩缩容

 1 [root@master ~]# kubectl scale deployment myweb(Deployment名字) --replicas=3(指定Pod数量)
 2  
 3 # 1、创建deployment
 4 [root@master ~]# kubectl create -f nginx-deployment.yaml --record=true
 5 deployment.apps/nginx-deployment created
 6  
 7 # 2、查看deployment
 8 # UP-TO-DATE 最新版本的pod的数量
 9 # AVAILABLE  当前可用的pod的数量
10 #   - your_namespace 你的命名空间名称
11 [root@master ~]# kubectl get deploy myweb -n your_spacename
12 NAME            READY   UP-TO-DATE   AVAILABLE   AGE
13 nginx-deployment   3/3     3            3           15s
14  
15 [root@master ~]#  kubectl get pods -n your_namespace
16 NAME                             READY   STATUS    RESTARTS   AGE
17 nginx-deployment-6696798b78-d2c8n   1/1     Running   0          4m19s
18 nginx-deployment-6696798b78-jxmdq   1/1     Running   0          94s
19 nginx-deployment-6696798b78-mktqv   1/1     Running   0          93s

 

3)镜像更新

  • deployment支持2种更新策略:重建更新 & 滚动更新
strategy:指定新的Pod替换旧的Pod的策略, 支持两个属性:
  type:指定策略类型,支持两种策略
    Recreate:在创建出新的Pod之前会先杀掉所有已存在的Pod
    RollingUpdate:滚动更新,就是杀死一部分,就启动一部分,在更新过程中,存在两个版本Pod
  rollingUpdate:当type为RollingUpdate时生效,用于为RollingUpdate设置参数,支持两个属性:
    maxUnavailable:用来指定在升级过程中不可用Pod的最大数量,默认为25%。
    maxSurge: 用来指定在升级过程中可以超过期望的Pod的最大数量,默认为25%。

 

4)滚动更新

  • deployment支持版本升级过程中的暂停、继续功能以及版本回退等诸多功能,下面具体来看.
  • kubectl rollout: 版本升级相关功能,支持下面的选项
    •   status 显示当前升级状态
    •   history 显示 升级历史记录
    •   pause 暂停版本升级过程
    •   resume 继续已经暂停的版本升级过程
    • restart 重启版本升级过程
    • undo 回滚到上一级版本(可以使用–to-revision回滚到指定版本)
# 修改镜像,滚动更新集群
[root@master ~]# kubectl set image deployment myweb webserver=myos:nginx
deployment.apps/myweb image updated
 
# 给新版本添加注释信息
[root@master ~]# kubectl annotate deployments myweb kubernetes.io/change-cause="nginx.v1"
deployment.apps/myweb annotated
 
# 查看历史版本信息
[root@master ~]# kubectl rollout history deployment myweb
deployment.apps/myweb
REVISION CHANGE-CAUSE
1 httpd:v1
2 nginx.v1
 
# 访问验证服务
[root@master ~]# curl -m 3 http://10.245.1.80
Nginx is running !

 

5)金丝雀发布

  • Deployment控制器支持控制更新过程中的控制,如“暂停(pause)”或“继续(resume)”更新操作。
  • 比如有一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本。然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行。确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布。
# 1、更新deployment的版本,并配置暂停deployment
[root@master ~]#  kubectl set image deploy your_deploy_name nginx=nginx:1.17.4 -n your_namespace && kubectl rollout pause deployment your_deploy_name -n your_namespace
deployment.apps/nginx-deployment image updated
deployment.apps/nginx-deployment paused
 
# 2、观察更新状态
#  - your_deploy_name 你的deploy名称
#  - your_namespace 你的命名空间名称
[root@master ~]# kubectl rollout status deploy your_deploy_name -n your_namespace 
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 4 new replicas have been updated...
 
# 3、监控更新的过程,可以看到已经新增了一个资源,但是并未按照预期的状态去删除一个旧的资源,就是因为使用了pause暂停命令
#   - your_namespace 你的命名空间名称
[root@master ~]# kubectl get rs -n your_namespace -o wide
NAME                       DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES         
nginx-deployment-5d89bdfbf9   3         3         3       19m     nginx        nginx:1.17.1   
nginx-deployment-675d469f8b   0         0         0       14m     nginx        nginx:1.17.2   
nginx-deployment-6c9f56fcfb   2         2         2       3m16s   nginx        nginx:1.17.4   
 
# - your_namespace 你的命名空间名称
[root@master ~]# kubectl get pods -n your_namespace
NAME                             READY   STATUS    RESTARTS   AGE
nginx-deployment-5d89bdfbf9-rj8sq   1/1     Running   0          7m33s
nginx-deployment-5d89bdfbf9-ttwgg   1/1     Running   0          7m35s
nginx-deployment-5d89bdfbf9-v4wvc   1/1     Running   0          7m34s
nginx-deployment-6c9f56fcfb-996rt   1/1     Running   0          3m31s
nginx-deployment-6c9f56fcfb-j2gtj   1/1     Running   0          3m31s
 
# 4、确保更新的pod没问题了,继续更新
#     - your_deploy_name 你的deploy名称
#     - your_namespace 你的命名空间名称
[root@master ~]# kubectl rollout resume deploy your_deploy_name -n your_namespace
deployment.apps/nginx-deployment resumed
 
# 5、查看最后的更新情况
#     - your_namespace 你的命名空间名称
[root@master ~]# kubectl get rs -n your_namespace -o wide
NAME                       DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES         
nginx-deployment-5d89bdfbf9   0         0         0       21m     nginx        nginx:1.17.1   
nginx-deployment-675d469f8b   0         0         0       16m     nginx        nginx:1.17.2   
nginx-deployment-6c9f56fcfb   4         4         4       5m11s   nginx        nginx:1.17.4   
 
# - your_namespace 你的命名空间名称
[root@master ~]# kubectl get pods -n your_namespace
NAME                             READY   STATUS    RESTARTS   AGE
nginx-deployment-6c9f56fcfb-7bfwh   1/1     Running   0          37s
nginx-deployment-6c9f56fcfb-996rt   1/1     Running   0          5m27s
nginx-deployment-6c9f56fcfb-j2gtj   1/1     Running   0          5m27s
nginx-deployment-6c9f56fcfb-rf84v   1/1     Running   0          37s

 

6)删除控制器

# 删除控制器方法1
[root@master ~]# kubectl delete deployments myweb
deployment.apps "myweb" deleted
 
# 删除控制器方法2
[root@master ~]# kubectl delete -f mydeploy.yaml
deployment.apps "myweb" deleted

 

二. DaemonSet

DaemonSet控制器

  • 无法自定义副本数量
  • 所创建的Pod与node节点绑定
  • 每个node上都会允许一个Pod
  • 当有新Node加入集群时,会为他新增Pod副本,当Node从集群移除时,这些Pod也会被回收,典型应用:kube-proxy

image

 

1)DaemonSet控制器的资源清单文件

 1 [root@master ~]# vim myds.yaml
 2 ---
 3 kind: DaemonSet       # 资源对象类型
 4 apiVersion: apps/v1   # 版本
 5 metadata:             # 元数据
 6   name: myds          # 名称
 7 spec: # 详细定义
 8   selector:           # 定义标签选择器
 9     matchLabels:      # 支持 matchExpressions 表达式语法
10       app: httpd      # 通过标签来确定那个 Pod 由它来管理
11   template:           # 定义用来创建 Pod 的模板,以下为 Pod 定义
12     metadata:
13       labels:
14         app: httpd
15   spec:
16     restartPolicy: Always
17     containers:
18     - name: webserver
19       image: myos:httpd
20       imagePullPolicy: Always
21  
22 [root@master ~]# kubectl apply -f myds.yaml
23 daemonset.apps/myds created
24  
25 [root@master ~]# kubectl get pods -o wide
26 NAME READY STATUS RESTARTS AGE IP NODE
27 NOMINATED NODE READINESS GATES
28 myds-78b2h 1/1 Running 0 31s 10.244.153.154 node-0005
29 <none> <none>
30 myds-78pgb 1/1 Running 0 31s 10.244.243.226 node-0003
31 <none> <none>
32 myds-cg2sv 1/1 Running 0 31s 10.244.147.30 node-0002
33 <none> <none>
34 myds-pp7s6 1/1 Running 0 31s 10.244.240.162 node-0004
35 <none> <none>
36 myds-qrp82 1/1 Running 0 32s 10.244.21.155 node-0001
37 <none> <none>

 

2)DS控制器 受Taint污点策略影响

 1 [root@master ~]# kubectl taint node node-0001 k=v:NoSchedule
 2 node/node-0001 tainted
 3  
 4 [root@master ~]# kubectl delete -f myds.yaml
 5 daemonset.apps "myds" deleted
 6  
 7 [root@master ~]# kubectl apply -f myds.yaml
 8 daemonset.apps/myds created
 9  
10 # 有污点不会部署,特殊需求可以设置容忍策略
11 [root@master ~]# kubectl get pods
12 NAME READY STATUS RESTARTS AGE
13 myds-fxlgq 1/1 Running 0 33s
14 myds-j5779 1/1 Running 0 33s
15 myds-nb6bv 1/1 Running 0 33s
16 myds-vkk6x 1/1 Running 0 33s
17  
18 # 删除污点后会立即部署
19 [root@master ~]# kubectl taint node node-0001 k=v:NoSchedule-
20 node/node-0001 untainted
21 [root@master ~]# kubectl get pods
22 NAME READY STATUS RESTARTS AGE
23 myds-bq2nv 1/1 Running 0 3s
24 myds-fxlgq 1/1 Running 0 114s
25 myds-j5779 1/1 Running 0 114s
26 myds-nb6bv 1/1 Running 0 114s
27 myds-vkk6x 1/1 Running 0 114s
28  
29 # 删除控制器
30 [root@master ~]# kubectl delete -f myds.yaml
31 daemonset.apps "myds" deleted

 

 三. Job / CronJob

1)Job

  • 单任务控制器,执行一次任务
  • CronJob是Job的升级版,基于时间管理的Job控制器
  • restartPOlicy策略会判断exit状态码,状态为0表示正常,其他都是失败
  • 任务执行出错,会重新执行该任务
[root@master ~]# vim myjob.yaml
---
kind: Job
apiVersion: batch/v1
metadata:
  name: myjob
spec:
  template: # 以下定义 Pod 模板
    spec:
      restartPolicy: OnFailure
      containers:
      - name: myjob
        image: myos:8.5
        command: ["/bin/bash"]
        args:
        - -c
        - |
          sleep 3
          exit $($RANDOM%2)
 
[root@master ~]# kubectl apply -f myjob.yaml
job.batch/myjob created
 
# 失败了会重启
[root@master ~]# kubectl get pods -l job-name=myjob -w
NAME READY STATUS RESTARTS AGE
myjob-plnhc 1/1 Running 0 3s
myjob-plnhc 0/1 Completed 0 4s
myjob-plnhc 0/1 Completed 0 5s
myjob-plnhc 0/1 Completed 0 6s
myjob-plnhc 0/1 Completed 0 6s
 
[root@master ~]# kubectl get jobs.batch
NAME COMPLETIONS DURATION AGE
myjob 1/1 6s 91s
 
# 删除Job控制器
[root@master ~]# kubectl delete -f myjob.yaml
job.batch "myjob" deleted

 

2)CronJob

  • 时间定义 schedule: 分 时 日 月 周
  • 会按照时间周期运行
  • 只保留执行三次的结果,多余被删除
[root@master ~]# vim mycj.yaml
---
kind: CronJob
apiVersion: batch/v1
metadata:
  name: mycj
spec:
  schedule: "* * * * 1-5"
  jobTemplate: # 以下定义Job模板
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: myjob
            image: myos:8.5
            command: ["/bin/bash"]
            args:
            - -c
            - |
              sleep 3
              exit $($RANDOM%2)
 
[root@master ~]# kubectl apply -f mycj.yaml
cronjob.batch/mycj created
 
[root@master ~]# kubectl get cronjobs
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
mycj * * * * 1-5 False 0 <none> 14s
 
# 按照时间周期,每分钟触发一个任务
[root@master ~]# kubectl get jobs -w
NAME COMPLETIONS DURATION AGE
mycj-28263259 1/1 29s 70s
mycj-28263260 1/1 6s 10s
mycj-28263261 0/1 0s
mycj-28263261 0/1 0s 0s
mycj-28263261 0/1 2s 2s
mycj-28263261 0/1 5s 5s
mycj-28263261 0/1 5s 5s
 
# 保留三次结果,多余的会被删除
[root@master ~]# kubectl get jobs
NAME COMPLETIONS DURATION AGE
mycj-28263261 1/1 24s 2m13s
mycj-28263262 1/1 27s 73s
mycj-28263263 1/1 6s 13s
 
# 删除CJ控制器
[root@master ~]# kubectl delete -f mycj.yaml
cronjob.batch "mycj" deleted

 

四. StatefulSet

Statefulset主要是用来部署有状态应用

  • 无状态应用中所有Pod之间是无法区分的,它们都是一样的,从而不需要考虑应用在哪个node上运行,能够进行随意伸缩和扩展。
  • 有状态应用中每个Pod都是各不相同的,各自具有唯一的网络标识符和存储
  • 对于StatefulSet中的Pod,每个Pod挂载自己独立的存储,如果一个Pod出现故障,从其他节点启动一个同样名字的Pod,要挂载上原来Pod的存储继续以它的状态提供服务。适合StatefulSet的业务包括数据库服务MySQL 和 PostgreSQL,集群化管理服务Zookeeper、etcd等有状态服务
  • 使用StatefulSet,Pod仍然可以通过漂移到不同节点提供高可用,而存储也可以通过外挂的存储来提供高可靠性,StatefulSet做的只是将确定的Pod与确定的存储关联起来保证状态的连续性。

image

 

  • StatefulSet控制器
    •   StatefulSet旨在与有状态的应用及分布式统一使用,涉及了Headless服务、存储卷、DNS等相关知识,是一个宽泛而复杂的话题
  • Headless服务
    •   在配置StatefulSets的时候,首先要定义一个Headless的服务
    •   在创建Pod的时候会自动把<Pod名称>注册为域名

1)headless服务

  在 Kubernetes 中,Headless Service(无头服务) 是一种特殊类型的 Service,其核心特点是不分配 ClusterIP,而是直接返回后端 Pod 的 DNS 记录。它专为需要直接访问 Pod 的场景设计,尤其适用于有状态应用(如数据库、分布式存储)

  Headless Service与普通Service的区别

特性普通 Service (ClusterIP)Headless Service
ClusterIP 分配虚拟 IP(如 10.96.xx.xx 显式设置为 None(无 ClusterIP)
DNS 解析 解析到 Service 的 ClusterIP 直接解析到后端 Pod 的 IP 列表
负载均衡 通过 kube-proxy 实现负载均衡 无负载均衡,客户端直连 Pod
适用场景 无状态应用(如 Web 服务) 有状态应用(如 MySQL、Redis 集群)

  示例 YAML 配置

# 配置 headless 服务
[root@master ~]# vim mysvc2.yaml
---
kind: Service
apiVersion: v1
metadata:
  name: mysvc2 # 服务名称
spec:
  type: ClusterIP
  clusterIP: None # 设置IP为None,表明这是一个headless服务
  selector:
    app: httpd
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
 
[root@master ~]# kubectl get service mysvc2
NAME        TYPE      CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysvc2   ClusterIP     None       <none>      80/TCP 17s

 

  Headless Service核心价值

  1. 提供稳定的网络标识

    当与 StatefulSet 结合使用时,每个 Pod 会获得一个固定且可预测的 DNS 名称,格式为:
    <pod-name>.<headless-service>.<namespace>.svc.cluster.local
    例如:web-0.nginx-headless.default.svc.cluster.local

  2. 支持 Pod 级服务发现

    客户端可通过 DNS 查询获取所有后端 Pod 的 IP 地址,实现:

    •   直接连接特定 Pod(如主从数据库)
    •   自定义负载均衡逻辑(如客户端分片)
    •   集群内成员发现(如 etcd 节点互连)

  3. 与 StatefulSet 深度集成

    StatefulSet 管理的 Pod 具有固定名称和有序部署特性,配合 Headless Service 可实现:

    • 稳定的 DNS 记录(Pod 重建后 DNS 名称不变)
    • 有序扩缩容(扩容时新 Pod 通过 DNS 发现现有成员)
    • 持久化存储绑定(PVC 随 Pod 名称持久化)

 

2)StatefulSet资源配置文件

 1 [root@master ~]# vim mysts.yaml
 2 ---
 3 kind: StatefulSet     # 资源对象类型
 4 apiVersion: apps/v1   # 版本
 5 metadata:             # 元数据
 6   name: mysts         # 名称
 7 spec:                 # 详细定义
 8   serviceName: mysvc2 # 关联Headless Service
 9   replicas: 3         # 副本数量
10   selector:           # 定义标签选择器
11     matchLabels:      # 支持 matchExpressions 表达式语法
12       app: httpd      # 通过标签来确定那个 Pod 由它来管理
13   template:           # 定义用来创建 Pod 的模板,以下为 Pod 定义
14     metadata:
15       labels:
16         app: httpd
17     spec:
18       restartPolicy: Always
19       containers:
20       - name: webserver
21         image: myos:httpd
22         imagePullPolicy: Always
23  
24 [root@master ~]# kubectl apply -f mysts.yaml
25 statefulset.apps/mysts created
26  
27 [root@master ~]# kubectl get pods
28 NAME READY STATUS RESTARTS AGE
29 mysts-0 1/1 Running 0 8s
30 mysts-1 1/1 Running 0 7s
31 mysts-2 1/1 Running 0 6s
32  
33 [root@master ~]# host mysts-0.mysvc2.default.svc.cluster.local 10.245.0.10
34 Using domain server:
35 Name: 10.245.0.10
36 Address: 10.245.0.10  #53
37 Aliases:
38 mysts-0.mysvc2.default.svc.cluster.local has address 10.244.153.159
39  
40 [root@master ~]# host mysvc2.default.svc.cluster.local 10.245.0.10
41 Using domain server:
42 Name: 10.245.0.10
43 Address: 10.245.0.10  #53
44 Aliases:
45 mysvc2.default.svc.cluster.local has address 10.244.147.37
46 mysvc2.default.svc.cluster.local has address 10.244.153.159
47 mysvc2.default.svc.cluster.local has address 10.244.240.164
48  
49 # 删除sts控制器
50 [root@master ~]# kubectl delete -f mysts.yaml -f mysvc2.yaml
51 statefulset.apps "mysts" deleted
52 service "mysvc2" deleted

 

总结

Headless Service 的核心本质是:
通过 DNS 暴露 Pod 的直接访问入口,而非代理层
其核心价值在于:
✅ 为 StatefulSet 提供稳定的网络标识
✅ 支持有状态应用的集群发现与通信
✅ 实现客户端直连 Pod 的自定义逻辑

使用模式固定:

# Headless Service 声明
spec:
  clusterIP: None   # 无 ClusterIP
  selector: ...     # 关联 Pod

# StatefulSet 引用
spec:
  serviceName: "your-headless-service"  # 绑定 Headless Service

 

五. Deployment 与 StatefulSet 的区别

1)核心差异

  • Deployment‌适用于‌无状态应用‌,不维护Pod的唯一标识和存储,通过ReplicaSet管理副本数量,支持滚动更新和回滚。 
  • StatefulSet‌适用于‌有状态应用‌,为Pod提供唯一且持久的网络标识符,绑定持久化存储,并按照定义的顺序管理Pod的创建、更新和删除。

2)具体区别

    • 1. 状态管理‌
      • Deployment不维护Pod的唯一身份,Pod可被任意替换且无需保持数据一致性。 ‌
      • StatefulSet为每个Pod分配固定且持久的标识符(如pod-name-0),即使重新调度也能保持唯一性。 ‌
    • ‌2. 存储与网络标识‌

      • Deployment不绑定持久化存储,Pod数据随实例消失。 ‌
      • StatefulSet通过PersistentVolumeClaim绑定存储,数据在Pod重启或重新调度时保留。 ‌
    • ‌3. 扩容与更新策略‌

      • Deployment支持滚动更新(逐个替换Pod),确保服务高可用。 ‌
      • StatefulSet通常不支持滚动更新(需考虑数据一致性),需按顺序部署或缩容。 ‌
    • ‌4. 适用场景‌

      • Deployment适合微服务、Web应用等无需持久化存储的应用。 ‌
      • StatefulSet适用于数据库集群、分布式缓存等需要稳定网络标识和持久存储的场景。 ‌

 

posted on 2025-09-18 14:56  Karlkiller  阅读(35)  评论(0)    收藏  举报

导航