k8s的pod管理

摘要:Pod 是 K8s 最小调度单元,

目录包括:Pod 核心概念、命令式管理、yaml 声明式编写、控制器管理 Pod、QoS、重启策略、init 容器、存活 / 就绪探针。

一、Pod 基础概念

Pod 是 Kubernetes最小可部署调度单元,一个 Pod 可以包含 1 个或多个紧密耦合的容器。

  • 同一个 Pod 内所有容器共享网络命名空间、IP、主机名 ,Pod 内部容器访问直接使用127.0.0.1
  • Pod 内部容器共享存储卷,实现容器间文件共享
  • 生产环境不建议直接手动创建 Pod,优先使用 Deployment 等控制器管理;直接创建的自主式 Pod 删除后不会自动重建,故障无法自愈。

补充:K8s 资源管理三种方式

  1. 命令式对象管理:直接 kubectl 命令操作,适合测试快速验证
  2. 命令式对象配置kubectl create -f xxx.yaml
  3. 声明式对象配置kubectl apply -f xxx.yaml,生产主流,支持版本管理、重复执行更新资源

二、命令式 Pod 管理实操

2.1 命名空间基础

Namespace 实现资源隔离,不同命名空间资源相互隔离。

复制代码
# 查看命名空间
[root@k8s-master ~]# kubectl get namespaces 
NAME              STATUS   AGE
default           Active   5d5h
kube-flannel      Active   5d4h
kube-node-lease   Active   5d5h
kube-public       Active   5d5h
kube-system       Active   5d5h
metallb-system    Active   23h

# 创建命名空间
[root@k8s-master ~]# kubectl create zq
error: Unexpected args: [zq]
See 'kubectl create -h' for help and examples
[root@k8s-master ~]# kubectl create namespace zq
namespace/zq created
[root@k8s-master ~]# kubectl get namespaces 
NAME              STATUS   AGE
default           Active   5d5h
kube-flannel      Active   5d4h
kube-node-lease   Active   5d5h
kube-public       Active   5d5h
kube-system       Active   5d5h
metallb-system    Active   23h
zq                Active   11s

# 删除命名空间(会删除该命名空间下所有资源)

[root@k8s-master ~]# kubectl delete namespaces zq
namespace "zq" deleted

2.2 Pod 常用命令

复制代码
# 创建pod
[root@k8s-master ~]# kubectl run  zq  --image nginx:latest
pod/zq created

# 查看pod基础信息
[root@k8s-master ~]# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
zq     1/1     Running   0          8s

# 查看pod详细信息(节点、podIP)
[root@k8s-master ~]# kubectl get pods  -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP           NODE        NOMINATED NODE   READINESS GATES
zq     1/1     Running   0          13s   10.244.2.3   k8s-node2   <none>           <none>

# 排查pod异常,查看事件Events(排错最重要)
[root@k8s-master ~]# kubectl run  error --image lee:v1
pod/error created
[root@k8s-master ~]# kubectl get pods -o wide
NAME    READY   STATUS              RESTARTS   AGE   IP           NODE        NOMINATED NODE   READINESS GATES
error   0/1     ContainerCreating   0          9s    <none>       k8s-node2   <none>           <none>
zq      1/1     Running             0          36s   10.244.2.3   k8s-node2   <none>           <none>
[root@k8s-master ~]# kubectl describe  pods  error
Name:             error
Namespace:        default
Priority:         0
Service Account:  default
Node:             k8s-node2/172.25.254.20
Start Time:       Tue, 25 Aug 2026 16:35:35 +0800
Labels:           run=error
Annotations:      <none>
Status:           Pending
IP:               
IPs:              <none>
Containers:
  error:
    Container ID:   
    Image:          lee:v1
    Image ID:       
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
      Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-w7w9l (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   False 
  Initialized                 True 
  Ready                       False 
  ContainersReady             False 
  PodScheduled                True 
Volumes:
  kube-api-access-w7w9l:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    Optional:                false
    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  17s   default-scheduler  Successfully assigned default/error to k8s-node2
  Normal  Pulling    17s   kubelet            spec.containers{error}: Pulling image "lee:v1"


# 删除单个pod
[root@k8s-master ~]#  kubectl delete  pods error
pod "error" deleted from default namespace
# 删除当前命名空间全部pod
[root@k8s-master ~]# kubectl delete pods --all
pod "zq" deleted from default namespace
常见 Pod 异常状态
  • ImagePullBackOff:镜像拉取失败,镜像名字错误、私有仓库没有 secret、网络无法访问仓库,使用kubectl describe pod看事件报错信息。
  • CrashLoopBackOff:容器反复启动失败,检查镜像、启动命令、日志。

2.3 上传实验镜像到 Harbor 仓库 library 项目(实验前置)

实验环境说明:本地已经有myapp.tar.gz镜像包,私有 Harbor 仓库地址为reg.timinglee.orglibrary是 Harbor 的公共项目,k8s 所有节点都默认可以拉取 library 项目镜像,不需要额外配置镜像拉取 secret。 前提:所有 k8s 节点的 docker 配置了 harbor 域名解析,docker 信任该私有仓库。

复制代码
#1. 将本地tar镜像包导入docker本地镜像库
[root@k8s-master ~]# docker load  -i myapp.tar.gz

#2. 给本地镜像打标签,格式:仓库地址/项目名/镜像名:版本

[root@k8s-master ~]# docker tag timinglee/myapp:v1 reg.timinglee.org/library/myapp:v1
[root@k8s-master ~]# docker tag timinglee/myapp:v2 reg.timinglee.org/library/myapp:v2

#3. 将打好标签镜像推送到harbor仓库library项目

[root@k8s-master ~]# docker push  reg.timinglee.org/library/myapp:v1
The push refers to repository [reg.timinglee.org/library/myapp]
68695a6cfd7d: Layer already exists 
d39d92664027: Layer already exists 
8460a579ab63: Layer already exists 
c1dc81a64903: Layer already exists 
05a9e65e2d53: Layer already exists 
a0d2c4392b06: Layer already exists 
v1: digest: sha256:238a348a45b26007ee5ecead440a7bb9cb31446081a823172797ba3c8c7acfb4 size: 1157

[root@k8s-master ~]# docker push  reg.timinglee.org/library/myapp:v2

2.4 控制器管理 Pod(Deployment)

生产环境使用 Deployment 控制器管理 Pod,实现副本管理、滚动更新、版本回滚、自愈。

复制代码
# 创建deployment,2副本
[root@k8s-master ~]# kubectl create deployment webcluster --replicas 2 --image myapp:v1
deployment.apps/webcluster created


# 查看deployment
root@k8s-master ~]#  kubectl get deployments.apps
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
webcluster   2/2     2            2           13s

