2025,每天10分钟,跟我学K8S(十一)- POD的生命周期
2025,每天10分钟,跟我学K8S(十一)- POD的生命周期-CSDN博客
上节课我们创建了一个pod,成功启动了他。本章节我们来继续了解一下创建pod的其他功能。
上节课在第一次拉取镜像的时候,出现了一个报错ImagePullBackOff ,如果继续等待,可能会变成ErrImagePull,在调整了镜像地址重新拉取之后,状态又变成了Running,这告诉我们,在创建Pod的时候,是有多种状态的。这就叫做pod的生命周期。
Pod的生命周期
Kubernetes (k8s) 的 Pod 生命周期管理是其核心功能之一,它涉及到 Pod 从创建到终止的整个过程。理解 Pod 的生命周期对于有效地管理和维护 Kubernetes 集群至关重要。以下是一个 Pod 生命周期的基本概述:

1. 创建阶段
当你在 Kubernetes 集群中创建一个 Pod 时,它会经历以下阶段:
-
Pending:Pod 已被 API Server 接受,但容器镜像尚未被完全拉取或调度到某个节点上。
-
Running:Pod 已经被调度到某个节点上,并且至少有一个容器正在运行。
2. 运行阶段
一旦 Pod 进入运行状态,它可能会经历以下几种状态:
-
Running:Pod 正在运行。如果 Pod 中有多个容器,其中一个或多个容器处于运行状态,Pod 也会处于此状态。
-
Waiting:Pod 正在等待某些条件(如启动探针检查)满足。
-
Succeeded:所有容器都已成功终止,并且不会再重启。
-
Failed:所有容器都已终止,且至少有一个容器因为失败而退出。
3. 终止阶段
Pod 可能因为多种原因被终止,包括但不限于手动删除、自动缩放、系统维护等:
-
Terminating:Pod 正在被终止过程中。此时,Pod 会尝试优雅地关闭容器,即在关闭之前执行清理操作。
-
Completed:Pod 中的所有容器都已成功完成执行并被删除。这个状态通常出现在一次性任务(如 Job)完成后。
-
Unknown:由于某些原因(如节点宕机),Pod 的状态无法被 kubelet 报告。
2025,每天10分钟,跟我学K8S(十二)- Deployment-CSDN博客
前面2个章节,了解了pod的创建过程和生命周期。但是在实际应用中,直接创建pod是很少见的,因为一旦这个pod挂掉了。整个服务就宕机了。所以 kubernetes 提供了一个Deployment的概念,可以让 Deployment来管理一组 POD 的副本,也就是副本集,这样就可以保证一定数量的副本一直可用的,不会因为一个 POD 挂掉导致整个服务挂掉。
Deployment是Kubernetes中的一个核心概念,它是一种高级别的控制器,用于管理Pod和ReplicaSet,确保应用程序的高可用性和稳定性。Deployment通过声明式配置来创建和更新Pod和ReplicaSet,从而管理应用程序的生命周期。

Deployment: 管理 ReplicaSet 的创建和更新。Deployment 允许用户声明希望运行的应用状态,包括 Pod 的模板、副本数量和更新策略。通过 Deployment,用户可以轻松实现滚动更新和回滚。
ReplicaSet: 确保指定数量的 Pod 实例在任何时候都在运行。它通过监控 Pod 的状态来管理 Pod 的创建和删除。如果某个 Pod 异常终止,ReplicaSet 会创建一个新的 Pod 来替代它。
Pod:一个或多个容器的集合。Pod 共享存储、网络和上下文。
Deployment主要功能和特点
副本管理:Deployment确保在集群中有指定数量的Pod副本运行。如果Pod副本数量少于期望值,Deployment会自动创建新的Pod;如果副本数量超过期望值,则会删除多余的Pod。
滚动更新:Deployment支持滚动更新策略,逐步替换旧版本的Pod为新版本,保障业务的连续性,避免一次性更新导致的服务中断。
版本回滚:如果应用程序升级后出现问题,可以通过Deployment回滚到之前的版本。
高可用性:当Pod失效时,Deployment会自动创建新的Pod以替换失效的Pod,保证服务的连续运行。
Deployment使用场景和示例
Deployment的使用场景包括但不限于:
应用部署:将构建好的容器镜像部署到Kubernetes集群中,并提供服务。
应用升级:通过更新容器镜像并重新部署Deployment来实现应用的更新。
回滚操作:当应用升级出现问题时,可以回滚到之前的稳定版本。
以下是一个Deployment资源清单的示例:
-
---
-
apiVersion: apps/v1
-
kind: Deployment
-
metadata:
-
name: nginx
-
spec:
-
replicas: 2
-
selector:
-
matchLabels:
-
app: web
-
template:
-
metadata:
-
labels:
-
app: web
-
spec:
-
containers:
-
- name: front-end
-
image: m.daocloud.io/docker.io/nginx
-
ports:
-
- containerPort: 80
上述内容看起来和之前的pod创建的yaml文件有点类似,尤其是template下面一部分,其实就是对pod的定义,和之前的pod的yaml文件写的是一样的。

