kubernets的pod管理
一.kubernetes中的资源
1.1 资源管理介绍
这张图展示了kubernetes核心组件的层级关系和协作逻辑,分为Pod和Container、控制器家族、服务暴露service、存储与配置四个维度

1.1.1 Pod和Container----应用的运行载体
Container(容器):是运行的最小单元,比如一个 Nginx 容器提供网页服务,一个 Java 容器跑后端代码。容器相互隔离,但同一个 Pod 内的容器共享网络、存储等资源,可以协同工作(比如 Nginx 容器 + 日志收集容器)。
Pod:Kubernetes 里最小的可部署单元(不能直接部署 “容器”,必须包在 Pod 里)。可以理解为豆荚,Container就是里面的一个个的豆子,而Pod就是包裹豆子的豆荚,让他们作为一个整体来运行。
1.1.2 控制器家族----管理Pod的生命周期
各种 “控制器” 负责管理 Pod 的生命周期(创建、副本数、更新、删除等),不同控制器对应不同场景:
| 控制器 | 核心作用 | 典型场景 |
|---|---|---|
| Deployment | 管理 “无状态应用”,确保指定数量的 Pod 一直运行,还能滚动更新(逐步替换 Pod,不中断服务)。 | 部署 Web 服务(如 Nginx、Node.js)、普通后端服务。 |
| ReplicaSet | 保证 “固定数量的 Pod 副本存在”(比如要 3 个 Pod,挂了就自动新建)。 | 是 Deployment 的 “底层支撑”(Deployment 通过管理 ReplicaSet 间接管理 Pod),一般不直接用。 |
| DaemonSet | 确保每个节点上都有一个 Pod 副本。 | 节点监控(每个节点跑 “监控代理”)、日志收集(每个节点跑 “日志收集器”)。 |
| Job | 执行 “一次性任务”(任务完成后,Pod 自动结束)。 | 数据备份、批量计算(如统计数据库某张表的行数)。 |
| CronJob | 定时触发的 Job(类似 Linux 的 crontab,按时间规则重复执行)。 | 定时备份数据库、定时清理日志。 |
| StatefulSet | 管理 “有状态应用”(需要稳定标识、持久存储的应用,如数据库)。 | 部署 MySQL、MongoDB 等数据库集群(Pod 重启 / 迁移后,身份和数据不丢失)。 |
1.1.3 service----服务暴露
Pod 的 IP 是动态变化的(重启、扩容、迁移都会换 IP),但 Service 能给 Pod 提供一个固定的访问地址(IP + 端口)。
- 工作逻辑:
Service通过标签选择器(比如 Pod 打了app: nginx标签,Service 也配置这个标签),把流量转发到匹配的 Pod 上。 - 效果:不管后端 Pod 怎么变(新增、删除、IP 变化),前端只需访问
Service的地址,就能稳定访问到应用。
1.1.4 Volume ----Pod的资源支撑
Pod 里的容器是 “临时的”(重启就丢数据),所以需要持久化存储和配置管理:
| 组件 | 核心作用 | 关联场景 |
|---|---|---|
| Volume | 给 Pod 提供 “存储卷”(让容器能读写数据,数据不随容器重启丢失)。 | 是存储的 “抽象层”,需要结合下面的 PVC/ConfigMap/Secret 用。 |
| ConfigMap | 存储应用配置文件(比如 Nginx 的配置、Java 应用的参数)。 | 把 “配置” 和 “镜像” 解耦(改配置不用重新做镜像,直接改 ConfigMap),然后挂载到 Volume 给容器用。 |
| PVC(PersistentVolumeClaim) | 向集群 “申请持久化存储”(集群里有 PersistentVolume 资源池,PVC 是 “申请单”)。 | 数据库存储(MySQL 数据需要持久化,通过 PVC 绑定存储,Pod 重启后数据还在)。 |
| Secret | 存储敏感信息(比如数据库密码、HTTPS 证书),会加密。 | 和 ConfigMap 类似,但用于敏感数据,同样挂载到 Volume 给容器用。 |
整体逻辑:
- 控制器创建 Pod:比如
Deployment根据配置,创建指定数量的 Pod(每个 Pod 包含业务容器)。 - 存储 / 配置注入 Pod:通过
ConfigMap/Secret管理配置,通过PVC提供持久化存储,这些资源被挂载到 Pod 的Volume中,供容器使用。 - Service 暴露服务:
Service通过标签匹配 Pod,提供固定访问地址,让外部(或集群内其他服务)能稳定访问 Pod 里的应用。
1.2 资源管理方式
-
命令式对象管理:直接使用命令去操作kubernetes资源
kubectl run nginx-pod --image=nginx:latest --port=80
# 命令式对象管理:直接通过kubectl命令创建Pod
# 以下命令创建一个名为test的Pod,使用nginx:1.23镜像,暴露80端口
[root@master pod]# kubectl run test --image nginx:1.23 --port 80
pod/test created # 执行结果:提示Pod创建成功# 查看当前集群中的Pod列表,验证是否创建成功
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test 1/1 Running 0 7s # 结果分析:test Pod状态为Running,说明正常运行,1/1表示容器就绪#### 发现命令式对象管理没记录,没历史,而且只能操作正在运行的资源,相当于口头命令
# 思路:这种方式适合临时测试,因为简单直接,但缺点是没有配置文件留存,后续修改或追溯困难
-
命令式对象配置:通过命令配置和配置文件去操作kubernetes资源
kubectl create/patch -f nginx-pod.yaml
# 命令式对象配置:先创建配置文件,再通过命令执行配置
[root@master ~]# mkdir pod # 创建存放Pod配置文件的目录
[root@master ~]# cd pod/ # 进入目录
# 生成一个名为test.yml的配置文件,--dry-run=client表示仅模拟创建不实际执行,-o yaml输出为yaml格式
[root@master pod]# kubectl run test --image busyboxplus --port 80 --dry-run=client -o yaml > test.yml
# 查看配置文件内容
[root@master pod]# cat test.yml
apiVersion: v1 # 使用 Kubernetes 核心API版本(v1是稳定版本)
kind: Pod # 资源类型为Pod(固定值)
metadata:labels:run: test # 给Pod打标签run=test,用于后续筛选和关联Service等name: test # Pod的名称(必须唯一)
spec:containers:- image: busyboxplus # 容器使用的镜像name: test # 容器名称(在Pod内唯一)ports:- containerPort: 80 # 容器暴露的端口(仅标识作用,不实际映射)command: # 容器启动命令- /bin/sh # 启动shell解释器- -c # 告诉shell执行后面的字符串作为命令- sleep 10000 # 实际执行的命令:让容器休眠10000秒(避免容器启动后立即退出)# 通过配置文件创建Pod
[root@master pod]# kubectl create -f test.yml
pod/test created # 结果:Pod创建成功# 查看Pod状态
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test 1/1 Running 0 3s # 状态正常# 修改配置文件:将镜像从busyboxplus改为nginx:1.23
[root@master pod]# vim test.yml
- image: nginx:1.23# 尝试用create命令更新已存在的Pod(会失败)
[root@master pod]# kubectl create -f test.yml
Error from server (AlreadyExists): error when creating "test.yml": pods "test" already exists # 结果分析:create命令只能创建新资源,不能更新已有资源