# 删除deployment
[root@k8s-master ~]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-77c87d9946-d8dzt   1/1     Running   0          2m27s
webcluster-77c87d9946-kx8rq   1/1     Running   0          2m27s
[root@k8s-master ~]# kubectl delete deployments.apps webcluster
deployment.apps "webcluster" deleted from default namespace
[root@k8s-master ~]# kubectl get pods
No resources found in default namespace.

# 扩缩容
[root@k8s-master ~]# kubectl scale deployment webcluster --replicas 4
deployment.apps/webcluster scaled
[root@k8s-master ~]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-7f8f75f8b9-5v252   1/1     Running   0          14s
webcluster-7f8f75f8b9-mf4db   1/1     Running   0          3m45s
webcluster-7f8f75f8b9-wmh8v   1/1     Running   0          14s
webcluster-7f8f75f8b9-wpmbm   1/1     Running   0          14s
[root@k8s-master ~]# kubectl scale deployment webcluster --replicas 1
deployment.apps/webcluster scaled
[root@k8s-master ~]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-7f8f75f8b9-mf4db   1/1     Running   0          3m51s


# 查看发布状态
[root@k8s-master ~]# kubectl rollout status deployment webcluster
deployment "webcluster" successfully rolled out


# 重启deployment所有pod
[root@k8s-master ~]# kubectl rollout restart deployment webcluster
deployment.apps/webcluster restarted


# 将deployment暴露为service,实现访问pod
[root@k8s-master ~]#  kubectl expose deployment webcluster --port  80 --target-port 80
service/webcluster exposed
[root@k8s-master ~]# kubectl get service
NAME          TYPE           CLUSTER-IP       EXTERNAL-IP         PORT(S)   AGE
extrnalname   ExternalName   <none>           www.timinglee.org   <none>    24h
kubernetes    ClusterIP      10.96.0.1        <none>              443/TCP   5d6h
webcluster    ClusterIP      10.107.105.133   <none>              80/TCP    10s
[root@k8s-master ~]# kubectl describe  svc webcluster
Name:                     webcluster
Namespace:                default
Labels:                   app=webcluster
Annotations:              <none>
Selector:                 app=webcluster
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.107.105.133
IPs:                      10.107.105.133
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                10.244.2.10:80
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>
[root@k8s-master ~]# curl 10.107.105.133/hostname.html
webcluster-77c87d9946-h4lr5



# 直接修改资源
# edit:编辑yaml在线修改
[root@k8s-master ~]# kubectl create deployment webcluster --image myapp:v1
deployment.apps/webcluster created
[root@k8s-master ~]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-77c87d9946-h4lr5   1/1     Running   0          10s
[root@k8s-master ~]# kubectl edit deployments.apps webcluster
   replicas: 2
