一、什么是控制器

控制器是 Kubernetes 中管理 Pod 的一种手段。自主式 Pod 在退出或意外关闭后不会被重新创建,而控制器管理的 Pod 在控制器的生命周期里,始终会维持 Pod 的副本数目。

Pod 控制器是管理 Pod 的中间层。使用 Pod 控制器之后,只需要告诉控制器想要多少个什么样的 Pod,它就会创建出满足条件的 Pod,并确保每一个 Pod 资源处于用户期望的目标状态。如果 Pod 资源在运行中出现故障,控制器会基于指定策略重新编排 Pod。

当建立控制器后,会把期望值写入 etcd,Kubernetes 中的 apiserver 检索 etcd 中保存的期望状态,并对比 Pod 的当前状态,如果出现差异,代码会自驱动立即恢复。

官方文档:https://v1-30.docs.kubernetes.io/zh-cn/docs/concepts/workloads/controllers/
 

二、控制器常用类 型

三、ReplicaSet 控制器

3.1 ReplicaSet 功能

ReplicaSet 是下一代的 Replication Controller,官方推荐使用 ReplicaSet。ReplicaSet 和 Replication Controller 的唯一区别是选择器的支持,ReplicaSet 支持新的基于集合的选择器需求。

ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行。虽然 ReplicaSet 可以独立使用,但今天它主要被 Deployments 用作协调 Pod 创建、删除和更新的机制。

3.2 ReplicaSet 参数说明

3.3 ReplicaSet 示例

生成 yml 文件:

[root@k8s-master ~]# kubectl create deployment replicaset --image myapp:v1 --dry-run=client -o yaml > replicaset.yml
[root@k8s-master ~]# vim replicaset.yml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset      # 指定 pod 名称,一定小写,如果出现大写报错
spec:
  replicas: 2           # 指定维护 pod 数量为 2
  selector:             # 指定检测匹配方式
    matchLabels:        # 指定匹配方式为匹配标签
      app: myapp        # 指定匹配的标签为 app=myapp
  template:             # 模板,当副本数量不足时,会根据下面的模板创建 pod 副本
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: myapp:v1
        name: myapp
[root@k8s-master ~]# kubectl apply -f replicaset.yml
replicaset.apps/replicaset created
[root@k8s-master ~]# kubectl get pods --show-labels
NAME               READY   STATUS    RESTARTS   AGE   LABELS
replicaset-l4xnr   1/1     Running   0          96s   app=myapp
replicaset-t2s5p   1/1     Running   0          96s   app=myapp

ReplicaSet 是通过标签匹配 Pod。当修改 Pod 标签后,ReplicaSet 会自动创建新的 Pod 来维持副本数量;当删除 Pod 后,ReplicaSet 也会自动创建新的 Pod 来维持副本数量,实现 Pod 自愈。

四、Deployment 控制器

4.1 Deployment 控制器的功能

为了更好的解决服务编排的问题,Kubernetes 在 V1.2 版本开始引入了 Deployment 控制器。Deployment 控制器并不直接管理 Pod,而是通过管理 ReplicaSet 来间接管理 Pod。Deployment 管理 ReplicaSet,ReplicaSet 管理 Pod。

Deployment 为 Pod 和 ReplicaSet 提供了一个声明式的定义方法。在 Deployment 中,ReplicaSet 相当于一个版本。

典型的应用场景:

  • 用来创建 Pod 和 ReplicaSet
  • 滚动更新和回滚
  • 扩容和缩容
  • 暂停与恢复

4.2 Deployment 控制器示例

生成 yaml 文件:
 

[root@k8s-master ~]# kubectl create deployment deployment --image myapp:v1 --dry-run=client -o yaml > deployment.yml
[root@k8s-master ~]# vim deployment.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment
spec:
  replicas: 4
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: myapp:v1
        name: myapp
[root@k8s-master ~]# kubectl apply -f deployment.yml
deployment.apps/deployment created

4.3 版本迭代

更新容器运行版本时,只需要修改镜像版本并重新 apply 即可。更新的过程是重新建立一个版本的 ReplicaSet,新版本的 ReplicaSet 会把 Pod 重建,然后把老版本的 ReplicaSet 回收。默认每次更新 25%。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment
spec:
  minReadySeconds: 5                # 最小就绪时间 5 秒
  replicas: 4
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: myapp:v2             # 更新为版本 2
        name: myapp

4.4 版本回滚

将镜像版本改回 v1 并重新 apply,即可回滚到之前的版本。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment
spec:
  replicas: 4
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: myapp:v1             # 回滚到之前版本
        name: myapp

4.5 滚动更新策略