-
apiVersion,这里它的值是 apps/v1,这个版本号需要根据我们安装的 kubernetes 版本和资源类型进行变化的,记住不是写死的
-
kind,这里我们创建的是一个 Deployment
-
metadata:包含了我们定义的 Deployment的一些 meta 信息,比如名称、namespace、namede信息。
-
spec:
-
replicas:会创建几个pod的副本,上面的例子写了2个副本,就会生成2个pod
-
selector:pod标签选择器,和下面的template里面的labels是对应关系,表名这个deployment通过app: web 这一组标签,进行pod的选择,而下面的template中labels也提供的pod的标签也是app: web。
-
-
template: 描述pod的一些属性
查看此时的deployment和pod的状态

可以看到有2个pod已经启动,和之前设置的replicas保持一致。
2025,每天10分钟,跟我学K8S(十三)- ReplicaSet-CSDN博客
上节课讲述Deployment的时候引入了一个ReplicaSet的东西,也讲解了他是来管理pod的的创建和删除。并且保证pod的数量和我们设置的参数保持一致。本章节来了解下他如何来工作的。
示例:Nginx应用的ReplicaSet
一个简单的Nginx应用,我们将使用ReplicaSet来部署和管理它。
创建一个rs.yaml文件
-
apiVersion: apps/v1
-
kind: ReplicaSet
-
metadata:
-
name: nginx-replicaset
-
spec:
-
replicas: 3
-
selector:
-
matchLabels:
-
app: nginx
-
template:
-
metadata:
-
labels:
-
app: nginx
-
spec:
-
containers:
-
- name: nginx-container
-
image: m.daocloud.io/docker.io/nginx:latest
-
ports:
-
- containerPort: 80
查看replicaset和pod。红色方框里面内容表名,启动了一个ReplicaSet和3个对应的Pod。

扩缩容
如果我们希望将Nginx的实例数量扩展到4个,我们只需修改ReplicaSet定义文件中的 replicas 字段:
-
spec:
-
replicas: 4
然后再次应用:
kubectl apply -f rs.yaml
Kubernetes将根据新的定义逐步创建1个额外的Pod副本,从而将总实例数扩展到4个。

自愈能力
假设其中一个Pod副本由于故障被终止,ReplicaSet会自动检测到这一变化并尝试创建新的Pod副本以保持指定数量的实例:
kubectl delete pod <pod-name>
ReplicaSet会自动创建新的Pod副本来替代被删除的Pod,确保所需数量的实例一直存在。