[root@k8s-master ~]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-77c87d9946-gf9hm   1/1     Running   0          10s
webcluster-77c87d9946-h4lr5   1/1     Running   0          52s

# patch补丁方式修改
[root@k8s-master ~]# kubectl patch deployments.apps webcluster -p '{"spec":{"replicas":1}}'
deployment.apps/webcluster patched
[root@k8s-master ~]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-77c87d9946-h4lr5   1/1     Running   0          2m32s

# 查看pod日志
[root@k8s-master ~]# kubectl logs pods/webcluster-77c87d9946-h4lr5 
10.244.0.0 - - [25/Aug/2026:09:11:53 +0000] "GET /hostname.html HTTP/1.1" 200 28 "-" "curl/7.76.1" "-"

# 进入pod容器
# attach:直接接入容器控制台,不分配伪终端
root@k8s-master ~]# kubectl run -it testpod --image busybox:latest
All commands and output from this session will be recorded in container logs, including credentials and sensitive information passed through the command prompt.
If you don't see a command prompt, try pressing enter.
/ # 
/ # 
/ # Session ended, resume using 'kubectl attach testpod -c testpod -i -t' command when the pod is running
[root@k8s-master ~]# kubectl attach pods/testpod -it
All commands and output from this session will be recorded in container logs, including credentials and sensitive information passed through the command prompt.
If you don't see a command prompt, try pressing enter.
/ # 

# exec:在pod中执行命令,最常用进入容器
[root@k8s-master ~]# kubectl run  testpod --image  nginx:latest
pod/testpod created
[root@k8s-master ~]#  kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
testpod                       1/1     Running   0          8s
webcluster-77c87d9946-h4lr5   1/1     Running   0          19m
[root@k8s-master ~]# kubectl exec -it pods/testpod -c testpod -- /bin/bash
root@testpod:/# 

# pod与本地主机文件互相拷贝
[root@k8s-master ~]# kubectl cp  testpod:/usr/share/nginx/html/index.html  /mnt/test
tar: Removing leading `/' from member names
[root@k8s-master ~]# kubectl cp  testpod:/usr/share/nginx/html  /mnt/
tar: Removing leading `/' from member names
[root@k8s-master ~]# ls /mnt/
50x.html  hgfs  index.html  test
[root@k8s-master ~]#  echo timinglee > /mnt/index.html
[root@k8s-master ~]#  kubectl cp /mnt/index.html testpod:/usr/share/nginx/html/index.html
[root@k8s-master ~]# kubectl get pods  -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
testpod                       1/1     Running   0          2m21s   10.244.2.13   k8s-node2   <none>           <none>
webcluster-77c87d9946-h4lr5   1/1     Running   0          22m     10.244.2.10   k8s-node2   <none>           <none>
[root@k8s-master ~]# curl 10.244.2.13
timinglee

2.5 标签管理 label

标签是 key=value 键值对,控制器依靠标签选择器匹配管理 Pod。

复制代码
# 查看pod标签
[root@k8s-master ~]# kubectl get pods  --show-labels
NAME                          READY   STATUS    RESTARTS   AGE     LABELS
webcluster-7f8f75f8b9-mf4db   1/1     Running   0          9m55s   app=webcluster,pod-template-hash=7f8f75f8b9


# 增加标签
[root@k8s-master ~]# kubectl label pods webcluster-7f8f75f8b9-mf4db app=webcluster
pod/webcluster-7f8f75f8b9-mf4db labeled
[root@k8s-master ~]# kubectl get pods  --show-labels
NAME                          READY   STATUS    RESTARTS   AGE   LABELS
webcluster-7f8f75f8b9-mf4db   1/1     Running   0          11m   app=webcluster,pod-template-hash=7f8f75f8b9


# 覆盖已有标签
kubectl label pods webcluster-7f8f75f8b9-mf4db app=webcluster --overwrite

# 删除标签,key后面加减号
k[root@k8s-master ~]# kubectl label pods webcluster-7f8f75f8b9-mf4db app-
pod/webcluster-7f8f75f8b9-mf4db unlabeled
[root@k8s-master ~]# kubectl get pods  --show-labels
NAME                          READY   STATUS    RESTARTS   AGE   LABELS
webcluster-7f8f75f8b9-h2llz   1/1     Running   0          6s    app=webcluster,pod-template-hash=7f8f75f8b9
webcluster-7f8f75f8b9-mf4db   1/1     Running   0          10m   pod-template-hash=7f8f75f8b9-

# 根据标签筛选资源 -l
[root@k8s-master ~]# kubectl get pods -l app=webcluster
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-7f8f75f8b9-mf4db   1/1     Running   0          18m

2.6 利用控制器实现版本更替

实验前提:harbor 仓库 library 项目中已经准备好myapp:v1myapp:v2两个镜像;Deployment 控制器依靠滚动更新机制完成业务版本升级、版本回退,业务更新过程不中断服务。