可以通过 strategy 字段指定滚动更新策略:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment
spec:
  minReadySeconds: 5        # 最小就绪时间,指定 pod 每隔多久更新一次
  replicas: 4
  strategy:                 # 指定更新策略
    rollingUpdate:
      maxSurge: 1           # 比定义 pod 数量多几个
      maxUnavailable: 0     # 比定义 pod 个数少几个
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: myapp:v1
        name: myapp
4.6 暂停及恢复

在实际生产环境中,我们做的变更可能不止一处。当修改了一处后,如果执行变更就直接触发了更新,而我们期望的是当把所有修改都搞定后一次触发。因此可以使用暂停功能,避免触发不必要的线上更新。

[root@k8s2 pod]# kubectl rollout pause deployment deployment-example

暂停后,调整副本数、修改镜像和资源都不会触发更新。修改完成后,使用以下命令恢复:

[root@k8s2 pod]# kubectl rollout resume deployment deployment-example

五、DaemonSet 控制器

5.1 DaemonSet 功能

DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时,也会为他们新增一个 Pod;当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。

DaemonSet 的典型用法:

  • 在每个节点上运行集群存储 DaemonSet,例如 glusterd、ceph
  • 在每个节点上运行日志收集 DaemonSet,例如 fluentd、logstash
  • 在每个节点上运行监控 DaemonSet,例如 Prometheus Node Exporter、zabbix agent 等

5.2 DaemonSet 示例

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemonset-example
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      tolerations:      # 对于污点节点的容忍
      - effect: NoSchedule
        operator: Exists
      containers:
      - name: nginx
        image: nginx
[root@k8s-master ~]# kubectl get pods -o wide
NAME              READY   STATUS    RESTARTS   AGE   IP           NODE
daemonset-87h6s   1/1     Running   0          47s   10.244.0.8   k8s-master
daemonset-n4vs4   1/1     Running   0          47s   10.244.2.38  k8s-node2
daemonset-vhxmq   1/1     Running   0          47s   10.244.1.40  k8s-node1

六、Job 控制器

6.1 Job 控制器功能

Job 主要用于负责批量处理(一次要处理指定数量任务)短暂的一次性(每个任务仅运行一次就结束)任务。

Job 特点如下:

  • 当 Job 创建的 Pod 执行成功结束时,Job 将记录成功结束的 Pod 数量
  • 当成功结束的 Pod 达到指定的数量时,Job 将完成执行

关于重启策略设置的说明:

  • 如果指定为 OnFailure,则 Job 会在 Pod 出现故障时重启容器,而不是创建 Pod,failed 次数不变
  • 如果指定为 Never,则 Job 会在 Pod 出现故障时创建新的 Pod,并且故障 Pod 不会消失,也不会重启,failed 次数加 1
  • 如果指定为 Always 的话,就意味着一直重启

6.2 Job 控制器示例
 

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  completions: 6        # 一共完成任务数为 6
  parallelism: 2        # 每次并行完成 2 个
  template:
    spec:
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]    # 计算 Π 的后 2000 位
      restartPolicy: Never                      # 关闭后不自动重启
  backoffLimit: 4                               # 运行失败后尝试 4 次重新运行
[root@k8s2 pod]# kubectl apply -f job.yml

七、CronJob 控制器

7.1 CronJob 控制器功能

CronJob 创建基于时间调度的 Jobs。CronJob 控制器以 Job 控制器资源为其管控对象,并借助它管理 Pod 资源对象。CronJob 可以以类似于 Linux 操作系统的周期性任务作业计划的方式控制其运行时间点及重复运行的方式。CronJob 可以在特定的时间点(反复的)去运行 Job 任务。

7.2 CronJob 控制器示例

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
[root@k8s2 pod]# kubectl apply -f cronjob.yml

八、总结

控制器是 K8s 管理 Pod 的中间层,将期望状态存入 etcd,apiserver 对比实际状态,出现差异自动调回期望状态,实现 Pod 自愈,自主式 Pod 无该能力。

ReplicaSet:通过标签匹配管理 Pod 副本,保证指定数量 Pod 运行;主要被 Deployment 调用,不建议直接使用。

Deployment:生产最常用,间接管理 ReplicaSet,ReplicaSet 对应一个版本。支持扩容缩容、滚动更新、版本回滚;可配置 maxSurge、maxUnavailable 控制更新节奏;支持 rollout 暂停 / 恢复,适合分批修改后一次性生效。

DaemonSet:在全部或指定节点运行一个 Pod 副本,节点新增 / 删除会同步增减 Pod,多用于日志采集、监控代理、存储组件这类节点级守护程序,可配置容忍度处理污点节点。

Job:一次性任务控制器,运行短暂任务,可配置完成数、并行数;通过 restartPolicy 控制失败行为,backoffLimit 限定失败重试次数,任务完成后结束。

CronJob:基于 Cron 时间调度周期性创建 Job,实现定时任务,底层依赖 Job 完成实际业务执行。

更多推荐