Kubernetes Pod 是什么?
文章目录
- Kubernetes Pod 是什么?
- 1. Pod 是什么?
- 2. 为什么需要 Pod?(设计哲学)
- 3. Pod 的核心特性与生命周期
- 生命周期与状态
- 重要子对象
- 4. Pod 的定义:YAML 文件剖析
- 5. Pod 与控制器
- 6. 总结与最佳实践
1. Pod 是什么?
Pod 是 Kubernetes 中可以创建和管理的最小、最简单的可部署计算单元。你可以把它想象成一个“逻辑主机”,里面运行着一个或多个紧密相关的容器。
核心比喻:
- 如果把 Kubernetes 看作一个数据中心或服务器农场,那么一个Node(节点)就是一台物理或虚拟服务器。
- 一个Pod就像是这台服务器上的一个应用实例(例如一个虚拟机或一个 Linux 命名空间环境)。
- 而这个应用实例(Pod)内部可以运行一个或多个容器,这些容器共享网络和存储资源,就像在同一个虚拟机里运行多个进程。
关键点:
- 原子性单元:Kubernetes 不直接管理容器,而是管理 Pod。扩缩容、调度、管理的最小单位是 Pod,而不是单个容器。
- 共享上下文:Pod 内的容器共享:
- 网络命名空间:它们拥有相同的 IP 地址和端口空间,可以通过
localhost互相通信。一个 Pod 在集群中有一个唯一的 IP。 - 存储卷:它们可以挂载相同的存储卷(Volumes),从而共享数据。
- 主机名:它们拥有相同的主机名(即 Pod 名)。
- 网络命名空间:它们拥有相同的 IP 地址和端口空间,可以通过
2. 为什么需要 Pod?(设计哲学)
为什么不直接调度容器?Pod 的设计源于“一个容器一个进程”的理念。但现实中的应用程序通常需要多个协同工作的进程(例如 Web 服务器和日志收集器、主应用和 sidecar 代理)。
Pod 抽象允许你将多个耦合紧密、需要共享资源的容器组合在一起,作为一个单一实体进行管理。
常见场景:
- 主应用 + Sidecar 容器:例如:
- Web 服务器 + 日志收集器:Nginx 容器将日志写入共享卷,Filebeat 容器读取并发送到 Elasticsearch。
- 应用 + 代理:你的应用容器和一个 Service Mesh 的 Sidecar 代理(如 Envoy)运行在同一个 Pod。
- 数据提取/加载 + 处理:一个容器从外部源下载数据到共享目录,另一个容器处理这些数据。
- 适配器模式:一个容器转换输出格式以适应另一个系统的输入。
3. Pod 的核心特性与生命周期
生命周期与状态
Pod 在其生命周期中会处于不同的阶段(Phase):
- Pending(挂起):Pod 已被系统接受,但有一个或多个容器尚未创建或运行。通常是因为正在拉取镜像、调度或配置存储卷。
- Running(运行中):Pod 已绑定到某个节点,所有容器均已创建。至少有一个容器正在运行,或者正在启动/重启。
- Succeeded(成功):Pod 中的所有容器都已成功终止,并且不会再重启。常见于一次性任务(Job)。
- Failed(失败):Pod 中的所有容器都已终止,并且至少有一个容器是因为失败而终止(非零退出码)。
- Unknown(未知):通常是因为与 Pod 所在节点的通信出错,无法获取其状态。
重要子对象
- Init 容器:在应用容器启动前运行的一个或多个初始化容器。它们必须成功执行完毕后,主应用容器才会启动。用于执行安装脚本、等待依赖服务就绪等。
- 生命周期钩子:
- 启动后钩子(PostStart):容器创建后立即执行。
- 终止前钩子(PreStop):容器终止前执行,用于优雅关闭。
- 探针:用于检测容器健康状态的机制。
- 存活探针(Liveness Probe):判断容器是否“活着”。如果失败,kubelet 会重启容器。
- 就绪探针(Readiness Probe):判断容器是否“准备就绪”可以接收流量。如果失败,Service 会将该 Pod 从端点列表中移除。
- 启动探针(Startup Probe):用于处理启动时间长的容器,在其成功前,其他探针会失效。
4. Pod 的定义:YAML 文件剖析
一个 Pod 通常通过一个 YAML 文件(声明式配置)来定义。以下是一个包含关键字段的示例:
apiVersion:v1# Kubernetes API 版本kind:Pod# 资源类型,这里指定为 Podmetadata:# 元数据name:my-nginx-pod# Pod 名称labels:# 标签,用于选择和关联app:nginxtier:frontendnamespace:default# 所属命名空间spec:# Pod 的规格定义,这是核心部分containers:# 容器列表-name:nginx-container# 容器名称image:nginx:1.19.10# 容器镜像imagePullPolicy:IfNotPresent# 镜像拉取策略ports:# 容器暴露的端口-containerPort:80# --- 资源限制 ---resources:requests:# 请求的资源,调度依据memory:"64Mi"cpu:"250m"limits:# 资源上限,超过可能被终止memory:"128Mi"cpu:"500m"# --- 环境变量 ---env:-name:ENV_VAR_NAMEvalue:"some-value"# --- 挂载存储卷 ---volumeMounts:-name:app-logsmountPath:/var/log/nginx# --- 探针 ---livenessProbe:httpGet:path:/port:80initialDelaySeconds:15periodSeconds:20readinessProbe:tcpSocket:port:80initialDelaySeconds:5periodSeconds:10# --- 共享存储卷定义 ---volumes:-name:app-logsemptyDir:{}# 临时目录,Pod 删除后数据丢失# --- Init 容器示例 ---initContainers:-name:init-service-checkimage:busybox:1.28command:['sh','-c','until nslookup my-db-service; do echo waiting for my-db; sleep 2; done;']# --- 其他 ---restartPolicy:Always# 重启策略: Always, OnFailure, NevernodeSelector:# 节点选择器disktype:ssdtolerations:# 容忍度-key:"key"operator:"Equal"value:"value"effect:"NoSchedule"5. Pod 与控制器
通常你不需要直接创建裸 Pod(kubectl run或直接applyPod YAML),因为它们是“易失的”(ephemeral)。节点故障、资源不足、驱逐等都可能导致 Pod 消失。
因此,Kubernetes 提供了更高级的控制器来管理 Pod 的生命周期,确保系统状态与你的期望相符:
- Deployment:用于管理无状态应用。它创建和管理一组完全相同的 Pod(称为 ReplicaSet)。支持滚动更新、回滚。这是最常用的控制器。
- StatefulSet:用于管理有状态应用。为 Pod 提供稳定的、唯一的标识符(有序编号、稳定的网络标识、持久的存储)。例如 MySQL 集群、ZooKeeper。
- DaemonSet:确保集群中每个(或部分)节点上都运行一个 Pod 副本。常用于运行集群基础服务,如日志收集器(Fluentd)、节点监控代理。
- Job / CronJob:用于运行一次性任务或定时任务。任务完成后 Pod 会进入
Succeeded状态。
这些控制器通过标签选择器来管理和识别它们所控制的 Pod。
6. 总结与最佳实践
- Pod 是 Kubernetes 的原子调度单元,一个 Pod 封装一个或多个紧密协作的容器。
- “一个容器一个进程”,但“一个 Pod 一个应用实例”:将需要紧密共享资源的辅助进程放入 Sidecar 容器,而非主应用容器。
- 尽量使用控制器,而非裸 Pod:使用 Deployment、StatefulSet 等来管理 Pod,获得自愈、扩缩容和滚动更新能力。
- 合理使用探针:配置 Liveness 和 Readiness 探针,确保应用健康和服务发现正确。
- 为容器设置资源请求和限制:这是良好集群公民和稳定性的关键。
- 使用命名空间和标签进行组织:标签是 Kubernetes 中资源和对象关联的灵魂。
- 理解 Pod 是临时的:持久化数据应存储在持久卷(PersistentVolume,PV)中,而非 Pod 的本地存储。
Pod 是理解 Kubernetes 所有高级概念(如 Service、Ingress、配置管理)的基石。掌握了 Pod,你就掌握了 Kubernetes 应用模型的核心。