2.6.1 建立控制器

两种方式创建 Deployment 控制器,命令行直接创建,或者导出 yaml 文件 apply 部署。

复制代码
# 导出yaml模板
[root@k8s-master ~]# kubectl create deployment webcluster --image myapp:v1 --replicas 2 --dry-run=client -o yaml > webcluster.yml

webcluster.yml 内容:

复制代码
root@k8s-master ~]#  vim webcluster.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: webcluster
  name: webcluster
spec:
  replicas: 2
  selector:
    matchLabels:
      app: webcluster
  template:
    metadata:
      labels:
        app: webcluster
    spec:
      containers:
      - image: myapp:v1
        name: myapp

# 应用yaml创建控制器
[root@k8s-master ~]# kubectl apply -f webcluster.yml
deployment.apps/webcluster created

# 查看pod状态
[root@k8s-master ~]#  kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-77c87d9946-jcrlz   1/1     Running   0          7s
webcluster-77c87d9946-rs8cd   1/1     Running   0          7s

# 查看更新历史
[root@k8s-master ~]#  kubectl rollout history deployment webcluster
deployment.apps/webcluster 
REVISION  CHANGE-CAUSE
1         <none>


# 暴露service为NodePort,外部可以访问业务
[root@k8s-master ~]# kubectl expose deployment webcluster --port 80 --target-port 80 --type NodePort
service/webcluster exposed


# 查看service获取nodePort端口
[root@k8s-master ~]#  kubectl get svc
NAME          TYPE           CLUSTER-IP     EXTERNAL-IP         PORT(S)        AGE
extrnalname   ExternalName   <none>         www.timinglee.org   <none>         25h
kubernetes    ClusterIP      10.96.0.1      <none>              443/TCP        5d7h
webcluster    NodePort       10.111.60.94   <none>              80:38224/TCP   5s



[root@k8s-master ~]# curl http://172.25.254.100:38224/hostname.html
webcluster-77c87d9946-h8pdm
2.6.2 更新业务版本(滚动更新)
复制代码
# 更新镜像版本为v2,触发滚动更新
[root@k8s-master ~]# kubectl set image deployments webcluster myapp=myapp:v2
deployment.apps/webcluster image updated


# 给本次更新添加版本注释,方便history查看记录
[root@k8s-master ~]# kubectl annotate deployment webcluster kubernetes.io/change-cause="myappv2" --overwrite
deployment.apps/webcluster annotated

# 观察pod变化,旧pod逐步销毁,新pod逐步创建
[root@k8s-master ~]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-6c8b4bb9d7-48f9r   1/1     Running   0          19s
webcluster-6c8b4bb9d7-vthnl   1/1     Running   0          21s


# 查看版本变更历史记录
[root@k8s-master ~]# kubectl rollout history deployment webcluster
deployment.apps/webcluster 
REVISION  CHANGE-CAUSE
1         <none>
2         myappv2


[root@k8s-master ~]# curl http://172.25.254.100:38224
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
2.6.3 版本回退

新版本业务出现 bug,执行 rollout undo 进行版本回滚,回滚会复用旧版本 ReplicaSet。

复制代码
# 回退至上一个版本
[root@k8s-master ~]# kubectl rollout undo deployment webcluster
deployment.apps/webcluster rolled back
[root@k8s-master ~]# kubectl rollout history deployment webcluster
deployment.apps/webcluster 
REVISION  CHANGE-CAUSE
2         myappv2
3         <none>


# 回退到指定revision版本,例如回退revision=1(v1版本)
[root@k8s-master ~]# kubectl rollout undo deployment webcluster --to-revision=2
deployment.apps/webcluster rolled back
[root@k8s-master ~]# kubectl rollout history deployment webcluster
deployment.apps/webcluster 
REVISION  CHANGE-CAUSE
3         <none>
4         myappv2


# 监控回滚pod变化
root@k8s-master ~]# kubectl get pods -w
NAME                          READY   STATUS    RESTARTS   AGE
webcluster-6c8b4bb9d7-64d4d   1/1     Running   0          15s
webcluster-6c8b4bb9d7-nktnz   1/1     Running   0          14s

补充命令

复制代码
# 查看发布进度
kubectl rollout status deployment webcluster
# 重启控制器下全部pod
kubectl rollout restart deployment webcluster

三、YAML 声明式编写 Pod

3.1 快速生成 yaml 模板

复制代码
# --dry-run=client 只输出yaml,不会创建资源

root@k8s-master ~]# kubectl run  testpod --image  myapp:v1  --dry-run=client -o yaml > testpod.yaml

3.2 Pod yaml 核心字段说明

