Kubernetes Pod

环境准备

[root@master30 ~ 11:41:16]# kubectl create ns pods
[root@master30 ~ 11:41:16]# kubectl config set-context --current --namespace pods

Pod 介绍

pod 代表一个deployment单元:a single instance of an application in Kubernetes。

k8s通过定义一个Pod的资源,然后在Pod里面运行容器,容器需要指定镜像,用来运行具体的服务。Pod代表集群上正在运行的一个进程,一个Pod封装一个容器(也可以封装多个容器),Pod里的容器共享存储、网络等。也就是说,应该把整个pod看作虚拟机,然后每个容器相当于运行在虚拟机的进程。

  • 运行单个容器的 Pod:将Pod看作是单个容器的包装器,kubernetes管理pods而不是直接管理容器。
  • 运行多个容器的 Pod:POD可以封装一个由多个共存容器组成的应用程序。pod中的容器会自动在集群中的同一物理机或虚拟机上运行。POD中多个容器共享资源和依赖项,彼此通信,以及协调何时以及如何终止它们。POD将这些容器、网络资源和存储资源作为一个单一的可管理实体包装在一起。pod中多个容器共享网络和存储资源。每个pod分配唯一的ip地址,pod中容器共享netns,包括ip地址和port端口。多个容器之间使用localhost通信。当pod中容器与其他pod通信,需要使用共享的网络资源。pod可以使用多个volume,pod中所有容器都可以访问这些卷。

pod 基本管理

创建 pod

# 空运行,只生成yaml文件
[root@master30 ~ 11:42:16]# kubectl run web --image=docker.io/library/nginx --dry-run=client -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: web
  name: web
spec:
  containers:
  - image: docker.io/library/nginx
    name: web
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
# 直接创建pod
[root@master30 ~]# kubectl run web --image=docker.io/library/nginx
pod/web created

[root@master30 ~]# kubectl get pod
NAME   READY   STATUS              RESTARTS   AGE
web    0/1     ContainerCreating   0          36s

#查看pod信息
[root@master30 ~]# kubectl get pod
NAME   READY   STATUS    RESTARTS   AGE
web    1/1     Running   0          51s

#查看pod详细信息
[root@master30 ~]# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP              NODE               NOMINATED NODE   READINESS GATES
web    1/1     Running   0          67s   10.224.51.131   worker31.laoma.cloud   <none>           <none>

查看 pod

# 以yaml格式查看pod
[root@master30 ~]# kubectl get pod web -o yaml

# 查看pod
[root@master30 ~ 11:04:10]# kubectl describe pod b2
Name:             b2
Namespace:        pods
Priority:         0
Service Account:  default
Node:             worker32/10.1.8.32
Start Time:       Wed, 24 Jun 2026 11:03:58 +0800
Labels:           run=b2
Annotations:      cni.projectcalico.org/containerID: 728a351f8f673c50aa3b8d1b6a1f5cd5f25e2d920e6678a6e4d8349174fa55e5
                  cni.projectcalico.org/podIP: 10.224.45.1/32
                  cni.projectcalico.org/podIPs: 10.224.45.1/32
Status:           Running
IP:               10.224.45.1
IPs:
  IP:  10.224.45.1
