Kubernetes 入门教程之四

大纲

Kubernetes 核心技术

Controller 的使用

部署应用

部署无状态应用

学习目标

本节将演示在 Kubernetes 集群中,如何通过 Deployment 部署一个 Nginx 的 Pod,并通过 Service 暴露端口,以便从 Kubernetes 集群外部访问 Nginx。

Kubernetes 无状态应用(Stateless)的特点

  • 主要特点:
    • Pod 之间完全一致
      • 所有 Pod 完全等价,没有区别,任意一个 Pod 都可以处理请求。
    • 没有启动顺序要求
      • Pod 启动、停止的先后顺序不影响整体业务。
    • 不依赖固定 Node 节点
      • Pod 可以在任意 Node 节点上调度和运行,不需要绑定特定节点。
    • 可随意扩缩容
      • Pod 数量可以随时增加或减少,自动水平扩容(HPA)非常适合。
    • 无持久化存储依赖
      • 不保存本地状态,数据通常存储在外部系统中,例如:数据库、对象存储、缓存服务等。
    • Kubernetes 控制器
      • 通常使用 Deployment 管理,支持滚动升级和回滚。
  • 典型代表:
    • Nginx、Web 服务、后端接口、无状态微服务。

Kubernetes 通过 Deployment 部署无状态应用

  • 生成用于部署一个 Nginx 的 Deployment 的 YAML 配置文件,其中 Deployment 的名称为 nginx
1
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > nginx_deployment.yaml
  • 自动生成的 YAML 配置文件的内容如下所示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels: # 标签:标识 Deployment 自身
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels: # 标签:在 Deployment 与 Pod 之间建立管理关系
app: nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels: # 标签:定义 Pod 的身份(标签)
app: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
配置信息作用对象核心作用简单解释
metadata.labelsDeployment 自身标识 Deployment 自身给 Deployment 资源对象自己打上标签,用于被其他资源(如 Service、HPA)查询和选择,或者方便用户管理。它说:” 我是谁。”
spec.selector.matchLabelsDeployment 的选择器在 Deployment 与 Pod 之间建立管理关系 Deployment 用来寻找和管理拥有指定标签的 Pod 的规则。它说:” 哪些 Pod 归我管。”
spec.template.metadata.labelsPod 模板定义 Pod 的身份(标签)规定了 Deployment 在创建新 Pod 时会为其打上的标签。它确保了新 Pod 都带有能被选择器识别的标签。它说:” 我创建的 Pod 长这样。”
  • 创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Deployment)
1
kubectl apply -f nginx_deployment.yaml
  • 查看所有 Pod 的运行状态
1
kubectl get pods -o wide
1
2
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-6799fc88d8-jwp6g 1/1 Running 0 29m 10.244.2.18 k8s-node3 <none> <none>

Kubernetes 通过 Service 暴露无状态应用

  • 生成 YAML 配置文件,用于为名称为 nginx 的 Deployment 创建一个 NodePort 类型的 Service,将该 Deployment 的 80 端口暴露到 Kubernetes 集群每个节点的静态端口上,以便从集群外部访问 Nginx
1
kubectl expose deployment nginx --port=80 --type=NodePort --target-port=80 --name=nginx --dry-run=client -o yaml > nginx_service.yaml
  • 自动生成的 YAML 配置文件的内容如下所示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2025-09-11T10:15:16Z"
labels:
app: nginx
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:labels:
.: {}
f:app: {}
f:spec:
f:externalTrafficPolicy: {}
f:ports:
.: {}
k:{"port":80,"protocol":"TCP"}:
.: {}
f:port: {}
f:protocol: {}
f:targetPort: {}
f:selector:
.: {}
f:app: {}
f:sessionAffinity: {}
f:type: {}
manager: kubectl-expose
operation: Update
time: "2025-09-11T10:15:16Z"
name: nginx
namespace: default
resourceVersion: "491002"
selfLink: /api/v1/namespaces/default/services/nginx
uid: e3729f4c-17f9-4100-86dd-2178fe1aa65f
spec:
clusterIP: 10.0.0.106
externalTrafficPolicy: Cluster
ports:
- nodePort: 30754
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}
  • 创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Service)
1
kubectl apply -f nginx_service.yaml
  • 查看 Servcie 列表