字段 说明
apiVersion 资源 API 版本,Pod 使用 v1,Deployment 使用 apps/v1
kind 资源类型:Pod/Deployment/Service
metadata 元数据,name 名称、namespace 命名空间、labels 标签
spec 期望状态,核心配置
spec.containers\[\] 容器数组,可以写多个容器实现多容器 Pod
spec.restartPolicy 重启策略 Always/OnFailure/Never
spec.nodeSelector 节点标签选择,指定 pod 调度到哪个节点
spec.hostNetwork 是否共享宿主机网络
spec.resources CPU 内存资源请求与限制

基础单容器 Pod

复制代码
[root@k8s-master ~]# vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: reg.timinglee.org/library/myapp:v1
    name: myapp

执行:

复制代码
# 创建/更新资源
kubectl apply -f testpod.yaml
# 删除资源
kubectl delete -f testpod.yaml

Pod 内部多容器

同一个 Pod 多个容器共享网络,可以localhost互相访问,注意端口不能冲突。

复制代码
[root@k8s-master ~]# vim testpod.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: myapp:v1
    name: myapp1
  - image: busyboxplus:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000

[root@k8s-master ~]# kubectl apply -f testpod.yaml
pod/testpod created
[root@k8s-master ~]# kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
testpod   2/2     Running   0          25s

进入指定容器
[root@k8s-master ~]#  kubectl exec -it pods/testpod -c busybox -- /bin/sh
/bin/sh: shopt: not found
[ root@testpod:/ ]$  curl  127.0.0.1
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

端口配置 hostPort

hostPort 将容器端口映射到宿主机节点端口,注意同一个节点不能启动多个相同 hostPort 的 Pod,端口冲突。

复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: myapp:v1
    name: myapp1
    ports:
    - name: http
      containerPort: 80			#pod内部容器端口
      hostPort: 80				#pod所在节点端口
      protocol: TCP				#端口所用协议

[root@k8s-master ~]# kubectl apply -f testpod.yaml
pod/testpod created
[root@k8s-master ~]# kubectl get pods   -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
testpod   1/1     Running   0          7s    10.244.2.32   k8s-node2   <none>           <none>
[root@k8s-master ~]# curl  k8s-node2 
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

环境变量 env

复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: mysql
  name: mysql
spec:
  containers:
  - image: mysql:8.0
    name: mysql8
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: lee

  - image: phpmyadmin:latest
    name: mysqladmin
    env:
    - name: PMA_ARBITRARY
      value: "1"
    ports:
    - name: phpadminport
      containerPort: 80
      hostPort: 80
      protocol: TCP

[root@k8s-master ~]# kubectl apply -f mysql.yml
pod/mysql created
[root@k8s-master ~]# kubectl get pods  -o wide
NAME    READY   STATUS              RESTARTS   AGE   IP       NODE        NOMINATED NODE   READINESS GATES
mysql   0/2     ContainerCreating   0          7s    <none>   k8s-node2   <none>           <none>

指定调度节点 nodeSelector

根据节点标签,强制 Pod 调度匹配标签的节点。

复制代码
[root@k8s-master ~]#  kubectl get nodes --show-labels
NAME         STATUS     ROLES           AGE    VERSION   LABELS
k8s-master   Ready      control-plane   5d7h   v1.35.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
k8s-node1    Ready      <none>          5d2h   v1.35.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
k8s-node2    Ready      <none>          5d7h   v1.35.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux

root@k8s-master ~]# vim testpod.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: mysql
  name: mysql
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-node2
  containers:
  - image: mysql:8.0
    name: mysql8
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: lee

  - image: phpmyadmin:latest
    name: mysqladmin
    env:
    - name: PMA_ARBITRARY
      value: "1"
    ports:
    - name: phpadminport
      containerPort: 80
      hostPort: 80
      protocol: TCP

root@k8s-master ~]# kubectl apply -f mysql.yml
pod/mysql created
[root@k8s-master ~]#  kubectl get pods  -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
mysql   2/2     Running   0          7s    10.244.2.34   k8s-node2   <none>           <none>

共享宿主机网络 hostNetwork:true

Pod 直接复用宿主机网络栈,PodIP 就是节点主机 IP。

复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  hostNetwork: true
  containers:
  - image: busybox:latest
    name: busybox
    command:
    - /bin/sh
    - -c
    - sleep 10000

[root@k8s-master ~]# kubectl apply -f testpod.yaml
pod/testpod created 
[root@k8s-master ~]#  kubectl exec -it pods/testpod -c busybox -- /bin/sh
/ # 
/ # ifconfig 
cni0      Link encap:Ethernet  HWaddr F2:F4:C3:31:6E:44  
          inet addr:10.244.2.1  Bcast:10.244.2.255  Mask:255.255.255.0
          inet6 addr: fe80::f0f4:c3ff:fe31:6e44/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:19498 errors:0 dropped:0 overruns:0 frame:0
          TX packets:19576 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1769571 (1.6 MiB)  TX bytes:2418429 (2.3 MiB)

