重温k8s基础概念知识系列二(Pod)
文章目录
- 1、Pod概念
- 2、K8s 中的 Pod 的两种用法
- 3、定义Pod
- 4、Pod的创建资源
- 5、Pod 模板
- 6、容器探针
- 7、总结干货
- 8、 K8s Pod 经典面试题速查表
Pod是Kubernetes中最小的单元:
1、Pod概念
Pod 是可以在 Kubernetes中创建和管理的、最小的可部署的计算单元。它由一组、一个或多个容器组成,每个Pod还包含了一个Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理,通过Pause容器可以使同一个Pod里面的多个容器共享存储、网络、PID、IPC等。
Pod(就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个) 容器; 这些容器共享存储、网络、以及怎样运行这些容器的规约。 Pod中的内容总是并置(colocated)的并且一同调度,在共享的上下文中运行。 Pod所建模的是特定于应用的“逻辑主机”,其中包含一个或多个应用容器, 这些容器相对紧密地耦合在一起。在非云环境中,在相同的物理机或虚拟机上运行的应用类似于在同一逻辑主机上运行的云应用。
除了应用容器,Pod 还可以包含在 Pod 启动期间运行的 Init 容器。 你也可以注入临时性容器来调试正在运行的 Pod。
Pod 的共享上下文包括一组 Linux 名字空间、控制组(CGroup)和可能一些其他的隔离方面, 即用来隔离容器的技术。 在 Pod 的上下文中,每个独立的应用可能会进一步实施隔离。
2、K8s 中的 Pod 的两种用法
Pod 类似于共享名字空间并共享文件系统卷的一组容器。
Kubernetes 集群中的 Pod 主要有两种用法:
运行单个容器的 Pod。"每个 Pod 一个容器"模型是最常见的 Kubernetes 用例; 在这种情况下,可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。
运行多个协同工作的容器的 Pod。 Pod 可以封装由紧密耦合且需要共享资源的多个并置容器组成的应用。 这些位于同一位置的容器构成一个内聚单元。
将多个并置、同管的容器组织到一个 Pod 中是一种相对高级的使用场景。 只有在一些场景中,容器之间紧密关联时你才应该使用这种模式。
3、定义Pod
定义一个Pod:
下面是一个 Pod 示例,它由一个运行镜像 nginx:1.14.2 的容器组成。
apiVersion: v1
kind: Pod
metadata:name: nginx
spec:containers:- name: nginximage: nginx:1.14.2ports:- containerPort: 80
要创建上面显示的 Pod,请运行以下命令:
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据name: nginx # 必选,符合RFC 1035规范的Pod名称namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace labels: # 可选,标签选择器,一般用于过滤和区分Podapp: nginxrole: frontend # 可以写多个annotations: # 可选,注释列表,可以写多个app: nginx
spec: # 必选,用于定义容器的详细信息initContainers: # 初始化容器,在容器启动之前执行的一些初始化操作- command:- sh- -c- echo "I am InitContainer for init some configuration"image: busyboximagePullPolicy: IfNotPresentname: init-containercontainers: # 必选,容器列表- name: nginx # 必选,符合RFC 1035规范的容器名称image: nginx:latest # 必选,容器所用的镜像的地址imagePullPolicy: Always # 可选,镜像拉取策略command: # 可选,容器启动执行的命令- nginx - -g- "daemon off;"workingDir: /usr/share/nginx/html # 可选,容器的工作目录volumeMounts: # 可选,存储卷配置,可以配置多个- name: webroot # 存储卷名称mountPath: /usr/share/nginx/html # 挂载目录readOnly: true # 只读ports: # 可选,容器需要暴露的端口号列表- name: http # 端口名称containerPort: 80 # 端口号protocol: TCP # 端口协议,默认TCPenv: # 可选,环境变量配置列表- name: TZ # 变量名value: Asia/Shanghai # 变量的值- name: LANGvalue: en_US.utf8resources: # 可选,资源限制和资源请求限制limits: # 最大限制设置cpu: 1000mmemory: 1024Mirequests: # 启动所需的资源cpu: 100mmemory: 512Mi
# startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
# path: /api/successStart # 检查路径
# port: 80readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。path: / # 检查路径port: 80 # 监控端口livenessProbe: # 可选,健康检查#exec: # 执行容器命令检测方式#command: #- cat#- /health#httpGet: # httpGet检测方式# path: /_health # 检查路径# port: 8080# httpHeaders: # 检查的请求头# - name: end-user# value: Jason tcpSocket: # 端口检测方式port: 80initialDelaySeconds: 60 # 初始化时间timeoutSeconds: 2 # 超时时间periodSeconds: 5 # 检测间隔successThreshold: 1 # 检查成功为2次表示就绪failureThreshold: 2 # 检测失败1次表示未就绪lifecycle:postStart: # 容器创建完成后执行的指令, 可以是exec httpGet TCPSocketexec:command:- sh- -c- 'mkdir /data/ 'preStop:httpGet: path: /port: 80# exec:# command:# - sh# - -c# - sleep 9restartPolicy: Always # 可选,默认为Always#nodeSelector: # 可选,指定Node节点# region: subnet7imagePullSecrets: # 可选,拉取镜像使用的secret,可以配置多个- name: default-dockercfg-86258hostNetwork: false # 可选,是否为主机模式,如是,会占用主机端口volumes: # 共享存储卷列表- name: webroot # 名称,与上述对应emptyDir: {} # 挂载目录#hostPath: # 挂载本机目录# path: /etc/hosts
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据name: nginx # 必选,符合RFC 1035规范的Pod名称# namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace labels: # 可选,标签选择器,一般用于过滤和区分Podapp: nginxrole: frontend # 可以写多个annotations: # 可选,注释列表,可以写多个app: nginx
spec: # 必选,用于定义容器的详细信息
# initContainers: # 初始化容器,在容器启动之前执行的一些初始化操作
# - command:
# - sh
# - -c
# - echo "I am InitContainer for init some configuration"
# image: busybox
# imagePullPolicy: IfNotPresent
# name: init-containercontainers: # 必选,容器列表- name: nginx # 必选,符合RFC 1035规范的容器名称image: nginx:1.15.2 # 必选,容器所用的镜像的地址imagePullPolicy: IfNotPresent # 可选,镜像拉取策略, IfNotPresent: 如果宿主机有这个镜像,那就不需要拉取了. Always: 总是拉取, Never: 不管是否存储都不拉去command: # 可选,容器启动执行的命令 ENTRYPOINT, arg --> cmd- nginx - -g- "daemon off;"workingDir: /usr/share/nginx/html # 可选,容器的工作目录
# volumeMounts: # 可选,存储卷配置,可以配置多个
# - name: webroot # 存储卷名称
# mountPath: /usr/share/nginx/html # 挂载目录
# readOnly: true # 只读ports: # 可选,容器需要暴露的端口号列表- name: http # 端口名称containerPort: 80 # 端口号protocol: TCP # 端口协议,默认TCPenv: # 可选,环境变量配置列表- name: TZ # 变量名value: Asia/Shanghai # 变量的值- name: LANGvalue: en_US.utf8
# resources: # 可选,资源限制和资源请求限制
# limits: # 最大限制设置
# cpu: 1000m
# memory: 1024Mi
# requests: # 启动所需的资源
# cpu: 100m
# memory: 512Mi
# startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
# path: /api/successStart # 检查路径
# port: 80
# readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
# path: / # 检查路径
# port: 80 # 监控端口
# livenessProbe: # 可选,健康检查#exec: # 执行容器命令检测方式#command: #- cat#- /health#httpGet: # httpGet检测方式# path: /_health # 检查路径# port: 8080# httpHeaders: # 检查的请求头# - name: end-user# value: Jason
# tcpSocket: # 端口检测方式
# port: 80
# initialDelaySeconds: 60 # 初始化时间
# timeoutSeconds: 2 # 超时时间
# periodSeconds: 5 # 检测间隔
# successThreshold: 1 # 检查成功为2次表示就绪
# failureThreshold: 2 # 检测失败1次表示未就绪
# lifecycle:
# postStart: # 容器创建完成后执行的指令, 可以是exec httpGet TCPSocket
# exec:
# command:
# - sh
# - -c
# - 'mkdir /data/ '
# preStop:
# httpGet:
# path: /
# port: 80# exec:# command:# - sh# - -c# - sleep 9restartPolicy: Always # 可选,默认为Always,容器故障或者没有启动成功,那就自动该容器,Onfailure: 容器以不为0的状态终止,自动重启该容器, Never:无论何种状态,都不会重启#nodeSelector: # 可选,指定Node节点# region: subnet7
# imagePullSecrets: # 可选,拉取镜像使用的secret,可以配置多个
# - name: default-dockercfg-86258
# hostNetwork: false # 可选,是否为主机模式,如是,会占用主机端口
# volumes: # 共享存储卷列表
# - name: webroot # 名称,与上述对应
# emptyDir: {} # 挂载目录
# #hostPath: # 挂载本机目录
# # path: /etc/hosts
4、Pod的创建资源
Pod 通常不是直接创建的,而是使用工作负载资源创建的。
用于管理 Pod 的工作负载资源:
- Deployment
- StatefulSet
- DaemonSet
通常你不需要直接创建 Pod,甚至单实例 Pod。相反,你会使用诸如 Deployment 或 Job 这类工作负载资源来创建 Pod。 如果 Pod 需要跟踪状态,可以考虑 StatefulSet 资源。
每个 Pod 都旨在运行给定应用程序的单个实例。如果希望横向扩展应用程序 (例如,运行多个实例以提供更多的资源),则应该使用多个 Pod,每个实例使用一个 Pod。 在 Kubernetes 中,这通常被称为副本(Replication)。 通常使用一种工作负载资源及其控制器来创建和管理一组 Pod 副本。
Pod 天生地为其成员容器提供了两种共享资源:网络和存储。
说明:
重启 Pod 中的容器不应与重启 Pod 混淆。 Pod 不是进程,而是容器运行的环境。 在被删除之前,Pod 会一直存在。
5、Pod 模板
工作负载资源的控制器通常使用 Pod 模板(Pod Template) 来替你创建 Pod 并管理它们。
Pod 模板是包含在工作负载对象中的规范,用来创建 Pod。这类负载资源包括 Deployment、 Job 和 DaemonSet 等。
工作负载的控制器会使用负载对象中的 PodTemplate 来生成实际的 Pod。 PodTemplate 是你用来运行应用时指定的负载资源的目标状态的一部分。
创建 Pod 时,你可以在 Pod 模板中包含 Pod 中运行的容器的环境变量。
6、容器探针
probe 是由 kubelet 对容器执行的定期诊断。 要执行诊断,kubelet 既可以在容器内执行代码,也可以发出一个网络请求。
检查机制
使用探针来检查容器有四种不同的方法。 每个探针都必须准确定义为这四种机制中的一种:
- exec
在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。 - grpc
使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC 健康检查。 如果响应的状态是 “SERVING”,则认为诊断成功。 - httpGet
对容器的 IP 地址上指定端口和路径执行 HTTP GET 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。 - tcpSocket
对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。 如果远程系统(容器)在打开连接后立即将其关闭,这算作是健康的。
注意:
和其他机制不同,exec 探针的实现涉及每次执行时创建/复制多个进程。 因此,在集群中具有较高 pod 密度、较低的 initialDelaySeconds 和 periodSeconds 时长的时候, 配置任何使用 exec 机制的探针可能会增加节点的 CPU 负载。 这种场景下,请考虑使用其他探针机制以避免额外的开销。
探测结果
每次探测都将获得以下三种结果之一:
- Success(成功)
容器通过了诊断。 - Failure(失败)
容器未通过诊断。 - Unknown(未知)
诊断失败,因此不会采取任何行动。
探测类型
针对运行中的容器,kubelet 可以选择是否执行以下三种探针,以及如何针对探测结果作出反应:
- livenessProbe
指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success。 - readinessProbe
指示容器是否准备好为请求提供服务。如果就绪态探测失败, EndpointSlice 控制器将从与该 Pod 匹配的所有 Service 的 EndpointSlice 中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。 - startupProbe
指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被 禁用,直到此探针成功为止。如果启动探测失败,kubelet 将杀死容器, 而容器依其重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success。
如欲了解如何设置存活态、就绪态和启动探针的进一步细节, 可以参阅配置存活态、就绪态和启动探针。
何时该使用存活态探针?
如果容器中的进程能够在遇到问题或不健康的情况下自行崩溃,则不一定需要存活态探针; kubelet 将根据 Pod 的 restartPolicy 自动执行修复操作。
如果你希望容器在探测失败时被杀死并重新启动,那么请指定一个存活态探针, 并指定 restartPolicy 为 “Always” 或 “OnFailure”。
何时该使用就绪态探针?
如果要仅在探测成功时才开始向 Pod 发送请求流量,请指定就绪态探针。 在这种情况下,就绪态探针可能与存活态探针相同,但是规约中的就绪态探针的存在意味着 Pod 将在启动阶段不接收任何数据,并且只有在探针探测成功后才开始接收数据。
如果你希望容器能够自行进入维护状态,也可以指定一个就绪态探针, 检查某个特定于就绪态的因此不同于存活态探测的端点。
如果你的应用程序对后端服务有严格的依赖性,你可以同时实现存活态和就绪态探针。 当应用程序本身是健康的,存活态探针检测通过后,就绪态探针会额外检查每个所需的后端服务是否可用。 这可以帮助你避免将流量导向只能返回错误信息的 Pod。
如果你的容器需要在启动期间加载大型数据、配置文件或执行迁移, 你可以使用启动探针。 然而,如果你想区分已经失败的应用和仍在处理其启动数据的应用,你可能更倾向于使用就绪探针。
说明:
请注意,如果你只是想在 Pod 被删除时能够排空请求,则不一定需要使用就绪态探针; 当 Pod 被删除时,EndpointSlice 中对应的端点会更新其状况: 该端点的 ready 状况将被设置为 false,因此负载均衡器不会再将该 Pod 用于常规流量。 关于 kubelet 如何处理 Pod 删除的更多信息,请参见 Pod 终止。
何时该使用启动探针?
对于所包含的容器需要较长时间才能启动就绪的 Pod 而言,启动探针是有用的。 你不再需要配置一个较长的存活态探测时间间隔,只需要设置另一个独立的配置选定, 对启动期间的容器执行探测,从而允许使用远远超出存活态时间间隔所允许的时长。
如果你的容器启动时间通常超出
initialDelaySeconds+failureThreshold×periodSeconds 总值,你应该设置一个启动探测,对存活态探针所使用的同一端点执行检查。 periodSeconds 的默认值是 10 秒。你应该将其 failureThreshold 设置得足够高, 以便容器有充足的时间完成启动,并且避免更改存活态探针所使用的默认值。 这一设置有助于减少死锁状况的发生。
7、总结干货
Pod 是 Kubernetes 的最小执行单元,是“一组共享网络和存储的容器”,通常通过控制器来管理
序号 | 内容 |
---|---|
1 | Pod 内部可以包含一个或多个容器(常见情况是 1 个容器)。 |
1 | Pod 里的容器 共享网络和存储卷。 |
2 | 同一网络命名空间:Pod 内的容器共享 IP、Port。 |
3 | 共享存储卷:多个容器能访问相同的持久存储。 |
4 | 紧密耦合:Pod 内容器一般完成一个整体任务。 |
5 | 单容器 Pod:最常见,一个容器一个 Pod。 |
6 | 调度器:将 Pod 分配到合适的节点。 |
7 | 控制器:保证 Pod 的副本数和状态(如 Deployment、DaemonSet)。 |
8 | 亲和/反亲和:Pod 可以指定与节点或其他 Pod 的调度关系。 |
9 | Pod 的 IP 不稳定(Pod 删除重建后会变) |
Pod 的状态描述
状态 | 描述 |
---|---|
Pending: | Pod 已提交,等待调度。 |
Running: | Pod 已调度到节点上,至少一个容器运行中。 |
Succeeded: | 所有容器成功退出(状态码 0)。 |
Failed: | 至少一个容器异常退出。 |
CrashLoopBackOff: | 容器不断重启,说明有错误。 |
Pod 相关命令速查
# 查看 Pod
kubectl get pods -o wide# 查看 Pod 详细信息
kubectl describe pod <pod-name># 查看 Pod 日志
kubectl logs -f <pod-name> [-c 容器名]# 进入 Pod 容器
kubectl exec -it <pod-name> -c <容器名> -- /bin/bash
8、 K8s Pod 经典面试题速查表
1️⃣ 基础概念类
Q1: 为什么 Kubernetes 引入 Pod,而不是直接用容器?
👉 因为有些场景需要多个容器紧密协作(例如主应用 + 日志收集 + 代理),Pod 提供:
共享网络命名空间(一个 IP,多个容器);
共享存储卷;
作为 调度和伸缩的最小单位。
Q2: Pod 和容器的区别是什么?
👉 容器是应用的运行实例;
Pod 是 Kubernetes 调度的基本单位,可以包含一个或多个容器;
Pod 提供共享网络和存储,是容器的逻辑集合。
Q3: Pod 的类型有哪些?
👉单容器 Pod(最常见);
多容器 Pod(Sidecar、Ambassador、Adapter 模式);
静态 Pod(由 kubelet 直接管理,不受 API Server 控制)。
2️⃣ 生命周期与状态类
Q4: Pod 有哪些状态?
👉 Pending → Running → Succeeded/Failed → CrashLoopBackOff(异常重启)。
Q5: 什么是 Init 容器,有什么作用?
👉 Init 容器在主容器启动前运行,用于:
执行初始化任务(配置下载、检查依赖服务);
保证主容器在准备好环境后再启动。
Q6: Pod CrashLoopBackOff 怎么排查?
👉 常见原因:
应用启动失败(配置错误、缺少依赖)。
存储挂载失败。
探针检查失败(liveness/readiness probe)。 👉 排查命令:
kubectl describe pod <pod-name>
kubectl logs <pod-name> -c <container>
3️⃣ 调度与控制类
Q7: Pod 如何被调度到节点?
👉 调度器会根据:
资源请求/限制(CPU、内存);
节点选择器(nodeSelector, nodeAffinity);
Pod 亲和性/反亲和性;
Taints & Tolerations(污点与容忍)。
Q8: Pod 与 Deployment/ReplicaSet 的关系?
👉Pod:最小运行单位;
ReplicaSet:保证 Pod 的副本数;
Deployment:声明式管理 ReplicaSet,支持滚动更新、回滚。
4️⃣ 网络与存储类
Q9: Pod 如何通信?
👉同一 Pod 内:容器共享 localhost;
同一 Node 内不同 Pod:通过 Pod IP 通信;
跨 Node Pod:依赖 CNI 插件(Flannel, Calico, Cilium);
外部访问 Pod:通过 Service(ClusterIP、NodePort、LoadBalancer)。
Q🔟: Pod 为什么需要 Service?
👉 Pod 的 IP 不是固定的,重启后会变化。 Service 提供一个 稳定的虚拟 IP(ClusterIP),解决 Pod
动态变化带来的访问问题。
5️⃣ 高级与实战类
Q11: Pod 重启策略有哪些?
👉 在 Pod Spec 中 restartPolicy:
Always(默认,适用于长期运行的服务);
OnFailure(任务型,失败才重启);
Never(一次性任务)。
Q12: 怎么排查 Pod 处于 Pending 状态?
👉 常见原因:
没有可用的 Node(资源不足);
PVC 未绑定(存储不足);
Node 上的 Taint 无法被容忍。
👉 排查命令:
kubectl describe pod <pod-name>
kubectl get events --sort-by=.metadata.creationTimestamp
Q13: 静态 Pod 和普通 Pod 的区别?
👉静态 Pod:由 kubelet 直接管理,通常用于运行核心组件(kube-apiserver 等),存放在
/etc/kubernetes/manifests。普通 Pod:由 API Server 管理,通过 etcd 存储。
“人的一生会经历很多痛苦,但回头想想,都是传奇”。