1
kubectl get svc
1
2
3
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 38d
nginx NodePort 10.0.0.106 <none> 80:30754/TCP 30s
  • 通过浏览器访问 http://192.168.2.112:30754,请自行更改 IP 和端口;其中 IP 可以是 Kubernetes 集群任意节点的 IP 地址,端口由 kubectl get svc 命令可得知。若 Ngninx 容器在 Kubernetes 集群中创建并启动成功,则浏览器可以正常访问 Nginx 的首页(如下图所示)。

Kubernetes 删除 Deployment 和 Service

  • 如果需要删除上面创建的 Deployment 和 Service,可以执行以下命令:
1
2
3
4
5
# 删除Service
kubectl delete service nginx

# 删除Deployment
kubectl delete deployment nginx
部署有状态应用

学习目标

本节将演示在 Kubernetes 集群中,如何通过 StatefulSet 部署一个 Nginx 的 Pod,并通过 Headless Service(无头服务)暴露应用,以便从 Kubernetes 集群内部访问。

Kubernetes 有状态应用(Stateful)的特点

  • 主要特点:

    • 每个 Pod 独立且不可互换
      • 每个 Pod 都有自己的身份、配置、存储,不能随意替换或重建。
    • 需要固定的网络标识
      • Pod 需要固定的名称(DNS)或网络标识符,便于集群内通信,比如 mysql-0.mysql
    • 有启动和停止顺序
      • Pod 必须按照特定顺序启动或停止。
      • 例如,先启动主节点,再启动从节点。
    • 需要持久化存储
      • 必须使用 PersistentVolume(PV)保证数据不随 Pod 删除而丢失。
    • Pod 调度位置需要考虑
      • Pod 可能需要绑定特定的 Node 节点,确保存储卷挂载一致性或性能需求。
    • Kubernetes 控制器
      • 使用 StatefulSet 管理,支持:
        • 固定的 Pod 命名(如 mysql-0, mysql-1);
        • 有序部署、有序扩容和缩容;
        • 持久化存储与 Pod 一一对应。
  • 典型代表:

    • MySQL、Kafka、ZooKeeper、ElasticSearch、Redis Cluster。

Kubernetes 通过 StatefulSet 部署有状态应用

  • 创建 YAML 配置文件(比如 nginx_statefulset.yaml),用于通过 StatefulSet 部署一个 Nginx 的 Pod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-statefulset
namespace: default
spec:
serviceName: nginx
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
  • 创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 StatefulSet)
1
kubectl apply -f nginx_statefulset.yaml
  • 查看所有 Pod 的运行状态,可以看到 Pod 的名称是根据一定规则生成的(全局唯一)
1
kubectl get pods -o wide
1
2
3
4
NAME                  READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
nginx-statefulset-0 1/1 Running 0 77s 10.244.2.29 k8s-node3 <none> <none>
nginx-statefulset-1 1/1 Running 0 65s 10.244.3.11 k8s-node2 <none> <none>
nginx-statefulset-2 1/1 Running 0 37s 10.244.0.15 k8s-node1 <none> <none>

Kubernetes 通过 Service 暴露有状态应用

  • 创建 YAML 配置文件(如 nginx_service.yaml),用于通过 Service 暴露有状态应用
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 60
name: web
clusterIP: None # None 表示无头服务(Headless Service)
selector:
app: nginx

无头服务(Headless Service)是什么

  • 无头服务是没有虚拟 IP(ClusterIP)的 Service(Headless Service),是一种没有 ClusterIP 的特殊 Service 类型,详细介绍请看 这里
  • 无头服务可以用于暴露 Kubernetes 集群内 Pod 的真实 IP 和 DNS 名称(域名),而不是通过一个统一的虚拟 IP(ClusterIP)进行负载均衡,即 Kubernetes 不会做流量负载均衡。
  • 创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Service)
1
kubectl apply -f nginx_service.yaml
  • 查看 Servcie 列表,可以看到有状态应用的 ClusterIP 为 None
1
kubectl get svc
1
2
3
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 53d
nginx ClusterIP None <none> 60/TCP 2m12s

提示

  • 通过 Headless Service 暴露 Pod 后,每个 Pod 都有一个唯一的名称和 DNS 名称(域名),域名格式:<pod-name>.<service-name>.<namespace>.svc.cluster.local,默认的命名空间(namespace)是 default
  • 在 Kubernetes 集群内,可以通过 Pod 的 DNS 域名直接访问 Pod(前提是已经部署 CoreDNS),比如:http:://nginx-statefulset-0.nginx.default.svc.cluster.local:80