docker0   Link encap:Ethernet  HWaddr 4A:99:2E:8F:C4:BD  
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:16 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

eth0      Link encap:Ethernet  HWaddr 00:0C:29:D9:65:AB  
          inet addr:172.25.254.20  Bcast:172.25.254.255  Mask:255.255.255.0
          inet6 addr: fe80::4e19:1e0d:4a92:a53f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1088624 errors:0 dropped:0 overruns:0 frame:0
          TX packets:69815 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1597749729 (1.4 GiB)  TX bytes:6793679 (6.4 MiB)

flannel.1 Link encap:Ethernet  HWaddr DE:49:EF:37:F9:00  
          inet addr:10.244.2.0  Bcast:0.0.0.0  Mask:255.255.255.255
          inet6 addr: fe80::dc49:efff:fe37:f900/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:91 errors:0 dropped:0 overruns:0 frame:0
          TX packets:65 errors:0 dropped:41 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:5992 (5.8 KiB)  TX bytes:6971 (6.8 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:20217 errors:0 dropped:0 overruns:0 frame:0
          TX packets:20217 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1672988 (1.5 MiB)  TX bytes:1672988 (1.5 MiB)

veth44aae0d1 Link encap:Ethernet  HWaddr 5A:F6:18:2B:6E:84  
          inet6 addr: fe80::58f6:18ff:fe2b:6e84/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:9732 errors:0 dropped:0 overruns:0 frame:0
          TX packets:10193 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1065375 (1.0 MiB)  TX bytes:1411443 (1.3 MiB)

veth8697265e Link encap:Ethernet  HWaddr A2:53:62:B1:DD:32  
          inet6 addr: fe80::a053:62ff:feb1:dd32/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:9358 errors:0 dropped:0 overruns:0 frame:0
          TX packets:9936 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:901610 (880.4 KiB)  TX bytes:1051768 (1.0 MiB)

/ # 

四、Pod 资源 QoS 优先级

Pod 设置resources.requests(资源请求,调度时保证最小资源)、resources.limits(资源上限,最大可用资源),会生成 QoS 等级,当节点资源不足,内核优先驱逐低优先级 Pod。

  1. Guaranteed(最高优先级):requests 与 limits 的 cpu、memory 全部相等

    [root@k8s-master ~]# vim testpod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
    labels:
    run: testpod
    name: testpod
    spec:
    hostNetwork: true
    containers:

    • image: busybox:latest
      name: busybox
      command:
      • /bin/sh
      • -c
      • sleep 10000
        apiVersion: v1
        kind: Pod
        metadata:
        labels:
        run: testpod
        name: testpod
        spec:
        hostNetwork: true
        containers:
    • image: busybox:latest
      name: busybox
      command:
      • /bin/sh
      • -c
      • sleep 10000
        resources:
        limits:
        cpu: 500m
        memory: 100M
        requests:
        cpu: 500m
        memory: 100M

    [root@k8s-master ~]# kubectl apply -f testpod.yaml
    pod/testpod created
    [root@k8s-master ~]# kubectl describe pods testpod | grep "QoS Class:"
    QoS Class: Guaranteed

  2. Burstable(中等优先级):设置了 requests/limits,但两者值不相等

    resources:
    limits:
    cpu: 700m
    memory: 200M
    requests:
    cpu: 500m
    memory: 100M

    [root@k8s-master ~]# kubectl apply -f testpod.yaml
    pod/testpod created
    [root@k8s-master ~]# kubectl describe pods testpod | grep "QoS Class:"
    QoS Class: Burstable

  3. BestEffort(最低优先级):完全不设置 resources 任何参数,资源不足最先被驱逐。

复制代码
[root@k8s-master ~]# kubectl apply -f testpod.yaml
pod/testpod created
[root@k8s-master ~]#  kubectl describe pods  testpod  | grep "QoS Class:"
QoS Class:                   BestEffort

五、Pod 重启策略 restartPolicy

三种策略,Deployment 控制器只能使用 Always

  1. Always(默认):容器无论什么退出,都会重启。适合 web 服务类。

    apiVersion: v1
    kind: Pod
    metadata:
    labels:
    run: testpod
    name: testpod
    spec:
    hostNetwork: true
    restartPolicy: Always
    containers:

    • image: busybox:latest
      name: busybox
      command:
      • /bin/sh
      • -c
      • sleep 60

    [root@k8s-node2 ~]# docker ps --filter "name=testpod"
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    06c27207c73f 40680ace50cf "/bin/sh -c 'sleep 6..." 19 seconds ago Up 19 seconds k8s_busybox_testpod_default_ee34008d-1019-4afc-9c4b-6e5b0785d55d_2
    [root@k8s-node2 ~]# docker rm -f 06c27207c73f
    06c27207c73f
    root@k8s-master ~]# kubectl get pods -o wide -w
    NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
    testpod 0/1 Completed 2 (2m55s ago) 4m58s 172.25.254.20 k8s-node2
    testpod 0/1 CrashLoopBackOff 2 (58s ago) 5m13s 172.25.254.20 k8s-node2
    testpod 1/1 Running 3 (59s ago) 5m14s 172.25.254.20 k8s-node2

  2. OnFailure:容器异常退出(退出码非 0)才重启;正常退出 (0) 不会重启。适合批处理任务。

    spec:
    restartPolicy: OnFailure

  3. Never:容器退出,无论成功失败,绝不重启。一次性任务。

    spec:
    restartPolicy: Never