通过上图可以得知,名为nginx-replicaset-4tt8l的pod已经被删除,但是ReplicaSet又启动了一个nginx-replicaset-msv4k的pod。保证数量为之前设置的4。
ReplicaSet的最佳实践
- 合理设置副本数:根据应用的负载和性能需求,合理设置ReplicaSet的副本数,确保足够的实例来处理流量,并非越多越好,每个pod都是需要消耗硬件资源的。
- 使用标签选择器:合理使用标签选择器,确保ReplicaSet正确选择要管理的Pod副本。
- 谨慎进行扩缩容:在进行扩缩容时,要谨慎调整副本数,避免引入不必要的变化。
- 备份和恢复策略:根据应用的重要性,考虑实施备份和恢复策略,以防止意外数据丢失或服务中断。
- 监控和报警:通过监控ReplicaSet和相关的Pod状态,设置相应的报警机制,可以及时发现并解决潜在的问题,确保应用的可用性和稳定性。
2025,每天10分钟,跟我学K8S(十四)- StatefulSet-CSDN博客
上一章节,初步通过Deployment和ReplicaSet了解到了他们对Pod的管理方式,但是这里有一个问题,pod的名字都是无序的随机生成无状态服务,我们又知道同pod之间是可以互相访问的。那有没有一种方式能让这种变成可预测的呢?
举例,有2个pod程序,其中一个是web服务,一个是是mysql服务,web需要去连接mysql进行数据查询,那么就得在web服务中写好mysql的IP地址,但是如果mysql的pod被重建了,IP就发生改变了。如果web是通过主机名去连接mysql,同时这个mysql即便重建主机名也不发生改变,岂不美哉?
K8S为了这种环境提供了一个新的对象:StatefulSet。
StatefulSet类似于ReplicaSet,但是它可以处理Pod的启动顺序,为保留每个Pod的状态设置唯一标识,同时具有以下功能:
- 稳定的、唯一的网络标识符
- 稳定的、持久化的存储
- 有序的、优雅的部署和缩放
- 有序的、优雅的删除和终止
- 有序的、自动滚动更新
接下来还是以具体的例子来演示。
-
apiVersion: apps/v1
-
kind: StatefulSet
-
metadata:
-
name: web
-
spec:
-
serviceName: "nginx"
-
replicas: 3
-
selector:
-
matchLabels:
-
app: nginx
-
template:
-
metadata:
-
labels:
-
app: nginx
-
spec:
-
containers:
-
- name: nginx
-
image: m.daocloud.io/docker.io/nginx:latest
-
ports:
-
- containerPort: 80
-
name: web
上述例子使用StatefulSet类型来创建了一个3副本的pod,通过下图可以看到pod的编号不再无序,而是在有序的以0,1,2数字往后叠加。

通过kubectl delete命令删除其中一个pod,可以观察出来,IP发生了改变,但是主机名没有变化。

在我们学习了service的章节后,可以使用 <pod名>.<命名空间>.svc.cluster.local 的方式,通过主机名来直达pod节点。
2025,每天10分钟,跟我学K8S(十五)- DaemonSet-CSDN博客
前面了解学习了K8S中的对象deployment和statefulset,知道他们对pod的管理,今天学习一种特殊的对象:DaemonSet。
什么是DaemonSet?
DaemonSet用于确保在集群的每个节点上都运行一个或多个Pod的副本。与其他控制器(如statefulset和deployment)不同,DaemonSet主要用于在整个集群中的节点上运行系统级别的任务,如日志收集、监控代理等。
DaemonSet的主要作用
- 节点级别任务的部署:DaemonSet确保在每个节点上运行一个或多个Pod的副本,用于执行节点级别的任务。
- 自动扩展:当新的节点加入集群时,DaemonSet会自动在新节点上启动Pod实例,确保集群中每个节点都有一个或多个Pod的副本。
- 系统服务的运行:DaemonSet常用于运行集群中的系统服务,如日志收集、监控代理、群集数据库等。
还是以一个例子说明:
-
apiVersion: apps/v1
-
kind: DaemonSet
-
metadata:
-
name: daemonset-nginx
-
spec:
-
selector:
-
matchLabels:
-
app: ds-nginx
-
template:
-
metadata:
-
labels:
-
app: ds-nginx
-
spec:
-
containers:
-
- name: ds-nginx
-
image: m.daocloud.io/docker.io/nginx:latest
注意DaemonSet 类型是没有replicas属性的。通过kubectl get pod -o wide命令 可以看到在每个node上面都启动了一个pod。并且当有新的服务器加入这个K8S群集,也会在这个新的服务器上自动扩展启动一个新的pod。
2025,每天10分钟,跟我学K8S(十六)- Job-CSDN博客
本章节来学习K8s中一种新的资源对象Job。
什么是Job?
Job是Kubernetes中的一个核心概念,用于在集群中运行独立的任务。与其他控制器(如ReplicaSet和Deployment)不同,Job关注的是执行一次性任务而不是保持指定数量的实例运行。
Job的主要作用
- 独立任务执行:Job确保在集群中运行独立的任务,并在任务成功完成后自动终止。
- 任务的重试:Job支持定义任务的重试策略,以应对任务执行失败的情况。
- 并行任务:Job允许定义多个并行执行的任务,以提高任务执行效率。
Job的例子
我们用Job这个资源对象来创建一个任务,我们定一个Job来执行一个倒计时的任务,定义YAML文件:
-
apiVersion: batch/v1
-
kind: Job
-
metadata:
-
name: job-test
-
spec:
-
template:
-
metadata:
-
name: job-test
-
spec:
-
restartPolicy: Never
-
containers:
-
- name: counter
-
image: m.daocloud.io/docker.io/busybox
-
command:
-
- "bin/sh"
-
- "-c"
-
- "for i in 1 2 3 4 5 6 7 8 9 ; do echo $i; done"
注意Job的RestartPolicy仅支持Never和OnFailure两种,不支持Always,我们知道Job就相当于来执行一个批处理任务,执行完就结束了,如果支持Always的话是不是就陷入了死循环了?
然后来创建该Job,保存为job-demo.yaml:
-
root@k8s-master:~# kubectl apply -f job.yaml
-
job.batch/job-test created
通过命令查看当前的Job资源对象:
# kubectl get pod
发现job的状态为Completed,表示这个job已经完成,通过kubectl logs来查看当前任务的执行结果。看到yaml里面执行的shell命令也运行完毕