Containers:
  b2:
    Container ID:  containerd://bee3278ae3b544e63b40e764bee78df186dfb3597a393982ae0614a3a55e48a4
    Image:         busybox
    Image ID:      docker.io/library/busybox@sha256:fd8d9aa63ba2f0982b5304e1ee8d3b90a210bc1ffb5314d980eb6962f1a9715d
    Port:          <none>
    Host Port:     <none>
    Args:
      sh
    State:          Running
      Started:      Wed, 24 Jun 2026 11:04:12 +0800
    Last State:     Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Wed, 24 Jun 2026 11:04:00 +0800
      Finished:     Wed, 24 Jun 2026 11:04:10 +0800
    Ready:          True
    Restart Count:  1
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-7w6mr (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True 
  Initialized                 True 
  Ready                       True 
  ContainersReady             True 
  PodScheduled                True 
Volumes:
  kube-api-access-7w6mr:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age                From               Message
  ----    ------     ----               ----               -------
  Normal  Scheduled  23s                default-scheduler  Successfully assigned pods/b2 to worker32
  Normal  Pulled     22s                kubelet            Successfully pulled image "busybox" in 1.444s (1.444s including waiting). Image size: 2236931 bytes.
  Normal  Pulling    12s (x2 over 23s)  kubelet            Pulling image "busybox"
  Normal  Created    10s (x2 over 22s)  kubelet            Created container b2
  Normal  Started    10s (x2 over 22s)  kubelet            Started container b2
  Normal  Pulled     10s                kubelet            Successfully pulled image "busybox" in 1.43s (1.43s including waiting). Image size: 2236931 bytes.
# 查看pod标准输出,可以是选项-f动态查看pod输出
[root@master30 ~]# kubectl logs -f web 

编辑 pod

[root@master30 ~ 11:03:41]# kubectl edit pod web

提示:并不是所有属性都可以编辑,例如pod名称。如果非要编辑特定属性,可以先删除pod,然后修改pod对的yaml文件,重新创建。

pod 中执行命令

[root@master30 ~ 11:03:41]# kubectl run b2 -it --image=busybox sh
If you don't see a command prompt, try pressing enter.
/ # pwd
/
/ # ls
bin    dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
/ # exit

cp 文件给 pod

[root@master30 ~]# kubectl cp /etc/hosts web:/new-hosts
[root@master30 ~]# kubectl exec web -- ls /new-hosts
/new-hosts

删除 pod

[root@master30 ~ 11:04:22]# kubectl get pods
NAME   READY   STATUS             RESTARTS      AGE
b1     0/1     CrashLoopBackOff   4 (54s ago)   2m23s
b2     1/1     Running            1 (26s ago)   38s
[root@master30 ~ 11:04:36]# kubectl delete pod b1
pod "b1" deleted
[root@master30 ~ 11:04:50]# kubectl delete pod b2
pod "b2" deleted
^C[root@master30 ~ 11:05:01]# 
#强制删除
[root@master30 ~ 11:05:02]# kubectl delete pod b2 --force 
Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "b2" force deleted
[root@master30 ~ 11:05:06]# kubectl get pods
No resources found in pods namespace.

yaml 文件创建 pod

# web.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: web
  name: web
spec:
  containers:
  - image: docker.io/library/nginx
    name: web
    
#创建
[root@master30 ~ 11:54:03]# kubectl create -f web.yaml
# 或者
[root@master30 ~ 11:54:04]# kubectl apply -f web.yaml

构建 wordpreess

  1. 创建 pod-mysql 数据库
  2. 创建 pod-wordpress 博客
# 创建 pod-mysql 数据库
[root@master30 ~ 11:06:51]# kubectl run wordpress-db --image=hub.laoma.cloud/library/mysql:latest --env MYSQL_ROOT_PASSWORD=123
pod/wordpress-db created

# 创建 pod-wordpress 博客
[root@master30 ~ 11:23:39]# kubectl run wordpress-app --image=hub.laoma.cloud/library/wordpress:latest
pod/wordpress-app created

##查看状态
[root@master30 ~ 11:24:06]# kubectl get pods
NAME            READY   STATUS              RESTARTS   AGE
wordpress-app   0/1     ContainerCreating   0          8s
wordpress-db    1/1     Running             0          35s

# 创建数据库
[root@master30 ~ 11:25:02]# kubectl exec -it  wordpress-db -- mysql -uroot -p123
mysql> create database wordpress;
Query OK, 1 row affected (0.002 sec)

mysql> create user wordpress identified by '123';
Query OK, 0 rows affected (0.006 sec)

mysql> grant all privileges on wordpress.* to wordpress;
Query OK, 0 rows affected (0.002 sec)

mysql> flush privileges;
Query OK, 0 rows affected, 1 warning (0.002 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| wordpress          |
+--------------------+
5 rows in set (0.001 sec)

mysql> exit
Bye

# 查看 IP
[root@master30 ~ 11:29:32]# kubectl get pods -o wide 
NAME            READY   STATUS    RESTARTS   AGE     IP             NODE       NOMINATED NODE   READINESS GATES
wordpress-app   1/1     Running   0          5m31s   10.224.45.2    worker32   <none>           <none>
wordpress-db    1/1     Running   0          5m58s   10.224.137.3   worker31   <none>           <none>

# 实现集群外访问集群内pod
# 该命令窗口不要关闭
[root@master30 ~ 11:29:37]# kubectl port-forward pod/wordpress-app --address 10.1.8.30 80:80
Forwarding from 10.1.8.30:80 -> 80
Handling connection for 80
Handling connection for 80
Handling connection for 80
。。。。。

访问web页面 http://10.1.8.30:80,配置站点。
在这里插入图片描述

多容器 pod

示例文件:blog.yaml

[root@master30 ~ 13:52:26]# vim pod-blog.yaml
apiVersion: v1
kind: Pod
metadata:
  name: bbs
  labels:
    run: bbs
spec:
  containers:
  - image: docker.io/library/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "123"
    - name: MYSQL_USER
      value: tom
    - name: MYSQL_PASSWORD
      value: "123"
    - name: MYSQL_DATABASE
      value: bbs
    ports:
    - containerPort: 3306
      name: mysql
      protocol: TCP
  - image: docker.io/library/wordpress:latest
    imagePullPolicy: IfNotPresent
    name: wordpress
    env:
    - name: WORDPRESS_DB_USER
      value: tom
    - name: WORDPRESS_DB_PASSWORD
      value: "123"
    - name: WORDPRESS_DB_NAME
      value: bbs
    - name: WORDPRESS_DB_HOST
      value: 127.0.0.1
    ports:
    - containerPort: 80
      name: wordpress
      protocol: TCP
      hostPort: 80
[root@master30 ~ 13:53:03]# kubectl apply -f pod-blog.yaml 
pod/bbs created

#查看pod运行节点
[root@master30 ~ 14:00:17]# kubectl get pod -o wide
NAME   READY   STATUS    RESTARTS   AGE     IP             NODE       NOMINATED NODE   READINESS GATES
bbs    2/2     Running   0          3m48s   10.224.137.4   worker31   <none>           <none>  

访问测试 10.1.8.31

通过所在宿主机(31)的80端口
在这里插入图片描述

# 多容器pod中执行命令,通过-c指定容器
[root@master30 ~ 14:03:30]# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
bbs    2/2     Running   0          10m

[root@master30 ~ 14:03:31]# kubectl exec bbs -c wordpress -- hostname
bbs

[root@master30 ~]# kubectl cp /etc/hosts bbs:/new-hosts -c wordpress
[root@master30 ~]# kubectl exec bbs -c wordpress -- ls /new-hosts
/new-hosts

pod 关键属性

pod.spec.containers.ImagePullPolicy
  • Always,总是从仓库下载镜像。
  • Never,只使用本地镜像,不下载。
  • IfNotPresent,优先使用本地镜像,如果没有才从仓库下载镜像。
pod lifecycle

容器的运行状态取决于容器中的进程。

pod的运行状态取决于pod中所有容器的状态。

Pod and Container status
  • ContainerCreating 正在创建
  • Running 正在运行
  • Completed 运行完成
  • RunContainerError 运行错误
  • CrashLoopBackOff 重新创建
  • ErrImagePull 获取镜像错误
  • ImagePullBackOff 重新获取镜像
container states
  • Waiting: 等待某个条件满足变成Running状态,例如下载镜像,更新secrets等。 通过describe pod查看message和reason详细信息。
  • Running: 容器正在运行,没有问题。同时记录Running开始时间。
  • Terminated: 容器运行完成,也有可能是运行失败终止。
pod.spec.restartPolicy

示例:

  restartPolicy: Never
  containers:
  - name: myapp-container
    image: docker.io/library/busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 5'] 

restartPolicy,针对pod中所有容器生效。

  • Always,除了 Running 状态,其他状态总是重启,默认值。
  • OnFailure,失败了才重启。
  • Never,从不重启。

pod中包含1个容器,验证pod状态

监控命令: watch -n 1 kubectl get pod

示例1:

[root@master30 ~ 14:54:12]# cd pods/
[root@master30 pods 14:55:00]# vim pod-test1.yaml
#文件内容如下
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 10']

观察pod状态为:ContainerCreating–>Running–>Completed

#观察状态
[root@master30 pods 14:55:33]# watch -n 1 kubectl get pod
#构建同时观察上面命令的状态
[root@master30 pods 14:55:33]# kubectl apply -f pod-test1.yaml 
pod/busybox created

示例2:

pod中包含2个容器,验证pod状态

[root@master30 pods 15:01:40]# vim pod-test2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox1
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 5']
  - name: busybox2
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 10']
[root@master30 pods 15:02:30]# kubectl apply -f pod-test2.yaml
#查看运行状态
[root@master30 pods 14:55:33]# watch -n 1 kubectl get pod

观察pod状态为:ContainerCreating–>Running–>NotReady–>Completed

示例3:

[root@master30 pods 15:01:40]# vim pod-test3.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  restartPolicy: Never
  containers:
  - name: busybox1
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echoxx Hello Kubernetes! && sleep 5']
  - name: busybox2
    image: docker.io/library/busybox
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 20']
[root@master30 pods 15:02:30]# kubectl apply -f pod-test3.yaml
#查看运行状态
[root@master30 pods 14:55:33]# watch -n 1 kubectl get pod

观察pod状态为:ContainerCreating–>Error

Always和OnFailure重启策略总是会重启pod;Never重启策略就不会重启pod。

Init Containers

一个pod可以有多个容器在其中运行应用程序,也可以有一个或多个initContainers。initContainers中容器状态必须是complete,containers容器才能运行。

如果pod的initContainers fail,kubernetes根据restartpolicy重启pod,直到initContainers状态为complete。

如果pod中initContainers有多个容器,那么会按顺序创建和执行。按顺序执行的initContainers必须成功才能执行下一个initContainers。所有init全部成功执行完成后,才开始执行pod中常规容器。

示例1:

[root@master30 pods 15:05:07]# vim pod-myapp.yaml
# myservice
---
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

# mydb
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377

# myapp
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  initContainers:
  - name: init-myservice
    image: docker.io/library/busybox
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;sleep 3;']
  - name: init-mydb
    image: docker.io/library/busybox
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;sleep 3;']
  containers:
  - name: myapp-container
    image: docker.io/library/busybox
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']

首先创建2个service,然后创建pod,观察pod状态变化。

kubernetes 中 Pod:是 K8s 独有的概念,是 K8s 中最小调度、管理、自愈单元,是容器的“外壳 + 运行环境”

  • **一个 Pod 里可以有 1 个或多个容器,**pod中所有容器:
  • 同住一个房间,共用网络、存储
  • 一起被调度到同一台机器,一起销毁。
特性 容器 Pod
K8s 最小调度单位 ❌ 不是 ✅ 是
独立 IP ✅ 有 ✅ 有
独立 存储 ✅ 有 ✅ 有
多容器支持 ❌ 不支持 ✅ 天然支持
网络/存储共享 ❌ 不能 ✅ 内部容器可共享
生命周期管理 ❌ 弱 ✅ 完整(重启、自愈)
属于谁 运行时(Docker/containerd) Kubernetes

kubernetes 为什么直接管理 pod 而不是容器?

  1. 容器太“原子”,不适合直接调度。K8s 需要一个能直接被调度、能独立运行、有完整身份的对象–Pod
  • 容器:只是一个进程/运行环境(Docker/containerd)。
  • Pod:是容器的封装 + 网络/存储/配置/生命周期的统一抽象。K8s 调度、扩缩容、自愈、服务发现、监控……全都以 Pod 为单位
  1. Pod 支持“多容器协同”(最关键设计)。

很多场景必须多个容器一起跑、共享资源

  • 业务容器 + Sidecar(日志、监控、代理)
  • 业务容器 + InitContainer(初始化)
  • 业务容器 + 网络/安全代理容器

它们需要:

  • 共享 Network Namespace(同一个 IP、端口空间)
  • 共享 Volume
  • 一起调度到同一台机器
  1. Pod 提供统一的生命周期与自愈

K8s 要做:

  • 重启失败容器
  • 替换崩溃节点上的实例
  • 滚动更新、回滚
  • 扩缩容

这些行为必须作用在一个稳定、标准、独立的单元上:

  • 如果直接管容器,多容器应用会乱
  • 以 Pod 为单位,管理语义清晰、一致
  1. 解耦底层容器运行时。

Pod 屏蔽了底层实现:

  • Docker
  • containerd
  • cri-o
  • 其他 CRI 运行时

K8s 只跟 Pod/CRI 打交道,不绑定某一种容器技术。

pod 中 pause 容器作用

在 Kubernetes 里,每个 Pod 都会自动创建一个 pause 容器(也叫 infra 容器),它是 Pod 里第一个启动、最后退出的容器,作用非常关键。

  1. pause 容器是干嘛的?

pause 容器就是为了“占坑”,把 Pod 的网络和命名空间先 hold 住。

  1. 它的 3 个核心作用

创建并持有 Pod 的 Linux Namespace

Pod 里所有容器要共享:

  • Network namespace(同一个 IP、端口)
  • PID namespace(可选)
  • IPC namespace

这些共享空间必须由一个“永远不死”的容器来持有,否则共享空间会消失。这个容器就是 pause

让 Pod 生命周期独立于业务容器

  • 业务容器挂了 → 重启
  • pause 容器不挂 → Pod 就不会消失
  • 网络、IP、存储挂载都能保持不变

如果没有 pause:业务容器一退出,整个 Pod 的网络就没了,重启也没用。

实现多容器共享网络

nginx、业务容器、sidecar 都加入 pause 的 network namespace:

  • 共享同一个 IP
  • 可以用 127.0.0.1 互相访问
  • 端口不能冲突
  1. 超形象比喻
  • pause = 房东
  • Pod = 房子
  • 业务容器 = 租客

房东(pause)先占好房子(网络/命名空间),租客(业务容器)才能住进来。租客换了一波又一波,房子一直都在。

pause 容器 = Pod 的基石

  • 只负责 holding namespace
  • 保证 Pod 网络、IP、生命周期稳定
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