六、Pod 生命周期、Init 容器

Pod 生命周期流程:初始化(init容器执行) → 启动业务容器 → 探针持续检测 → 终止销毁

Init 容器

Init 容器在业务容器启动之前顺序执行,必须全部成功退出,才会启动业务主容器;init 失败会反复重启 Pod。 典型场景:等待外部依赖服务就绪、下载配置、初始化数据库。

复制代码
[root@k8s-master ~]# kubectl run  webserver --image myapp:v1 --dry-run=client -o yaml > init-example.yml
[root@k8s-master ~]#  vim init-example.ymapiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  initContainers:
  - name: busybox
    image: busybox:latest
    command:
    - /bin/sh
    - -c
    - "until test -e /testfile;do echo wating for myservice; sleep 2;done"
  containers:
  - image: myapp:v1
    name: webserver
  restartPolicy: Alwaysl

root@k8s-master ~]# kubectl apply -f init-example.yml
pod/webserver created
[root@k8s-master ~]# kubectl exec -it pods/webserver -c busybox -- /bin/sh
/ # 
/ # touch /testfile
[root@k8s-master ~]# watch -n 1 kubectl get pods  -o wide

七、容器探针(Probe)健康检查

kubelet 定期执行探针,检测容器健康,分为 3 种探针:

  1. livenessProbe 存活探针:判断容器进程是否正常,探测失败直接杀死容器,根据重启策略重启容器,解决进程假死。
  2. readinessProbe 就绪探针 :判断业务是否可以接收流量,探测失败,把 pod 从 service 的 endpoints 移除,不再转发流量,不会杀死容器
  3. startupProbe 启动探针:慢启动应用,启动探针成功之后才启用另外两个探针。

探针支持三种探测方式:exec命令执行tcpSocket端口探测httpGet http请求探测

探针通用参数:

  • initialDelaySeconds:容器启动后延迟多久开始探测
  • periodSeconds:探测间隔时间
  • timeoutSeconds:探测超时时间

存活探针 tcp 探测端口

无存活探针

复制代码
[root@k8s-master ~]# kubectl run  testpod --image  myapp:v1  --dry-run=client -o yaml > livness-example.yaml
[root@k8s-master ~]# vim livness-example.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  containers:
  - image: myapp:v1
    name: webserver
    command: ["/bin/sh", "-c"]
    args:
    - |
      nginx -g "daemon off;"
      sleep 10000
  restartPolicy: Always

[root@k8s-master ~]#  kubectl apply -f livness-example.yaml
pod/webserver created
[root@k8s-master ~]# kubectl exec  -it  pods/webserver -c webserver  -- /bin/sh
/ # nginx -s stop
2026/08/25 11:21:25 [notice] 15#15: signal process started
/ # exec attach failed: error on attach stdin: read escape sequence
command terminated with exit code 126

#查看pod的状态仍然是runing,但是访问此pod时访问失败
[root@k8s-master ~]# watch -n 1 kubectl get pods  -o wide
[root@k8s-master ~]# curl 10.244.2.38  
curl: (7) Failed to connect to 10.244.2.38 port 80: 拒绝连接

有存活探针

复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  containers:
  - image: myapp:v1
    name: testpod
    command: ["/bin/sh", "-c"]
    args:
    - |
      nginx -g "daemon off;"
      sleep 10000
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 1
      timeoutSeconds: 1
  restartPolicy: Always

[root@k8s-master ~]# kubectl apply -f livness-example.yaml 
pod/webserver created
[root@k8s-master ~]# kubectl get pods  -o wide  -w
NAME        READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
webserver   1/1     Running   0          67s   10.244.2.41   k8s-node2   <none>           <none>
 
[root@k8s-master ~]# kubectl exec -it pods/webserver -c testpod -- /bin/sh
/ # nginx -s stop
2026/08/25 11:40:52 [notice] 14#14: signal process started
/ # exec attach failed: error on attach stdin: read escape sequence
command terminated with exit code 126
[root@k8s-master ~]# curl 10.244.2.41