2025,每天10分钟,跟我学K8S(十七)- CronJob-CSDN博客
CronJob和Job很像,就是在Job的基础上加上了时间调度,在给定的时间点运行一个任务,也可以周期性地在给定时间点运行。这个实际上和我们Linux中的crontab就非常类似了。
一个CronJob对象其实就对应中crontab文件中的一行,它根据配置的时间格式周期性地运行一个Job,格式和crontab也是一样的。
crontab的格式如下:
-
分 时 日 月 星期 要运行的命令
-
-
第1列分钟0~59
-
-
第2列小时0~23
-
-
第3列日1~31
-
-
第4列月1~12
-
-
第5列星期0~7(0和7表示星期天)
-
-
第6列要运行的命令
现在,创建一个CronJob的yaml文件来管理我们上面的Job任务,
-
apiVersion: batch/v1
-
kind: CronJob
-
metadata:
-
name: cronjob-test
-
spec:
-
schedule: "*/1 * * * *"
-
jobTemplate:
-
spec:
-
template:
-
spec:
-
restartPolicy: OnFailure
-
containers:
-
- name: cronjob-test
-
image: m.daocloud.io/docker.io/busybox
-
args:
-
- "bin/sh"
-
- "-c"
-
- "for i in 9 8 7 6 5 4 3 2 1; do echo $i; done"
这里的Kind是CronJob了,注意的是.spec.schedule字段是Crontab的必须字段,用来指定任务运行的周期,格式就和liunx中的crontab一样,另外一个字段是.spec.jobTemplate, 用来指定需要运行的任务,格式当然和Job是一致的。
还有一些值得我们关注的字段.spec.successfulJobsHistoryLimit和.spec.failedJobsHistoryLimit,表示历史限制,是可选的字段。它们指定了可以保留多少完成和失败的Job,默认没有限制,所有成功和失败的Job都会被保留。然而,当运行一个Cron Job时,Job可以很快就堆积很多,所以一般推荐设置这两个字段的值。如果设置限制的值为 0,那么相关类型的Job完成后将不会被保留。
接下来我们来创建这个cronjob
-
# kubectl apply -f crontab.yaml
-
cronjob.batch/cronjob-test created
一旦不再需要 Cron Job,简单地可以使用 kubectl 命令删除它:
-
root@k8s-master:~# kubectl delete -f crontab.yaml
-
cronjob.batch "cronjob-test" deleted
如果不进行清楚,这个定时任务会按照设定一直执行下去,下图为例,已经启动了3个job:

如果想要删除当前 Namespace 中的所有 Job,可以通过命令 kubectl delete jobs --all 立刻删除它们。
2025,每天10分钟,跟我学K8S(十八)- Service (一)-CSDN博客
前面讲解了Pod和deployment等多个核心对象,了解了可以通过这些对象来创建一些pod对象,并且提供内部的访问,但是在实际生产中,肯定是想将pod中的服务对外网提供服务,让外网用户能通过IP:Port的方式来访问到集群后端的服务。
实现的方法有很多,比如:1,已知Node可以通过pod的IP:Port来访问pod中的服务,那只要在Node上面安装一个nginx,通过这个nginx来转发即可;2.创建一个ingress服务来转发,这个后面会讲解;3.创建一个service服务对象,通过service的一些特性来对外提供服务。本章节,讲解的就是service服务对象。
什么是Kubernetes Service?
Service是K8s中的一种抽象,它定义了一组Pod的逻辑集合,并为这组Pod提供一个稳定的访问点(Endpoint)。这个访问点可以是一个固定的虚拟IP地址或者一个DNS名称,通过这个访问点,其他的应用或服务可以方便地访问到这组Pod,实现服务发现和负载均衡。
在K8s中,Pod是最小的可部署单元,而Service则提供了对这些Pod的抽象。使用Service,我们可以将后端Pod组织成一个逻辑单元,而不用担心它们的具体部署细节。这种抽象使得我们可以更加灵活地进行应用的扩展和维护。
Service的类型
K8s中的Service有四种类型,分别是ClusterIP、NodePort、LoadBalancer和ExternalName。接下来,我们将详细介绍每种类型的Service以及它们的用途。
ClusterIP:使用集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的ServiceType。
NodePort:通过每个 Node 节点上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 ,可以从集群的外部访问一个 NodePort 服务。
LoadBalancer:使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务,这个需要结合具体的云厂商进行操作。
ExternalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如, mydb.baidu.com)。
了解Service之前,我们先大概了解下k8s种的3种IP类型 和 3种Port类型。一会在后面的yaml文件举例中再来具体讲解。
3种IP类型
Node IP: Node节点的IP地址
Pod IP: Pod的IP地址
ClusterIP: Service的IP地址
3种Port类型
Port: service的端口号
targetPort: 后端Pod的端口号
NodePort: Node节点的端口
下面来对service的4中类型分别举例说明。
首先先创建一个nginx的pod。
-
# cat nginx_dep.yaml
-
apiVersion: apps/v1
-
kind: Deployment
-
metadata:
-
name: nginx-deploy
-
labels:
-
k8s-app: nginx-demo
-
spec:
-
replicas: 3
-
selector:
-
matchLabels:
-
app: nginx
-
template:
-
metadata:
-
labels:
-
app: nginx
-
spec:
-
containers:
-
- name: nginx
-
image: m.daocloud.io/docker.io/library/nginx
-
ports:
-
- containerPort: 80
-
-
-
# kubectl apply -f nginx_dep.yaml
-
deployment.apps/nginx-deploy created
ClusterIP类型:
ClusterIP,默认方式,集群内访问
创建一个ClusterIP类型的yaml文件
-
# cat nginx_svc_clusterIP.yaml
-
apiVersion: v1
-
kind: Service
-
metadata:
-
name: nginxservice
-
spec:
-
selector:
-
app: nginx
-
ports:
-
- protocol: TCP
-
port: 8080
-
targetPort: 80
-
name: service-cip
-
-
-
# kubectl apply -f nginx_svc_clusterIP.yaml
-
service/nginxservice created

①kind类型为Service
②service选择选择pod的标签为 app:nginx,刚好和上面创建的pod对应上了
③转发的协议为TCP
④service的port为8080
⑤选择的pod的端口为80
最后2个加起来的意思是将service的8080端口转发到后端pod的80端口。
查看pod和service

访问测试发现不管是PodIP:PORT还是ServiceIP:PORT访问,返回内容一样,这说明通过ServiceIP转发成功。
-
# curl 10.20.213.29
-
-
<html>
-
<head>
-
<title>Welcome to nginx!</title>
-
....
-
-
通过service的IP和端口来访问
-
# curl 10.10.188.174:8080
-
-
<html>
-
<head>
-
<title>Welcome to nginx!</title>
-
<style>
-
....
NodePort 类型:
NodePort 集群外访问