在 Kubernetes 集群内部,通过 Service 的 DNS 名称(域名)访问有状态应用

特别注意

ClusterIP 为 None 的 Service(Headless Service)只能在 Kubernetes 集群内部访问,如果在集群外部机器(比如直接在集群的 Master 节点)上,通过 Pod 的 DNS 名称直接访问 Pod(比如 http://nginx-statefulset-0.nginx.default.svc.cluster.local:80),肯定是无法访问成功的。

  • 创建一个临时 Pod,并进入 Pod 内部的交互式 Shell
1
2
# 添加 --rm 参数,为了在 Shell 中执行 exit 命令退出后自动销毁 Pod
kubectl run test-pod --image=busybox:1.35 --restart=Never -it --rm -- sh
  • 在临时 Pod 的内部,可以通过 Service 的 DNS 名称(域名)查询所有匹配 Pod 的 IP(必须保证临时 Pod 与 Service 处于同一个命名空间),域名格式:<service-name>.<namespace>.svc.cluster.local
1
nslookup nginx.default.svc.cluster.local
1
2
3
4
5
6
7
8
9
Server:		10.0.0.2
Address: 10.0.0.2:53

Name: nginx.default.svc.cluster.local
Address: 10.244.3.11
Name: nginx.default.svc.cluster.local
Address: 10.244.2.29
Name: nginx.default.svc.cluster.local
Address: 10.244.0.15
  • 在临时 Pod 的内部,还可以通过 Pod 的 DNS 名称(域名)直接访问指定的 Pod,域名格式:<pod-name>.<service-name>.<namespace>.svc.cluster.local
1
nslookup nginx-statefulset-0.nginx.default.svc.cluster.local
1
2
3
4
5
Server:		10.0.0.2
Address: 10.0.0.2:53

Name: nginx-statefulset-0.nginx.default.svc.cluster.local
Address: 10.244.2.29
1
2
# 或者通过 Pod 的 DNS 名称(域名)访问 Nginx 的首页面
wget -qO- http://nginx-statefulset-0.nginx.default.svc.cluster.local:80

Kubernetes 删除 StatefulSet 和 Service

  • 如果需要删除上面创建的 StatefulSet 和 Service,可以执行以下命令
1
2
3
4
5
# 删除 Service
kubectl delete service nginx

# 删除 StatefulSet,--cascade=true 参数表示连同 Pod 一起删除,但 PVC 默认不会被删除(如果存在)
kubectl delete statefulset nginx-statefulset --cascade=true
部署守护进程

note

  • 本节将演示在 Kubernetes 集群中,如何通过 DaemonSet 在每个 Node(工作节点)上分别部署一个守护进程。
  • 这里的守护进程是指节点级的后台服务,比如日志收集(Filebeat)、网络插件(Flannel)、监控代理(Prometheus Node Exporter)等服务,为了方便演示,下面直接使用 Nginx 来代替。

Kubernetes 中 DaemonSet 的主要功能和适用场景

  • 主要功能:

    • 在每个节点上运行一个指定的 Pod
      • 自动在集群中每个符合条件的节点上部署且只运行一个指定的 Pod 实例。
    • 节点加入自动部署
      • 当新节点加入集群时,DaemonSet 会自动在该节点上调度并启动 Pod。
    • 节点移除自动回收
      • 节点被移除或不可用时,对应 Pod 会自动删除,保持一致性。
    • 不支持手动扩容 / 缩容
      • Pod 的副本数量与节点数量直接关联,不支持手动管理 replicas
    • 支持滚动更新与回滚
      • 可平滑升级版本,并在出现问题时快速回滚。
    • 可结合节点选择器、节点亲和性、污点 / 容忍等使用
      • 支持精确控制 DaemonSet Pod 部署在哪些节点上。
    • 与 Deployment 区别
      • Deployment:通常用于无状态服务,副本数固定,由用户定义。
      • DaemonSet:与节点数量绑定,强调 “每个节点一个 Pod”。
    • 删除行为可控
      • 使用 kubectl delete daemonset 删除 DaemonSet 时,可通过 --cascade=orphan 参数控制是否保留关联的 Pod。
  • 适用场景:

    • 日志收集
      • 部署日志收集 Agent(如 Fluentd、Logstash、Filebeat),保证每个节点日志都能被采集。
    • 监控与指标采集
      • 例如 Prometheus Node Exporter、Datadog Agent、cAdvisor 等,采集节点和 Pod 的监控指标。
    • 网络插件或 CNI 管理
      • Kubernetes CNI 插件通常以 DaemonSet 运行,例如 Calico、Flannel、Cilium 等。
    • 存储插件或 CSI 驱动
      • 如 Ceph、Rook 等分布式存储系统的节点守护进程。
    • 安全与合规审计
      • 如 Falco、Sysdig Secure 等安全审计或防护 Agent。
    • 节点运维任务
      • 自动在每个节点运行健康检查、系统维护脚本或运维工具。

Kubernetes 通过 DaemonSet 部署守护进程

  • 创建 YAML 配置文件(比如 nginx_daemonset.yaml),用于通过 DaemonSet 在每个节点上分别部署一个 Nginx 的 Pod,,并将宿主机内的 /var/log 目录挂载到容器内部的 /tmp/log 目录(可选操作)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonset
labels:
app: nginx # DaemonSet 资源自身的标签,用于标识和选择这个 DaemonSet 资源
spec:
selector:
matchLabels:
app: nginx # DaemonSet 选择器标签,用于匹配和管理具有此标签的 Pod
template:
metadata:
labels:
app: nginx # Pod 模板标签,DaemonSet 创建的每个 Pod 都会被打上这个标签
spec:
containers:
- name: nginx
image: nginx:1.15
ports:
- containerPort: 80
volumeMounts:
- name: varlog
mountPath: /tmp/log
volumes:
- name: varlog
hostPath:
path: /var/log
  • 创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 DaemonSet)