[root@k8s-master ~]# curl 10.244.2.41
curl: (7) Failed to connect to 10.244.2.41 port 80: 拒绝连接
[root@k8s-master ~]# curl 10.244.2.41
curl: (7) Failed to connect to 10.244.2.41 port 80: 拒绝连接
[root@k8s-master ~]# curl 10.244.2.41
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

就绪探针 httpGet 访问页面

无就绪探针

复制代码
[root@k8s-master ~]# kubectl run  testpod --image  myapp:v1  --dry-run=client -o yaml > readness-example.yml
[root@k8s-master ~]# vim readness-example.yml

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  containers:
  - image: myapp:v1
    name: webserver
  restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: webserver

[root@k8s-master ~]# kubectl apply -f readness-example.yml
pod/webserver created
service/webserver created
[root@k8s-master ~]#  kubectl describe  svc webserver
Name:                     webserver
Namespace:                default
Labels:                   run=webserver
Annotations:              <none>
Selector:                 run=webserver
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.206.3
IPs:                      10.100.206.3
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                10.244.2.39:80
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>
[root@k8s-master ~]# kubectl exec -it pods/webserver -c webserver -- /bin/sh
/ # cd /usr/share/nginx/
/usr/share/nginx # ls
html
/usr/share/nginx # cd html/
/usr/share/nginx/html # rm -fr index.html
/usr/share/nginx/html # ls
50x.html
/usr/share/nginx/html # exec attach failed: error on attach stdin: read escape sequence
command terminated with exit code 126
[root@k8s-master ~]# kubectl describe  svc webserver
Name:                     webserver
Namespace:                default
Labels:                   run=webserver
Annotations:              <none>
Selector:                 run=webserver
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.206.3
IPs:                      10.100.206.3
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                10.244.2.39:80  #还在
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>
[root@k8s-master ~]# curl  10.100.206.3
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.12.2</center>
</body>
</html>

有就绪探针

复制代码
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  containers:
  - image: myapp:v1
    name: webserver
    readinessProbe:
      httpGet:
        path: /index.html
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 2
      timeoutSeconds: 1
  restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: webserver

[root@k8s-master ~]# kubectl apply -f readness-example.yml
pod/webserver created
service/webserver unchanged

[root@k8s-master ~]#  kubectl get pods  -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
webserver   1/1     Running   0          17s   10.244.2.40   k8s-node2   <none>           <none>
[root@k8s-master ~]#  kubectl describe  svc webserver
Name:                     webserver
Namespace:                default
Labels:                   run=webserver
Annotations:              <none>
Selector:                 run=webserver
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.206.3
IPs:                      10.100.206.3
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                10.244.2.40:80
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>
[root@k8s-master ~]#  kubectl exec -it pods/webserver -c webserver -- /bin/sh
/ # rm -fr /usr/share/nginx/html/index.html
/ #  echo timinglee > /usr/share/nginx/html/index.html
/ # exec attach failed: error on attach stdin: read escape sequence
command terminated with exit code 126
[root@k8s-master ~]# curl  10.100.206.3
timinglee

业务场景:nginx 进程还活着,但是主页文件丢失返回 403/404,liveness 探针认为进程端口正常不会重启;此时 readiness 探针失败,service 摘除该 pod,不再转发流量。

八、Pod 排错思路总结

  1. kubectl get pods看 pod 状态,确认 Running/Error/CrashLoopBackOff/ImagePullBackOff
  2. kubectl get pods -o wide确认调度节点、podIP
  3. kubectl describe pod xxx重点看 Events 事件,绝大多数错误都在这里
  4. kubectl logs podname [-c 容器名]查看容器内部日志
  5. kubectl exec -it podname -- /bin/bash进入容器内部复现问题
相关推荐
悠然南风1 小时前
【云原生学习】Prometheus监控、GitLab与Jenkins部署实战
kubernetes·gitlab
菜鸟界的菜鸟1 小时前
k8s-Service详解(七)
云原生·容器·kubernetes
wazmlp0018873691 小时前
k8s pod 管理
docker·容器·kubernetes
Dear~yxy1 小时前
k8s的pod
云原生·容器·kubernetes
Dear~yxy1 小时前
k8s中的控制器管理
云原生·容器·kubernetes
众人皆醒我独醉2 小时前
自动扩缩容:KPA/HPA/KEDA 三条路径
面试·kubernetes·llm
qizhideyu3 小时前
kubernetes中的pod管理
云原生·容器·kubernetes
lxw20230271163 小时前
k8s的pod管理
linux·容器·kubernetes
Yiiz.3 小时前
Kubernetes Pod 与控制器知识点
云原生·容器·kubernetes