创建一个NodePort 类型的yaml文件
-
# cat nginx_svc_nodePort.yaml
-
apiVersion: v1
-
kind: Service
-
metadata:
-
name: nginxservicenp
-
spec:
-
selector:
-
app: nginx
-
type: NodePort
-
ports:
-
- protocol: TCP
-
port: 8081
-
targetPort: 80
-
nodePort: 30080 #从api-server.conf中配置的端口范围来选取(通常是30000-32767)
-
name: svc-nodeport
注意这里增加了一个字段 spec.type: NodePort。为和上面例子区分开,这里的端口用的是8081.
从下图可以看到新创建的service的类型为NodePort,并且出现了2个端口,8081是service的端口,而30080是node服务器的端口。

访问测试
-
# curl 10.20.213.29
-
-
<html>
-
<head>
-
<title>Welcome to nginx!</title>
-
....
-
-
通过service的IP和端口来访问
-
# curl 10.10.207.250:8081
-
-
<html>
-
<head>
-
<title>Welcome to nginx!</title>
-
<style>
-
....
-
-
通过Node服务器的IP和端口来访问,这里使用的是master的IP,也可以使用node节点的IP
-
# curl 172.21.176.3:30080
-
-
<html>
-
<head>
-
<title>Welcome to nginx!</title>
-
<style>
-
....
通过测试可知,这时候已经可以通过NodeIP:port的方式来访问内部pod服务了。
2025,每天10分钟,跟我学K8S(十九)- Service (二)-CSDN博客
前面我们学习了K8S中service对象中ClusterIP和NodePort,今天来学习剩下的两种LoadBalancer和ExternalName。
service的另外两种方式
LoadBalancer:
大多是在公有云托管集群中使用,可以理解为在NodePort的前面再增加了一个公有云的负载均衡,这样就隐藏了真实的NodeIP。

Yaml文件例子
-
apiVersion: v1
-
kind: Service
-
metadata:
-
name: my-service
-
spec:
-
selector:
-
app: nginx
-
ports:
-
- protocol: TCP
-
port: 8082
-
targetPort: 80
-
nodePort: 30080
-
clusterIP: 10.10.30.30
-
type: LoadBalancer
-
status:
-
loadBalancer:
-
ingress:
-
- ip: 1.1.1.1

①标签选择器,通过app:nginx来选择用有这个标签的pod
②转发的协议为TCP
③service的port为8082
④选择的pod的端口为80
⑤service的IP为10.10.30.30
⑥service的nodeport为30081
⑦类型为LoadBalancer
⑧公有云LVS负载的IP为1.1.1.1 这里一般是通过创建了公有云负载均衡后后填写,本例只是演示
应用这个yaml文件后可以通过查看pod和svc的方式得知,loadbalancer的IP和端口都为我们之前指定的,数据流量就是从LVS(1.1.1.1)--> node节点的端口(30081)--> service的端口(8082)--> pod的端口(80)

由于没有实际购买lvs,这里get请求测试这里不做演示。
ExternalName:
ExternalName指定外部访问域名
ExternalName类型的Service用于引入集群外部的服务,它通过externalName属性指定外部一个服务的地址,然后在集群内部访问此service就可以访问到外部的服务了。在本例中,将外部域名www.qq.com定义为内部的 enqq。在pod中访问enqq就可以直接访问www.qq.com了

Yaml文件
-
apiVersion: v1
-
kind: Service
-
metadata:
-
name: enqq
-
spec:
-
type: ExternalName
-
externalName: www.qq.com

①内部域名 nsqq
② 类型为ExternalName
③外部域名 www.qq.com
应用后进入pod通过ping查看解析是否生效

由于nginx镜像默认没有ping命令,这里通过kubectl run命令创建一个ubuntu镜像来测试。
-
# 进入任意一个pod容器
-
-
# kubectl exec -it nginx-deploy-6c74c565d8-52jkm /bin/sh
-
-
# 默认镜像没有ping功能,这里需要先apt update 然后安装ping组件
-
apt-get update
-
apt install -y iproute2
-
apt install -y iputils-ping
-
-
# 通过ping enqq 和 www.qq.com
-
-
可以发现两个解析的地址是一样的



https://github.com/kubernetes/ingress-nginx?tab=readme-ov-file#supported-versions-table






浙公网安备 33010602011771号