-
声明式对象配置:通过apply命令和配置文件去操作kubernetes资源
kubectl apply -f nginx-pod.yaml
# 这个命令用于根据YAML配置文件删除Kubernetes集群中对应的资源
[root@master pod]# kubectl delete -f test.yml # 先删除之前的test Pod
pod "test" deleted # 结果:Pod删除成功# 使用apply命令创建Pod(apply支持创建和更新)
[root@master pod]# apply -f test.yml
pod/test created # 结果:创建成功# 查看Pod详情,验证镜像是否更新为nginx:1.23
[root@master pod]# kubectl describe pods test
Image: nginx:1.23 # 结果分析:镜像已更新,说明apply命令生效# 请注意:对于Pod而言,一旦创建,某些字段是不可变的,包括容器端口。
# 思路:声明式配置的核心是"描述最终状态",apply会自动对比当前状态和配置文件,只更新差异部分,适合长期维护的资源
- 命令式 = 口头临时命令;
- 命令式配置 = 写说明书 + 单次按说明书执行;
- 声明式配置 = 写说明书 + 让系统自动保持说明书里的最终样子。
| 类型 | 适用环境 | 优点 | 缺点 |
|---|---|---|---|
| 命令式对象管理 | 测试 | 简单 | 只能操作活动对象,无法审计、跟踪 |
| 命令式对象配置 | 开发 | 可以审计、跟踪 | 项目大时,配置文件多,操作麻烦 |
| 声明式对象配置 | 开发 | 支持目录操作 | 意外情况下难以调试 |
1.2.1 命令式对象管理
kubectl是kubernetes集群的命令行工具,通过它能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署
kubectl命令的语法如下:
kubectl [command] [type] [name] [flags]
comand:指定要对资源执行的操作,例如create、get、delete
type:指定资源类型,比如deployment、pod、service
name:指定资源的名称,名称大小写敏感
flags:指定额外的可选参数
# 查看所有pod
kubectl get pod # 查看某个pod
kubectl get pod pod_name# 查看某个pod,以yaml格式展示结果
kubectl get pod pod_name -o yaml
1.2.2 资源类型
kubernetes中所有的内容都抽象为资源
kubectl api-resources # 查看集群中所有可用的资源类型
常用资源类型
| 资源分类 | 资源名称 | 缩写 | 资源作用 |
|---|---|---|---|
| 集群级别资源 | nodes | no | 集群组成部分 |
| namespaces | ns | 隔离Pod | |
| pod资源 | pods | po | 装载容器 |
| pod资源控制器 | replicationcontrollers | rc | 控制pod资源 |
| replicasets | rs | 控制pod资源 | |
| deployments | deploy | 控制pod资源 | |
| daemonsets | ds | 控制pod资源 | |
| jobs | 控制pod资源 | ||
| cronjobs | q | 控制pod资源 | |
| horizontalpodautoscalers | hpa | 控制pod资源 | |
| statefulsets | sts | 控制pod资源 | |
| 服务发现资源 | services | svc | 统一pod对外接口 |
| ingress | ing | 统一pod对外接口 | |
| 存储资源 | volumeattachments | 存储 | |
| persistentvolumes | pv | 存储 | |
| persistentvolumeclaims | pvc | 存储 | |
| 配置资源 | configmaps | cm | 配置 |
| secrets | 配置 |
kubect 常见命令操作
| 命令分类 | 命令 | 翻译 | 命令作用 |
|---|---|---|---|
| 基本命令 | create | 创建 | 创建一个资源 |
| edit | 编辑 | 编辑一个资源 | |
| get | 获取 | 获取一个资源 | |
| patch | 更新 | 更新一个资源 | |
| delete | 删除 | 删除一个资源 | |
| explain | 解释 | 展示资源文档 | |
| 运行和调试 | run | 运行 | 在集群中运行一个指定的镜像 |
| expose | 暴露 | 暴露资源为Service | |
| describe | 描述 | 显示资源内部信息 | |
| logs | 日志 | 输出容器在pod中的日志 | |
| attach | 缠绕 | 进入运行中的容器 | |
| exec | 执行 | 执行容器中的一个命令 | |
| cp | 复制 | 在Pod内外复制文件 | |
| rollout | 首次展示 | 管理资源的发布 | |
| scale | 规模 | 扩(缩)容Pod的数量 | |
| autoscale | 自动调整 | 自动调整Pod的数量 | |
| 高级命令 | apply | rc | 通过文件对资源进行配置 |
| label | 标签 | 更新资源上的标签 | |
| 其他命令 | cluster-info | 集群信息 | 显示集群信息 |
| version | 版本 | 显示当前Server和Client的版本 |
1.2.3 基本命令示例
kubectl的详细说明地址:https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands
# 显示集群版本(客户端和服务端)
[root@master pod]# kubectl version
Client Version: v1.30.0 # 客户端(kubectl)版本
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.30.0 # 服务端(kube-apiserver)版本
# 结果分析:客户端和服务端版本一致,兼容性良好# 显示集群信息(控制平面和核心组件地址)
[root@master pod]# kubectl cluster-info
Kubernetes control plane is running at https://192.168.2.60:6443 # 控制平面地址
CoreDNS is running at https://192.168.2.60:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy # DNS服务地址To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
# 思路:这两个命令用于验证集群是否正常运行,版本是否匹配
# 创建一个名为webcluster的Deployment控制器,使用nginx:1.23镜像,指定副本数为2
[root@master pod]# kubectl create deployment webcluster --image nginx:1.23 --replicas 2
deployment.apps/webcluster created # 结果:Deployment创建成功# 查看Deployment状态
[root@master pod]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
webcluster 2/2 2 2 24s # 结果分析:2/2表示期望2个副本,当前就绪2个;UP-TO-DATE表示最新版本的副本数;AVAILABLE表示可用副本数# 查看由Deployment创建的Pod
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-74f6bcfffd-45hsx 1/1 Running 0 32s
webcluster-74f6bcfffd-mdlh5 1/1 Running 0 32s # 结果:2个Pod正常运行,名称格式为"Deployment名称-随机字符串"
# 思路:通过Deployment创建Pod,可以自动维护副本数,比直接创建Pod更可靠
如果记不住命令,可以使用explain来展示 Kubernetes 资源的文档和字段说明
# 查看Pod资源的帮助文档(了解Pod的基本结构和字段)
[root@master pod]# kubectl explain pod
KIND: Pod # 资源类型
VERSION: v1 # API版本DESCRIPTION:Pod is a collection of containers that can run on a host. This resource iscreated by clients and scheduled onto hosts. # Pod的描述:包含一组容器的集合,可被调度到节点上运行FIELDS: # Pod的核心字段apiVersion <string> # API版本(如v1)APIVersion defines the versioned schema of this representation of an object.Servers should convert recognized schemas to the latest internal value, andmay reject unrecognized values. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resourceskind <string> # 资源类型(固定为Pod)Kind is a string value representing the REST resource this objectrepresents. Servers may infer this from the endpoint the client submitsrequests to. Cannot be updated. In CamelCase. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kindsmetadata <ObjectMeta> # 元数据(名称、标签等)Standard object's metadata. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadataspec <PodSpec> # 期望状态(容器、存储等配置)Specification of the desired behavior of the pod. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-statusstatus <PodStatus> # 实际状态(由系统维护,只读)Most recently observed status of the pod. This data may not be up to date.Populated by the system. Read-only. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
# 思路:explain命令是学习Kubernetes资源配置的好工具,能快速了解每个字段的含义
查看Pod参数帮助
# 查看Pod的kind字段说明
[root@master pod]# kubectl explain pod.kind
KIND: Pod
VERSION: v1FIELD: kind <string> # 字段名和类型DESCRIPTION:Kind is a string value representing the REST resource this objectrepresents. Servers may infer this from the endpoint the client submitsrequests to. Cannot be updated. In CamelCase. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
# 编辑Deployment的配置(会打开默认编辑器,修改后保存自动生效)
[root@master pod]# kubectl edit deployments.apps webcluster
deployment.apps/webcluster edited # 结果:编辑成功# 查看编辑后的Deployment状态(副本数变为4)
[root@master pod]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
webcluster 4/4 4 4 22m # 结果分析:副本数从2扩展到4,控制器自动创建了新Pod
# 思路:edit命令适合临时修改资源配置,直接编辑生效,比手动改yaml再apply更快捷