1
kubectl apply -f nginx_daemonset.yaml
  • 查看 DaemonSet 的状态
1
kubectl get daemonset nginx-daemonset
1
2
NAME              DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
nginx-daemonset 4 4 4 4 4 <none> 6m17s
  • 查看所有 Pod 的运行状态,可以发现每个 Node(工作节点)都部署了一个 Nginx 的 Pod
1
kubectl get pods -o wide
1
2
3
4
NAME                    READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
nginx-daemonset-mhxpg 1/1 Running 0 4s 10.244.2.35 k8s-node3 <none> <none>
nginx-daemonset-nsb7r 1/1 Running 0 4s 10.244.1.16 k8s-node1 <none> <none>
nginx-daemonset-p9k2d 1/1 Running 0 4s 10.244.3.17 k8s-node2 <none> <none>
  • 进入某个 Pod 内部查看挂载的日志文件
1
2
3
4
5
# 进入某个 Pod 的内部
kubectl exec -it nginx-daemonset-p9k2d bash

# 查看 Pod 内部的日志文件
ls /tmp/log/

Kubernetes 删除 DaemonSet

  • 如果需要删除上面创建的 DaemonSet,可以执行以下命令
1
2
3
4
5
# 删除 DaemonSet,会级联删除该 DaemonSet 以及由它创建的所有 Pod
kubectl delete daemonset nginx-daemonset

# 或者使用 --cascade=orphan 参数,只删除 DaemonSet,但保留它创建的所有 Pod
kubectl delete daemonset nginx-daemonset --cascade=orphan
部署一次性任务

提示

本节将演示在 Kubernetes 集群中,如何通过 Job 执行一次性任务。

Kubernetes 中 Job 的主要功能和适用场景

  • 主要功能

    • 执行一次性任务,保证任务至少成功执行一次
      • Job 会确保定义的 Pod 按照预期执行,直到成功完成(运行状态为 Completed)。
      • Pod 运行失败时,Job 会根据重试策略自动重新创建新的 Pod 继续执行任务。
    • 支持并行或串行执行
      • 可以通过 spec.parallelism 控制同时运行的 Pod 数量;
      • 可以通过 spec.completions 控制任务总共需要成功完成的 Pod 数量。
    • 适合一次性任务,执行完成后不会再次运行
      • Job 完成后,Pod 不会被自动删除,但状态保持为 Completed
      • 可以通过配置 TTL 控制器自动清理已完成的 Job 及 Pod。
  • 适用场景

    • 一次性批处理作业
      • 数据清理、日志分析、批量数据转换等。
    • 离线计算任务
      • 机器学习模型训练、视频转码、大数据计算等。
    • 自动化任务
      • 备份数据库、生成报表、执行临时脚本等。
    • 测试任务
      • 压力测试、集成测试或单次验证任务。

