pod生命周期
Pod的状态如下表所示:
| 状态值 | 描述 | |
|---|---|---|
| Pending | API Server已经创建该Pod,等待调度器调度 | |
| ContainerCreating | 拉取镜像启动容器中 | |
| Running | Pod内容器均已创建,且至少有一个容器处于运行状态、正在启动状态或正在重启状态 | |
| Succeeded\ | Completed | Pod内所有容器均已成功执行退出,且不再重启 |
| Failed\ | Error | Pod内所有容器均已退出,但至少有一个容器退出为失败状态 |
| CrashLoopBackOff | Pod内有容器启动失败,比如配置文件丢失导致主进程启动失败 | |
| Unknown | 由于某种原因无法获取该Pod的状态,可能由于网络通信不畅导致 |
Pod启动和关闭示意
1. pause/infra容器,基础架构容器,提供pod的名称空间
2. main容器,业务容器,跑你的java程序的
3. init容器,如数据库初始化连接

pod钩子
Pod 是 Kubernetes 中最小的可调度对象,可以包含一个或多个容器。
在 Kubernetes 中,Pod 钩子是在 Pod 中运行特定事件的容器。以下是 Pod 中可用的钩子:
- PostStart:容器创建后立即运行。
- PreStop:容器停止之前运行。
- Init Container 钩子:在 Pod 中使用 Init Container 时,可以使用 PostStart 和 PreStop 钩子。
每个钩子都是可选的,可以在 Pod 的 YAML 文件中指定。
这些钩子可以用于执行任何自定义逻辑,例如初始化数据库连接、准备应用程序数据等。
init容器案例
初始化容器:
- 验证业务应用依赖的组件是否均已启动
- 修改目录的权限
- 调整系统参数
apiVersion: v1
kind: Pod
metadata:
name: init-container-example
spec:
containers:
- name: main-container
image: nginx
ports:
- containerPort: 80
initContainers:
- name: init-container
image: busybox
command: ['sh', '-c', 'wget -O /work-dir/index.html http://www.yuchaoit.cn/index.html']
volumeMounts:
- name: workdir
mountPath: /work-dir
volumes:
- name: workdir
emptyDir: {}
在这个示例中,Pod 包含两个容器:main-container 和 init-container。
init-container 的任务是从 example.com 网站下载一个 HTML 文件并保存在一个名为 work-dir 的卷中。
一旦这个任务完成,main-container 就会启动,并使用该卷中的文件作为 Nginx 服务器的默认主页。
需要注意的是,init-container 的工作目录和 main-container 不同。因此,需要在 volumes 字段中定义一个名为 workdir 的卷,并将其挂载到两个容器中。
EmptyDir是最简单的一种Volume类型,根据名字就能看出,这个Volume挂载后就是一个空目录,应用程序可以在里面读写文件,emptyDir Volume的生命周期与Pod相同,Pod删除后Volume的数据也同时删除掉。
此外,init 容器可以使用 kubernetes 提供的任何 api 对象,但是启动顺序是依照在 PodSpec 中定义的顺序。
演示init容器
[root@k8s-master ~/k8s-all]#kubectl create -f init-container.yml
pod/init-container-example created
[root@k8s-master ~/k8s-all]#kubectl get po -w
NAME READY STATUS RESTARTS AGE
init-container-example 0/1 Init:0/1 0 11s
ngx1 1/1 Running 1 (59s ago) 5d1h
test-nginx 1/1 Running 1 (59s ago) 7d1h
init-container-example 0/1 PodInitializing 0 18s
init-container-example 1/1 Running 0 44s
pod生命周期实战
一个综合性的yaml,演示pod综合知识点
- 初始化init
- 主容器
- 探针
- 钩子
apiVersion: v1
kind: Pod
metadata:
name: pod-lifecycle
namespace: yuchao
labels:
component: pod-lifecycless
spec:
initContainers:
- name: init
image: busybox
command: ['sh', '-c', 'echo $(date +%s): INIT >> /loap/timing']
volumeMounts:
- mountPath: /loap
name: timing
containers:
- name: main
image: busybox
command: ['sh', '-c', 'echo $(date +%s): START >> /loap/timing;
sleep 10; echo $(date +%s): END >> /loap/timing;']
volumeMounts:
- mountPath: /loap
name: timing
livenessProbe:
exec:
command: ['sh', '-c', 'echo $(date +%s): LIVENESS >> /loap/timing']
readinessProbe:
exec:
command: ['sh', '-c', 'echo $(date +%s): READINESS >> /loap/timing']
lifecycle:
postStart:
exec:
command: ['sh', '-c', 'echo $(date +%s): POST-START >> /loap/timing']
preStop:
exec:
command: ['sh', '-c', 'echo $(date +%s): PRE-STOP >> /loap/timing']
volumes:
- name: timing
hostPath:
path: /tmp/loap
创建pod
[root@k8s-master ~/k8s-all]#kubectl create -f pod-all.yaml
pod/pod-lifecycle created
[root@k8s-master ~/k8s-all]#
[root@k8s-master ~/k8s-all]#kubectl -n yuchao get po -w
NAME READY STATUS RESTARTS AGE
pod-lifecycle 0/1 Init:0/1 0 6s
pod-lifecycle 0/1 PodInitializing 0 16s
pod-lifecycle 0/1 Running 0 32s
pod-lifecycle 1/1 Running 0 32s
pod-lifecycle 0/1 Completed 0 42s
查看生命周期加载流程顺序
[root@k8s-master ~/k8s-all]#kubectl -n yuchao get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-lifecycle 0/1 CrashLoopBackOff 2 (8s ago) 104s 10.244.1.14 k8s-slave2 <none> <none>
[root@k8s-master ~/k8s-all]#
# 调度到了k8s-slave2机器,去这里找资料
[root@k8s-slave2 ~]#cat /tmp/loap/timing
1678989945: INIT
1678989960: START
1678989960: POST-START
1678989961: READINESS
1678989969: READINESS
1678989969: LIVENESS
1678989970: END
1678989986: START
1678989986: POST-START
1678989987: READINESS
1678989989: LIVENESS
1678989989: READINESS
1678989996: END
1678990015: START
1678990015: POST-START
1678990016: READINESS
1678990019: LIVENESS
1678990019: READINESS
1678990025: END
根据时间戳分析
- 先init
- 主容器、启动后钩子、同时执行
- 探针执行
- 容器结束、END
- 以及重启策略执行(默认always)
- 结束钩子呢?
- 必须主动杀掉 Pod 才会触发
pre-stop hook,如果是 Pod 自己 Down 掉,则不会执行pre-stop hook - 且杀掉Pod进程前,进程必须是正常运行状态,否则不会执行pre-stop钩子
- 也就是程序正常结束,正常执行的一些清理动作
- 必须主动杀掉 Pod 才会触发
mysql生命周期钩子
假设我们有一个基于容器的MySQL数据库应用程序,我们需要在容器启动之前和之后执行一些任务,例如创建数据库、添加用户等。我们可以使用Kubernetes的lifecycle钩子来实现这个目标。
下面是一个在MySQL容器启动之前和之后执行任务的简单lifecycle钩子:
apiVersion: v1
kind: Pod
metadata:
name: mysql-pod
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: www.yuchaoit.cn
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "mysql -u root -pwww.yuchaoit.cn -e 'CREATE DATABASE mydb;'"]
preStop:
exec:
command: ["/bin/sh", "-c", "mysql -u root -pwww.yuchaoit.cn -e 'DROP DATABASE mydb;'"]
这个Pod规范定义了一个名为mysql-pod的Pod,其中包含一个名为mysql的MySQL容器。在容器启动之后,postStart钩子将执行一个命令,创建名为mydb的数据库。在容器停止之前,preStop钩子将执行一个命令,删除名为mydb的数据库。
请注意,我们在容器启动时设置了环境变量MYSQL_ROOT_PASSWORD,用于指定MySQL root用户的密码。
在命令中使用该密码,以便在MySQL中执行数据库创建和删除操作。
如何编写k8s的yaml
拿来主义,从机器中已有的资源中拿
$ kubectl -n kube-system get po,deployment,ds
1. 学会在官网查找, https://kubernetes.io/docs/home/
2. 从kubernetes-api文档中查找, https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#pod-v1-core
3. kubectl explain 查看具体字段含义(于超老师推荐这个)
获取pod的标准yaml
# 核心就是kubectl get 资源 -o yaml
# 默认k8s会加入很多pod的属性字段,我们可以酌情删除,保留自己需要的即可
# 就可以得知如何学习,如何使用k8s资源
[root@k8s-master ~]#kubectl get po ngx1 -oyaml
获取svc的yaml
[root@k8s-master ~]#kubectl get svc kubernetes -oyaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2023-03-09T15:55:07Z"
labels:
component: apiserver
provider: kubernetes
name: kubernetes
namespace: default
resourceVersion: "199"
uid: ba95cdee-d8b6-4f55-b978-ab43a9383c56
spec:
clusterIP: 10.96.0.1
clusterIPs:
- 10.96.0.1
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: https
port: 443
protocol: TCP
targetPort: 6443
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
技巧
我们大多是在公司的现有k8s环境中,找到资源,拿到yaml,改造、理解,现有的k8s集群运维,是最快的方式。
若是想要更细节的去理解yaml,也就是k8s官网资料、或者kubectl explain了。
k8s核心之pod小结
- 实现k8s平台与特定的容器运行时解耦,提供更加灵活的业务部署方式,引入了Pod概念,作为k8s平台中业务服务运行时的最小调度单元
- k8s使用yaml格式定义资源文件,yaml比json更加简洁
- 通过
kubectl create|apply| get | exec | logs | delete等操作k8s资源,必须指定namespace - 每启动一个Pod,为了实现网络空间共享,会先创建pause容器,并把其他容器网络加入该容器,来实现Pod内所有容器使用同一个网络空间
- 通过nodeSelector选择器影响k8s的调度行为,实现服务定点部署
- Pod重建后Pod IP发生变化,所以使用Service类型的资源为Pod创建上层的VIP对外提供服务
- 通过
livenessProbe和readinessProbe实现Pod的存活性和就绪健康检查 - 通过requests和limit分别限定容器初始资源申请与最高上限资源申请
- 通过configMap和Secret来管理业务应用所需的配置(包含环境变量和配置文件等)
- Pod通过initContainer和lifecycle分别来执行初始化、pod启动和删除时候的操作,使得功能更加全面和灵活
- 编写yaml讲究方法,学习k8s,养成从官方网站查询知识的习惯
做了什么练习
- 定义Pod.yaml,将
eladmin-api,redis,mysql等服务使用Pod来启动 - mysql数据持久化,各应用添加了健康检查和资源限制
- yaml文件中的环境变量存在账号密码明文等敏感信息,使用configMap和Secret来统一配置,优化部署
还需要对pod学什么
- 业务应用启动多个副本
- 集群外部如何访问Pod服务
- 运行业务Pod的某个节点挂了,可以自动帮我把Pod转移到集群中的可用节点启动起来
- 我的业务应用功能是收集节点监控数据,需要把Pod运行在k8集群的各个节点上
pod控制器(重点)

Workload 工作负载类型
控制器又称工作负载是用于实现管理pod的中间层,确保pod资源符合预期的状态,pod的资源出现故障时,会尝试 进行重启,当根据重启策略无效,则会重新新建pod的资源。
- ReplicaSet: 用户创建指定数量的pod副本数量,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能
- Deployment:工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,提供声明式配置
- DaemonSet:用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。比如EFK服务
- Job:只要完成就立即退出,不需要重启或重建
- Cronjob:周期性任务控制,不需要持续后台运行
- StatefulSet:管理有状态应用
随着课程不断深入,逐步讲解每一个主流的控制器。
循序渐进的学习法。