
Pod的管理与使用
一、Pod基本概念
1. Pod概述
Pod由一个或多个紧密耦合的容器组成,它们之间共享网络、存储等资源。Pod是Kubernetes的最小工作单元,每个Pod包含一个或多个容器。Pod中的容器会作为一个整体被Master调度到一个Node上运行。

1.1 只包含一个应用容器的Pod
“一个pod一个容器”的模式是Kubernetes中主流的使用场景。在这种场景中,pod可以被看做是一个“有外壳”的容器,Kubernetes不能直接管理容器,而是需要通过管理Pod间接管理容器。
1.2 包含多个应用容器的Pod
仅当两种容器紧耦合,且需要共享相同的资源时才使用这一种模式。这些在一个Pod内的容器形成一个统一的服务单元。典型场景:一个容器通过共享卷提供文件资源,另一容器负责资源刷新与更新。Pod可将这类关联容器及存储资源,整合为单一可管理实体统一调度运维。
2. K8s引入Pod的目的
2.1 可管理性
部分业务容器天然需要紧密协作、协同运行,Pod提供了高于单个容器的抽象层级,将关联容器封装为统一部署单元。Kubernetes以Pod为最小调度、扩缩容、资源分配和生命周期管理单位,简化集群编排运维。
2.2 通信和资源共享
Pod中的所有容器使用同一个网络namespace,也就是相同的IP地址和Port空间。它们能够直接使用localhost通信,同时这些容器也可以共享存储。当Kubernetes挂载volume到Pod,本质是将volume挂载到Pod中的每一个容器。
3. 根容器
根容器(Pause容器/Infra容器)是Kubernetes为每个Pod自动创建的特殊容器,不运行业务逻辑,仅负责支撑Pod运行环境。Pause容器的状态代表整个pod的状态,是Pod内所有业务容器的“父容器”。
通俗一点解释,Pause容器是Pod的地基,只负责稳住网络、统一命名空间、管理进程、共享存储,让业务容器稳定协作。
3.1 核心特点
默认镜像:极简镜像,仅几百KB
自动创建:无需在YAML中定义,kubelet会在创建Pod时优先启动Pause容器。
生命周期:与Pod绑定,业务容器重启不会影响Pause容器,Pod IP始终稳定。

[Step1] 可以通过查看kubelet启动参数找到使用根容器镜像。
root@k8s-master:~# ps -ef | grep kubelet | grep pod-infra-container-image
4. Pod生命周期
Pod拥有固定的生命周期流转机制,初始为“Pending”状态。若至少一个主容器成功启动,则进入“Running”状态。运行结束后,根据容器是否异常退出而进入“Succeeded”正常终止状态或“Failed”异常终止状态。此外,如果集群节点发生网络故障、管理端无法正常获取Pod运行状态时,Pod会出现“Unknown”状态。