Kubernetes 通过 Job 执行一次性任务

  • 创建 YAML 配置文件(比如 pi_job.yaml),用于通过 Job 执行一次 Perl 脚本(计算圆周率)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: batch/v1
kind: Job
metadata:
name: pi-job
spec:
# completions: 3 # 总共需要 3 个 Pod 完成任务
# parallelism: 2 # 最多允许 2 个 Pod 并行运行
# ttlSecondsAfterFinished: 60 # 任务执行完成后 60 秒自动清理
backoffLimit: 4 # 任务执行失败后,最大重试次数为 4
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] # 计算圆周率,并打印日志信息
restartPolicy: Never # Pod 失败(任务执行失败)时的重启策略
  • 创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Job)
1
kubectl apply -f pi_job.yaml
  • 查看所有 Job 的运行状态
1
kubectl get jobs
1
2
NAME     COMPLETIONS   DURATION   AGE
pi-job 1/1 25s 25s
  • 查看所有 Pod 的运行状态,可以发现当 Job(一次性任务)执行完成后,Pod 的状态会切换为 Completed
1
kubectl get pods -o wide
1
2
NAME       READY   STATUS      RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
pi-ks6pn 0/1 Completed 0 41s 10.244.2.36 k8s-node3 <none> <none>
  • 查看 Pod 的日志信息
1
kubectl logs pi-ks6pn
1
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275901

Kubernetes 删除 Job

  • 如果需要删除上面创建的 Job,可以执行以下命令
1
2
3
4
5
# 删除 Job,会级联删除该 Job 以及由它创建的所有 Pod
kubectl delete job pi-job

# 或者使用 --cascade=orphan 参数,只删除 Job,但保留它创建的所有 Pod
kubectl delete job pi-job --cascade=orphan
部署定时任务

提示

本节将演示在 Kubernetes 集群中,如何通过 CronJob 周期性(定时)执行任务。

Kubernetes 中 CronJob 的主要功能和适用场景

  • 主要功能

    • 周期性任务调度
      • 使用 cron 表达式定义执行计划,精确到分钟;
      • 可在每天、每周、每月或特定时间点自动运行任务。
    • 自动创建 Job
      • CronJob 在到达调度时间后,会自动创建对应的 Job 资源;
      • Job 负责任务的执行、失败重试和状态维护。
    • 控制并发执行
      • 可通过 concurrencyPolicy 控制多次调度的 Job 是否允许并发执行:
        • Allow:允许多个任务并发运行;
        • Forbid:禁止并发,若上一个任务未完成,跳过新的调度;
        • Replace:如果上一个任务未完成,先删除旧任务,再启动新任务。
    • 支持任务历史管理
      • 可以配置保留的成功任务和失败任务历史数量,避免资源无限增长。
    • 支持一次性定时任务
      • 通过指定一次性运行的时间点,实现一次性定时触发的 Job。
  • 适用场景

    • 定时数据处理
      • 每天凌晨自动跑批处理作业,生成统计报表;
      • 定时清理临时文件或过期数据。
    • 数据库备份
      • 每天或每小时自动执行数据库备份任务。
    • 日志归档
      • 定期收集、压缩和上传日志文件到集中存储。
    • 周期性健康检查
      • 定时执行诊断脚本或检查任务,输出报告。
    • 定时通知或消息推送
      • 定时触发消息发送、告警提醒或业务事件。
    • 一次性延时执行任务
      • 通过设置特定时间点,完成一次性延时任务的执行。

Kubernetes 通过 CronJob 运行定时任务

  • 创建 YAML 配置文件(比如 hello_cronjob.yaml),用于通过 CronJob 周期性地执行 Shell 脚本(打印日志信息)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello-cronjob
spec:
schedule: "*/1 * * * *" # Cron 表达式
# concurrencyPolicy: Forbid # 禁止并发执行任务
# startingDeadlineSeconds: 300 # 最长允许任务延迟启动 5 分钟
# successfulJobsHistoryLimit: 3 # 保留最近 3 次执行成功的任务
# failedJobsHistoryLimit: 1 # 保留最近 1 次执行失败的任务
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure # Pod 失败(任务执行失败)时的重启策略
  • 创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 CronJob)
1
kubectl apply -f hello_cronjob.yaml
  • 查看所有 CronJob 的运行状态