# 用补丁(JSON格式)更新Deployment的副本数为6(无需编辑整个配置文件)
[root@master pod]# kubectl patch deployments.apps webcluster -p '{"spec":{"replicas":6}}'
deployment.apps/webcluster patched # 结果:补丁应用成功# 查看更新后的副本数
[root@master pod]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
webcluster 6/6 6 6 24m # 结果:副本数成功更新为6
# 思路:patch命令适合小范围更新资源,比edit更精准,适合脚本化操作
# 删除Deployment(会自动删除其管理的所有Pod)
[root@master pod]# kubectl delete deployments.apps webcluster
deployment.apps "webcluster" deleted # 结果:Deployment删除成功# 验证是否删除
[root@master pod]# kubectl get deployments.apps
No resources found in default namespace. # 结果:已无该Deployment
# 思路:删除控制器会级联删除其管理的资源,确保资源彻底清理
1.2.4 运行和调试命令示例
# 创建一个名为test的Pod,使用nginx:1.23镜像
[root@master pod]# kubectl run test --image nginx:1.23
pod/test created # 结果:Pod创建成功# 查看Pod状态
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
test 1/1 Running 0 10s # 状态正常# 查看当前集群中的Service(服务)
[root@master pod]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 43h # 仅集群默认的kubernetes服务# 暴露test Pod为Service,端口80(Service端口)映射到Pod的80端口(容器端口)
[root@master pod]# kubectl expose pod test --port 80 --target-port 80
service/test exposed # 结果:Service创建成功# 查看创建的Service
[root@master pod]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 43h
test ClusterIP 10.97.227.77 <none> 80/TCP 9s # 新创建的test服务,有唯一的ClusterIP# 访问Service的ClusterIP,验证是否能访问到Nginx
[root@master pod]# curl 10.97.227.77
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...(省略部分内容)...
</body>
</html> # 结果:成功访问到Nginx默认页面,说明Service转发正常
# 思路:通过expose命令快速创建Service,实现对Pod的稳定访问,不用关心Pod的IP变化
# 查看test Pod的详细信息(包括节点、容器、事件等)
[root@master pod]# kubectl describe pods test
Name: test # Pod名称
Namespace: default # 所属命名空间
Priority: 0
Service Account: default
Node: node2/192.168.2.63 # 运行在node2节点上
Start Time: Sat, 18 Oct 2025 18:03:25 +0800 # 启动时间
Labels: run=test # 标签
Annotations: <none>
Status: Running # 状态
IP: 10.244.2.122 # Pod的IP
IPs:IP: 10.244.2.122
Containers: # 容器信息test:Container ID: docker://f0befef973ce47bddf15757bb1cb3fe187049c0479166a04703d497e4d33ecd9 # 容器IDImage: nginx:1.23 # 使用的镜像Image ID: docker-pullable://nginx@sha256:a97a153152fcd6410bdf4fb64f5622ecf97a753f07dcc89dab14509d059736cfPort: <none>Host Port: <none>State: Running # 容器状态Started: Sat, 18 Oct 2025 18:03:25 +0800 # 启动时间Ready: True # 就绪状态Restart Count: 0 # 重启次数Environment: <none>Mounts: # 挂载的存储/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-dn985 (ro)
Conditions: # 状态条件(全部为True表示正常)Type StatusPodReadyToStartContainers True Initialized True Ready True ContainersReady True PodScheduled True
Volumes: # 卷信息kube-api-access-dn985:Type: Projected (a volume that contains injected data from multiple sources)TokenExpirationSeconds: 3607ConfigMapName: kube-root-ca.crtConfigMapOptional: <nil>DownwardAPI: true
QoS Class: BestEffort # 服务质量等级
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300snode.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events: # 事件记录(调度、拉取镜像、启动容器等过程)Type Reason Age From Message---- ------ ---- ---- -------Normal Scheduled 2m2s default-scheduler Successfully assigned default/test to node2 # 成功调度到node2Normal Pulled 2m2s kubelet Container image "nginx:1.23" already present on machine # 镜像已存在,无需拉取Normal Created 2m2s kubelet Created container test # 创建容器Normal Started 2m2s kubelet Started container test # 启动容器
# 结果分析:通过describe可以全面了解Pod的运行状态,排查问题时常用(比如Pod启动失败可看Events)
# 查看test Pod中容器的日志(默认是第一个容器)
[root@master pod]# kubectl logs pods/test
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/10/18 10:03:25 [notice] 1#1: using the "epoll" event method
2025/10/18 10:03:25 [notice] 1#1: nginx/1.23.4 # Nginx版本
2025/10/18 10:03:25 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2025/10/18 10:03:25 [notice] 1#1: OS: Linux 5.14.0-362.8.1.el9_3.x86_64
2025/10/18 10:03:25 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1073741816:1073741816
2025/10/18 10:03:25 [notice] 1#1: start worker processes
2025/10/18 10:03:25 [notice] 1#1: start worker process 29
2025/10/18 10:03:25 [notice] 1#1: start worker process 30
10.244.0.0 - - [18/Oct/2025:10:04:39 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.76.1" "-" # 之前的curl访问记录
# 结果分析:日志显示Nginx启动过程和访问记录,用于排查应用运行问题
# 创建一个交互式的busyboxplus Pod(-it表示交互式终端)
[root@master ~]# kubectl run -it test --image busyboxplus
If you don't see a command prompt, try pressing enter.
/ # # 成功进入容器终端# ctrl+p+q退出后重新创建一个nginx Pod
[root@master ~]# kubectl run nginx --image nginx:1.23
pod/nginx created# 尝试重新连接test Pod的终端(attach命令)
[root@master ~]# kubectl attach pods/test -it
If you don't see a command prompt, try pressing enter.
/ # Session ended, resume using 'kubectl attach test -c test -i -t' command when the pod is running# 在nginx Pod中执行/bin/bash命令(进入容器终端)
[root@master ~]# kubectl exec -it pods/nginx /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx:/# # 成功进入nginx容器终端
# 思路:exec和attach都能进入容器,exec适合临时执行命令,attach适合连接已运行的终端
# 创建nginx Pod
[root@master ~]# kubectl run nginx --image nginx:1.23
pod/nginx created# 将本地文件anaconda-ks.cfg复制到nginx Pod的根目录
[root@master ~]# kubectl cp anaconda-ks.cfg nginx:/
# 结果:复制成功(无提示即成功)# 进入nginx容器验证文件是否存在
[root@master ~]# kubectl exec -it pods/nginx /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx:/# ls
anaconda-ks.cfg boot docker-entrypoint.d etc lib media opt root sbin sys usr
...(省略部分内容)... # 可见anaconda-ks.cfg已存在# 将nginx容器内的/docker-entrypoint.sh文件复制到本地
[root@master ~]# kubectl cp nginx:/docker-entrypoint.sh docker-entrypoint.sh
tar: Removing leading `/' from member names # 提示:去除路径中的根目录符号# 查看本地是否有该文件
[root@master ~]# ls
... docker-entrypoint.sh ... # 已成功复制
# 思路:cp命令用于在本地和Pod之间传输文件,方便调试(比如获取日志文件、上传配置文件)
1.2.5 高级命令示例
# 生成webcluster Deployment的yaml配置文件(--dry-run模拟创建,-o yaml输出为yaml)
[root@master ~]# kubectl create deployment --image nginx:1.23 webcluster --dry-run=client -o yaml > webcluster.yaml# 查看配置文件内容
[root@master ~]# cat webcluster.yaml
apiVersion: apps/v1 # Deployment属于apps组的v1版本API
kind: Deployment # 资源类型为Deployment
metadata:creationTimestamp: null # 创建时间(自动生成,此处为null)labels:app: webcluster # 标签:app=webclustername: webcluster # Deployment名称
spec:replicas: 3 # 期望的Pod副本数selector: # 标签选择器(匹配Pod的标签)matchLabels:app: webclustertemplate: # Pod模板(定义Pod的配置)metadata:labels:app: webcluster # Pod的标签(需与selector匹配)spec:containers:- image: nginx:1.23 # 容器镜像name: nginx # 容器名称# 用apply命令创建Deployment(支持创建和更新)
[root@master ~]# kubectl apply -f webcluster.yaml
deployment.apps/webcluster configured # 结果:创建成功# 查看Deployment状态
[root@master ~]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
webcluster 3/3 3 3 92s # 3个副本均正常运行
# 思路:通过yaml配置文件管理资源,便于版本控制和重复部署,apply会自动处理创建/更新
# 用apply命令创建Deployment(若已存在则更新)
[root@master ~]# kubectl apply -f webcluster.yaml
deployment.apps/webcluster created # 结果:创建成功# 查看Pod并显示标签(--show-labels)
[root@master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
webcluster-74f6bcfffd-7lqs9 1/1 Running 0 18s app=webcluster,pod-template-hash=74f6bcfffd # 标签包含app=webcluster和自动生成的pod-template-hash
webcluster-74f6bcfffd-fclsc 1/1 Running 0 18s app=webcluster,pod-template-hash=74f6bcfffd
webcluster-74f6bcfffd-rxfnh 1/1 Running 0 18s app=webcluster,pod-template-hash=74f6bcfffd# 修改其中一个Pod的标签:将app=webcluster改为app=rch(--overwrite允许覆盖现有标签)
[root@master ~]# kubectl label pods webcluster-74f6bcfffd-7lqs9 app=rch --overwrite
pod/webcluster-74f6bcfffd-7lqs9 labeled # 结果:标签修改成功# 再次查看标签(发现该Pod标签已变,且Deployment自动新建了一个符合标签的Pod)
[root@master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
webcluster-74f6bcfffd-74n6z 1/1 Running 0 6s app=webcluster,pod-template-hash=74f6bcfffd # 新创建的Pod
webcluster-74f6bcfffd-7lqs9 1/1 Running 0 114s app=rch,pod-template-hash=74f6bcfffd # 被修改标签的Pod
...(省略部分内容)...
# 结果分析:Deployment通过标签选择器维护副本,当某个Pod标签不匹配时,会新建Pod补充数量# 移除一个Pod的app标签(标签名后加-表示删除)
[root@master ~]# kubectl label pods webcluster-74f6bcfffd-fclsc app-
pod/webcluster-74f6bcfffd-fclsc unlabeled # 结果:标签删除成功# 恢复标签为app=webcluster
[root@master ~]# kubectl label pods webcluster-74f6bcfffd-7lqs9 app=webcluster --overwrite
pod/webcluster-74f6bcfffd-7lqs9 labeled
[root@master ~]# kubectl label pods webcluster-74f6bcfffd-fclsc app=webcluster --overwrite
pod/webcluster-74f6bcfffd-fclsc labeled# 最终所有Pod标签恢复正常,Deployment副本数稳定
[root@master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
webcluster-74f6bcfffd-7lqs9 1/1 Running 0 3m41s app=webcluster,pod-template-hash=74f6bcfffd
...(省略部分内容)...
# 思路:标签是Kubernetes中资源关联的核心,通过修改标签可以控制资源的归属(如让Pod脱离控制器管理)
二 什么是pod
Pod 是 Kubernetes 里 “应用的最小执行单元”。你可以把它想象成一个 “盒子”,里面能装 1 个或多个容器(比如 Web 容器 + 日志收集容器)。这些容器在 Pod 内共享**网络、存储 ** 等资源,可紧密协作完成任务;且 Kubernetes 不直接管理 “容器”,而是通过管理 Pod 间接管理容器的生命周期。
2.1 Pod 的创建与管理方式
2.1.1 创建自主式 Pod(生产不推荐)
“自主式 Pod” 即手动创建 Pod,无控制器自动管理。例如用命令:
kubectl run mypod --image=nginx:1.23 # 创建一个名为mypod的自主式Pod,使用nginx:1.23镜像
可直接创建一个运行 Nginx 的 Pod。
但生产环境不推荐:若 Pod 意外崩溃、节点宕机,Kubernetes 不会自动重建它,服务会直接中断(相当于 “没人管的 Pod,死了就真死了”)。
2.1.2 利用控制器管理 Pod(推荐)
控制器是 Pod 的 “自动化管家”,负责维护 Pod 的全生命周期(创建、副本数维持、更新、自愈等)。常用控制器及场景:
- Deployment(最常用):管理无状态应用(如 Web 服务,不依赖固定存储 / 身份),能保证指定数量的 Pod 持续运行,还支持滚动更新(逐步替换 Pod,服务不中断)。
- StatefulSet:管理有状态应用(如数据库,需要稳定身份、持久存储),Pod 重启 / 迁移后,身份和数据不丢失。
- DaemonSet:保证每个集群节点上都有一个 Pod 副本(如节点监控代理、日志收集器)。
- Job/CronJob:执行一次性任务(Job)或定时任务(CronJob),任务完成后 Pod 自动结束。
用控制器的优势:
高可用性和可靠性:
- 自动故障恢复:如果一个 Pod 失败或被删除,控制器会自动创建新的 Pod 来维持期望的副本数量。确保应用始终处于可用状态,减少因单个 Pod 故障导致的服务中断。
- 健康检查和自愈:可以配置控制器对 Pod 进行健康检查(如存活探针和就绪探针)。如果 Pod 不健康,控制器会采取适当的行动,如重启 Pod 或删除并重新创建它,以保证应用的正常运行。
可扩展性:
- 轻松扩缩容:可以通过简单的命令或配置更改来增加或减少 Pod 的数量,以满足不同的工作负载需求。例如,在高流量期间可以快速扩展以处理更多请求,在低流量期间可以缩容以节省资源。
- 水平自动扩缩容(HPA):可以基于自定义指标(如 CPU 利用率、内存使用情况或应用特定的指标)自动调整 Pod 的数量,实现动态的资源分配和成本优化。
版本管理和更新:
- 滚动更新:对于 Deployment 等控制器,可以执行滚动更新来逐步替换旧版本的 Pod 为新版本,确保应用在更新过程中始终保持可用。可以控制更新的速率和策略,以减少对用户的影响。
- 回滚:如果更新出现问题,可以轻松回滚到上一个稳定版本,保证应用的稳定性和可靠性。
声明式配置:
- 简洁的配置方式:使用 YAML 或 JSON 格式的声明式配置文件来定义应用的部署需求。这种方式使得配置易于理解、维护和版本控制,同时也方便团队协作。
- 期望状态管理:只需要定义应用的期望状态(如副本数量、容器镜像等),控制器会自动调整实际状态与期望状态保持一致。无需手动管理每个 Pod 的创建和删除,提高了管理效率。
服务发现和负载均衡:
- 自动注册和发现:Kubernetes 中的服务(Service)可以自动发现由控制器管理的 Pod,并将流量路由到它们。这使得应用的服务发现和负载均衡变得简单和可靠,无需手动配置负载均衡器。
- 流量分发:可以根据不同的策略(如轮询、随机等)将请求分发到不同的 Pod,提高应用的性能和可用性。
多环境一致性:
- 一致的部署方式:在不同的环境(如开发、测试、生产)中,可以使用相同的控制器和配置来部署应用,确保应用在不同环境中的行为一致。这有助于减少部署差异和错误,提高开发和运维效率。
示例:
# 查看webcluster的Deployment配置文件
[root@master ~]# cat webcluster.yaml
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: webclustername: webcluster
spec:replicas: 3 # 期望3个Pod副本selector:matchLabels:app: webclustertemplate:metadata:labels:app: webclusterspec:containers:- image: nginx:1.23 # 容器镜像name: nginx# 应用配置文件创建/更新Deployment
[root@master ~]# kubectl apply -f webcluster.yaml
deployment.apps/webcluster configured # 结果:配置生效# 查看创建的Pod
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-74f6bcfffd-7lqs9 1/1 Running 0 16m
webcluster-74f6bcfffd-fclsc 1/1 Running 0 16m
webcluster-74f6bcfffd-rxfnh 1/1 Running 0 16m # 3个Pod正常运行# 扩容:将副本数从3扩展到8(scale命令快速调整副本数)
[root@master ~]# kubectl scale deployment webcluster --replicas 8
deployment.apps/webcluster scaled # 结果:扩容成功# 查看扩容后的Pod(新增5个Pod)
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-74f6bcfffd-78ddg 1/1 Running 0 3s
webcluster-74f6bcfffd-7lqs9 1/1 Running 0 16m
...(共8个Pod)... # 结果:成功扩容到8个副本# 缩容:将副本数从8缩减到2
[root@master ~]# kubectl scale deployment webcluster --replicas 2
deployment.apps/webcluster scaled # 结果:缩容成功# 查看缩容后的Pod(仅保留2个)
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
webcluster-74f6bcfffd-7lqs9 1/1 Running 0 16m
webcluster-74f6bcfffd-rxfnh 1/1 Running 0 16m # 结果:缩容到2个副本
# 思路:通过控制器的scale命令可以快速调整Pod数量,应对流量变化,比手动创建/删除Pod高效
2.2 应用版本的更新
Kubernetes 中,应用版本更新主要依赖控制器的 “滚动更新”(以 Deployment 为例):比如要将 Nginx 从 1.19 升级到 1.20,Deployment 会先创建新 Pod(运行 1.20),再逐步停止旧 Pod(运行 1.19),直到所有 Pod 都替换为新版本。
这种方式的好处是:服务不中断(用户无感知),且支持 “一键回滚”(若新版本有问题,可快速切回旧版本)。
注意:使用配置文件默认从harbor里面的library项目中拉取

示例(这里我用我仓库里myapp的v1和v2版本来演示):
[root@master ~]# vim webcluster.yaml
[root@master ~]# cat webcluster.yaml
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: webclustername: webcluster
spec:replicas: 2selector:matchLabels:app: webclustertemplate:metadata:labels:app: webclusterspec:containers:- image: myapp:v1 #镜像改为myapp:v1name: myapp
[root@master ~]# kubectl apply -f webcluster.yaml
deployment.apps/webcluster configured# 查看Pod及所在节点(-o wide显示更多信息)
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
webcluster-6b7f86b547-8msj4 1/1 Running 0 28s 10.244.1.35 node1 <none> <none>
webcluster-6b7f86b547-lfnh4 1/1 Running 0 30s 10.244.2.137 node2 <none> <none># 访问其中一个Pod的IP,验证版本(显示v1)
[root@master ~]# curl 10.244.1.35
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a># 暴露Deployment为Service,指定外部IP(192.168.2.100)方便外部访问
[root@master ~]# kubectl expose deployment webcluster --port 80 --target-port 80 --external-ip 192.168.2.100
service/webcluster exposed
# 访问Service的外部IP,验证版本
[root@master ~]# curl 192.168.2.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master ~]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d23h
webcluster ClusterIP 10.111.6.48 192.168.2.100 80/TCP 24s# 查看Deployment的更新历史(记录每次版本变化)
[root@master ~]# kubectl rollout history deployment webcluster
deployment.apps/webcluster
REVISION CHANGE-CAUSE
1 <none>
2 <none># 更新镜像为myapp:v2(set image命令快速更新容器镜像)
[root@master ~]# kubectl set image deployments/webcluster myapp=myapp:v2
deployment.apps/webcluster image updated
# 查看更新后的历史版本(新增第3版)
[root@master ~]# kubectl rollout history deployment webcluster
deployment.apps/webcluster
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>[root@master ~]# curl 192.168.2.100
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
# 回滚到版本2(--to-revision指定回滚版本)
[root@master ~]# kubectl rollout undo deployment webcluster --to-revision 2
deployment.apps/webcluster rolled back
[root@master ~]# curl 192.168.2.100
curl: (56) Recv failure: 连接被对方重设
[root@master ~]# curl 192.168.2.100
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@master ~]# kubectl rollout undo deployment webcluster --to-revision 1
deployment.apps/webcluster rolled back
[root@master ~]# curl 192.168.2.100
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p><p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@master ~]# kubectl rollout undo deployment webcluster --to-revision 3
deployment.apps/webcluster rolled back
[root@master ~]# curl 192.168.2.100
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
# 思路:通过滚动更新和回滚机制,可安全地更新应用版本,出现问题时快速恢复,保证服务稳定性
2.3 利用yaml文件部署应用
用 YAML 文件(资源清单)部署是 Kubernetes 推荐的方式 —— 它能 “把应用配置写成代码”,方便版本控制、重复部署。
2.3.1 用 YAML 部署的优点
声明式配置:
- 清晰表达期望状态:以声明式的方式描述应用的部署需求,包括副本数量、容器配置、网络设置等。这使得配置易于理解和维护,并且可以方便地查看应用的预期状态。
- 可重复性和版本控制:配置文件可以被版本控制,确保在不同环境中的部署一致性。可以轻松回滚到以前的版本或在不同环境中重复使用相同的配置。
- 团队协作:便于团队成员之间共享和协作,大家可以对配置文件进行审查和修改,提高部署的可靠性和稳定性。
灵活性和可扩展性:
- 丰富的配置选项:可以通过 YAML 文件详细地配置各种 Kubernetes 资源,如 Deployment、Service、ConfigMap、Secret 等。可以根据应用的特定需求进行高度定制化。
- 组合和扩展:可以将多个资源的配置组合在一个或多个 YAML 文件中,实现复杂的应用部署架构。同时,可以轻松地添加新的资源或修改现有资源以满足不断变化的需求。
与工具集成:
- 与 CI/CD 流程集成:可以将 YAML 配置文件与持续集成和持续部署(CI/CD)工具集成,实现自动化的应用部署。例如,可以在代码提交后自动触发部署流程,使用配置文件来部署应用到不同的环境。
- 命令行工具支持:Kubernetes 的命令行工具
kubectl对 YAML 配置文件有很好的支持,可以方便地应用、更新和删除配置。同时,还可以使用其他工具来验证和分析 YAML 配置文件,确保其正确性和安全性。
2.3.2 资源清单参数
Kubernetes YAML 资源清单有固定结构,核心字段包括:
apiVersion:API 版本(不同资源类型版本不同,如 Pod 用v1,Deployment 用apps/v1)。kind:资源类型(如Pod、Deployment、Service)。metadata:元数据(如名字name、标签labels—— 标签用于给资源 “分类”,方便控制器 / Service 匹配)。spec:具体配置(如 Pod 的容器、存储、网络等,不同资源的spec内容不同)。
| 参数名称 | 类型 | 参数说明 |
|---|---|---|
| version | String | 这里是指的是K8S API的版本,目前基本上是v1,可以用kubectl api-versions命令查询 |
| kind | String | 这里指的是yaml文件定义的资源类型和角色,比如:Pod |
| metadata | Object | 元数据对象,固定值就写metadata |
| metadata.name | String | 元数据对象的名字,这里由我们编写,比如命名Pod的名字 |
| metadata.namespace | String | 元数据对象的命名空间,由我们自身定义 |
| Spec | Object | 详细定义对象,固定值就写Spec |
| spec.containers[] | list | 这里是Spec对象的容器列表定义,是个列表 |
| spec.containers[].name | String | 这里定义容器的名字 |
| spec.containers[].image | string | 这里定义要用到的镜像名称 |
| spec.containers[].imagePullPolicy | String | 定义镜像拉取策略,有三个值可选: (1) Always: 每次都尝试重新拉取镜像 (2) IfNotPresent:如果本地有镜像就使用本地镜像 (3) )Never:表示仅使用本地镜像 |
| spec.containers[].command[] | list | 指定容器运行时启动的命令,若未指定则运行容器打包时指定的命令 |
| spec.containers[].args[] | list | 指定容器运行参数,可以指定多个 |
| spec.containers[].workingDir | String | 指定容器工作目录 |
| spec.containers[].volumeMounts[] | list | 指定容器内部的存储卷配置 |
| spec.containers[].volumeMounts[].name | String | 指定可以被容器挂载的存储卷的名称 |
| spec.containers[].volumeMounts[].mountPath | String | 指定可以被容器挂载的存储卷的路径 |
| spec.containers[].volumeMounts[].readOnly | String | 设置存储卷路径的读写模式,ture或false,默认为读写模式 |
| spec.containers[].ports[] | list | 指定容器需要用到的端口列表 |
| spec.containers[].ports[].name | String | 指定端口名称 |
| spec.containers[].ports[].containerPort | String | 指定容器需要监听的端口号 |
| spec.containers[] ports[].hostPort | String | 指定容器所在主机需要监听的端口号,默认跟上面containerPort相同,注意设置了hostPort同一台主机无法启动该容器的相同副本(因为主机的端口号不能相同,这样会冲突) |
| spec.containers[].ports[].protocol | String | 指定端口协议,支持TCP和UDP,默认值为 TCP |
| spec.containers[].env[] | list | 指定容器运行前需设置的环境变量列表 |
| spec.containers[].env[].name | String | 指定环境变量名称 |
| spec.containers[].env[].value | String | 指定环境变量值 |
| spec.containers[].resources | Object | 指定资源限制和资源请求的值(这里开始就是设置容器的资源上限) |
| spec.containers[].resources.limits | Object | 指定设置容器运行时资源的运行上限 |
| spec.containers[].resources.limits.cpu | String | 指定CPU的限制,单位为核心数,1=1000m |
| spec.containers[].resources.limits.memory | String | 指定MEM内存的限制,单位为MIB、GiB |
| spec.containers[].resources.requests | Object | 指定容器启动和调度时的限制设置 |
| spec.containers[].resources.requests.cpu | String | CPU请求,单位为core数,容器启动时初始化可用数量 |
| spec.containers[].resources.requests.memory | String | 内存请求,单位为MIB、GIB,容器启动的初始化可用数量 |
| spec.restartPolicy | string | 定义Pod的重启策略,默认值为Always. (1)Always: Pod-旦终止运行,无论容器是如何 终止的,kubelet服务都将重启它 (2)OnFailure: 只有Pod以非零退出码终止时,kubelet才会重启该容器。如果容器正常结束(退出码为0),则kubelet将不会重启它 (3) Never: Pod终止后,kubelet将退出码报告给Master,不会重启该 |
| spec.nodeSelector | Object | 定义Node的Label过滤标签,以key:value格式指定 |
| spec.imagePullSecrets | Object | 定义pull镜像时使用secret名称,以name:secretkey格式指定 |
| spec.hostNetwork | Boolean | 定义是否使用主机网络模式,默认值为false。设置true表示使用宿主机网络,不使用docker网桥,同时设置了true将无法在同一台宿主机 上启动第二个副本 |
2.3.3 如何获得资源帮助
若记不清 YAML 字段,可通过 kubectl explain 查官方帮助:
- 查看 Pod 整体结构:
kubectl explain pod - 查看 Pod 中
spec.containers的字段:kubectl explain pod.spec.containers - 类似地,查询 Deployment、Service 等资源:
kubectl explain deployment/kubectl explain service
这些命令会列出资源每个字段的含义、类型,相当于 “Kubernetes 官方的 YAML 字典”。
2.3.4 编写示例(通过场景理解 Pod 配置)
通过以下例子,可直观理解不同需求下 Pod 的 YAML 配置:
2.3.4.1 示例1:运行简单的单个容器pod
我想跑一个简单的应用,只需要一个容器就行。先用 kubectl run 快速生成基础的 YAML 配置,里面指定好镜像,然后用 kubectl apply 部署,最后查一下状态,确认它能正常跑起来。
[root@master ~]# cd pod/
# 用kubectl run生成一个基础的pod yaml文件(--dry-run=client表示仅模拟运行不实际创建,-o yaml表示输出为yaml格式)
[root@master pod]# kubectl run rch --image myapp:v1 --dry-run=client -o yaml > pod.yml
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1 # API版本,Pod使用v1
kind: Pod # 资源类型为Pod
metadata: # 元数据labels: # 标签(用于标识和筛选Pod)run: rchname: rch # Pod的名称
spec: # 详细配置containers: # 容器列表- image: myapp:v1 # 容器使用的镜像name: rch # 容器的名称
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rch 1/1 Running 0 7s
2.3.4.2 示例2:运行多个容器pod
# 先删除之前的pod(避免名称冲突)
[root@master pod]# kubectl delete -f pod.yml
# 编辑yaml文件,添加第二个容器
[root@master pod]# vim pod.yml
# 查看编辑后的yaml内容
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: myapp:v1 # 第一个容器:myapp镜像name: rch- image: busyboxplus # 第二个容器:busyboxplus镜像name: busyboxpluscommand: ["/bin/sh","-c","sleep 10000"] # 容器启动命令(休眠10000秒,避免容器退出)
# 尝试直接更新pod(会失败,因为Pod不能修改容器数量)
[root@master pod]# kubectl apply -f pod.yml
The Pod "rch" is invalid: spec.containers: Forbidden: pod updates may not add or remove containers
# 彻底删除旧pod
[root@master pod]# kubectl delete -f pod.yml
pod "rch" deleted
# 重新创建pod(此时会按新配置创建两个容器)
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
# 查看pod状态(READY 2/2表示两个容器都正常运行)
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rch 2/2 Running 0 3s
注意如果多个容器运行在一个pod中,资源共享的同时在使用相同资源时也会干扰,比如端口
#一个端口干扰示例:
[root@master pod]# kubectl delete -f pod.yml --force #也可以加--force
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: nginx:1.23 #两个容器都用nginx镜像(会占用80端口)name: rch- image: nginx:1.23name: rch1#command: ["/bin/sh","-c","sleep 10000"]
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
#查看状态(READY 1/2表示一个容器正常,一个失败)
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rch 1/2 Error 1 (9s ago) 12s
#查看失败容器的日志(发现端口被占用)
[root@master pod]# kubectl logs rch rch1
nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
2025/10/19 14:20:25 [notice] 1#1: try again to bind() after 500ms
2025/10/19 14:20:25 [emerg] 1#1: still could not bind()
nginx: [emerg] still could not bind()
- 首次尝试在原有 Pod 中添加第二个容器失败,因为 Kubernetes 不允许修改已有 Pod 的容器数量,必须删除后重新创建。
- 当两个容器都使用 Nginx 镜像(默认占用 80 端口)时,出现端口冲突,导致一个容器启动失败,说明同一 Pod 内的容器需避免资源(如端口)冲突。
注意:在一个pod中开启多个容器时一定要确保容器彼此不能互相干扰
想在一个 Pod 里跑两个容器试试。先改了 YAML 加了第二个容器,结果直接更新不行,原来 Pod 不能改容器数量,得删了重建。后来试了两个 Nginx 容器,发现它们都想用 80 端口,打架了,一个跑不起来,看来同一 Pod 里的容器不能抢资源。
2.3.4.3 示例3:理解pod间的网络整合
同在一个pod中的容器公用一个网络
[root@master pod]# kubectl delete -f pod.yml
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: myapp:v1 #第一个容器:myapp(web应用,监听80端口)name: myapp1- image: busyboxplus #第二个容器:busyboxplus(用于测试网络)name: busyboxpluscommand: ["/bin/sh","-c","sleep 10000"]
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rch 2/2 Running 0 13s
# 进入busyboxplus容器,访问localhost(验证网络共享)
[root@master pod]# kubectl exec rch -c busyboxplus -- curl -s localhost
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
同一 Pod 内的两个容器(myapp1 和 busyboxplus)共享网络空间,在 busyboxplus 容器中通过 localhost 可以访问到 myapp1 容器的 80 端口服务,验证了 Pod 内容器网络共享的特性。
2.3.4.4 示例4:端口映射
通过 hostPort 将容器的端口映射到宿主机的端口
[root@master pod]# kubectl delete -f pod.yml
pod "rch" deleted
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: myapp:v1name: myapp1ports:- name: web #端口名称(自定义,用于标识)containerPort: 80 #容器内的端口(应用实际监听的端口)hostPort: 80 #宿主机的端口(将容器端口映射到宿主机)protocol: TCP #协议类型(TCP/UDP)- image: busyboxplusname: busyboxpluscommand: ["/bin/sh","-c","sleep 10000"]
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
# 查看pod详情(包括运行节点)
[root@master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rch 2/2 Running 0 14s 10.244.2.146 node2 <none> <none>
# 访问宿主机node2的80端口(验证端口映射生效)
[root@master pod]# curl node2
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
通过 hostPort: 80 将容器的 80 端口映射到宿主机(node2)的 80 端口,部署后直接访问宿主机 node2 的 80 端口即可获取 myapp 服务的响应,说明端口映射配置生效。
2.3.4.5 示例5:如何设定环境变量
# 编辑yaml,添加mysql容器(未设置环境变量)
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: mysql:8.0 #mysql容器(需要环境变量配置密码)name: mysql- image: busyboxplusname: busyboxpluscommand: ["/bin/sh","-c","sleep 10000"]
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
# 查看pod状态(mysql容器启动失败)
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rch 1/2 CrashLoopBackOff 1 (7s ago) 9s
# 查看mysql容器日志(发现缺少环境变量)
[root@master pod]# kubectl logs pods/rch mysql
2025-10-19 14:36:31+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.43-1.el9 started.
2025-10-19 14:36:31+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2025-10-19 14:36:31+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.43-1.el9 started.
2025-10-19 14:36:31+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specifiedYou need to specify one of the following as an environment variable:- MYSQL_ROOT_PASSWORD- MYSQL_ALLOW_EMPTY_PASSWORD- MYSQL_RANDOM_ROOT_PASSWORD
#发现缺少环境变量,容器无法启动
[root@master pod]# kubectl delete -f pod.yml
pod "rch" deleted
# 编辑yaml,添加mysql的环境变量
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: mysql:8.0name: mysqlenv: # 环境变量配置- name: MYSQL_ROOT_PASSWORD # 环境变量名称(mysql要求的root密码变量)value: rch # 环境变量值(密码设为rch)- image: busyboxplusname: busyboxpluscommand: ["/bin/sh","-c","sleep 10000"]
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rch 2/2 Running 0 4s
- 首次部署 MySQL 容器时未设置必要的环境变量(如
MYSQL_ROOT_PASSWORD),导致容器启动失败(CrashLoopBackOff)。 - 添加环境变量后,MySQL 容器成功启动,说明环境变量是容器运行的重要配置(尤其对于需要初始化参数的应用)。
2.4.4.6 示例6:资源限制
资源限制会影响pod的Qos Class资源优先级,资源优先级分为Guaranteed > Burstable > BestEffort
QoS(Quality of Service)即服务质量
| 资源设定 | 优先级类型 |
|---|---|
| 资源限定未设定 | BestEffort |
| 资源限定设定且最大和最小不一致 | Burstable |
| 资源限定设定且最大和最小一致 | Guaranteed |
[root@master pod]# kubectl delete -f pod.yml
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: myapp:v1name: myappresources: # 资源配置limits: # 资源上限(容器最多能用这么多)cpu: 500m # CPU上限500毫核(0.5核)memory: 100M # 内存上限100Mrequests: # 资源请求(容器启动时至少需要这么多)cpu: 200m # CPU请求200毫核memory: 80M # 内存请求80M [root@master pod]# kubectl apply -f pod.yml
pod/rch created
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rch 1/1 Running 0 8s
# 查看pod详情(QoS Class为Burstable)
[root@master pod]# kubectl describe pods rchLimits:cpu: 500mmemory: 100MRequests:cpu: 200mmemory: 80M
QoS Class: Burstable
[root@master pod]# kubectl delete -f pod.yml
pod "rch" deleted
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: myapp:v1name: myappresources:limits:cpu: 500mmemory: 100Mrequests: # 请求值和上限值相同cpu: 500mmemory: 100M [root@master pod]# kubectl apply -f pod.yml
pod/rch created
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rch 1/1 Running 0 5s
# 查看pod详情(QoS Class为Guaranteed)
[root@master pod]# kubectl describe pods rchLimits:cpu: 500mmemory: 100MRequests:cpu: 500mmemory: 100M
QoS Class: Guaranteed
[root@master pod]# kubectl delete -f pod.yml
pod "rch" deleted
# 编辑yaml,不设置资源限制
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: myapp:v1name: myapp[root@master pod]# kubectl apply -f pod.yml
pod/rch created
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rch 1/1 Running 0 3s
# 查看pod详情(QoS Class为BestEffort)
[root@master pod]# kubectl describe pods rch
QoS Class: BestEffort
- 当
limits(资源上限)和requests(资源请求)不一致时,QoS 为Burstable; - 当
limits和requests完全一致时,QoS 为Guaranteed; - 未设置资源限制时,QoS 为
BestEffort。 - 这三种 QoS 决定了 Pod 在资源紧张时的优先级(Guaranteed 最不容易被驱逐)。
2.3.4.7 示例7 容器启动管理
# 查看restartPolicy的官方说明
[root@master pod]# kubectl explain pod.spec.restartPolicy
KIND: Pod
VERSION: v1FIELD: restartPolicy <string>
ENUM:Always #(默认值):容器退出时总是重启Never #仅在容器异常退出(非零状态码)时重启OnFailure #从不重启容器DESCRIPTION:Restart policy for all containers within the pod. One of Always, OnFailure,Never. In some contexts, only a subset of those values may be permitted.Default to Always. More info:https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policyPossible enum values:- `"Always"`- `"Never"`- `"OnFailure"`
- Always
[root@master pod]# kubectl delete -f pod.yml
pod "rch" deleted
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:restartPolicy: Always # 重启策略:总是重启(无论容器如何终止)containers:- image: mysql:8.0name: mysqlenv:- name: MYSQL_ROOT_PASSWORDvalue: rch[root@master pod]# kubectl apply -f pod.yml
pod/rch created
[root@master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rch 1/1 Running 0 4s 10.244.2.153 node2 <none> <none>

测试:
# 在宿主机node2上手动删除mysql容器(模拟容器故障)
[root@node2 ~]# docker rm -f efd8da40ef65
efd8da40ef65

图中显示容器被自动重启,RESTARTS 变为 1
- Never
[root@master pod]# kubectl delete -f pod.yml
pod "rch" deleted
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:restartPolicy: Never # 重启策略:从不重启(容器终止后不再启动)containers:- image: mysql:8.0name: mysqlenv:- name: MYSQL_ROOT_PASSWORDvalue: rch
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
[root@master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rch 1/1 Running 0 5s 10.244.2.155 node2 <none> <none>

测试:
# 在宿主机node2上手动删除mysql容器(模拟容器故障)
[root@node2 ~]# docker rm -f eedf43702b00
eedf43702b00

图中显示容器终止后未重启,状态变为 Completed
restartPolicy: Always时,即使手动删除容器,Kubernetes 也会自动重启容器(RESTARTS计数增加)。restartPolicy: Never时,容器被删除后不会重启,Pod 状态变为终止状态。- 重启策略控制了容器故障后的恢复行为,可根据应用需求选择。
2.3.4.8 示例8 选择运行节点
问:为什么上一个示例运行节点都在node2?
答:在之前的示例中,Pod 运行在 node2 上是因为 Kubernetes 的默认调度机制导致的。
Kubernetes 调度器会根据节点的资源可用性(如 CPU、内存等是否满足 Pod 需求)、节点健康状态等因素,自动选择合适的节点来运行 Pod。在未通过 nodeSelector 等方式指定节点的情况下,调度器会按照默认策略选择最优节点。因为node2拉过镜像!
# 查看所有节点的标签(用于选择节点)
[root@master pod]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master Ready control-plane 3d v1.30.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
node1 Ready <none> 3d v1.30.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux
node2 Ready <none> 3d v1.30.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node2,kubernetes.io/os=linux[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:nodeSelector: # 节点选择器(根据标签筛选节点)kubernetes.io/hostname: node1 # 选择主机名为node1的节点restartPolicy: Alwayscontainers:- image: mysql:8.0name: mysqlenv:- name: MYSQL_ROOT_PASSWORDvalue: rch
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
# 查看pod状态(运行在node1节点)
[root@master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rch 0/1 ContainerCreating 0 6s <none> node1 <none> <none>
通过 nodeSelector 配置 kubernetes.io/hostname: node1 后,Pod 被调度到了 node1 节点,说明节点选择器可以通过节点标签指定 Pod 运行的节点。
2.3.4.9 示例9 共享宿主机网络
有时候可能需要容器直接用宿主机的网络,比如想让容器的端口直接绑定到宿主机上。
[root@master pod]# kubectl delete -f pod.yml
pod "rch" deleted
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:nodeSelector:kubernetes.io/hostname: node1hostNetwork: true # 启用宿主机网络(容器使用宿主机的网络栈)restartPolicy: Alwayscontainers:- image: busyboxplusname: busyboxpluscommand:- /bin/sh- -c- sleep 1000
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
# 查看pod状态(IP显示为宿主机node1的IP)
[root@master pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rch 1/1 Running 0 4s 192.168.2.62 node1 <none> <none>
# 进入容器查看网络(容器的网络接口与宿主机一致)
[root@master pod]# kubectl exec -it pods/rch -c busyboxplus /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # ifconfig
cni0 Link encap:Ethernet HWaddr 62:E8:B2:76:8E:7E inet addr:10.244.1.1 Bcast:10.244.1.255 Mask:255.255.255.0inet6 addr: fe80::60e8:b2ff:fe76:8e7e/64 Scope:LinkUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1RX packets:81384 errors:0 dropped:0 overruns:0 frame:0TX packets:84771 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:6584631 (6.2 MiB) TX bytes:8073846 (7.6 MiB)docker0 Link encap:Ethernet HWaddr A6:EA:0B:E2:C3:DB inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0UP BROADCAST MULTICAST MTU:1500 Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)ens160 Link encap:Ethernet HWaddr 00:0C:29:FA:D5:B5 inet addr:192.168.2.62 Bcast:192.168.2.255 Mask:255.255.255.0inet6 addr: fe80::20c:29ff:fefa:d5b5/64 Scope:LinkUP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1RX packets:321580 errors:0 dropped:0 overruns:0 frame:0TX packets:101675 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:390795934 (372.6 MiB) TX bytes:10272973 (9.7 MiB)flannel.1 Link encap:Ethernet HWaddr 1A:3D:84:39:33:CD inet addr:10.244.1.0 Bcast:0.0.0.0 Mask:255.255.255.255inet6 addr: fe80::183d:84ff:fe39:33cd/64 Scope:LinkUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1RX packets:73 errors:0 dropped:0 overruns:0 frame:0TX packets:53 errors:0 dropped:47 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:4714 (4.6 KiB) TX bytes:6406 (6.2 KiB)lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING MTU:65536 Metric:1RX packets:176 errors:0 dropped:0 overruns:0 frame:0TX packets:176 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:18753 (18.3 KiB) TX bytes:18753 (18.3 KiB)veth2a64cf7c Link encap:Ethernet HWaddr CE:10:FA:09:F1:AE inet6 addr: fe80::cc10:faff:fe09:f1ae/64 Scope:LinkUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1RX packets:40592 errors:0 dropped:0 overruns:0 frame:0TX packets:42747 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:3852543 (3.6 MiB) TX bytes:4067827 (3.8 MiB)veth7a599959 Link encap:Ethernet HWaddr 4E:3E:6C:49:F9:43 inet6 addr: fe80::4c3e:6cff:fe49:f943/64 Scope:LinkUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1RX packets:40376 errors:0 dropped:0 overruns:0 frame:0TX packets:42779 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:3836750 (3.6 MiB) TX bytes:4067797 (3.8 MiB)
设置 hostNetwork: true 后,容器使用宿主机(node1)的网络栈,Pod 的 IP 显示为宿主机 IP,且容器内的网络接口与宿主机完全一致,说明宿主机网络模式下容器共享宿主机的网络资源。
三、Pod 的生命周期
3.1 INIT 容器
Pod 的生命周期描述了一个 Pod 从创建到销毁的完整过程,其中 Init 容器(负责启动前初始化)和 探针(检测健康状态)是保障 Pod 可靠运行的核心机制。
官方文档:https://kubernetes.io/zh/docs/concepts/workloads/pods/

-
Pod 可以包含多个容器,应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。
-
Init 容器与普通的容器非常像,除了如下两点:
-
它们总是运行到完成
-
init 容器不支持 Readiness,因为它们必须在 Pod 就绪之前运行完成,每个 Init 容器必须运行成功,下一个才能够运行。
-
-
如果Pod的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。但是,如果 Pod 对应的 restartPolicy 值为 Never,它不会重新启动。
3.1.1 INIT 容器的功能
Init 容器是 Pod 中在 “业务容器(主容器)” 启动前运行的特殊容器,核心作用是:
- 前置初始化:完成主容器启动前的准备工作(如等待依赖服务、下载配置、初始化数据)。
- 逻辑解耦:把 “初始化操作” 和 “业务逻辑” 分开,让主容器更简洁,也避免主容器镜像因初始化逻辑变得臃肿。
- 顺序执行:支持多个 Init 容器,按定义顺序依次运行,前一个成功后才会启动下一个;所有 Init 容器成功后,主容器才会启动。
特点
- Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。
- Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。
- 应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
- Init 容器能以不同于Pod内应用容器的文件系统视图运行。因此,Init容器可具有访问 Secrets 的权限,而应用容器不能够访问。
- 由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。一旦前置条件满足,Pod内的所有的应用容器会并行启动。
示例:
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers: # 主容器配置- image: myapp:v1 # 主容器使用的镜像name: web # 主容器的名称initContainers: # Init容器配置(在主容器前运行)- image: busyboxplus # Init容器使用的镜像(包含基础工具)name: check # Init容器的名称# 容器启动命令:循环检查/testfile是否存在,不存在则打印等待信息并休眠2秒command: ["sh","-c","until test -e /testfile;do echo wating for myservice; sleep 2;done"]
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
[root@master pod]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rch 0/1 Init:0/1 0 10s
[root@master pod]# kubectl exec -it pods/rch -c check /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # touch /testfile # 在容器内创建/testfile文件(满足Init容器的检查条件)
/ # command terminated with exit code 137 # 文件创建后,Init容器完成任务退出
未创建testfile之前:Pod 创建后,Init 容器(check)启动并执行循环检查命令,因 /testfile 不存在,会持续打印 “wating for myservice” 并休眠,此时 Pod 状态为Init:0/1(Init 容器未完成),主容器(web)未启动。

创建testfile之后:进入 Init 容器手动创建 /testfile 后,Init 容器的命令执行成功(退出码为 0),Init 容器完成任务,随后主容器(web)启动,Pod 状态变为Running。

3.2 探针
探针的检查方式
探针通过三种方式执行诊断,结果只有 “成功”“失败”“未知” 三种:
- ExecAction:在容器内执行指定命令。若命令退出时返回码为 0,诊断成功;否则失败。
- TCPSocketAction:对容器的 IP 地址和指定端口进行 TCP 连接检查。若端口能正常连接,诊断成功;否则失败。
- HTTPGetAction:向容器的 IP 地址、指定端口和路径发送 HTTP GET 请求。若响应状态码在 200-399 之间,诊断成功;否则失败。
三种探针的功能与处理逻辑
- 存活探针(Liveness Probe)
- 作用:判断容器是否 “正在运行”(未卡死、未崩溃)。
- 失败处理:若探测失败,kubelet 会杀死容器,容器会按照自身的重启策略(如 Always 自动重启、OnFailure 失败时重启等)进行处理。
- 默认状态:若未配置存活探针,默认状态为 “成功”。
- 就绪探针(Readiness Probe)
- 作用:判断容器是否 “准备好接收请求”(即使容器在运行,若未就绪,也不应接收流量)。
- 失败处理:若探测失败,端点控制器会将该 Pod 的 IP 和端口从对应的 Service 端点列表中移除,不再向其转发请求;直到探测成功,才重新加入列表。
- 默认状态:初始延迟(首次探测前的等待时间)前默认 “失败”;若未配置就绪探针,默认状态为 “成功”。
- 启动探针(Startup Probe)
- 作用:针对启动较慢的应用(如大型服务),判断应用是否 “完全启动完成”。
- 特殊逻辑:若配置了启动探针,其他探针(存活、就绪)会被暂时禁用,直到启动探针成功;启动探针成功后,其他探针才开始工作。
- 失败处理:若探测失败,kubelet 会杀死容器,容器按重启策略重启。
- 默认状态:若未配置启动探针,默认状态为 “成功”。
探针的核心区别
- 存活探针 vs 就绪探针:
- 存活探针关注 “容器是否存活”,失败会触发容器重启;
- 就绪探针关注 “容器是否能处理请求”,失败仅移除流量,不重启容器。
- 启动探针 vs 其他两种探针:
- 启动探针仅在容器启动阶段工作,成功后不再执行,主要解决 “启动慢导致的误判”;
- 存活和就绪探针在容器整个生命周期内持续执行,分别监控 “存活状态” 和 “服务能力”。
存活探针示例:
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: myapp:v1 # 主容器镜像(是一个Web服务,默认监听80端口)name: weblivenessProbe: # 配置存活探针tcpSocket: # 探测方式:TCP连接检查port: 8080 # 检查容器的8080端口(但容器实际监听80端口)initialDelaySeconds: 3 # 容器启动后,延迟3秒再开始首次探测periodSeconds: 1 # 每1秒探测一次timeoutSeconds: 1 # 探测超时时间1秒(1秒内未连接成功则视为失败)
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
#另开一个终端,实时监控pods状态,发现存活探针检测失败,一直重启
- 配置中存活探针检查 8080 端口,但容器实际监听 80 端口,因此每次探测都会失败。
- 由于探测失败,kubelet 会杀死容器并根据默认重启策略(Always)自动重启,导致 Pod 状态频繁显示 “CrashLoopBackOff”(崩溃后重启循环)。

如果从容器内部让其无法运行,存活探针能检测到吗?
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: myapp:v1name: weblivenessProbe:tcpSocket:port: 80 # 现在探测容器实际监听的80端口initialDelaySeconds: 3periodSeconds: 1timeoutSeconds: 1
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
[root@master pod]# kubectl exec -it pods/rch -c web /bin/sh
/ # vi /etc/nginx/conf.d/default.conf # 修改Nginx配置文件,将监听端口改为8080
/ # grep listen /etc/nginx/conf.d/default.conf # 确认修改:监听端口变为8080listen 8080;
/ # nginx -s reload # 重新加载Nginx配置,此时容器实际监听8080端口
2025/10/20 07:14:02 [notice] 17#17: signal process started
/ # command terminated with exit code 137 # 退出容器

- 初始状态:探针检查 80 端口,容器正常监听 80 端口,探测成功,Pod 状态为
Running。 - 修改后:容器内将 Nginx 监听端口改为 8080,导致 80 端口不再提供服务,存活探针探测 80 端口失败,触发容器重启。重启后容器恢复默认配置(监听 80 端口),探针再次成功,Pod 回到
Running状态。
就绪探针示例:
[root@master pod]# kubectl delete -f pod.yml
pod "rch" deleted
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: myapp:v1 # 主容器为Nginx,默认网页目录为/usr/share/nginx/htmlname: webreadinessProbe: # 配置就绪探针httpGet: # 探测方式:发送HTTP GET请求path: /rch.html # 请求路径(检查是否存在rch.html文件)port: 80 # 请求端口(Nginx默认端口)initialDelaySeconds: 3 # 启动后延迟3秒首次探测periodSeconds: 1 # 每1秒探测一次timeoutSeconds: 1 # 超时时间1秒
[root@master pod]# kubectl apply -f pod.yml
pod/rch created

- 容器启动后,就绪探针会持续请求
http://容器IP:80/rch.html,但容器内默认没有rch.html文件,因此每次请求返回 404(失败)。 - 此时 Pod 状态为
Running(容器本身在运行),但READY列显示0/1(未就绪),意味着该 Pod 不会被 Service 转发流量。
#查看日志
[root@master pod]# kubectl logs pods/rch web
#尝试打开文件 "/usr/share/nginx/html/rch.html" 失败,原因是文件不存在(错误代码2:No such file or directory
2025/10/20 07:23:26 [error] 7#7: *93 open() "/usr/share/nginx/html/rch.html" failed (2: No such file or directory), client: 10.244.2.1, server: localhost, request: "GET /rch.html HTTP/1.1", host: "10.244.2.159:80"
10.244.2.1 - - [20/Oct/2025:07:23:27 +0000] "GET /rch.html HTTP/1.1" 404 169 "-" "kube-probe/1.30" "-"
接着我们进入到容器中创建rch.html
[root@master pod]# kubectl exec -it pods/rch -c web /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # touch rch.html
结果如下所示:

再提供服务,存活探针探测 80 端口失败,触发容器重启。重启后容器恢复默认配置(监听 80 端口),探针再次成功,Pod 回到Running状态。
就绪探针示例:
[root@master pod]# kubectl delete -f pod.yml
pod "rch" deleted
[root@master pod]# vim pod.yml
[root@master pod]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:labels:run: rchname: rch
spec:containers:- image: myapp:v1 # 主容器为Nginx,默认网页目录为/usr/share/nginx/htmlname: webreadinessProbe: # 配置就绪探针httpGet: # 探测方式:发送HTTP GET请求path: /rch.html # 请求路径(检查是否存在rch.html文件)port: 80 # 请求端口(Nginx默认端口)initialDelaySeconds: 3 # 启动后延迟3秒首次探测periodSeconds: 1 # 每1秒探测一次timeoutSeconds: 1 # 超时时间1秒
[root@master pod]# kubectl apply -f pod.yml
pod/rch created
![[外链图片转存中...(img-2tkXlKQO-1761225545214)]](https://i-blog.csdnimg.cn/direct/12b31e74010047809285ce02542609a5.png)
- 容器启动后,就绪探针会持续请求
http://容器IP:80/rch.html,但容器内默认没有rch.html文件,因此每次请求返回 404(失败)。 - 此时 Pod 状态为
Running(容器本身在运行),但READY列显示0/1(未就绪),意味着该 Pod 不会被 Service 转发流量。
#查看日志
[root@master pod]# kubectl logs pods/rch web
#尝试打开文件 "/usr/share/nginx/html/rch.html" 失败,原因是文件不存在(错误代码2:No such file or directory
2025/10/20 07:23:26 [error] 7#7: *93 open() "/usr/share/nginx/html/rch.html" failed (2: No such file or directory), client: 10.244.2.1, server: localhost, request: "GET /rch.html HTTP/1.1", host: "10.244.2.159:80"
10.244.2.1 - - [20/Oct/2025:07:23:27 +0000] "GET /rch.html HTTP/1.1" 404 169 "-" "kube-probe/1.30" "-"
接着我们进入到容器中创建rch.html
[root@master pod]# kubectl exec -it pods/rch -c web /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # touch rch.html
结果如下所示:
![[外链图片转存中...(img-4WxmEKMX-1761225545214)]](https://i-blog.csdnimg.cn/direct/5447171fd0d1443f8d809bca1a596c4c.png)
- 创建
rch.html后,就绪探针再次请求/rch.html会返回 200(成功),Pod 的READY列变为1/1(就绪),此时 Service 会将流量转发到该 Pod。