二、Pod的基本操作
1. 通过YAML声明式创建单容器Pod
[Step1] 本地新建YAML清单,定义Pod资源描述模板。
root@k8s-master:~# vim nginx-pod.yml
# 写入下列内容
apiVersion: v1 # 固定配置
kind: Pod # 资源类型
metadata:
name: nginx-pod # Pod的名称
spec:
containers:
- name: nginx # 容器名称
image: nginx:latest # 容器镜像名称
imagePullPolicy: IfNotPresent # 优先使用本地镜像,不存在则联网拉取[Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。
root@k8s-master:~# kubectl create -f nginx-pod.yml[Step3] 验证:获取当前命名空间下所有Pod资源的运行状态与简要信息。
root@k8s-master:~# kubectl get pod
[Step4] 验证:通过添加“-o wide”参数查看更详细信息。
# [-o]是[--output]的缩写形式
root@k8s-master:~# kubectl get pod -o wide
root@k8s-master:~# kubectl get pod --output wide
2. 通过命令创建单容器Pod
[Step1] 通过命令直接创建Pod。
root@k8s-master:~# kubectl run nginx-pod2 --image=nginx:latest --image-pull-policy=IfNotPresent[Step2] 验证:获取当前命名空间下所有Pod资源的运行状态与简要信息。
root@k8s-master:~# kubectl get pod
3. 通过YAML声明式创建多容器Pod
[Step1] 本地手动编写YAML文件时,可以通过“-”清晰区分多个容器。YAML中以“-”作为起始标记,从当前“-”开始,到下一个“-”出现之前的所有配置参数,都属于同一个容器。每出现一个“-”,代表定义了一个新容器。
root@k8s-master:~# vim more-web-pod.yml
# 写入下列内容
apiVersion: v1 # 固定配置
kind: Pod # 资源类型
metadata:
name: more-web-pod
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080 # 指定端口号,避免出现冲突
- name: php
image: php:latest
imagePullPolicy: IfNotPresent
command: ["sleep","infinity"][Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。
root@k8s-master:~# kubectl create -f more-web-pod.yml[Step3] 验证:获取当前命名空间下所有Pod资源的运行状态与简要信息。
root@k8s-master:~# kubectl get pod
4. 删除Pod
[Step1] 通过子命令“delete”删除指定Pod。
root@k8s-master:~# kubectl delete pod nginx-pod2
5. 查看Pod完整信息
[Step1] 可以通过子命令“describe”查看Pod的详细信息,特别是Pod状态出现异常时,可以重点关注“Event”字段。
root@k8s-master:~# kubectl describe pod nginx-pod
6. 进入单容器Pod
[Step1] 单容器Pod内部仅运行一个业务容器,因此无需额外指定容器名称,可以直接通过Pod名称进入容器。
root@k8s-master:~# kubectl exec -it nginx-pod -- /bin/shkubectl exec:进入容器执行命令
-it:交互式进入容器
--:分隔符,后面的内容不被当作kubectl的参数,直接在容器中运行
/bin/sh:启动shell命令行

7. 进入多容器Pod
[Step1] 当一个Pod中存在多个业务容器时,需要使用“--container”指定容器名称,从而进入目标容器。
# "--container"可以简写为"-c"
root@k8s-master:~# kubectl exec -it more-web-pod --container nginx -- /bin/sh
root@k8s-master:~# kubectl exec -it more-web-pod --container php -- /bin/sh
8. Pod容器定位
[Step1] 通过添加“-o wide”参数可以查看Pod详细部署信息,精准定位节点位置。根据输出可以看到,“more-web-pod”运行在“k8s-worker2”节点,“nginx-pod”运行在“k8s-worker1”节点。
root@k8s-master:~# kubectl get pod -o wide
[Step2] 登录到k8s-worker1上列出当前正在运行的容器,能够看到nginx。
root@k8s-worker1:~# crictl ps
9. 临时创建Pod
[Step1] 使用busybox镜像临时创建一个名为demopod的容器,直接进入容器交互终端,退出后自动删除这个Pod。
root@k8s-master:~# kubectl run --rm --image busybox:latest --image-pull-policy IfNotPresent -it demopodkubectl run:快速创建并运行一个Pod
--rm:退出后自动删除Pod
--image:指定容器使用的镜像
--image-pull-policy IfNotPresent:如果本地节点已经有这个镜像,就不再去网上拉取

三、特殊类型
1. Init类型容器
在Pod中存在一类特殊容器,Init容器是在业务容器启动前先执行的临时容器,执行完成后就退出,不会常驻运行,主要用来完成前置初始化准备工作。
环境预处理:配置时区、初始化目录、修改文件权限、生成配置文件等
等待依赖:等待数据库、Redis、后端服务、第三方组件就绪后,再启动业务容器
前置资源准备:从配置中心、Git、对象存储拉取配置、脚本、静态资源到本地目录,以供业务容器使用。
安全隔离:初始化操作需要独立权限、独立工具栈,可以放在Init容器单独实现,不需要给业务容器高权限
多阶段串行控制:多个Init容器按顺序依次执行,前一个成功后才运行下一个,全部完成后才运行业务容器。
如果Init容器启动失败,kubelet会持续重启Init容器,直至运行成功。如果Pod重启策略“restartPolicy”设置为“Never”,且Init容器启动失败,Kubernetes会将整个Pod标记为失败状态。
Init容器与普通容器用法基本一致,仅存在两点核心区别:
执行完成后,状态均固定为“completed”
多个Init容器按顺序串行执行,前一个必须执行成功,后一个才会启动
[Step1] 本地新建YAML清单。
root@k8s-master:~# vim init-demo-pod.yml
# 写入下列内容
apiVersion: v1 # 固定配置
kind: Pod # 资源类型
metadata:
name: init-demo-pod
namespace: default # 指定命名空间
spec:
initContainers: # 定义Init容器
- name: wait-busybox
image: busybox:latest
command: ['sh','-c','echo busybox && sleep 20']
imagePullPolicy: IfNotPresent
containers:
- name: nginx-app
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9090[Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。
root@k8s-master:~# kubectl create -f init-demo-pod.yml[Step3] 验证:获取当前命名空间下所有Pod资源的运行状态与简要信息,可以看到当前“STATUS”字段显示为“Init:0/1”这是因为我们只定义了一个Init容器,且该容器还未运行结束。“READY”显示“0/1”是因为我们定义了一个业务容器,但是Init容器还未运行结束,因此显示Ready状态数为0。
root@k8s-master:~# kubectl get pod
[Step4] 验证:等待“sleep”时间结束后,业务容器正常启动。
root@k8s-master:~# kubectl get pod
2. Sidecar类型容器
Sidecar(边车)是在同一Pod中与业务主容器共生的辅助容器,共享网络和存储、生命周期保持一致,无需修改业务代码,能够以外挂的形式统一提供日志采集、流量代理、服务治理、监控追踪、配置下发等通用基础能力,实现业务逻辑与运维管控能力的解耦复用。Init容器要优于Sidecar容器运行,但是Init执行完后会退出,Sidecar容器则是和业务主容器长期运行。Sidecar容器典型用途如下:
日志代理/转发:主容器写日志到共享卷,Sidecar(如Fluentd/Filebeat)采集并发送到ELK
Service Mesh与网络代理:用Envoy做Sidecar,接管进出流量,实现限流、熔断、mTLS、灰度测试(Istio核心模式)
探活:检查某些组件是否正常工作
其它辅助性工作,例如拷贝文件、下载文件等

[Step1] 本地新建YAML清单。由于Sidecar容器与业务容器以并行共生的方式运行在同一个Pod中,因此k8s并未给Sidecar容器设定专属字段。在实际使用中,只能依据容器自身的业务职责与运行作用来判断出哪一个是Sidecar容器。根据业务职责能够看到httpd容器为主业务容器,busybox为Sidecar容器,用于生成网页内容。
root@k8s-master:~# vim sidecar-demo-pod.yml
# 写入下列内容
apiVersion: v1 # 固定配置
kind: Pod # 资源类型
metadata:
name: sidecar-demo-pod
spec:
containers:
# --------------- 第一个容器:httpd(主容器,Web 服务)---------------
- name: httpd
image: httpd:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /usr/local/apache2/html/ # 容器内挂载目录
name: apachevolume # 挂载卷名称
# --------------- 第二个容器:busybox(Sidecar 辅助容器)---------------
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ['sh','-c','echo "sidecar apache"> /usr/local/apache2/html/index.html && sleep 3600']
volumeMounts:
- mountPath: /usr/local/apache2/html # 与httpd挂载到同一个目录
name: apachevolume
restartPolicy: OnFailure # 重启策略:只有当容器异常退出时才重启
volumes: # 定义Pod中的共享存储卷
- name: apachevolume # 存储卷名称
emptyDir: {} # 临时空目录卷,Pod生命周期内存活,删除则消失[Step2] 基于YAML清单向Kubernetes集群声明式地创建Pod资源。
root@k8s-master:~# kubectl create -f sidecar-demo-pod.yml[Step3] 验证:获取当前命名空间下所有Pod资源的运行状态与简要信息,能够看到容器状态为“Running”。
root@k8s-master:~# kubectl get pod
3. 静态Pod
静态Pod由节点kubelet守护进程直接管理,无需Kubernetes API Server参与管控,区别于Deployment等控制面调度管理的普通Pod。kubelet会持续监控静态Pod的运行状态,一旦Pod异常崩溃,将自动进行重启恢复。
静态Pod固定绑定在指定节点上,仅由该节点的kubelet全权负责生命周期管理。同时,kubelet会通过Kubernetes API Server为每个静态Pod自动创建镜像Pod(Mirror Pod)。
这使节点上的静态Pod可以在集群API中被查询看见,但是无法通过API Server进行任何调度、编辑和删除操作。静态Pod名称会默认追加带连字符的节点主机名作为后缀。

[Step1] 在Master节点上查看所有命名空间下的Pod,能够看到几个以“k8s-master”主机名作为后缀的,就是静态Pod。
root@k8s-master:~# kubectl get pod -A
[Step2] 上述这种查看方法其实也不准确,携带主机名作为后缀的Pod可能也是管理员自定义创建的,因此在Kubernetes也提供了其他的查询方式。首先查询kubelet服务文件,找到“Drop-In”字段指向的配置文件。“Drop-In”的作用就是不修改原systemd服务文件,在单独配置目录里追加或覆盖服务配置,实现无改动原生文件的灵活配置扩展。
root@k8s-master:~# systemctl status kubelet.service
[Step3] 查看该文件内容,找到“Environment”字段。该字段的意思是给kubelet设置一个环境变量,指定它的核心配置文件路径。
root@k8s-master:~# cat /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
[Step4] 查看该文件内容,过滤出“staticPodPath”字段。该字段指定了一个目录,目录是kubelet静态Pod的监听目录。只需要将Pod的YAML文件放置到该目录,kubelet会自动创建、运行这个静态Pod。
root@k8s-master:~# cat /var/lib/kubelet/config.yaml | grep staticPodPath
[Step5] 查看所有命名空间下携带主机名的Pod,与静态Pod监听目录内容对比,能够对应上。
root@k8s-master:~# kubectl get pod -A | grep k8s-master
root@k8s-master:~# ls /etc/kubernetes/manifests/
[Step6] 在静态Pod监听目录下创建一个YAML文件。
root@k8s-master:~# vim /etc/kubernetes/manifests/static-nginx.yml
# 写入下列内容
apiVersion: v1 # 固定配置
kind: Pod # 资源类型
metadata:
name: static-nginx
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8082[Step7] 运行中的kubelet会定期扫描目录中的变化,并根据文件中增加/减少的Pod来添加/删除Pod。等待片刻后所有命名空间下的Pod,能够看到新增的静态Pod。
root@k8s-master:~# kubectl get pod -A