1
kubectl get cronjobs
1
2
NAME            SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello-cronjob */1 * * * * False 0 49s 52s
  • 查看所有 Job 的运行状态,CronJob 不直接创建和运行 Pod,所有 Pod 都由其生成的 Job 进行管理
1
kubectl get jobs
1
2
3
4
NAME                       COMPLETIONS   DURATION   AGE
hello-cronjob-1759064520 1/1 17s 3m11s
hello-cronjob-1759064580 1/1 13s 2m20s
hello-cronjob-1759064640 1/1 17s 78s
  • 查看所有 Pod 的运行状态,可以发现当 CronJob 每次执行完成后,Pod 的状态会切换为 Completed
1
kubectl get pods -o wide
1
2
3
4
NAME                             READY   STATUS      RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
hello-cronjob-1759064340-mfppj 0/1 Completed 0 2m28s 10.244.2.38 k8s-node3 <none> <none>
hello-cronjob-1759064400-djk6l 0/1 Completed 0 86s 10.244.2.39 k8s-node3 <none> <none>
hello-cronjob-1759064460-5lbxj 0/1 Completed 0 25s 10.244.3.18 k8s-node2 <none> <none>
  • 查看 Pod 的日志信息
1
kubectl logs hello-cronjob-1759064460-5lbxj
1
2
Sun Sep 28 13:01:26 UTC 2025
Hello from the Kubernetes cluster

Kubernetes 删除 CronJob

  • 如果需要删除上面创建的 CronJob,可以执行以下命令
1
2
3
4
5
# 删除 CronJob,会级联删除该 CronJob 以及由它创建的所有 Job 和 Pod
kubectl delete cronjob hello-cronjob

# 或者使用 --cascade=orphan 参数,只删除 CronJob,但保留它创建的所有 Job 和 Pod
kubectl delete cronjob hello-cronjob --cascade=orphan

应用升级回滚

学习目标

本节将演示在 Kubernetes 集群中部署 Nginx 后,如何升级 Nginx 的版本,还有如何回滚 Nginx 的版本,更详细的应用升级回滚实战可以看 这里

部署应用
  • 生成用于部署一个 Nginx 的 Deployment 的 YAML 配置文件,其中 Deployment 的名称为 nginx,Nginx 的版本号为 1.14
1
kubectl create deployment nginx --image=nginx:1.14 --dry-run=client -o yaml > nginx_deployment.yaml
  • 更改自动生成的 YAML 配置文件内容(如下所示),将 replicas 改为 2(表示 Pod 有两个副本)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels: # 标签:标识 Deployment 自身
app: nginx
name: nginx
spec:
replicas: 2
selector:
matchLabels: # 标签:在 Deployment 与 Pod 之间建立管理关系
app: nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels: # 标签:定义 Pod 的身份(标签)
app: nginx
spec:
containers:
- image: nginx:1.14
name: nginx
resources: {}
status: {}
  • 创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Deployment)
1
kubectl apply -f nginx_deployment.yaml
  • 查看所有 Pod 的运行状态
1
kubectl get pods -o wide
1
2
3
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE        NOMINATED NODE   READINESS GATES
nginx-5658bdf5d4-6sbmg 1/1 Running 0 31m 10.244.1.2 k8s-node1 <none> <none>
nginx-5658bdf5d4-ksjgm 1/1 Running 0 31m 10.244.3.2 k8s-node2 <none> <none>
升级应用版本
  • 当执行完上述步骤将 Nginx 部署到 Kubernetes 集群后,可以执行以下命令来升级 Nginx 的版本(比如,将 Nginx 升级到 1.15 版本)
1
kubectl set image deployment nginx nginx=nginx:1.15
  • 查看应用升级版本的状态(过程)
1
kubectl rollout status deployment nginx
  • 查看所有 Pod 的运行状态
1
kubectl get pods -o wide
1
2
3
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE        NOMINATED NODE   READINESS GATES
nginx-764b95f4c5-f744r 1/1 Running 0 31m 10.244.1.2 k8s-node3 <none> <none>
nginx-764b95f4c5-w96gl 1/1 Running 0 31m 10.244.3.2 k8s-node2 <none> <none>

  • 若执行完应用升级版本的命令后,在查看所有 Pod 的运行状态时,新 Pod 的 STATUS 一直显示 ContainerCreating,则说明应用升级版本存在问题
1
2
3
4
NAME                     READY   STATUS              RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
nginx-5658bdf5d4-6sbmg 1/1 Running 0 77m 10.244.1.2 k8s-node1 <none> <none>
nginx-764b95f4c5-f744r 1/1 Running 0 27m 10.244.2.19 k8s-node3 <none> <none>
nginx-764b95f4c5-w96gl 0/1 ContainerCreating 0 3m36s <none> k8s-node2 <none> <none>
  • 可以执行以下命令来排查问题(比如,原因是一直卡在拉取镜像的环节上)
1
kubectl describe pod nginx-764b95f4c5-w96gl
  • 若无法排查应用升级版本的问题,则可以删除卡住的 Pod 以触发重建
1
kubectl delete pod nginx-764b95f4c5-w96gl
  • 若无法排查应用升级版本的问题,又急需恢复服务,最快捷的方法是回滚(回退)到上一个版本(即用旧版本的 Pod 替换掉所有新版本的 Pod),之后服务会逐渐恢复正常
1
kubectl rollout undo deployment nginx

特别注意

Kubernetes 在升级应用的版本时,是不会中断服务的(比如,升级期间 Nginx 依然可以对外提供服务),这主要归功于其精细的流量控制和渐进的替换过程。具体是通过 Deployment 控制器,先启动新版本的 Pod 并确认其就绪,然后逐步终止旧版本的 Pod,同时 Service 的负载均衡器会确保流量只路由到健康的 Pod 上,从而实现了服务的平滑升级。

回滚应用版本
  • 当执行完上述步骤将 Nginx 的版本从 1.14 升级到 1.15 后,若希望回滚到旧的版本(即用旧版本的 Pod 替换掉所有新版本的 Pod),可以执行以下命令
1
2
# 查看指定 Deployment 的所有历史版本
kubectl rollout history deployment nginx
1
2
3
4
5
# 回滚指定 Deployment 到上一个版本
kubectl rollout undo deployment nginx

# 或者,回滚指定 Deployment 到指定的版本
kubectl rollout undo deployment nginx --to-revision=2
  • 查看所有 Pod 的运行状态
1
kubectl get pods -o wide
1
2
3
NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE        NOMINATED NODE   READINESS GATES
nginx-5658bdf5d4-6sbmg 1/1 Running 0 31m 10.244.1.2 k8s-node1 <none> <none>
nginx-5658bdf5d4-ksjgm 1/1 Running 0 31m 10.244.3.2 k8s-node2 <none> <none>

应用弹性伸缩

学习目标

本节将演示在 Kubernetes 集群中部署 Nginx 后,如何对 Nginx 进行扩容(即增加 Pod 的副本数量),更详细的应用扩容缩容实战可以看 这里

部署应用
  • 生成用于部署一个 Nginx 的 Deployment 的 YAML 配置文件,其中 Deployment 的名称为 nginx
1
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > nginx_deployment.yaml
  • 自动生成的 YAML 配置文件的内容如下所示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels: # 标签:标识 Deployment 自身
app: nginx
name: nginx
spec:
replicas: 1
selector:
matchLabels: # 标签:在 Deployment 与 Pod 之间建立管理关系
app: nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels: # 标签:定义 Pod 的身份(标签)
app: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}
  • 创建或更新 YAML 文件中定义的 Kubernetes 资源对象(比如 Deployment)
1
kubectl apply -f nginx_deployment.yaml
  • 查看所有 Pod 的运行状态
1
kubectl get pods -o wide
1
2
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-5658bdf5d4-kt6fv 1/1 Running 0 29m 10.244.2.18 k8s-node3 <none> <none>
应用扩缩容
  • 当执行完上述步骤将 Nginx 部署到 Kubernetes 集群后,可以执行以下命令来对 Pod 的副本数进行扩缩容
1
2
# 对 Pod 的副本进行扩容(比如,扩容至 3 个副本)
kubectl scale deployment nginx --replicas=3
  • 查看所有 Pod 的运行状态
1
kubectl get pods -o wide
1
2
3
4
NAME                     READY   STATUS    RESTARTS   AGE     IP           NODE         NOMINATED NODE   READINESS GATES
nginx-5658bdf5d4-kt6fv 1/1 Running 0 29m 10.244.0.7 k8s-node3 <none> <none>
nginx-5658bdf5d4-tbvzz 1/1 Running 0 2m55s 10.244.1.3 k8s-node1 <none> <none>
nginx-5658bdf5d4-z48mx 1/1 Running 0 2m57s 10.244.3.6 k8s-node2 <none> <none>

参考资料